commit 7e38b8d9714a0c598e10735f5795378059231e03 Author: ran.shang <> Date: Wed Jun 11 09:42:13 2025 +0800 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5eac309 --- /dev/null +++ b/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..3817f49 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# alita-bjy-uygur + diff --git a/db/聊天功能.sql b/db/聊天功能.sql new file mode 100644 index 0000000..b82fdd7 --- /dev/null +++ b/db/聊天功能.sql @@ -0,0 +1,58 @@ +CREATE TABLE "xs_chat" +( + "id" BIGINT IDENTITY(1, 1) NOT NULL PRIMARY KEY, + "org_id" BIGINT, + "org_user_id" BIGINT, + "person_user_id" BIGINT, + "type" VARCHAR(32), + "status" TINYINT, + "deleted" BIT DEFAULT 0 NOT NULL, + "create_by" BIGINT NOT NULL, + "create_time" TIMESTAMP(0) NOT NULL, + "update_by" BIGINT, + "update_time" TIMESTAMP(0), + "proxy_by" BIGINT + ) ; + +COMMENT ON TABLE "xs_chat" IS '聊天表'; +COMMENT ON COLUMN "xs_chat"."org_id" IS '机构id'; +COMMENT ON COLUMN "xs_chat"."org_user_id" IS '机构用户id'; +COMMENT ON COLUMN "xs_chat"."person_user_id" IS '个人用户id'; +COMMENT ON COLUMN "xs_chat"."type" IS '类型(chat_type)'; +COMMENT ON COLUMN "xs_chat"."status" IS '状态:1有效,2关闭'; +COMMENT ON COLUMN "xs_chat"."create_by" IS '创建人'; +COMMENT ON COLUMN "xs_chat"."create_time" IS '创建时间'; +COMMENT ON COLUMN "xs_chat"."deleted" IS '是否逻辑删除'; +COMMENT ON COLUMN "xs_chat"."proxy_by" IS '代理人'; +COMMENT ON COLUMN "xs_chat"."update_by" IS '更新人'; +COMMENT ON COLUMN "xs_chat"."update_time" IS '更新时间'; + + + +CREATE TABLE "xs_chat_msg" +( + "id" BIGINT IDENTITY(1, 1) NOT NULL PRIMARY KEY, + "chat_id" BIGINT, + "sender_id" BIGINT, + "msg_type" VARCHAR(16), + "content" VARCHAR(1024), + "msg_status" TINYINT, + "deleted" BIT DEFAULT 0 NOT NULL, + "create_by" BIGINT NOT NULL, + "create_time" TIMESTAMP(0) NOT NULL, + "update_by" BIGINT, + "update_time" TIMESTAMP(0), + "proxy_by" BIGINT +) ; +COMMENT ON TABLE "xs_chat_msg" IS '聊天消息表'; +COMMENT ON COLUMN "xs_chat_msg"."chat_id" IS '聊天id'; +COMMENT ON COLUMN "xs_chat_msg"."sender_id" IS '发送用户id'; +COMMENT ON COLUMN "xs_chat_msg"."msg_type" IS '消息类型(chat_msg_type):text等'; +COMMENT ON COLUMN "xs_chat_msg"."content" IS '个人用户id'; +COMMENT ON COLUMN "xs_chat_msg"."msg_status" IS '消息状态:1未读,2已读'; +COMMENT ON COLUMN "xs_chat_msg"."create_by" IS '创建人'; +COMMENT ON COLUMN "xs_chat_msg"."create_time" IS '创建时间'; +COMMENT ON COLUMN "xs_chat_msg"."deleted" IS '是否逻辑删除'; +COMMENT ON COLUMN "xs_chat_msg"."proxy_by" IS '代理人'; +COMMENT ON COLUMN "xs_chat_msg"."update_by" IS '更新人'; +COMMENT ON COLUMN "xs_chat_msg"."update_time" IS '更新时间'; \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..4c95a07 --- /dev/null +++ b/pom.xml @@ -0,0 +1,408 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.4.2 + + + com.newyetai + alita-bjy-uygur + 0.0.1 + jar + + + 1.2.0.Final + + + + + + org.springframework.boot + spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-test + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-validation + + + + + org.springframework.boot + spring-boot-starter-aop + + + + org.projectlombok + lombok + + + + com.google.guava + guava + 18.0 + compile + + + + + commons-io + commons-io + 2.6 + + + org.apache.commons + commons-lang3 + + + commons-collections + commons-collections + 3.2.2 + + + org.apache.commons + commons-collections4 + 4.2 + + + + org.mapstruct + mapstruct-jdk8 + ${org.mapstruct.version} + provided + + + org.mapstruct + mapstruct-processor + ${org.mapstruct.version} + provided + + + + + org.springframework.data + spring-data-commons + + + + + org.freemarker + freemarker + + + + + io.springfox + springfox-swagger2 + 2.7.0 + + + io.springfox + springfox-swagger-ui + 2.7.0 + + + + com.fasterxml.jackson.core + jackson-core + + + + com.alibaba + easyexcel + 3.1.1 + + + + + org.bouncycastle + bcprov-jdk15on + 1.55 + + + + + com.github.ulisesbocchio + jasypt-spring-boot-starter + 3.0.2 + + + + + + com.dameng + Dm8JdbcDriver18 + 8.1.1.49 + + + + com.alibaba + druid-spring-boot-starter + 1.2.4 + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.0 + + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 2.1.3 + + + + + com.github.pagehelper + pagehelper-spring-boot-starter + 1.4.6 + + + + + org.springframework.boot + spring-boot-starter-amqp + + + + + redis.clients + jedis + + + org.springframework.boot + spring-boot-starter-data-redis + + + org.redisson + redisson-spring-boot-starter + 3.15.6 + + + io.netty + netty-all + + + + + cn.hutool + hutool-all + 5.8.16 + + + + + org.apache.pdfbox + pdfbox + 2.0.20 + + + org.apache.pdfbox + fontbox + 2.0.20 + + + + + e-iceblue + spire.pdf + 3.7.4 + + + com.itextpdf + itextpdf + 5.5.11 + + + com.itextpdf + itext-asian + 5.2.0 + + + + + org.springframework.boot + spring-boot-starter-security + + + + + org.springframework.boot + spring-boot-starter-oauth2-client + + + + io.jsonwebtoken + jjwt + 0.9.0 + + + + spring-boot-starter-websocket + org.springframework.boot + + + + + + com.aliyun + aliyun-java-sdk-core + 4.1.0 + + + + com.tencentcloudapi + tencentcloud-sdk-java + 3.1.100 + + + + com.aliyun + alibaba-dingtalk-service-sdk + 1.0.1 + + + + com.baidu.aip + java-sdk + 4.15.3 + + + org.slf4j + slf4j-simple + + + + + + + io.github.toolgood + toolgood-words + 3.1.0.0 + + + + com.spatial4j + spatial4j + 0.5 + + + + + com.squareup.okhttp3 + okhttp + 4.10.0 + + + + + com.squareup.okio + okio + 2.10.0 + + + + ws.schild + jave-core + 3.4.0 + + + + + ws.schild + jave-nativebin-linux64 + 3.4.0 + + + + + ws.schild + jave-nativebin-osx64 + 3.4.0 + + + + + ws.schild + jave-nativebin-win64 + 3.4.0 + + + + + + + + + ${project.artifactId} + + + src/main/resources + + + src/main/java + + + **/*.xml + + + + src/main/resources + true + + application.yml + bootstrap.yml + ${project.artifactId}-${profile.active}.yaml + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + com.spotify + docker-maven-plugin + 1.2.1 + + ${project.build.finalName}:${project.version} + ${project.build.outputDirectory} + + ${project.build.finalName}.jar + + + + ${project.build.directory} + ${project.build.finalName}.jar + + + + ${docker.host} + ${docker.certPath} + + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/AlitaBjyUygurApplication.java b/src/main/java/com/newyetai/AlitaBjyUygurApplication.java new file mode 100644 index 0000000..2decefe --- /dev/null +++ b/src/main/java/com/newyetai/AlitaBjyUygurApplication.java @@ -0,0 +1,22 @@ +package com.newyetai; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.EnableAspectJAutoProxy; +import org.springframework.scheduling.annotation.EnableScheduling; + + +/** + * @author sr on 2020-04-16 + */ +@SpringBootApplication(scanBasePackages = {"com.newyetai"}) +@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true) +@EnableScheduling +public class AlitaBjyUygurApplication { + + public static void main(String[] args) { + SpringApplication.run(AlitaBjyUygurApplication.class, args); + } + + +} diff --git a/src/main/java/com/newyetai/ai/interview/controller/InterviewRecordController.java b/src/main/java/com/newyetai/ai/interview/controller/InterviewRecordController.java new file mode 100644 index 0000000..4ec7e00 --- /dev/null +++ b/src/main/java/com/newyetai/ai/interview/controller/InterviewRecordController.java @@ -0,0 +1,67 @@ +package com.newyetai.ai.interview.controller; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import com.newyetai.common.AlitaResult; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.ai.interview.dto.*; +import com.newyetai.ai.interview.service.InterviewRecordService; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.beans.factory.annotation.Autowired; +import java.util.List; + +/** + * ai面试记录 + * + * @author guixinman + * @since 1.0.0 2024-12-11 + */ +@Api(tags = "ai面试记录") +@RestController +@RequestMapping("/ai/interviewRecord") +public class InterviewRecordController { + + @Autowired + private InterviewRecordService interviewRecordService; + + @PostMapping("/create") + @ApiOperation("ai面试记录-创建") + public AlitaResult create(@RequestBody @Validated(value = Create.class) InterviewRecordOperatorDTO operatorDTO) { + return AlitaResult.success(interviewRecordService.create(operatorDTO)); + } + + @PutMapping("/modify") + @ApiOperation("ai面试记录-修改") + public AlitaResult modify(@RequestBody @Validated(value = Update.class) InterviewRecordOperatorDTO operatorDTO) { + return AlitaResult.success(interviewRecordService.modify(operatorDTO)); + } + + @DeleteMapping("{id}") + @ApiOperation("ai面试记录-删除") + public AlitaResult delete(@PathVariable("id") Long id) { + return AlitaResult.success(interviewRecordService.delete(id)); + } + + @GetMapping("{id}") + @ApiOperation("ai面试记录-查询单个") + public AlitaResult findById(@PathVariable("id") Long id) { + return AlitaResult.success(interviewRecordService.findById(id)); + } + + @GetMapping("list") + @ApiOperation("ai面试记录-列表查询") + public AlitaResult> list(InterviewRecordQueryDTO queryDTO) { + return AlitaResult.success(interviewRecordService.list(queryDTO)); + } + + @GetMapping("page") + @ApiOperation("ai面试记录-分页查询") + public AlitaResult> page(InterviewRecordPageQueryDTO queryDTO) { + interviewRecordService.page(queryDTO); + return AlitaResult.success(queryDTO.getPageResult()); + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/ai/interview/convert/InterviewRecordConvert.java b/src/main/java/com/newyetai/ai/interview/convert/InterviewRecordConvert.java new file mode 100644 index 0000000..5676a5f --- /dev/null +++ b/src/main/java/com/newyetai/ai/interview/convert/InterviewRecordConvert.java @@ -0,0 +1,28 @@ +package com.newyetai.ai.interview.convert; + +import com.newyetai.ai.interview.entity.InterviewRecord; +import com.newyetai.ai.interview.dto.InterviewRecordDTO; +import com.newyetai.ai.interview.dto.InterviewRecordOperatorDTO; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * ai面试记录 + * + * @author guixinman + * @since 1.0.0 2024-12-11 + */ +@Mapper +public interface InterviewRecordConvert { + InterviewRecordConvert INSTANCE = Mappers.getMapper(InterviewRecordConvert.class); + + InterviewRecord convert(InterviewRecordDTO dto); + + InterviewRecordDTO convert(InterviewRecord entity); + + InterviewRecord convert(InterviewRecordOperatorDTO dto); + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/ai/interview/dao/InterviewRecordMapper.java b/src/main/java/com/newyetai/ai/interview/dao/InterviewRecordMapper.java new file mode 100644 index 0000000..a569b0d --- /dev/null +++ b/src/main/java/com/newyetai/ai/interview/dao/InterviewRecordMapper.java @@ -0,0 +1,26 @@ +package com.newyetai.ai.interview.dao; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.ai.interview.entity.InterviewRecord; +import com.newyetai.ai.interview.dto.InterviewRecordDTO; +import com.newyetai.ai.interview.dto.InterviewRecordQueryDTO; +import com.newyetai.ai.interview.dto.InterviewRecordPageQueryDTO; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * ai面试记录 + * + * @author guixinman + * @since 1.0.0 2024-12-11 + */ +@Mapper +public interface InterviewRecordMapper extends MyMapper { + + List page(@Param("param") InterviewRecordPageQueryDTO queryDTO); + + List list(@Param("param") InterviewRecordQueryDTO queryDTO); +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/ai/interview/dto/InterviewRecordDTO.java b/src/main/java/com/newyetai/ai/interview/dto/InterviewRecordDTO.java new file mode 100644 index 0000000..8120bb0 --- /dev/null +++ b/src/main/java/com/newyetai/ai/interview/dto/InterviewRecordDTO.java @@ -0,0 +1,45 @@ +package com.newyetai.ai.interview.dto; + +import com.newyetai.common.dto.BaseDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.SuperBuilder; + +import java.util.Date; + +/** + * ai面试记录 + * + * @author guixinman + * @since 1.0.0 2024-12-11 + */ +@ApiModel("ai面试记录") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class InterviewRecordDTO extends BaseDTO { + private static final long serialVersionUID = 1L; + + @ApiModelProperty("用户ID(xs_user)") + private Long userId; + + @ApiModelProperty("模拟岗位名称") + private String positionName; + + @ApiModelProperty("面试状态(1.待开始、2.待继续、3.已完成)") + private Integer state; + + @ApiModelProperty("报告出具状态(1.未出具 2.已出具)") + private Integer reportStatus; + + private String jsonData; + + @ApiModelProperty("节点") + private Integer node; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/ai/interview/dto/InterviewRecordOperatorDTO.java b/src/main/java/com/newyetai/ai/interview/dto/InterviewRecordOperatorDTO.java new file mode 100644 index 0000000..17fa561 --- /dev/null +++ b/src/main/java/com/newyetai/ai/interview/dto/InterviewRecordOperatorDTO.java @@ -0,0 +1,69 @@ +package com.newyetai.ai.interview.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; + +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +import java.util.Date; + +/** + * ai面试记录 + * + * @author guixinman + * @since 1.0.0 2024-12-11 + */ +@ApiModel("ai面试记录") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InterviewRecordOperatorDTO implements Serializable { + private static final long serialVersionUID = 1L; + + @NotNull(message = "id不能为空",groups = Update.class) + private Long id; + + @ApiModelProperty("用户ID(xs_user)") + private Long userId; + + + @Length(max = 32,message = "模拟岗位名称超长") + @NotBlank(message = "模拟岗位名称不能为空",groups = {Create.class}) + @ApiModelProperty("模拟岗位名称") + private String positionName; + + @ApiModelProperty("面试状态(1.待开始、2.待继续、3.已完成)") + private Integer state; + + @ApiModelProperty("报告出具状态(1.未出具 2.已出具)") + private Integer reportStatus; + + @NotNull(message = "数据不能为空",groups = {Update.class}) + private String jsonData; + + @NotNull(message = "节点不能为空",groups = {Update.class}) + @ApiModelProperty("节点") + private Integer node; + + //是否评分 + @Builder.Default + private Boolean gradeInterview = Boolean.FALSE; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/ai/interview/dto/InterviewRecordPageQueryDTO.java b/src/main/java/com/newyetai/ai/interview/dto/InterviewRecordPageQueryDTO.java new file mode 100644 index 0000000..a3b956b --- /dev/null +++ b/src/main/java/com/newyetai/ai/interview/dto/InterviewRecordPageQueryDTO.java @@ -0,0 +1,74 @@ +package com.newyetai.ai.interview.dto; + +import com.newyetai.common.dto.PageQueryDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import java.io.Serializable; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.format.annotation.DateTimeFormat; + + +import java.util.Date; + +/** + * ai面试记录 + * + * @author guixinman + * @since 1.0.0 2024-12-11 + */ + +@ApiModel("ai面试记录") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class InterviewRecordPageQueryDTO extends PageQueryDTO { + private static final long serialVersionUID = 1L; + + private Long id; + + @ApiModelProperty("用户ID(xs_user)") + private Long userId; + + @ApiModelProperty("模拟岗位名称 (模糊匹配)") + private String positionNameLike; + + @ApiModelProperty("面试状态(1.待开始、2.待继续、3.已完成)") + private Integer state; + + @ApiModelProperty("报告出具状态(1.未出具 2.已出具)") + private Integer reportStatus; + + private String jsonData; + + @ApiModelProperty("节点") + private Integer node; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("修改时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeStart; + + @ApiModelProperty("修改时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeEnd; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/ai/interview/dto/InterviewRecordQueryDTO.java b/src/main/java/com/newyetai/ai/interview/dto/InterviewRecordQueryDTO.java new file mode 100644 index 0000000..90f003c --- /dev/null +++ b/src/main/java/com/newyetai/ai/interview/dto/InterviewRecordQueryDTO.java @@ -0,0 +1,74 @@ +package com.newyetai.ai.interview.dto; + +import com.newyetai.common.dto.BaseDTO; + +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; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +/** + * ai面试记录 + * + * @author guixinman + * @since 1.0.0 2024-12-11 + */ +@ApiModel("ai面试记录") +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class InterviewRecordQueryDTO implements Serializable { + private static final long serialVersionUID = 1L; + + private Long id; + + @ApiModelProperty("用户ID(xs_user)") + private Long userId; + + @ApiModelProperty("模拟岗位名称 (模糊匹配)") + private String positionNameLike; + + @ApiModelProperty("面试状态(1.待开始、2.待继续、3.已完成)") + private Integer state; + + @ApiModelProperty("报告出具状态(1.未出具 2.已出具)") + private Integer reportStatus; + + private String jsonData; + + @ApiModelProperty("节点") + private Integer node; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("修改时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeStart; + + @ApiModelProperty("修改时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeEnd; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/ai/interview/entity/InterviewRecord.java b/src/main/java/com/newyetai/ai/interview/entity/InterviewRecord.java new file mode 100644 index 0000000..776128a --- /dev/null +++ b/src/main/java/com/newyetai/ai/interview/entity/InterviewRecord.java @@ -0,0 +1,53 @@ +package com.newyetai.ai.interview.entity; + + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * ai面试记录 + * + * @author guixinman + * @since 1.0.0 2024-12-11 + */ +@TableName(value = "ai_interview_record") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class InterviewRecord extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * 用户ID(xs_user) + */ + private Long userId; + /** + * 模拟岗位名称 + */ + private String positionName; + /** + * 面试状态(1.待开始、2.待继续、3.已完成) + */ + private Integer state; + /** + * 报告出具状态(1.未出具 2.已出具) + */ + private Integer reportStatus; + /** + * + */ + private String jsonData; + /** + * 节点 + */ + private Integer node; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/ai/interview/enums/InterviewRecordEnum.java b/src/main/java/com/newyetai/ai/interview/enums/InterviewRecordEnum.java new file mode 100644 index 0000000..5b72d3f --- /dev/null +++ b/src/main/java/com/newyetai/ai/interview/enums/InterviewRecordEnum.java @@ -0,0 +1,33 @@ +package com.newyetai.ai.interview.enums; +/** + * @description: 面试状态 + * @return: + * @author: guixinman + * @param: + */ +public enum InterviewRecordEnum { + INIT(1,"待开始"), + TO_BE_CONTINUED(2,"待继续"), + SUCCESS(3,"已完成"), + ; + + private Integer status; + /** + * 类型描述 + */ + private String desc; + + + InterviewRecordEnum(Integer status, String desc) { + this.status = status; + this.desc = desc; + } + + public Integer getStatus() { + return status; + } + + public String getDesc() { + return desc; + } +} diff --git a/src/main/java/com/newyetai/ai/interview/enums/InterviewRecordReportStatusEnum.java b/src/main/java/com/newyetai/ai/interview/enums/InterviewRecordReportStatusEnum.java new file mode 100644 index 0000000..fbbb346 --- /dev/null +++ b/src/main/java/com/newyetai/ai/interview/enums/InterviewRecordReportStatusEnum.java @@ -0,0 +1,33 @@ +package com.newyetai.ai.interview.enums; + +/** + * @description: 报告出具状态 + * @return: + * @author: guixinman + * @param: + */ +public enum InterviewRecordReportStatusEnum { + INIT(1,"未出具"), + SUCCESS(2,"已出具"), + ; + + private Integer status; + /** + * 类型描述 + */ + private String desc; + + + InterviewRecordReportStatusEnum(Integer status, String desc) { + this.status = status; + this.desc = desc; + } + + public Integer getStatus() { + return status; + } + + public String getDesc() { + return desc; + } +} diff --git a/src/main/java/com/newyetai/ai/interview/mapper/InterviewRecordMapper.xml b/src/main/java/com/newyetai/ai/interview/mapper/InterviewRecordMapper.xml new file mode 100644 index 0000000..0c4bde7 --- /dev/null +++ b/src/main/java/com/newyetai/ai/interview/mapper/InterviewRecordMapper.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + FROM + ai_interview_record t + WHERE t.deleted = 0 + + AND t.id = #{param.id} + + + AND t.user_id = #{param.userId} + + + + AND t.position_name like #{positionNameLike} + + + AND t.state = #{param.state} + + + AND t.report_status = #{param.reportStatus} + + + AND t.json_data = #{param.jsonData} + + + AND t.node = #{param.node} + + + AND t.create_time >= #{param.createTimeStart} + + + AND t.create_time <= #{param.createTimeEnd} + + + AND t.update_time >= #{param.updateTimeStart} + + + AND t.update_time <= #{param.updateTimeEnd} + + ORDER BY t.id DESC + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/ai/interview/service/InterviewRecordService.java b/src/main/java/com/newyetai/ai/interview/service/InterviewRecordService.java new file mode 100644 index 0000000..e7f52a8 --- /dev/null +++ b/src/main/java/com/newyetai/ai/interview/service/InterviewRecordService.java @@ -0,0 +1,68 @@ +package com.newyetai.ai.interview.service; + +import org.springframework.validation.annotation.Validated; + +import javax.validation.Valid; +import javax.validation.groups.Default; + +import java.util.List; + +import com.newyetai.ai.interview.dto.*; + +/** + * ai面试记录 + * + * @author guixinman + * @since 1.0.0 2024-12-11 + */ +@Validated(Default.class) +public interface InterviewRecordService { + + /** + * ai面试记录 - 创建 + * + * @param operatorDto 操作dto + * @return {@link InterviewRecordDTO} + */ + InterviewRecordDTO create(@Valid InterviewRecordOperatorDTO operatorDto); + + /** + * ai面试记录 - 修改 + * + * @param operatorDto 操作dto + * @return {@link InterviewRecordDTO} + */ + InterviewRecordDTO modify(@Valid InterviewRecordOperatorDTO operatorDto); + + /** + * ai面试记录 - 删除 + * + * @param id id + * @return {@link InterviewRecordDTO} + */ + InterviewRecordDTO delete(Long id); + + /** + * ai面试记录 - 根据ID查询单个 + * + * @param id id + * @return {@link InterviewRecordDTO} + */ + InterviewRecordDTO findById(Long id); + + /** + * ai面试记录 - 列表查询 + * + * @param queryDTO 列表查询dto + * @return {@link List}<{@link InterviewRecordDTO}> + */ + List list(InterviewRecordQueryDTO queryDTO); + + /** + * ai面试记录 - 分页查询 + * + * @param queryDTO 分页查询dto + * @return {@link InterviewRecordDTO} + */ + List page(InterviewRecordPageQueryDTO queryDTO); +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/ai/interview/service/impl/InterviewRecordServiceImpl.java b/src/main/java/com/newyetai/ai/interview/service/impl/InterviewRecordServiceImpl.java new file mode 100644 index 0000000..be5f54f --- /dev/null +++ b/src/main/java/com/newyetai/ai/interview/service/impl/InterviewRecordServiceImpl.java @@ -0,0 +1,108 @@ +package com.newyetai.ai.interview.service.impl; + +import cn.hutool.json.JSONUtil; +import lombok.extern.slf4j.Slf4j; + +import com.newyetai.ai.interview.convert.InterviewRecordConvert; +import com.newyetai.ai.interview.entity.InterviewRecord; +import com.newyetai.ai.interview.dto.*; +import com.newyetai.ai.interview.dao.InterviewRecordMapper; +import com.newyetai.ai.interview.enums.InterviewRecordEnum; +import com.newyetai.ai.interview.enums.InterviewRecordReportStatusEnum; +import com.newyetai.ai.interview.service.InterviewRecordService; + +import org.springframework.stereotype.Service; + +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.sdk.xf.dto.InterviewContentDTO; +import com.newyetai.sdk.xf.util.XfUtils; + +import javax.annotation.Resource; + +import java.util.*; + +/** + * ai面试记录 + * + * @author guixinman + * @since 1.0.0 2024-12-11 + */ +@Slf4j +@Service +public class InterviewRecordServiceImpl implements InterviewRecordService { + + @Resource + private InterviewRecordMapper interviewRecordMapper; + + @Override + public InterviewRecordDTO create(InterviewRecordOperatorDTO operatorDto) { + InterviewRecord interviewRecord = InterviewRecordConvert.INSTANCE.convert(operatorDto); + interviewRecord.setUserId(UserContextHolder.getExistLoginUserId()); + interviewRecord.setNode(1); + interviewRecord.setState(InterviewRecordEnum.INIT.getStatus()); + interviewRecord.setReportStatus(InterviewRecordReportStatusEnum.INIT.getStatus()); + + String data = XfUtils.generateInterviewQuestion(InterviewContentDTO.builder().positionName(operatorDto.getPositionName()).build()); + interviewRecord.setJsonData(data); + interviewRecordMapper.saveEntity(interviewRecord); + return InterviewRecordConvert.INSTANCE.convert(interviewRecord); + } + + @Override + public InterviewRecordDTO modify(InterviewRecordOperatorDTO operatorDto) { + InterviewRecordDTO interviewRecordDto = this.findById(operatorDto.getId()); + if (Objects.isNull(interviewRecordDto)) { + return null; + } + InterviewRecord interviewRecord = InterviewRecordConvert.INSTANCE.convert(operatorDto); + + String jsonData = interviewRecord.getJsonData(); + InterviewContentDTO interviewContentDTO = JsonUtils.toObject(jsonData, InterviewContentDTO.class); + + if (Boolean.TRUE.equals(operatorDto.getGradeInterview())) { + String jsonDataNew = XfUtils.gradeInterview(interviewContentDTO); + interviewRecord.setReportStatus(InterviewRecordReportStatusEnum.SUCCESS.getStatus()); + interviewRecord.setJsonData(jsonDataNew); + interviewRecord.setState(InterviewRecordEnum.SUCCESS.getStatus()); + }else { + interviewRecord.setState(InterviewRecordEnum.TO_BE_CONTINUED.getStatus()); + } + interviewRecordMapper.updateEntitySelective(interviewRecord); + + return this.findById(operatorDto.getId()); + } + + @Override + public InterviewRecordDTO delete(Long id) { + InterviewRecordDTO interviewRecordDto = this.findById(id); + if (Objects.isNull(interviewRecordDto)) { + return null; + } + InterviewRecord interviewRecord = InterviewRecord.builder().build(); + interviewRecord.setId(id); + interviewRecordMapper.deleteEntity(interviewRecord, UserContextHolder.getLoginUserId()); + return interviewRecordDto; + } + + @Override + public InterviewRecordDTO findById(Long id) { + InterviewRecord interviewRecord = interviewRecordMapper.getById(id); + if (Objects.isNull(interviewRecord)) { + return null; + } + return InterviewRecordConvert.INSTANCE.convert(interviewRecord); + } + + @Override + public List list(InterviewRecordQueryDTO queryDTO) { + return interviewRecordMapper.list(queryDTO); + } + + @Override + public List page(InterviewRecordPageQueryDTO queryDTO) { + queryDTO.setUserId(UserContextHolder.getExistLoginUserId()); + return interviewRecordMapper.page(queryDTO); + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/ai/mbti/controller/MbtiRecordController.java b/src/main/java/com/newyetai/ai/mbti/controller/MbtiRecordController.java new file mode 100644 index 0000000..7def508 --- /dev/null +++ b/src/main/java/com/newyetai/ai/mbti/controller/MbtiRecordController.java @@ -0,0 +1,76 @@ +package com.newyetai.ai.mbti.controller; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.ai.mbti.dto.*; +import com.newyetai.ai.mbti.service.MbtiRecordService; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; + +/** + * AI测评记录 + * + * @author guixinman + * @since 1.0.0 2024-12-20 + */ +@Api(tags = "AI测评记录") +@RestController +@RequestMapping("/ai/mbtiRecord") +public class MbtiRecordController { + + @Autowired + private MbtiRecordService mbtiRecordService; + + @PostMapping("/create") + @ApiOperation("AI测评记录-创建") + public AlitaResult create(@RequestBody @Validated(value = Create.class) MbtiRecordOperatorDTO operatorDTO) { + return AlitaResult.success(mbtiRecordService.create(operatorDTO)); + } + + @PutMapping("/modify") + @ApiOperation("AI测评记录-修改") + public AlitaResult modify(@RequestBody @Validated(value = Update.class) MbtiRecordOperatorDTO operatorDTO) { + return AlitaResult.success(mbtiRecordService.modify(operatorDTO)); + } + + @ApiOperation("AI测评记录-出具报告") + @PostMapping("/report") + public AlitaResult report(@RequestParam("id") Long id){ + mbtiRecordService.report(id); + return AlitaResult.success(); + } + + @DeleteMapping("{id}") + @ApiOperation("AI测评记录-删除") + public AlitaResult delete(@PathVariable("id") Long id) { + return AlitaResult.success(mbtiRecordService.delete(id)); + } + + @GetMapping("{id}") + @ApiOperation("AI测评记录-查询单个") + public AlitaResult findById(@PathVariable("id") Long id) { + return AlitaResult.success(mbtiRecordService.findById(id)); + } + + @GetMapping("list") + @ApiOperation("AI测评记录-列表查询") + public AlitaResult> list(MbtiRecordQueryDTO queryDTO) { + return AlitaResult.success(mbtiRecordService.list(queryDTO)); + } + + @GetMapping("page") + @ApiOperation("AI测评记录-分页查询") + public AlitaResult> page(MbtiRecordPageQueryDTO queryDTO) { + mbtiRecordService.page(queryDTO); + return AlitaResult.success(queryDTO.getPageResult()); + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/ai/mbti/convert/MbtiRecordConvert.java b/src/main/java/com/newyetai/ai/mbti/convert/MbtiRecordConvert.java new file mode 100644 index 0000000..79c3897 --- /dev/null +++ b/src/main/java/com/newyetai/ai/mbti/convert/MbtiRecordConvert.java @@ -0,0 +1,28 @@ +package com.newyetai.ai.mbti.convert; + +import com.newyetai.ai.mbti.entity.MbtiRecord; +import com.newyetai.ai.mbti.dto.MbtiRecordDTO; +import com.newyetai.ai.mbti.dto.MbtiRecordOperatorDTO; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * AI测评记录 + * + * @author guixinman + * @since 1.0.0 2024-12-20 + */ +@Mapper +public interface MbtiRecordConvert { + MbtiRecordConvert INSTANCE = Mappers.getMapper(MbtiRecordConvert.class); + + MbtiRecord convert(MbtiRecordDTO dto); + + MbtiRecordDTO convert(MbtiRecord entity); + + MbtiRecord convert(MbtiRecordOperatorDTO dto); + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/ai/mbti/dao/MbtiRecordMapper.java b/src/main/java/com/newyetai/ai/mbti/dao/MbtiRecordMapper.java new file mode 100644 index 0000000..70e6e15 --- /dev/null +++ b/src/main/java/com/newyetai/ai/mbti/dao/MbtiRecordMapper.java @@ -0,0 +1,26 @@ +package com.newyetai.ai.mbti.dao; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.ai.mbti.entity.MbtiRecord; +import com.newyetai.ai.mbti.dto.MbtiRecordDTO; +import com.newyetai.ai.mbti.dto.MbtiRecordQueryDTO; +import com.newyetai.ai.mbti.dto.MbtiRecordPageQueryDTO; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * AI测评记录 + * + * @author guixinman + * @since 1.0.0 2024-12-20 + */ +@Mapper +public interface MbtiRecordMapper extends MyMapper { + + List page(@Param("param") MbtiRecordPageQueryDTO queryDTO); + + List list(@Param("param") MbtiRecordQueryDTO queryDTO); +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/ai/mbti/dto/MbtiRecordDTO.java b/src/main/java/com/newyetai/ai/mbti/dto/MbtiRecordDTO.java new file mode 100644 index 0000000..d4c380d --- /dev/null +++ b/src/main/java/com/newyetai/ai/mbti/dto/MbtiRecordDTO.java @@ -0,0 +1,51 @@ +package com.newyetai.ai.mbti.dto; + +import com.newyetai.common.dto.BaseDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.SuperBuilder; + +import java.util.Date; + +/** + * AI测评记录 + * + * @author guixinman + * @since 1.0.0 2024-12-20 + */ +@ApiModel("AI测评记录") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class MbtiRecordDTO extends BaseDTO { + private static final long serialVersionUID = 1L; + + private Long userId; + + private String liangBiaoId; + + @ApiModelProperty("节点") + private Integer node; + + private String jsonData; + + private String orderId; + + @ApiModelProperty("状态(1.待开始、2.待继续、3.已完成)") + private Integer state; + + @ApiModelProperty("报告出具状态(1.未出具 2.已出具)") + private Integer reportStatus; + + private String content; + + private String reportId; + + private String name; + + private String phone; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/ai/mbti/dto/MbtiRecordOperatorDTO.java b/src/main/java/com/newyetai/ai/mbti/dto/MbtiRecordOperatorDTO.java new file mode 100644 index 0000000..2b92554 --- /dev/null +++ b/src/main/java/com/newyetai/ai/mbti/dto/MbtiRecordOperatorDTO.java @@ -0,0 +1,76 @@ +package com.newyetai.ai.mbti.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; + +import org.springframework.format.annotation.DateTimeFormat; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +import java.util.Date; +import java.util.Map; + +/** + * AI测评记录 + * + * @author guixinman + * @since 1.0.0 2024-12-20 + */ +@ApiModel("AI测评记录") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MbtiRecordOperatorDTO implements Serializable { + private static final long serialVersionUID = 1L; + + @NotNull(message = "id不能为空",groups = Update.class) + private Long id; + + private Long userId; + + @NotBlank(message = "liangBiaoId不能为空",groups = {Create.class, Update.class}) + private String liangBiaoId; + + @NotNull(message = "节点不能为空",groups = {Update.class}) + @ApiModelProperty("节点") + private Integer node; + + @NotNull(message = "数据不能为空",groups = {Update.class}) + private Map answers; + + private String orderId; + + @ApiModelProperty("状态(2.待继续、3.已完成)") + private Integer state; + + @ApiModelProperty("报告出具状态(1.未出具 2.已出具)") + private Integer reportStatus; + + + @Builder.Default + private Boolean submit = Boolean.FALSE; + + private String content; + + private String reportId; + + @NotBlank(message = "name不能为空",groups = {Create.class, Update.class}) + private String name; + + @NotBlank(message = "phone不能为空",groups = {Create.class, Update.class}) + private String phone; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/ai/mbti/dto/MbtiRecordPageQueryDTO.java b/src/main/java/com/newyetai/ai/mbti/dto/MbtiRecordPageQueryDTO.java new file mode 100644 index 0000000..fd76fd5 --- /dev/null +++ b/src/main/java/com/newyetai/ai/mbti/dto/MbtiRecordPageQueryDTO.java @@ -0,0 +1,74 @@ +package com.newyetai.ai.mbti.dto; + +import com.newyetai.common.dto.PageQueryDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import java.io.Serializable; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.format.annotation.DateTimeFormat; + + +import java.util.Date; + +/** + * AI测评记录 + * + * @author guixinman + * @since 1.0.0 2024-12-20 + */ + +@ApiModel("AI测评记录") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class MbtiRecordPageQueryDTO extends PageQueryDTO { + private static final long serialVersionUID = 1L; + + private Long id; + + private Long userId; + + private String liangBiaoId; + + @ApiModelProperty("节点") + private Integer node; + + private String jsonData; + + private String orderId; + + @ApiModelProperty("状态(1.待开始、2.待继续、3.已完成)") + private Integer state; + + @ApiModelProperty("报告出具状态(1.未出具 2.已出具)") + private Integer reportStatus; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("更新时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeStart; + + @ApiModelProperty("更新时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeEnd; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/ai/mbti/dto/MbtiRecordQueryDTO.java b/src/main/java/com/newyetai/ai/mbti/dto/MbtiRecordQueryDTO.java new file mode 100644 index 0000000..388c72c --- /dev/null +++ b/src/main/java/com/newyetai/ai/mbti/dto/MbtiRecordQueryDTO.java @@ -0,0 +1,74 @@ +package com.newyetai.ai.mbti.dto; + +import com.newyetai.common.dto.BaseDTO; + +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; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +/** + * AI测评记录 + * + * @author guixinman + * @since 1.0.0 2024-12-20 + */ +@ApiModel("AI测评记录") +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class MbtiRecordQueryDTO implements Serializable { + private static final long serialVersionUID = 1L; + + private Long id; + + private Long userId; + + private String liangBiaoId; + + @ApiModelProperty("节点") + private Integer node; + + private String jsonData; + + private String orderId; + + @ApiModelProperty("状态(1.待开始、2.待继续、3.已完成)") + private Integer state; + + @ApiModelProperty("报告出具状态(1.未出具 2.已出具)") + private Integer reportStatus; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("更新时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeStart; + + @ApiModelProperty("更新时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeEnd; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/ai/mbti/entity/MbtiRecord.java b/src/main/java/com/newyetai/ai/mbti/entity/MbtiRecord.java new file mode 100644 index 0000000..ea11df0 --- /dev/null +++ b/src/main/java/com/newyetai/ai/mbti/entity/MbtiRecord.java @@ -0,0 +1,63 @@ +package com.newyetai.ai.mbti.entity; + + +import lombok.*; +import lombok.experimental.SuperBuilder; + +import com.baomidou.mybatisplus.annotation.*; +import com.newyetai.common.entity.BaseEntity; + +/** + * AI测评记录 + * + * @author guixinman + * @since 1.0.0 2024-12-20 + */ +@TableName(value = "ai_mbti_record") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class MbtiRecord extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * + */ + private Long userId; + /** + * + */ + private String liangBiaoId; + /** + * 节点 + */ + private Integer node; + /** + * + */ + private String jsonData; + /** + * + */ + private String orderId; + + /** + * 状态(1.待开始、2.待继续、3.已完成) + */ + private Integer state; + /** + * 报告出具状态(1.未出具 2.已出具) + */ + private Integer reportStatus; + + private String content; + + private String reportId; + + private String name; + + private String phone; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/ai/mbti/enums/MbtiRecordEnum.java b/src/main/java/com/newyetai/ai/mbti/enums/MbtiRecordEnum.java new file mode 100644 index 0000000..bf35f41 --- /dev/null +++ b/src/main/java/com/newyetai/ai/mbti/enums/MbtiRecordEnum.java @@ -0,0 +1,32 @@ +package com.newyetai.ai.mbti.enums; +/** + * @description: 状态 + * @return: + * @author: guixinman + * @param: + */ +public enum MbtiRecordEnum { + TO_BE_CONTINUED(2,"待继续"), + SUCCESS(3,"已完成"), + ; + + private Integer status; + /** + * 类型描述 + */ + private String desc; + + + MbtiRecordEnum(Integer status, String desc) { + this.status = status; + this.desc = desc; + } + + public Integer getStatus() { + return status; + } + + public String getDesc() { + return desc; + } +} diff --git a/src/main/java/com/newyetai/ai/mbti/enums/MbtiRecordReportStatusEnum.java b/src/main/java/com/newyetai/ai/mbti/enums/MbtiRecordReportStatusEnum.java new file mode 100644 index 0000000..1d7a4d3 --- /dev/null +++ b/src/main/java/com/newyetai/ai/mbti/enums/MbtiRecordReportStatusEnum.java @@ -0,0 +1,33 @@ +package com.newyetai.ai.mbti.enums; + +/** + * @description: 报告出具状态 + * @return: + * @author: guixinman + * @param: + */ +public enum MbtiRecordReportStatusEnum { + INIT(1,"未出具"), + SUCCESS(2,"已出具"), + ; + + private Integer status; + /** + * 类型描述 + */ + private String desc; + + + MbtiRecordReportStatusEnum(Integer status, String desc) { + this.status = status; + this.desc = desc; + } + + public Integer getStatus() { + return status; + } + + public String getDesc() { + return desc; + } +} diff --git a/src/main/java/com/newyetai/ai/mbti/mapper/MbtiRecordMapper.xml b/src/main/java/com/newyetai/ai/mbti/mapper/MbtiRecordMapper.xml new file mode 100644 index 0000000..001cb85 --- /dev/null +++ b/src/main/java/com/newyetai/ai/mbti/mapper/MbtiRecordMapper.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + FROM + ai_mbti_record t + WHERE t.deleted = 0 + + AND t.id = #{param.id} + + + AND t.user_id = #{param.userId} + + + AND t.liang_biao_id = #{param.liangBiaoId} + + + AND t.node = #{param.node} + + + AND t.json_data = #{param.jsonData} + + + AND t.order_id = #{param.orderId} + + + AND t.state = #{param.state} + + + AND t.report_status = #{param.reportStatus} + + + AND t.create_time >= #{param.createTimeStart} + + + AND t.create_time <= #{param.createTimeEnd} + + + AND t.update_time >= #{param.updateTimeStart} + + + AND t.update_time <= #{param.updateTimeEnd} + + ORDER BY t.id DESC + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/ai/mbti/service/MbtiRecordService.java b/src/main/java/com/newyetai/ai/mbti/service/MbtiRecordService.java new file mode 100644 index 0000000..5088202 --- /dev/null +++ b/src/main/java/com/newyetai/ai/mbti/service/MbtiRecordService.java @@ -0,0 +1,76 @@ +package com.newyetai.ai.mbti.service; + +import org.springframework.validation.annotation.Validated; + +import javax.validation.Valid; +import javax.validation.groups.Default; + +import java.util.List; + +import com.newyetai.ai.mbti.dto.*; + +/** + * AI测评记录 + * + * @author guixinman + * @since 1.0.0 2024-12-20 + */ +@Validated(Default.class) +public interface MbtiRecordService { + + /** + * AI测评记录 - 创建 + * + * @param operatorDto 操作dto + * @return {@link MbtiRecordDTO} + */ + MbtiRecordDTO create(@Valid MbtiRecordOperatorDTO operatorDto); + + /** + * AI测评记录 - 修改 + * + * @param operatorDto 操作dto + * @return {@link MbtiRecordDTO} + */ + MbtiRecordDTO modify(@Valid MbtiRecordOperatorDTO operatorDto); + + /** + * @description: 出具报告 + * @return: + * @author: guixinman + * @param: + */ + void report(Long id); + + /** + * AI测评记录 - 删除 + * + * @param id id + * @return {@link MbtiRecordDTO} + */ + MbtiRecordDTO delete(Long id); + + /** + * AI测评记录 - 根据ID查询单个 + * + * @param id id + * @return {@link MbtiRecordDTO} + */ + MbtiRecordDTO findById(Long id); + + /** + * AI测评记录 - 列表查询 + * + * @param queryDTO 列表查询dto + * @return {@link List}<{@link MbtiRecordDTO}> + */ + List list(MbtiRecordQueryDTO queryDTO); + + /** + * AI测评记录 - 分页查询 + * + * @param queryDTO 分页查询dto + * @return {@link MbtiRecordDTO} + */ + List page(MbtiRecordPageQueryDTO queryDTO); +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/ai/mbti/service/impl/MbtiRecordServiceImpl.java b/src/main/java/com/newyetai/ai/mbti/service/impl/MbtiRecordServiceImpl.java new file mode 100644 index 0000000..cf6f2d2 --- /dev/null +++ b/src/main/java/com/newyetai/ai/mbti/service/impl/MbtiRecordServiceImpl.java @@ -0,0 +1,166 @@ +package com.newyetai.ai.mbti.service.impl; + +import lombok.extern.slf4j.Slf4j; + +import com.newyetai.ai.interview.enums.InterviewRecordEnum; +import com.newyetai.ai.interview.enums.InterviewRecordReportStatusEnum; +import com.newyetai.ai.mbti.convert.MbtiRecordConvert; +import com.newyetai.ai.mbti.entity.MbtiRecord; +import com.newyetai.ai.mbti.dto.*; +import com.newyetai.ai.mbti.dao.MbtiRecordMapper; +import com.newyetai.ai.mbti.enums.MbtiRecordEnum; +import com.newyetai.ai.mbti.enums.MbtiRecordReportStatusEnum; +import com.newyetai.ai.mbti.service.MbtiRecordService; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.sensitive.SensitiveInfoUtils; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.common.util.RandomUtils; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.sdk.mbti.mobel.AnswerReq; +import com.newyetai.sdk.mbti.mobel.AnswerReqDTO; +import com.newyetai.sdk.mbti.mobel.AnswerRes; +import com.newyetai.sdk.mbti.mobel.OrderQueryReq; +import com.newyetai.sdk.mbti.mobel.OrderQueryRes; +import com.newyetai.sdk.mbti.mobel.ReportReq; +import com.newyetai.sdk.mbti.mobel.ReportRes; +import com.newyetai.sdk.mbti.service.MbtiProvider; + +import javax.annotation.Resource; + +import java.util.*; + +/** + * AI测评记录 + * + * @author guixinman + * @since 1.0.0 2024-12-20 + */ +@Slf4j +@Service +public class MbtiRecordServiceImpl implements MbtiRecordService { + + @Resource + private MbtiRecordMapper mbtiRecordMapper; + + @Autowired + private MbtiProvider mbtiProvider; + + @Override + public MbtiRecordDTO create(MbtiRecordOperatorDTO operatorDto) { + MbtiRecord mbtiRecord = MbtiRecordConvert.INSTANCE.convert(operatorDto); + mbtiRecord.setUserId(UserContextHolder.getExistLoginUserId()); + mbtiRecord.setState(MbtiRecordEnum.TO_BE_CONTINUED.getStatus()); + mbtiRecord.setReportStatus(MbtiRecordReportStatusEnum.INIT.getStatus()); + mbtiRecord.setJsonData(JsonUtils.toJsonString(operatorDto.getAnswers())); + mbtiRecord.setName(operatorDto.getName()); + mbtiRecord.setPhone(operatorDto.getPhone()); + + if (operatorDto.getSubmit()) { + if (Objects.isNull(operatorDto.getAnswers())) { + throw new BusinessException("answers不能为空"); + } + AnswerReq answerReq = new AnswerReq(); + AnswerReqDTO answerData = AnswerReqDTO.builder() + .Answers(operatorDto.getAnswers()) + .test_name(SensitiveInfoUtils.mobilePhone2(operatorDto.getPhone()) + RandomUtils.getRandomString(5)) + .test_email(RandomUtils.getRandomString(5)) + .build(); + answerReq.setLiangbiaoId(operatorDto.getLiangBiaoId()); + answerReq.setAnswerData(answerData); + AlitaResult answerResAlitaResult = mbtiProvider.http(answerReq); + Assert.isTrue(answerResAlitaResult.getSuccess(),answerResAlitaResult.getMsg()); + AnswerRes answerRes = answerResAlitaResult.getData(); + mbtiRecord.setOrderId(answerRes.getOrderId()); + mbtiRecord.setState(MbtiRecordEnum.SUCCESS.getStatus()); + } + mbtiRecordMapper.saveEntity(mbtiRecord); + return MbtiRecordConvert.INSTANCE.convert(mbtiRecord); + } + + @Override + public MbtiRecordDTO modify(MbtiRecordOperatorDTO operatorDto) { + MbtiRecordDTO mbtiRecordDto = this.findById(operatorDto.getId()); + if (Objects.isNull(mbtiRecordDto)) { + return null; + } + MbtiRecord mbtiRecord = MbtiRecordConvert.INSTANCE.convert(operatorDto); + mbtiRecord.setJsonData(JsonUtils.toJsonString(operatorDto.getAnswers())); + mbtiRecord.setName(operatorDto.getName()); + mbtiRecord.setPhone(operatorDto.getPhone()); + if (operatorDto.getSubmit()) { + AnswerReq answerReq = new AnswerReq(); + answerReq.setLiangbiaoId(operatorDto.getLiangBiaoId()); + answerReq.setAnswerData(AnswerReqDTO.builder() + .Answers(operatorDto.getAnswers()) + .test_name(SensitiveInfoUtils.mobilePhone2(operatorDto.getPhone()) + RandomUtils.getRandomString(5)) + .test_email(RandomUtils.getRandomString(5)) + .build()); + AlitaResult answerResAlitaResult = mbtiProvider.http(answerReq); + Assert.isTrue(answerResAlitaResult.getSuccess(),answerResAlitaResult.getMsg()); + AnswerRes answerRes = answerResAlitaResult.getData(); + mbtiRecord.setOrderId(answerRes.getOrderId()); + mbtiRecord.setState(MbtiRecordEnum.SUCCESS.getStatus()); + } + mbtiRecordMapper.updateEntitySelective(mbtiRecord); + return this.findById(operatorDto.getId()); + } + + @Override + public void report(Long id) { + MbtiRecordDTO mbtiRecordDto = this.findById(id); + if (Objects.isNull(mbtiRecordDto)) { + return; + } + AlitaResult queryRes = mbtiProvider.http(OrderQueryReq.builder().liangbiaoId(mbtiRecordDto.getLiangBiaoId()).orderId(mbtiRecordDto.getOrderId()).build()); + Assert.isTrue(queryRes.getSuccess(),queryRes.getMsg()); + + AlitaResult reportRes = mbtiProvider.http(ReportReq.builder().liangbiaoId(mbtiRecordDto.getLiangBiaoId()).reportId(queryRes.getData().getReportId()).build()); + Assert.isTrue(reportRes.getSuccess(),reportRes.getMsg()); + + MbtiRecord mbtiRecord = MbtiRecordConvert.INSTANCE.convert(mbtiRecordDto); + mbtiRecord.setReportId(queryRes.getData().getReportId()); + mbtiRecord.setReportStatus(MbtiRecordReportStatusEnum.SUCCESS.getStatus()); + mbtiRecord.setContent(reportRes.getData().getContent()); + mbtiRecordMapper.updateEntitySelective(mbtiRecord); + } + + @Override + public MbtiRecordDTO delete(Long id) { + MbtiRecordDTO mbtiRecordDto = this.findById(id); + if (Objects.isNull(mbtiRecordDto)) { + return null; + } + MbtiRecord mbtiRecord = MbtiRecord.builder().build(); + mbtiRecord.setId(id); + mbtiRecordMapper.deleteEntity(mbtiRecord, UserContextHolder.getLoginUserId()); + return mbtiRecordDto; + } + + @Override + public MbtiRecordDTO findById(Long id) { + MbtiRecord mbtiRecord = mbtiRecordMapper.getById(id); + if (Objects.isNull(mbtiRecord)) { + return null; + } + return MbtiRecordConvert.INSTANCE.convert(mbtiRecord); + } + + @Override + public List list(MbtiRecordQueryDTO queryDTO) { + return mbtiRecordMapper.list(queryDTO); + } + + @Override + public List page(MbtiRecordPageQueryDTO queryDTO) { + queryDTO.setUserId(UserContextHolder.getExistLoginUserId()); + return mbtiRecordMapper.page(queryDTO); + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/ai/resume/controller/AiResumeController.java b/src/main/java/com/newyetai/ai/resume/controller/AiResumeController.java new file mode 100644 index 0000000..2d0eb61 --- /dev/null +++ b/src/main/java/com/newyetai/ai/resume/controller/AiResumeController.java @@ -0,0 +1,73 @@ +package com.newyetai.ai.resume.controller; + +import com.newyetai.ai.resume.dto.AiResumeReqDTO; +import com.newyetai.ai.resume.service.AiResumeService; +import com.newyetai.common.AlitaResult; +import com.newyetai.sdk.xf.util.XfUtils; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Map; + +import cn.hutool.json.JSONUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +/** + * @description: + * @author: guixinman + * @create: 2024-12-12 10:03 + **/ +@Api(tags = "AI简历") +@RestController +@RequestMapping("/ai/resume") +public class AiResumeController { + + @Autowired + private AiResumeService aiResumeService; + + @PostMapping("/create") + @ApiOperation("ai简历-创建") + public AlitaResult create(@RequestBody @Validated AiResumeReqDTO reqDto) { + aiResumeService.create(reqDto); + return AlitaResult.success(); + } + + @PostMapping("/iat") + @ApiOperation("ai简历-语音听写") + public AlitaResult iat(@RequestParam("fileCode") String fileCode) { + return AlitaResult.success(XfUtils.iat(fileCode)); + } + + @PostMapping("/tts") + @ApiOperation("ai简历-语音合成") + public AlitaResult tts(@RequestParam("text") String text) { + return AlitaResult.success(XfUtils.tts(text)); + } + + @PostMapping("/analyseResume") + @ApiOperation("分析简历") + public AlitaResult analyseResume(@RequestParam("text") String text) { + return AlitaResult.success(XfUtils.analyseResume(text)); + } + + @PostMapping("/generateSelfEvaluate") + @ApiOperation("生成自我评价") + public AlitaResult generateSelfEvaluate(@RequestBody Map map) { + return AlitaResult.success(XfUtils.generateSelfEvaluate(JSONUtil.toJsonStr(map))); + } + + @PostMapping("/generateWorkExperience") + @ApiOperation("生成工作经历") + public AlitaResult generateWorkExperience(@RequestBody Map map) { + return AlitaResult.success(XfUtils.generateWorkExperience(JSONUtil.toJsonStr(map))); + } + +} diff --git a/src/main/java/com/newyetai/ai/resume/dto/AiResumeReqDTO.java b/src/main/java/com/newyetai/ai/resume/dto/AiResumeReqDTO.java new file mode 100644 index 0000000..190d087 --- /dev/null +++ b/src/main/java/com/newyetai/ai/resume/dto/AiResumeReqDTO.java @@ -0,0 +1,43 @@ +package com.newyetai.ai.resume.dto; + +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; + +import java.io.Serializable; +import java.math.BigDecimal; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @description: + * @author: guixinman + * @create: 2024-12-12 10:07 + **/ +@ApiModel("ai面试记录") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class AiResumeReqDTO implements Serializable { + private static final long serialVersionUID = 1L; + + @NotBlank(message = "请输入内容") + private String content; + + @ApiModelProperty("岗位类型") + private String typeCode; + + @ApiModelProperty("期望城市") + private String expectCity; + + @ApiModelProperty("期望月薪") + private BigDecimal expectSalary; +} diff --git a/src/main/java/com/newyetai/ai/resume/model/AiResumeModel.java b/src/main/java/com/newyetai/ai/resume/model/AiResumeModel.java new file mode 100644 index 0000000..031d46c --- /dev/null +++ b/src/main/java/com/newyetai/ai/resume/model/AiResumeModel.java @@ -0,0 +1,44 @@ +package com.newyetai.ai.resume.model; + +import java.io.Serializable; +import java.util.List; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @description: Ai生成简历返回model + * @author: guixinman + * @create: 2024-12-12 11:31 + **/ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class AiResumeModel implements Serializable { + + private String name; + private String birthday; + @ApiModelProperty("期望工作地") + private String desiredWorkLocation; + @ApiModelProperty("期望最低薪资") + private String desiredSalaryMin; + @ApiModelProperty("期望最高薪资") + private String desiredSalaryMax; + @ApiModelProperty("期望岗位性质") + private String desiredPositionNature; + @ApiModelProperty("期望岗位") + private String desiredPosition; + @ApiModelProperty("最高学历") + private String highestDegree; + @ApiModelProperty("到岗状态") + private String reportStatus; + @ApiModelProperty("自我介绍") + private String selfIntroduction; +// @ApiModelProperty("简历标签") +// private String tags; + +} diff --git a/src/main/java/com/newyetai/ai/resume/service/AiResumeService.java b/src/main/java/com/newyetai/ai/resume/service/AiResumeService.java new file mode 100644 index 0000000..3fc002c --- /dev/null +++ b/src/main/java/com/newyetai/ai/resume/service/AiResumeService.java @@ -0,0 +1,14 @@ +package com.newyetai.ai.resume.service; + +import com.newyetai.ai.resume.dto.AiResumeReqDTO; + +/** + * @description: + * @author: guixinman + * @create: 2024-12-12 10:57 + **/ +public interface AiResumeService { + + void create(AiResumeReqDTO reqDto); + +} diff --git a/src/main/java/com/newyetai/ai/resume/service/impl/AiResumeServiceImpl.java b/src/main/java/com/newyetai/ai/resume/service/impl/AiResumeServiceImpl.java new file mode 100644 index 0000000..5a0b80a --- /dev/null +++ b/src/main/java/com/newyetai/ai/resume/service/impl/AiResumeServiceImpl.java @@ -0,0 +1,99 @@ +package com.newyetai.ai.resume.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.newyetai.ai.resume.dto.AiResumeReqDTO; +import com.newyetai.ai.resume.model.AiResumeModel; +import com.newyetai.ai.resume.service.AiResumeService; +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.component.dict.util.DictUtils; +import com.newyetai.config.service.ConfigService; +import com.newyetai.recruit.position.dao.PositionTypeMapper; +import com.newyetai.recruit.position.entity.PositionType; +import com.newyetai.recruit.user.dao.JobExpectMapper; +import com.newyetai.recruit.user.dao.ResumeMapper; +import com.newyetai.recruit.user.dto.JobExpectOperateDTO; +import com.newyetai.recruit.user.dto.ResumeDTO; +import com.newyetai.recruit.user.dto.ResumeOperatorDTO; +import com.newyetai.recruit.user.entity.Resume; +import com.newyetai.recruit.user.enums.InductionCycleEnum; +import com.newyetai.recruit.user.service.JobExpectService; +import com.newyetai.recruit.user.service.ResumeService; +import com.newyetai.sdk.xf.util.XfUtils; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.List; +import java.util.Objects; + +import javax.annotation.Resource; + +import lombok.extern.slf4j.Slf4j; + +/** + * @description: + * @author: guixinman + * @create: 2024-12-12 10:57 + **/ +@Slf4j +@Service +public class AiResumeServiceImpl implements AiResumeService { + + @Autowired + private ConfigService configService; + @Autowired + private ResumeService resumeService; + @Resource + private ResumeMapper resumeMapper; + + @Autowired + private JobExpectService jobExpectService; + + @Autowired + private PositionTypeMapper positionTypeMapper; + + + @Transactional(rollbackFor = Exception.class) + @Override + public void create(AiResumeReqDTO reqDto) { + String errMsg = "抱歉,我无法回答,请告诉我你想找什么样的工作"; + try { + String jsonData = XfUtils.generateResume(reqDto.getContent()); + if (StringUtils.equalsAny(jsonData, errMsg)) { + throw new BusinessException(jsonData); + } + AiResumeModel aiResumeModel = JsonUtils.toObject(jsonData, AiResumeModel.class); + + if (StringUtils.isBlank(aiResumeModel.getDesiredPosition())) { + throw new BusinessException(errMsg); + } + //学历 + String education = DictUtils.getNameCodeMap("education").get(StringUtils.isNotBlank(aiResumeModel.getHighestDegree()) ? aiResumeModel.getHighestDegree() : ""); + + jobExpectService.removeByUserId(); + jobExpectService.create( + JobExpectOperateDTO.builder() + .userId(UserContextHolder.getExistLoginUserId()) + .typeCode(reqDto.getTypeCode()) + .expectCity(reqDto.getExpectCity()) + .expectSalary(reqDto.getExpectSalary()) + .onDuty(false) + .inductionCycle(InductionCycleEnum.findTypeByDesc(aiResumeModel.getReportStatus())) + .positionName(aiResumeModel.getDesiredPosition()) + .build()); + + } catch (Exception e) { + log.error(e.getMessage()); + throw new BusinessException(errMsg); + } + } + +} diff --git a/src/main/java/com/newyetai/alitaforward/common/mq/constant/ForwardMqConstants.java b/src/main/java/com/newyetai/alitaforward/common/mq/constant/ForwardMqConstants.java new file mode 100644 index 0000000..594f78e --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/common/mq/constant/ForwardMqConstants.java @@ -0,0 +1,15 @@ +package com.newyetai.alitaforward.common.mq.constant; + +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.constant.SystemCodeEnum; + +/** + * mq常量类(routingkey) + * @author sr on 2021-08-09 + */ +public interface ForwardMqConstants { + + /** 用户中心系统mq前缀 **/ + String MQ_PREFIX = SystemCodeEnum.ALITA_FORWARD.getName() + CommonConstants.POINT; + +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/constants/FactorVerificationSourceTypeEnum.java b/src/main/java/com/newyetai/alitaforward/verification/constants/FactorVerificationSourceTypeEnum.java new file mode 100644 index 0000000..df4dd76 --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/constants/FactorVerificationSourceTypeEnum.java @@ -0,0 +1,29 @@ +package com.newyetai.alitaforward.verification.constants; + +/** + * @author czy + * @date 2021-06-21 + */ +public enum FactorVerificationSourceTypeEnum { + + FXQ("放心签", 1), + CL("创蓝", 2), + SYS("系统", 3); + + private final String desc; + + private final Integer type; + + FactorVerificationSourceTypeEnum(String desc, Integer type) { + this.desc = desc; + this.type = type; + } + + public String getDesc() { + return desc; + } + + public Integer getType() { + return type; + } +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/constants/VerificationTypeEnum.java b/src/main/java/com/newyetai/alitaforward/verification/constants/VerificationTypeEnum.java new file mode 100644 index 0000000..6882019 --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/constants/VerificationTypeEnum.java @@ -0,0 +1,33 @@ +package com.newyetai.alitaforward.verification.constants; + +import com.newyetai.alitaforward.common.mq.constant.ForwardMqConstants; + +public enum VerificationTypeEnum { + + /** 二要素认证 */ + TWO("real_name_two_verification"), + /** 银行卡三要素认证 */ + THREE("three_verification"), + /** 手机三要素认证 **/ + PHONE_THREE("phone_three_verification"), + /** 银行卡四要素认证 **/ + FOUR("four_verification"); + + private String fullname; + VerificationTypeEnum(String fullname){ + this.fullname = fullname; + } + + public String getFullName() { + return this.fullname; + } + + public String getAsyncKey() { + return ForwardMqConstants.MQ_PREFIX + this.fullname ; + } + + public String getStatusChangeKey() { + return getAsyncKey() + "_status_update"; + } + +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/consumer/providers/SystemFourFactorVerificationProvider.java b/src/main/java/com/newyetai/alitaforward/verification/consumer/providers/SystemFourFactorVerificationProvider.java new file mode 100644 index 0000000..30c7930 --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/consumer/providers/SystemFourFactorVerificationProvider.java @@ -0,0 +1,64 @@ +package com.newyetai.alitaforward.verification.consumer.providers; + +import cn.hutool.json.JSONUtil; +import com.newyetai.alitaforward.verification.dto.FourFactorVerificationDTO; +import com.newyetai.alitaforward.verification.dto.PhoneThreeFactorVerificationDTO; +import com.newyetai.alitaforward.verification.dto.ThreeFactorVerificationDTO; +import com.newyetai.alitaforward.verification.factor.PhoneThreeVerify; +import com.newyetai.alitaforward.verification.factor.ThreeVerify; +import com.newyetai.alitaforward.verification.service.FourFactorVerificationProvider; +import com.newyetai.common.constant.AuthStatusEnum; +import com.newyetai.mq.dto.TopicMqMessage; +import com.newyetai.usercenter.user.consumer.FourFactorVerifyStatusUpdateHandler; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Slf4j +@Component +public class SystemFourFactorVerificationProvider implements FourFactorVerificationProvider { + @Autowired + private FourFactorVerifyStatusUpdateHandler fourFactorVerifyStatusUpdateHandler; + + + @Override + public void onMessage(TopicMqMessage message) { + log.info("系统手机号四要素处理->生成三要素数据 开始,参数:{}", JSONUtil.toJsonStr(message)); + FourFactorVerificationDTO verificationDTO = message.getData(); + Integer status = verificationDTO.getStatus(); + if (!AuthStatusEnum.AUTH_SUCCESS.getType().equals(status)) { + return; + } + fourFactorVerifyStatusUpdateHandler.onMessage(verificationDTO); + try { + ThreeFactorVerificationDTO threeFactorVerificationDTO = ThreeFactorVerificationDTO.builder() + .realName(verificationDTO.getRealName()) + .cardNo(verificationDTO.getCardNo()) + .bankAccountNo(verificationDTO.getBankAccountNo()) + .build(); + threeFactorVerificationDTO.setStatus(verificationDTO.getStatus()); + threeVerify.autoVerify(threeFactorVerificationDTO); + } catch (Exception e) { + log.info("系统手机号四要素处理->生成三要素数据 异常,", e); + } + + try { + PhoneThreeFactorVerificationDTO phoneThreeFactorVerificationDTO = PhoneThreeFactorVerificationDTO.builder() + .realName(verificationDTO.getRealName()) + .cardNo(verificationDTO.getCardNo()) + .phone(verificationDTO.getPhone()) + .build(); + phoneThreeFactorVerificationDTO.setStatus(verificationDTO.getStatus()); + phoneThreeVerify.autoVerify(phoneThreeFactorVerificationDTO); + } catch (Exception e) { + log.info("系统手机号四要素处理->生成手机三要素数据 异常,", e); + } + } + + @Autowired + private PhoneThreeVerify phoneThreeVerify; + + @Autowired + private ThreeVerify threeVerify; +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/consumer/providers/SystemPhoneThreeFactorVerificationProvider.java b/src/main/java/com/newyetai/alitaforward/verification/consumer/providers/SystemPhoneThreeFactorVerificationProvider.java new file mode 100644 index 0000000..cf9c503 --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/consumer/providers/SystemPhoneThreeFactorVerificationProvider.java @@ -0,0 +1,46 @@ +package com.newyetai.alitaforward.verification.consumer.providers; + +import cn.hutool.json.JSONUtil; +import com.newyetai.alitaforward.verification.dto.PhoneThreeFactorVerificationDTO; +import com.newyetai.alitaforward.verification.dto.RealNameTwoFactorVerificationDTO; +import com.newyetai.alitaforward.verification.factor.RealNameTwoVerify; +import com.newyetai.alitaforward.verification.service.PhoneThreeFactorVerificationProvider; +import com.newyetai.common.constant.AuthStatusEnum; +import com.newyetai.mq.dto.TopicMqMessage; +import com.newyetai.usercenter.user.consumer.PhoneThreeFactorVerifyStatusUpdateHandler; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Slf4j +@Component +public class SystemPhoneThreeFactorVerificationProvider implements PhoneThreeFactorVerificationProvider { + + @Autowired + private RealNameTwoVerify realNameTwoVerify; + + @Autowired + private PhoneThreeFactorVerifyStatusUpdateHandler phoneThreeFactorVerifyStatusUpdateHandler; + + @Override + public void onMessage(TopicMqMessage message) { + log.info("系统手机号三要素成功处理->生成二要素数据 开始,参数:{}", JSONUtil.toJsonStr(message)); + PhoneThreeFactorVerificationDTO verificationDTO = message.getData(); + Integer status = verificationDTO.getStatus(); + if (!AuthStatusEnum.AUTH_SUCCESS.getType().equals(status)) { + return; + } + phoneThreeFactorVerifyStatusUpdateHandler.onMessage(verificationDTO); + try { + RealNameTwoFactorVerificationDTO realNameTwoFactorVerificationDTO = RealNameTwoFactorVerificationDTO.builder() + .realName(verificationDTO.getRealName()) + .cardNo(verificationDTO.getCardNo()) + .build(); + realNameTwoFactorVerificationDTO.setStatus(status); + realNameTwoVerify.autoVerify(realNameTwoFactorVerificationDTO); + } catch (Exception e) { + log.info("系统手机号三要素处理->生成二要素数据 异常,", e); + } + } +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/consumer/providers/SystemThreeFactorVerificationProvider.java b/src/main/java/com/newyetai/alitaforward/verification/consumer/providers/SystemThreeFactorVerificationProvider.java new file mode 100644 index 0000000..6148582 --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/consumer/providers/SystemThreeFactorVerificationProvider.java @@ -0,0 +1,46 @@ +package com.newyetai.alitaforward.verification.consumer.providers; + +import cn.hutool.json.JSONUtil; +import com.newyetai.alitaforward.verification.dto.RealNameTwoFactorVerificationDTO; +import com.newyetai.alitaforward.verification.dto.ThreeFactorVerificationDTO; +import com.newyetai.alitaforward.verification.factor.RealNameTwoVerify; +import com.newyetai.alitaforward.verification.service.ThreeFactorVerificationProvider; +import com.newyetai.common.constant.AuthStatusEnum; +import com.newyetai.mq.dto.TopicMqMessage; +import com.newyetai.usercenter.user.consumer.ThreeFactorVerifyStatusUpdateHandler; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Slf4j +@Component +public class SystemThreeFactorVerificationProvider implements ThreeFactorVerificationProvider { + + @Autowired + private RealNameTwoVerify realNameTwoVerify; + + @Autowired + private ThreeFactorVerifyStatusUpdateHandler threeFactorVerifyStatusUpdateHandler; + + @Override + public void onMessage(TopicMqMessage message) { + log.info("系统三要素成功处理->生成二要素数据 开始,参数:{}", JSONUtil.toJsonStr(message)); + ThreeFactorVerificationDTO verificationDTO = message.getData(); + Integer status = verificationDTO.getStatus(); + if (!AuthStatusEnum.AUTH_SUCCESS.getType().equals(status)) { + return; + } + threeFactorVerifyStatusUpdateHandler.onMessage(verificationDTO); + try { + RealNameTwoFactorVerificationDTO realNameTwoFactorVerificationDTO = RealNameTwoFactorVerificationDTO.builder() + .realName(verificationDTO.getRealName()) + .cardNo(verificationDTO.getCardNo()) + .build(); + realNameTwoFactorVerificationDTO.setStatus(verificationDTO.getStatus()); + realNameTwoVerify.autoVerify(realNameTwoFactorVerificationDTO); + } catch (Exception e) { + log.info("系统三要素处理->生成二要素数据 异常,", e); + } + } +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/controller/FactorVerificationContorller.java b/src/main/java/com/newyetai/alitaforward/verification/controller/FactorVerificationContorller.java new file mode 100644 index 0000000..953a899 --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/controller/FactorVerificationContorller.java @@ -0,0 +1,214 @@ +package com.newyetai.alitaforward.verification.controller; + +import com.newyetai.alitaforward.verification.dto.*; +import com.newyetai.alitaforward.verification.factor.FourVerify; +import com.newyetai.alitaforward.verification.factor.PhoneThreeVerify; +import com.newyetai.alitaforward.verification.factor.RealNameTwoVerify; +import com.newyetai.alitaforward.verification.factor.ThreeVerify; +import com.newyetai.alitaforward.verification.service.BankCardVerificationService; +import com.newyetai.common.AlitaResult; +import com.newyetai.tkmybatis.pojo.Page; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @author czy + * @date 2021-06-21 + */ +@Api("要素认证") +@RestController +@RequestMapping("factor_verify") +public class FactorVerificationContorller { + @Autowired + private FourVerify fourVerify; + + @Autowired + private BankCardVerificationService bankCardVerificationService; + + @Autowired + private RealNameTwoVerify realNameTwoVerify; + + @Autowired + private ThreeVerify threeVerify; + + @Autowired + private PhoneThreeVerify phoneThreeVerify; + + @ApiOperation("二要素认证(同步)") + @PostMapping("/real_name/two/sync") + public AlitaResult syncRealNameTwoAuthenticate( + @Validated @RequestBody RealNameTwoFactorVerificationDTO verificationInfo) { + return AlitaResult.success(realNameTwoVerify.sync(verificationInfo)); + } + + @ApiOperation("二要素认证(批量、同步)") + @PostMapping("/real_name/two/sync/batch") + public AlitaResult> syncRealNameTwoAuthenticate( + @Validated @RequestBody List verificationInfoList) { + return AlitaResult.success(realNameTwoVerify.sync(verificationInfoList)); + } + + @ApiOperation("二要素认证(异步)") + @PostMapping("/real_name/two/async") + public AlitaResult asyncRealNameTwoAuthenticate( + @Validated @RequestBody RealNameTwoFactorVerificationDTO verificationInfo) { + return AlitaResult.success(realNameTwoVerify.async(verificationInfo)); + } + + @ApiOperation("二要素认证(批量、异步)") + @PostMapping("/real_name/two/async/batch") + public AlitaResult> asyncRealNameTwoAuthenticate( + @Validated @RequestBody List verificationInfoList) { + return AlitaResult.success(realNameTwoVerify.async(verificationInfoList)); + } + + + @ApiOperation("手机三要素认证(同步)") + @PostMapping("/phone/three/sync") + public AlitaResult syncPhoneThreeAuthenticate( + @Validated @RequestBody PhoneThreeFactorVerificationDTO verificationInfo) { + return AlitaResult.success(phoneThreeVerify.sync(verificationInfo)); + } + + @ApiOperation("手机三要素认证(批量、同步)") + @PostMapping("/phone/three/sync/batch") + public AlitaResult> syncPhoneThreeAuthenticate( + @Validated @RequestBody List verificationInfoList) { + return AlitaResult.success(phoneThreeVerify.sync(verificationInfoList)); + } + + @ApiOperation("手机三要素认证(异步)") + @PostMapping("/phone/three/async") + public AlitaResult asyncPhoneThreeAuthenticate( + @Validated @RequestBody PhoneThreeFactorVerificationDTO verificationInfo) { + return AlitaResult.success(phoneThreeVerify.async(verificationInfo)); + } + + @ApiOperation("手机三要素认证(批量、异步)") + @PostMapping("/phone/three/async/batch") + public AlitaResult> asyncPhoneThreeAuthenticate( + @Validated @RequestBody List verificationInfoList) { + return AlitaResult.success(phoneThreeVerify.async(verificationInfoList)); + } + + @ApiOperation("三要素认证(同步)") + @PostMapping("/three/sync") + public AlitaResult syncThreeAuthenticate( + @Validated @RequestBody ThreeFactorVerificationDTO verificationInfo) { + return AlitaResult.success(threeVerify.sync(verificationInfo)); + } + + @ApiOperation("三要素认证(批量、同步)") + @PostMapping("/three/sync/batch") + public AlitaResult> syncThreeAuthenticate( + @Validated @RequestBody List verificationInfoList) { + return AlitaResult.success(threeVerify.sync(verificationInfoList)); + } + + @ApiOperation("三要素认证(异步)") + @PostMapping("/three/async") + public AlitaResult asyncThreeAuthenticate( + @Validated @RequestBody ThreeFactorVerificationDTO verificationInfo) { + return AlitaResult.success(threeVerify.async(verificationInfo)); + } + + @ApiOperation("三要素认证(批量、异步)") + @PostMapping("/three/async/batch") + public AlitaResult> asyncThreeAuthenticate( + @Validated @RequestBody List verificationInfoList) { + return AlitaResult.success(threeVerify.async(verificationInfoList)); + } + + @ApiOperation("获取匹配请求内容的三要素认证数据") + @PostMapping("/match_three/list") + public AlitaResult> queryMatchThreeList(@RequestBody List queryDtoList){ + return AlitaResult.success(threeVerify.queryListByData(queryDtoList)); + }; + + @ApiOperation("三要素认证根据id获取") + @PostMapping("/three/find/id") + public AlitaResult threeFindById(@RequestParam("id") Long id){ + return AlitaResult.success(threeVerify.findById(id)); + }; + + @ApiOperation("三要素认证根据查询条件获取列表") + @PostMapping("/three/list") + public AlitaResult> threeList(@RequestBody FactorVerificationQueryDTO query){ + query.setNeedPage(Boolean.FALSE); + return AlitaResult.success(threeVerify.list(query)); + }; + + @ApiOperation("三要素认证根据查询条件获取列表(分页)") + @PostMapping("/three/page") + public AlitaResult> threePage(@RequestBody FactorVerificationQueryDTO query){ + threeVerify.list(query); + return AlitaResult.success(query.getPageResult()); + }; + + @ApiOperation("四要素认证(同步)") + @PostMapping("/four/sync") + public AlitaResult syncFourAuthenticate( + @Validated @RequestBody FourFactorVerificationDTO verificationInfoList) { + return AlitaResult.success(fourVerify.sync(verificationInfoList)); + } + + @ApiOperation("四要素认证(批量、同步)") + @PostMapping("/four/sync/batch") + public AlitaResult> syncFourAuthenticate( + @Validated @RequestBody List verificationInfoList) { + return AlitaResult.success(fourVerify.sync(verificationInfoList)); + } + + @ApiOperation("四要素认证(异步)") + @PostMapping("/four/async") + public AlitaResult asyncFourAuthenticate( + @Validated @RequestBody FourFactorVerificationDTO verificationInfoList) { + return AlitaResult.success(fourVerify.async(verificationInfoList)); + } + + @ApiOperation("四要素认证(批量、异步)") + @PostMapping("/four/async/batch") + public AlitaResult> asyncFourAuthenticate( + @Validated @RequestBody List verificationInfoList) { + return AlitaResult.success(fourVerify.async(verificationInfoList)); + } + + @ApiOperation("四要素认证根据id获取") + @PostMapping("/four/find/id") + public AlitaResult fourFindById(@RequestParam("id") Long id){ + return AlitaResult.success(fourVerify.findById(id)); + }; + + @ApiOperation("获取匹配请求内容的四要素认证数据") + @PostMapping("/match_four/list") + public AlitaResult> queryMatchFourList(@RequestBody List queryDtoList){ + return AlitaResult.success(fourVerify.queryListByData(queryDtoList)); + }; + + @ApiOperation("四要素认证根据查询条件获取列表") + @PostMapping("/four/list") + public AlitaResult> fourList(@RequestBody FactorVerificationQueryDTO query){ + query.setNeedPage(Boolean.FALSE); + return AlitaResult.success(fourVerify.list(query)); + }; + + @ApiOperation("四要素认证根据查询条件获取列表(分页)") + @PostMapping("/four/page") + public AlitaResult> fourPage(@RequestBody FactorVerificationQueryDTO query){ + fourVerify.list(query); + return AlitaResult.success(query.getPageResult()); + }; + + + @ApiOperation("白名单管理-->三、四要素查询合并为银行卡查询") + @PostMapping("/bank_card/page") + AlitaResult> bankCardPage(String cardNo,Integer status){ + return AlitaResult.success(bankCardVerificationService.list(cardNo, status)); + } + +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/dao/BankCardVerificationMapper.java b/src/main/java/com/newyetai/alitaforward/verification/dao/BankCardVerificationMapper.java new file mode 100644 index 0000000..4f8b194 --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/dao/BankCardVerificationMapper.java @@ -0,0 +1,36 @@ +package com.newyetai.alitaforward.verification.dao; + +import com.newyetai.alitaforward.verification.dto.BankCordVerificationResDTO; +import com.newyetai.alitaforward.verification.factor.four.entity.BankCardFourVerification; +import com.newyetai.tkmybatis.mybatis.MyMapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** + * @author fzp + * @date 2021年9月6日13:42:17 + */ +public interface BankCardVerificationMapper{ + + /** + * 白名单管理-->三、四要素查询合并为银行卡查询 + * @param cardNo + */ + @Select("select " + + " t.id,t.card_no,t.real_name,t.bank_account_no,'' as phone,'三要素' as `type`, " + + " (case t.authentication_source when '1' then '放心签' when '2' then '创蓝' when '3' then '系统' else '' end) as source, " + + " t.status,t.fail_reason,t.deleted " + + "from bank_card_three_verification t " + + "where t.deleted = 0 and t.card_no = #{cardNo} " + + "union all " + + "select " + + " f.id,f.card_no,f.real_name,f.bank_account_no,f.phone,'四要素' as `type`, " + + " (case f.authentication_source when '1' then '放心签' when '2' then '创蓝' when '3' then '系统' else '' end) as source, " + + " f.status,f.fail_reason,f.deleted " + + "from bank_card_four_verification f " + + "where f.deleted = 0 and f.card_no = #{cardNo} ") + List list(@Param("cardNo") String cardNo); + +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/dto/BankCordVerificationResDTO.java b/src/main/java/com/newyetai/alitaforward/verification/dto/BankCordVerificationResDTO.java new file mode 100644 index 0000000..57c4bf3 --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/dto/BankCordVerificationResDTO.java @@ -0,0 +1,47 @@ +package com.newyetai.alitaforward.verification.dto; + +import com.newyetai.common.dto.BaseDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author fzp + * @date 三、四要素合并银行卡查询 + */ +@ApiModel("三、四要素合并银行卡查询") +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class BankCordVerificationResDTO extends BaseDTO { + + private static final long serialVersionUID = 4820612112161649806L; + @ApiModelProperty("姓名") + private String realName; + + @ApiModelProperty("证件号") + private String cardNo; + + @ApiModelProperty("银行卡号") + private String bankAccountNo; + + @ApiModelProperty("手机号") + private String phone; + + @ApiModelProperty("要素类型") + private String type; + + @ApiModelProperty("认证来源 1系统,2放心签,3创蓝") + private String source; + + @ApiModelProperty("认证状态(1-未认证 2-认证中 3-认证成功 4-认证失败)") + private Integer status; + + @ApiModelProperty("失败原因") + private String failReason; + +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/dto/FactorVerificationDTO.java b/src/main/java/com/newyetai/alitaforward/verification/dto/FactorVerificationDTO.java new file mode 100644 index 0000000..9332a5d --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/dto/FactorVerificationDTO.java @@ -0,0 +1,37 @@ +package com.newyetai.alitaforward.verification.dto; + +import com.newyetai.common.dto.BaseDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author czy + * @date 2021-06-17 + */ +@ApiModel("要素认证DTO") +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +public class FactorVerificationDTO extends BaseDTO { + + private static final long serialVersionUID = 2838128328843902963L; + @ApiModelProperty("认证状态(1-未认证 2-认证中 3-认证成功 4-认证失败)") + private Integer status; + + @ApiModelProperty("认证来源") + private Integer authenticationSource; + + @ApiModelProperty("调用数据") + private String invokeData; + + @ApiModelProperty("失败原因") + private String failReason; + +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/dto/FactorVerificationQueryDTO.java b/src/main/java/com/newyetai/alitaforward/verification/dto/FactorVerificationQueryDTO.java new file mode 100644 index 0000000..0fd2e6e --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/dto/FactorVerificationQueryDTO.java @@ -0,0 +1,47 @@ +package com.newyetai.alitaforward.verification.dto; + +import com.newyetai.common.annotation.trimAndUpper.TrimAndUpper; +import com.newyetai.common.dto.PageQueryDTO; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import java.util.Set; + +/** + * @author czy + * @date 2021-07-01 + */ + +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class FactorVerificationQueryDTO extends PageQueryDTO { + + private static final long serialVersionUID = -2357416347060650749L; + + private Long id; + + private Set ids; + + @ApiModelProperty("姓名") + @TrimAndUpper + private String realName; + + @ApiModelProperty("证件号") + @TrimAndUpper + private String cardNo; + + @ApiModelProperty("银行卡号") + @TrimAndUpper + private String bankAccountNo; + + @ApiModelProperty("手机号") + @TrimAndUpper + private String phone; + + @ApiModelProperty("认证状态(1-未认证 2-认证中 3-认证成功 4-认证失败)") + private Integer status; + +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/dto/FourFactorVerificationDTO.java b/src/main/java/com/newyetai/alitaforward/verification/dto/FourFactorVerificationDTO.java new file mode 100644 index 0000000..1891f30 --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/dto/FourFactorVerificationDTO.java @@ -0,0 +1,45 @@ +package com.newyetai.alitaforward.verification.dto; + +import com.newyetai.common.annotation.trimAndUpper.TrimAndUpper; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotBlank; + +/** + * @author czy + * @date 2021-06-17 + */ +@ApiModel("四要素认证DTO") +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class FourFactorVerificationDTO extends FactorVerificationDTO { + + private static final long serialVersionUID = -5514764157174505641L; + @ApiModelProperty("姓名") + @NotBlank(message = "姓名不能为空") + @TrimAndUpper + private String realName; + + @ApiModelProperty("证件号") + @NotBlank(message = "证件号不能为空") + @TrimAndUpper + private String cardNo; + + @ApiModelProperty("银行卡号") + @NotBlank(message = "银行卡号不能为空") + @TrimAndUpper + private String bankAccountNo; + + @ApiModelProperty("手机号") + @NotBlank(message = "手机号不能为空") + @TrimAndUpper + private String phone; + +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/dto/PhoneThreeFactorVerificationDTO.java b/src/main/java/com/newyetai/alitaforward/verification/dto/PhoneThreeFactorVerificationDTO.java new file mode 100644 index 0000000..dfcd61b --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/dto/PhoneThreeFactorVerificationDTO.java @@ -0,0 +1,40 @@ +package com.newyetai.alitaforward.verification.dto; + +import com.newyetai.common.annotation.trimAndUpper.TrimAndUpper; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.SuperBuilder; + +import javax.validation.constraints.NotBlank; + +/** + * @author czy + * @date 2021-06-17 + */ +@EqualsAndHashCode(callSuper = true) +@ApiModel("手机号三要素认证DTO") +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class PhoneThreeFactorVerificationDTO extends FactorVerificationDTO { + + + private static final long serialVersionUID = 1594482919800883278L; + @ApiModelProperty("姓名") + @NotBlank(message = "姓名不能为空") + @TrimAndUpper + private String realName; + + @ApiModelProperty("证件号") + @NotBlank(message = "证件号不能为空") + @TrimAndUpper + private String cardNo; + + @ApiModelProperty("手机号") + @NotBlank(message = "手机号不能为空") + @TrimAndUpper + private String phone; + +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/dto/RealNameTwoFactorVerificationDTO.java b/src/main/java/com/newyetai/alitaforward/verification/dto/RealNameTwoFactorVerificationDTO.java new file mode 100644 index 0000000..14865e7 --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/dto/RealNameTwoFactorVerificationDTO.java @@ -0,0 +1,35 @@ +package com.newyetai.alitaforward.verification.dto; + +import com.newyetai.common.annotation.trimAndUpper.TrimAndUpper; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.SuperBuilder; + +import javax.validation.constraints.NotBlank; + +/** + * 二要素认证DTO + * + * @author Administrator + * @date 2022/07/22 + */ +@ApiModel("二要素认证DTO") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class RealNameTwoFactorVerificationDTO extends FactorVerificationDTO { + + private static final long serialVersionUID = -2114148883543603016L; + @ApiModelProperty("姓名") + @NotBlank(message = "姓名不能为空") + @TrimAndUpper + private String realName; + + @ApiModelProperty("证件号") + @NotBlank(message = "证件号不能为空") + @TrimAndUpper + private String cardNo; +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/dto/ThreeFactorVerificationDTO.java b/src/main/java/com/newyetai/alitaforward/verification/dto/ThreeFactorVerificationDTO.java new file mode 100644 index 0000000..106d7bd --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/dto/ThreeFactorVerificationDTO.java @@ -0,0 +1,39 @@ +package com.newyetai.alitaforward.verification.dto; + +import com.newyetai.common.annotation.trimAndUpper.TrimAndUpper; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.SuperBuilder; + +import javax.validation.constraints.NotBlank; + +/** + * @author czy + * @date 2021-06-17 + */ +@ApiModel("三要素认证DTO") +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +@EqualsAndHashCode(callSuper = true) +public class ThreeFactorVerificationDTO extends FactorVerificationDTO { + + private static final long serialVersionUID = 656164023756231640L; + @ApiModelProperty("姓名") + @NotBlank(message = "姓名不能为空") + @TrimAndUpper + private String realName; + + @ApiModelProperty("证件号") + @NotBlank(message = "证件号不能为空") + @TrimAndUpper + private String cardNo; + + @ApiModelProperty("银行卡号") + @NotBlank(message = "银行卡号不能为空") + @TrimAndUpper + private String bankAccountNo; + +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/factor/AbstractVerify.java b/src/main/java/com/newyetai/alitaforward/verification/factor/AbstractVerify.java new file mode 100644 index 0000000..a2db1aa --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/factor/AbstractVerify.java @@ -0,0 +1,240 @@ +package com.newyetai.alitaforward.verification.factor; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.newyetai.alitaforward.verification.constants.FactorVerificationSourceTypeEnum; +import com.newyetai.alitaforward.verification.dto.FactorVerificationDTO; +import com.newyetai.alitaforward.verification.source.FactorVerificationSourceService; +import com.newyetai.common.constant.AuthStatusEnum; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.EnvironmentUtils; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.frame.redis.dto.LockDTO; +import com.newyetai.frame.redis.redisson.RedissonUtils; +import com.newyetai.mq.consumer.handler.ITopicMqHandler; +import com.newyetai.mq.dto.TopicMqMessage; +import com.newyetai.mq.util.MqSendUtils; + +import cn.hutool.json.JSONUtil; +import lombok.extern.slf4j.Slf4j; + +/** + * 要素校验顶层接口 + * + * @author cheny + * @date 2022/08/11 + */ +@Slf4j +@Component +@SuppressWarnings("rawtypes,unchecked") +public abstract class AbstractVerify implements IVerify, ITopicMqHandler{ + + private static final Integer DEFAULT_TYPE = FactorVerificationSourceTypeEnum.CL.getType(); + + static final Map SOURCE_SERVICE_MAP = Maps.newConcurrentMap(); + + /** + * 终态通知key + * @return + * @author sr on 2023-11-27 + */ + final String statusChangeRoutingKey() { + return getType().getStatusChangeKey(); + } + + + @Override + public final String getRoutingKey() { + return getType().getAsyncKey(); + } + + @Override + public final void onMessage(TopicMqMessage message) { + T verificationDTO = message.getData(); + log.info("【MQ】异步处理认证开始,参数:{}", JsonUtils.toJsonString(verificationDTO)); + if (verificationDTO == null) { + return; + } + try { + T sync = this.sync(verificationDTO); + log.info("【MQ】异步处理认证结束,参数:{}", JsonUtils.toJsonString(sync)); + } catch (Exception e) { + log.info("【MQ】异步处理认证异常", e); + } + } + + // 幂等创建 + abstract T createAndGet(T t); + + /** + * 得到锁 + * + * @param t t + * @return {@link LockDTO} + */ + abstract LockDTO getLock(T t); + + // 上一级认证创建 + abstract void autoVerify(T t); + + /** + * 同步校验前置hook + * + * @param t t + * @return {@link T} + */ + protected T syncBeforeVerify(T t) { + // 认证源根据配置文件不同调用不同SDK 1放心签、2创蓝 + String source = EnvironmentUtils.getProperty("alita.authenticationSource"); + int authenticationSource = DEFAULT_TYPE; + try { + authenticationSource = Integer.parseInt(source); + //如果不是这两种认证源,用默认的源 + if (!(FactorVerificationSourceTypeEnum.CL.getType().equals(authenticationSource) + || FactorVerificationSourceTypeEnum.FXQ.getType().equals(authenticationSource))) { + authenticationSource = DEFAULT_TYPE; + } + } catch (NumberFormatException e) { + //doNothing + } + t.setAuthenticationSource(authenticationSource); + return t; + } + + /** + * 真正执行校验逻辑的方法 + * + * @param verifyDto 验证dto + * @return {@link T} + */ + @Transactional(propagation = Propagation.REQUIRES_NEW) + public T doSyncVerify(T verifyDto) { + String failReason = verifyDto.getFailReason(); + //如果校验失败了 直接返回 + if (StringUtils.isNotEmpty(failReason)) { + return verifyDto; + } + //拿锁 + LockDTO lockDTO = getLock(verifyDto); + try { + Assert.isTrue(RedissonUtils.tryLock(lockDTO), "要素认证正在处理中,请稍后再试"); + T preVerifyDto = createAndGet(verifyDto); + //如果不是待认证的数直接返回 + if (!AuthStatusEnum.NOT_AUTH.getType().equals(preVerifyDto.getStatus())) { + return preVerifyDto; + } + + return realVerification(preVerifyDto); + } finally { + RedissonUtils.unlock(lockDTO); + } + } + + abstract T realVerification(T verificationDTO); + + T syncVerifyWrapper(T t) { + T beforeVerify = syncBeforeVerify(t); + + T doVerify = (T) ((AbstractVerify) AopContext.currentProxy()).doSyncVerify(beforeVerify); + + Integer status = doVerify.getStatus(); + //如果执行到了终态 发送消息通知 + if (AuthStatusEnum.AUTH_FAIL.getType().equals(status) + || AuthStatusEnum.AUTH_SUCCESS.getType().equals(status)) { + log.info("【MQ】通知认证状态变更,参数:{}", JSONUtil.toJsonStr(doVerify)); + MqSendUtils.send(statusChangeRoutingKey(), doVerify); + } + return doVerify; + } + + /** + * 同步校验 + * + * @param list 列表 + * @return {@link List}<{@link T}> + */ + @Override + public List sync(List list) { + if (CollectionUtils.isEmpty(list)) { + return Lists.newArrayList(); + } + return list.stream().map(this::syncVerifyWrapper).collect(Collectors.toList()); + } + + // -------------------------------------------------------- async ------------------------------------------------------- + + /** + * 异步校验前置hook + * + * @param t t + * @return {@link T} + */ + protected T asyncBeforeVerify(T t) { + return syncBeforeVerify(t); + } + + /** + * 真正执行校验逻辑的方法 + * + * @param verifyDto 验证dto + * @return {@link T} + */ + protected T doAsyncVerify(T verifyDto) { + String failReason = verifyDto.getFailReason(); + //如果校验失败了 直接返回 + if (StringUtils.isNotEmpty(failReason)) { + return verifyDto; + } + //拿锁 + LockDTO lockDTO = getLock(verifyDto); + try { + Assert.isTrue(RedissonUtils.tryLock(lockDTO), "要素认证正在处理中,请稍后再试"); + T preVerifyDto = createAndGet(verifyDto); + //如果不是待认证的数直接返回 + if (AuthStatusEnum.NOT_AUTH.getType().equals(preVerifyDto.getStatus())) { + //mq异步处理认证 + log.info("async【MQ】要素认证异步处理,参数:{}", JSONUtil.toJsonStr(preVerifyDto)); + MqSendUtils.send(getRoutingKey(), preVerifyDto); + } + return preVerifyDto; + } finally { + RedissonUtils.unlock(lockDTO); + } + + } + + + T asyncVerifyWrapper(T t) { + T beforeVerify = asyncBeforeVerify(t); + + T doVerify = doAsyncVerify(beforeVerify); + + Integer status = doVerify.getStatus(); + //如果执行到了终态 发送消息通知 + if (AuthStatusEnum.AUTH_FAIL.getType().equals(status) + || AuthStatusEnum.AUTH_SUCCESS.getType().equals(status)) { + log.info("【MQ】通知认证状态变更,参数:{}", JSONUtil.toJsonStr(doVerify)); + MqSendUtils.send(statusChangeRoutingKey(), doVerify); + } + return doVerify; + } + + @Override + public List async(List list) { + if (CollectionUtils.isEmpty(list)) { + return Lists.newArrayList(); + } + return list.stream().map(this::asyncVerifyWrapper).collect(Collectors.toList()); + } +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/factor/FourVerify.java b/src/main/java/com/newyetai/alitaforward/verification/factor/FourVerify.java new file mode 100644 index 0000000..2c7cf00 --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/factor/FourVerify.java @@ -0,0 +1,176 @@ +package com.newyetai.alitaforward.verification.factor; + +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.StringJoiner; +import java.util.stream.Collectors; + +import javax.annotation.Resource; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; + +import com.google.common.collect.Lists; +import com.newyetai.alitaforward.verification.constants.FactorVerificationSourceTypeEnum; +import com.newyetai.alitaforward.verification.constants.VerificationTypeEnum; +import com.newyetai.alitaforward.verification.dto.FactorVerificationQueryDTO; +import com.newyetai.alitaforward.verification.dto.FourFactorVerificationDTO; +import com.newyetai.alitaforward.verification.factor.four.dao.FourVerificationMapper; +import com.newyetai.alitaforward.verification.factor.four.entity.BankCardFourVerification; +import com.newyetai.alitaforward.verification.factor.four.mapstruct.FourVerificationMapMapper; +import com.newyetai.common.constant.AuthStatusEnum; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.common.validation.util.ValidateUtils; +import com.newyetai.frame.redis.aop.annotation.AutoUnLock; +import com.newyetai.frame.redis.dto.LockDTO; +import com.newyetai.frame.redis.redisson.RedissonUtils; +import com.newyetai.mq.util.MqSendUtils; + +import cn.hutool.json.JSONUtil; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Component +public class FourVerify extends AbstractVerify implements IQueryVerify { + + @Resource + private FourVerificationMapper fourVerificationMapper; + + @Override + protected FourFactorVerificationDTO syncBeforeVerify(FourFactorVerificationDTO verificationDTO) { + StringJoiner stringJoiner = new StringJoiner("、"); + if (!ValidateUtils.checkRealName(verificationDTO.getRealName())) { + stringJoiner.add("姓名格式有误"); + } + if (!ValidateUtils.isIdCard(verificationDTO.getCardNo())) { + stringJoiner.add("证件号格式有误"); + } + if (StringUtils.isBlank(verificationDTO.getBankAccountNo())) { + stringJoiner.add("银行卡号为空"); + } + if (StringUtils.isBlank(verificationDTO.getPhone())) { + stringJoiner.add("手机号为空"); + } + String failReason = stringJoiner.toString(); + if (StringUtils.isNotBlank(failReason)) { + verificationDTO.setFailReason(failReason); + } else { + //校验成功调用 + super.syncBeforeVerify(verificationDTO); + } + return verificationDTO; + } + + @Override + FourFactorVerificationDTO createAndGet(FourFactorVerificationDTO verificationDTO) { + BankCardFourVerification bankCardFourVerification = fourVerificationMapper.selectInfo(verificationDTO); + if (bankCardFourVerification == null) { + //认证库不存在,以默认状态入库——"未认证" + verificationDTO.setStatus(AuthStatusEnum.NOT_AUTH.getType()); + bankCardFourVerification = FourVerificationMapMapper.INSTANCE.toEntity(verificationDTO); + fourVerificationMapper.saveEntity(bankCardFourVerification); + } + return FourVerificationMapMapper.INSTANCE.toDto(bankCardFourVerification); + } + + @Override + LockDTO getLock(FourFactorVerificationDTO verificationDTO) { + return LockDTO.builder().methodName("verify:four").tryLockWaitTime(0L) + .arg(verificationDTO.getRealName()) + .arg(verificationDTO.getCardNo()) + .arg(verificationDTO.getBankAccountNo()) + .arg(verificationDTO.getPhone()) + .build(); + } + + @Override + @AutoUnLock + public void autoVerify(FourFactorVerificationDTO verificationDTO) { + //拿锁 + LockDTO lockDTO = getLock(verificationDTO); + Assert.isTrue(RedissonUtils.tryLockAutomatically(lockDTO), "请勿重复校验四要素"); + + BankCardFourVerification verificationEntity = fourVerificationMapper.selectInfo(verificationDTO); + + if (Objects.nonNull(verificationEntity)) { + if (AuthStatusEnum.AUTH_SUCCESS.getType().equals(verificationEntity.getStatus())) { + return; + } + verificationEntity.setAuthenticationSource(FactorVerificationSourceTypeEnum.SYS.getType()); + verificationEntity.setStatus(AuthStatusEnum.AUTH_SUCCESS.getType()); + fourVerificationMapper.updateEntitySelective(verificationEntity, + UserContextHolder.getLoginUserId()); + } else { + verificationEntity = + BankCardFourVerification.builder() + .realName(verificationDTO.getRealName()) + .cardNo(verificationDTO.getCardNo()) + .phone(verificationDTO.getPhone()) + .bankAccountNo(verificationDTO.getBankAccountNo()) + .authenticationSource(FactorVerificationSourceTypeEnum.SYS.getType()) + .status(AuthStatusEnum.AUTH_SUCCESS.getType()) + .build(); + fourVerificationMapper.saveEntity(verificationEntity); + } + log.info("【MQ】通知认证状态变更,参数:{}", JSONUtil.toJsonStr(verificationDTO)); + MqSendUtils.send(statusChangeRoutingKey(), verificationDTO); + } + + @Override + public List list(FactorVerificationQueryDTO queryDTO) { + return fourVerificationMapper.list(queryDTO); + } + + @Override + public List queryListByData(List queryDTOList) { + List resultList = Lists + .newArrayListWithCapacity(queryDTOList.size()); + if (CollectionUtils.isEmpty(queryDTOList)) { + return resultList; + } + List bankCardThreeVerifications = fourVerificationMapper + .findFinishStatusData(); + Map threeVerificationMap = bankCardThreeVerifications + .stream().collect( + Collectors.toMap(k -> k.getRealName() + k.getCardNo() + k.getBankAccountNo() + k.getPhone(), v -> v, (v1, v2) -> v1)); + + for (FactorVerificationQueryDTO queryDTO : queryDTOList) { + FourFactorVerificationDTO FourFactorVerificationDTO = threeVerificationMap + .get(queryDTO.getRealName() + queryDTO.getCardNo() + queryDTO.getBankAccountNo() + queryDTO + .getPhone()); + if (FourFactorVerificationDTO != null) { + resultList.add(FourFactorVerificationDTO); + } + } + return resultList; + } + + @Override + public FourFactorVerificationDTO findById(Long id) { + FourFactorVerificationDTO fourFactorVerificationDTO = null; + BankCardFourVerification entity = fourVerificationMapper.getById(id); + if (entity != null) { + fourFactorVerificationDTO = FourVerificationMapMapper.INSTANCE.toDto(entity); + } + return fourFactorVerificationDTO; + } + + @Override + FourFactorVerificationDTO realVerification(FourFactorVerificationDTO verificationDTO) { + Integer authenticationSource = verificationDTO.getAuthenticationSource(); + SOURCE_SERVICE_MAP.get(authenticationSource).fourVerify(verificationDTO); + //更新状态 + BankCardFourVerification entity = FourVerificationMapMapper.INSTANCE + .toEntity(verificationDTO); + fourVerificationMapper.updateEntitySelective(entity, UserContextHolder.getLoginUserId()); + return verificationDTO; + } + + @Override + public VerificationTypeEnum getType() { + return VerificationTypeEnum.FOUR; + } +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/factor/IQueryVerify.java b/src/main/java/com/newyetai/alitaforward/verification/factor/IQueryVerify.java new file mode 100644 index 0000000..1ad4ddc --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/factor/IQueryVerify.java @@ -0,0 +1,42 @@ +package com.newyetai.alitaforward.verification.factor; + +import com.newyetai.alitaforward.verification.dto.FactorVerificationDTO; +import com.newyetai.alitaforward.verification.dto.FactorVerificationQueryDTO; + +import java.util.List; + +/** + * 要素查询顶层接口 + * + * @author cheny + * @date 2022/08/11 + */ +public interface IQueryVerify { + + + /** + * 根据参数查list + * + * @param queryDTO 查询DTO + * @return {@link List}<{@link T}> + */ + List list(FactorVerificationQueryDTO queryDTO); + + + /** + * 根据传来的数据,查出认证库中存在的数据 + * + * @param queryDTOList 查询DTO集合 + * @return {@link List}<{@link T}> + */ + List queryListByData(List queryDTOList); + + + /** + * 根据id获取 + * + * @param id id + * @return {@link T} + */ + T findById(Long id); +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/factor/IVerify.java b/src/main/java/com/newyetai/alitaforward/verification/factor/IVerify.java new file mode 100644 index 0000000..d250333 --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/factor/IVerify.java @@ -0,0 +1,48 @@ +package com.newyetai.alitaforward.verification.factor; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.alitaforward.verification.constants.VerificationTypeEnum; + +/** + * 要素校验顶层接口 + * + * @author cheny + * @date 2022/08/11 + */ +public interface IVerify { + + /** + * 同步校验 + * + * @param list 列表 + * @return {@link List}<{@link T}> + */ + List sync(List list); + + /** + * 异步校验 + * + * @param list 列表 + * @return {@link List}<{@link T}> + */ + List async(List list); + + default T sync(T t) { + List syncSingle = new ArrayList<>(1); + syncSingle.add(t); + return sync(syncSingle).get(0); + } + + default T async(T t) { + List asyncSingle = new ArrayList<>(1); + asyncSingle.add(t); + return async(asyncSingle).get(0); + } + + VerificationTypeEnum getType(); +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/factor/PhoneThreeVerify.java b/src/main/java/com/newyetai/alitaforward/verification/factor/PhoneThreeVerify.java new file mode 100644 index 0000000..daad4c1 --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/factor/PhoneThreeVerify.java @@ -0,0 +1,170 @@ +package com.newyetai.alitaforward.verification.factor; + +import cn.hutool.json.JSONUtil; +import com.google.common.collect.Lists; +import com.newyetai.alitaforward.common.mq.constant.ForwardMqConstants; +import com.newyetai.alitaforward.verification.constants.FactorVerificationSourceTypeEnum; +import com.newyetai.alitaforward.verification.constants.VerificationTypeEnum; +import com.newyetai.alitaforward.verification.dto.FactorVerificationQueryDTO; +import com.newyetai.alitaforward.verification.dto.PhoneThreeFactorVerificationDTO; +import com.newyetai.alitaforward.verification.factor.phoneThree.dao.PhoneThreeVerificationMapper; +import com.newyetai.alitaforward.verification.factor.phoneThree.entity.PhoneThreeVerification; +import com.newyetai.alitaforward.verification.factor.phoneThree.mapstruct.PhoneThreeVerificationMapMapper; +import com.newyetai.common.constant.AuthStatusEnum; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.common.validation.util.ValidateUtils; +import com.newyetai.frame.redis.aop.annotation.AutoUnLock; +import com.newyetai.frame.redis.dto.LockDTO; +import com.newyetai.frame.redis.redisson.RedissonUtils; +import com.newyetai.mq.util.MqSendUtils; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.StringJoiner; +import java.util.stream.Collectors; + +@Slf4j +@Component +public class PhoneThreeVerify extends AbstractVerify implements IQueryVerify { + + @Resource + private PhoneThreeVerificationMapper phoneThreeVerificationMapper; + + @Override + protected PhoneThreeFactorVerificationDTO syncBeforeVerify(PhoneThreeFactorVerificationDTO verificationDTO) { + StringJoiner stringJoiner = new StringJoiner("、"); + if (!ValidateUtils.checkRealName(verificationDTO.getRealName())) { + stringJoiner.add("姓名格式有误"); + } + if (!ValidateUtils.isIdCard(verificationDTO.getCardNo())) { + stringJoiner.add("证件号格式有误"); + } + if (StringUtils.isBlank(verificationDTO.getPhone())) { + stringJoiner.add("手机号为空"); + } + String failReason = stringJoiner.toString(); + if (StringUtils.isNotBlank(failReason)) { + verificationDTO.setFailReason(failReason); + } else { + //校验成功调用 + super.syncBeforeVerify(verificationDTO); + } + return verificationDTO; + } + + @Override + PhoneThreeFactorVerificationDTO createAndGet(PhoneThreeFactorVerificationDTO verificationDTO) { + PhoneThreeVerification entity = phoneThreeVerificationMapper.find(verificationDTO); + if (entity == null) { + //认证库不存在,以默认状态入库——"未认证" + verificationDTO.setStatus(AuthStatusEnum.NOT_AUTH.getType()); + entity = PhoneThreeVerificationMapMapper.INSTANCE.exchange(verificationDTO); + phoneThreeVerificationMapper.saveEntity(entity); + } + return PhoneThreeVerificationMapMapper.INSTANCE.exchange(entity); + } + + @Override + LockDTO getLock(PhoneThreeFactorVerificationDTO verificationDTO) { + return LockDTO.builder() + .methodName("verify:three:phone") + .tryLockWaitTime(0L) + .arg(verificationDTO.getRealName()) + .arg(verificationDTO.getCardNo()) + .arg(verificationDTO.getPhone()) + .build(); + } + + @Override + @AutoUnLock + public void autoVerify(PhoneThreeFactorVerificationDTO verificationDTO) { +//拿锁 + LockDTO lockDTO = getLock(verificationDTO); + Assert.isTrue(RedissonUtils.tryLockAutomatically(lockDTO), "请勿重复校验手机三要素"); + + PhoneThreeVerification verificationEntity = phoneThreeVerificationMapper.find(verificationDTO); + + if (Objects.nonNull(verificationEntity)) { + if (!AuthStatusEnum.NOT_AUTH.getType().equals(verificationEntity.getStatus())) { + return; + } + verificationEntity.setAuthenticationSource(FactorVerificationSourceTypeEnum.SYS.getType()); + verificationEntity.setStatus(verificationDTO.getStatus()); + phoneThreeVerificationMapper.updateEntitySelective(verificationEntity, + UserContextHolder.getLoginUserId()); + } else { + verificationEntity = + PhoneThreeVerification.builder() + .realName(verificationDTO.getRealName()) + .cardNo(verificationDTO.getCardNo()) + .phone(verificationDTO.getPhone()) + .authenticationSource(FactorVerificationSourceTypeEnum.SYS.getType()) + .status(verificationDTO.getStatus()) + .build(); + phoneThreeVerificationMapper.saveEntity(verificationEntity); + } + log.info("【MQ】通知认证状态变更,参数:{}", JSONUtil.toJsonStr(verificationDTO)); + MqSendUtils.send(statusChangeRoutingKey(), verificationDTO); + } + + @Override + public List list(FactorVerificationQueryDTO queryDTO) { + return phoneThreeVerificationMapper.list(queryDTO); + } + + @Override + public List queryListByData(List queryDTOList) { + List resultList = Lists + .newArrayListWithCapacity(queryDTOList.size()); + if (CollectionUtils.isEmpty(queryDTOList)) { + return resultList; + } + List bankCardThreeVerifications = phoneThreeVerificationMapper + .findFinishStatusData(); + Map threeVerificationMap = bankCardThreeVerifications + .stream().collect( + Collectors.toMap(k -> k.getRealName() + k.getCardNo() + k.getPhone(), v -> v, (v1, v2) -> v1)); + + for (FactorVerificationQueryDTO queryDTO : queryDTOList) { + PhoneThreeFactorVerificationDTO PhoneThreeFactorVerificationDTO = threeVerificationMap + .get(queryDTO.getRealName() + queryDTO.getCardNo() + queryDTO.getPhone()); + if (PhoneThreeFactorVerificationDTO != null) { + resultList.add(PhoneThreeFactorVerificationDTO); + } + } + return resultList; + } + + @Override + public PhoneThreeFactorVerificationDTO findById(Long id) { + PhoneThreeFactorVerificationDTO threeFactorVerificationDTO = null; + PhoneThreeVerification entity = phoneThreeVerificationMapper.getById(id); + if (entity != null) { + threeFactorVerificationDTO = PhoneThreeVerificationMapMapper.INSTANCE.exchange(entity); + } + return threeFactorVerificationDTO; + } + + @Override + PhoneThreeFactorVerificationDTO realVerification( + PhoneThreeFactorVerificationDTO verificationDTO) { + Integer authenticationSource = verificationDTO.getAuthenticationSource(); + SOURCE_SERVICE_MAP.get(authenticationSource).phoneThreeVerify(verificationDTO); + //更新状态 + PhoneThreeVerification entity = PhoneThreeVerificationMapMapper.INSTANCE.exchange(verificationDTO); + phoneThreeVerificationMapper.updateEntitySelective(entity, UserContextHolder.getLoginUserId()); + return verificationDTO; + } + + @Override + public VerificationTypeEnum getType() { + return VerificationTypeEnum.PHONE_THREE; + } +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/factor/RealNameTwoVerify.java b/src/main/java/com/newyetai/alitaforward/verification/factor/RealNameTwoVerify.java new file mode 100644 index 0000000..d0fc698 --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/factor/RealNameTwoVerify.java @@ -0,0 +1,165 @@ +package com.newyetai.alitaforward.verification.factor; + +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.StringJoiner; +import java.util.stream.Collectors; + +import javax.annotation.Resource; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; + +import com.google.common.collect.Lists; +import com.newyetai.alitaforward.verification.constants.FactorVerificationSourceTypeEnum; +import com.newyetai.alitaforward.verification.constants.VerificationTypeEnum; +import com.newyetai.alitaforward.verification.dto.FactorVerificationQueryDTO; +import com.newyetai.alitaforward.verification.dto.RealNameTwoFactorVerificationDTO; +import com.newyetai.alitaforward.verification.factor.two.convert.RealNameTwoVerificationConvert; +import com.newyetai.alitaforward.verification.factor.two.dao.RealNameTwoVerificationMapper; +import com.newyetai.alitaforward.verification.factor.two.entity.RealNameTwoVerification; +import com.newyetai.common.constant.AuthStatusEnum; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.common.validation.util.ValidateUtils; +import com.newyetai.frame.redis.aop.annotation.AutoUnLock; +import com.newyetai.frame.redis.dto.LockDTO; +import com.newyetai.frame.redis.redisson.RedissonUtils; +import com.newyetai.mq.util.MqSendUtils; + +import cn.hutool.json.JSONUtil; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Component +public class RealNameTwoVerify extends AbstractVerify implements IQueryVerify { + + @Resource + private RealNameTwoVerificationMapper realNameTwoVerificationMapper; + + @Override + protected RealNameTwoFactorVerificationDTO syncBeforeVerify(RealNameTwoFactorVerificationDTO verificationDTO) { + StringJoiner stringJoiner = new StringJoiner("、"); + if (!ValidateUtils.checkRealName(verificationDTO.getRealName())) { + stringJoiner.add("姓名格式有误"); + } + if (!ValidateUtils.isIdCard(verificationDTO.getCardNo())) { + stringJoiner.add("证件号格式有误"); + } + String failReason = stringJoiner.toString(); + if (StringUtils.isNotBlank(failReason)) { + verificationDTO.setFailReason(failReason); + } else { + //校验成功调用 + super.syncBeforeVerify(verificationDTO); + } + return verificationDTO; + } + + @Override + RealNameTwoFactorVerificationDTO createAndGet(RealNameTwoFactorVerificationDTO verificationDTO) { + RealNameTwoVerification entity = realNameTwoVerificationMapper.selectInfo(verificationDTO); + if (entity == null) { + //认证库不存在,以默认状态入库——"未认证" + verificationDTO.setStatus(AuthStatusEnum.NOT_AUTH.getType()); + entity = RealNameTwoVerificationConvert.INSTANCE.convert(verificationDTO); + realNameTwoVerificationMapper.saveEntity(entity); + } + return RealNameTwoVerificationConvert.INSTANCE.convertDTO(entity); + } + + @Override + LockDTO getLock(RealNameTwoFactorVerificationDTO verificationDTO) { + return LockDTO.builder() + .methodName("verify:real_name:two") + .tryLockWaitTime(0L) + .arg(verificationDTO.getRealName()) + .arg(verificationDTO.getCardNo()) + .build(); + } + + @Override + @AutoUnLock + public void autoVerify(RealNameTwoFactorVerificationDTO verificationDTO) { + //拿锁 + LockDTO lockDTO = getLock(verificationDTO); + Assert.isTrue(RedissonUtils.tryLockAutomatically(lockDTO), "请勿重复校验二要素"); + + RealNameTwoVerification realNameTwoVerification = realNameTwoVerificationMapper.selectInfo(verificationDTO); + + if (Objects.nonNull(realNameTwoVerification)) { + if (!AuthStatusEnum.NOT_AUTH.getType().equals(realNameTwoVerification.getStatus())) { + return; + } + realNameTwoVerification.setAuthenticationSource(FactorVerificationSourceTypeEnum.SYS.getType()); + realNameTwoVerification.setStatus(verificationDTO.getStatus()); + realNameTwoVerificationMapper.updateEntitySelective(realNameTwoVerification, + UserContextHolder.getLoginUserId()); + } else { + realNameTwoVerification = + RealNameTwoVerification.builder() + .realName(verificationDTO.getRealName()) + .cardNo(verificationDTO.getCardNo()) + .authenticationSource(FactorVerificationSourceTypeEnum.SYS.getType()) + .status(verificationDTO.getStatus()) + .build(); + realNameTwoVerificationMapper.saveEntity(realNameTwoVerification); + } + log.info("【MQ】通知认证状态变更,参数:{}", JSONUtil.toJsonStr(verificationDTO)); + MqSendUtils.send(statusChangeRoutingKey(), verificationDTO); + } + + @Override + public List list(FactorVerificationQueryDTO queryDTO) { + return realNameTwoVerificationMapper.list(queryDTO); + } + + @Override + public List queryListByData(List queryDTOList) { + List resultList = Lists + .newArrayListWithCapacity(queryDTOList.size()); + if (CollectionUtils.isEmpty(queryDTOList)) { + return resultList; + } + List bankCardThreeVerifications = realNameTwoVerificationMapper + .findFinishStatusData(); + Map threeVerificationMap = bankCardThreeVerifications + .stream().collect( + Collectors.toMap(k -> k.getRealName() + k.getCardNo(), v -> v, (v1, v2) -> v1)); + + for (FactorVerificationQueryDTO queryDTO : queryDTOList) { + RealNameTwoFactorVerificationDTO RealNameTwoFactorVerificationDTO = threeVerificationMap + .get(queryDTO.getRealName() + queryDTO.getCardNo()); + if (RealNameTwoFactorVerificationDTO != null) { + resultList.add(RealNameTwoFactorVerificationDTO); + } + } + return resultList; + } + + @Override + public RealNameTwoFactorVerificationDTO findById(Long id) { + RealNameTwoFactorVerificationDTO threeFactorVerificationDTO = null; + RealNameTwoVerification entity = realNameTwoVerificationMapper.getById(id); + if (entity != null) { + threeFactorVerificationDTO = RealNameTwoVerificationConvert.INSTANCE.convertDTO(entity); + } + return threeFactorVerificationDTO; + } + + @Override + RealNameTwoFactorVerificationDTO realVerification(RealNameTwoFactorVerificationDTO verificationDTO) { + Integer authenticationSource = verificationDTO.getAuthenticationSource(); + SOURCE_SERVICE_MAP.get(authenticationSource).twoVerify(verificationDTO); + RealNameTwoVerification entity = RealNameTwoVerificationConvert.INSTANCE.convert(verificationDTO); + realNameTwoVerificationMapper.updateEntitySelective(entity, UserContextHolder.getLoginUserId()); + return verificationDTO; + } + + @Override + public VerificationTypeEnum getType() { + return VerificationTypeEnum.TWO; + } +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/factor/ThreeVerify.java b/src/main/java/com/newyetai/alitaforward/verification/factor/ThreeVerify.java new file mode 100644 index 0000000..8308043 --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/factor/ThreeVerify.java @@ -0,0 +1,171 @@ +package com.newyetai.alitaforward.verification.factor; + +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.StringJoiner; +import java.util.stream.Collectors; + +import javax.annotation.Resource; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; + +import com.google.common.collect.Lists; +import com.newyetai.alitaforward.verification.constants.FactorVerificationSourceTypeEnum; +import com.newyetai.alitaforward.verification.constants.VerificationTypeEnum; +import com.newyetai.alitaforward.verification.dto.FactorVerificationQueryDTO; +import com.newyetai.alitaforward.verification.dto.ThreeFactorVerificationDTO; +import com.newyetai.alitaforward.verification.factor.three.dao.ThreeVerificationMapper; +import com.newyetai.alitaforward.verification.factor.three.entity.BankCardThreeVerification; +import com.newyetai.alitaforward.verification.factor.three.mapstruct.ThreeVerificationMapMapper; +import com.newyetai.common.constant.AuthStatusEnum; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.common.validation.util.ValidateUtils; +import com.newyetai.frame.redis.aop.annotation.AutoUnLock; +import com.newyetai.frame.redis.dto.LockDTO; +import com.newyetai.frame.redis.redisson.RedissonUtils; +import com.newyetai.mq.util.MqSendUtils; + +import cn.hutool.json.JSONUtil; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Component +public class ThreeVerify extends AbstractVerify implements IQueryVerify { + + @Resource + private ThreeVerificationMapper threeVerificationMapper; + + @Override + protected ThreeFactorVerificationDTO syncBeforeVerify(ThreeFactorVerificationDTO verificationDTO) { + StringJoiner stringJoiner = new StringJoiner("、"); + if (!ValidateUtils.checkRealName(verificationDTO.getRealName())) { + stringJoiner.add("姓名格式有误"); + } + if (!ValidateUtils.isIdCard(verificationDTO.getCardNo())) { + stringJoiner.add("证件号格式有误"); + } + if (StringUtils.isBlank(verificationDTO.getBankAccountNo())) { + stringJoiner.add("银行卡号为空"); + } + String failReason = stringJoiner.toString(); + if (StringUtils.isNotBlank(failReason)) { + verificationDTO.setFailReason(failReason); + } else { + //校验成功调用 + super.syncBeforeVerify(verificationDTO); + } + return verificationDTO; + } + + @Override + ThreeFactorVerificationDTO createAndGet(ThreeFactorVerificationDTO verificationDTO) { + BankCardThreeVerification entity = threeVerificationMapper.find(verificationDTO); + if (entity == null) { + //认证库不存在,以默认状态入库——"未认证" + verificationDTO.setStatus(AuthStatusEnum.NOT_AUTH.getType()); + entity = ThreeVerificationMapMapper.INSTANCE.toEntity(verificationDTO); + threeVerificationMapper.saveEntity(entity); + } + return ThreeVerificationMapMapper.INSTANCE.toDto(entity); + } + + @Override + @AutoUnLock + public void autoVerify(ThreeFactorVerificationDTO verificationDTO) { + //拿锁 + LockDTO lockDTO = getLock(verificationDTO); + Assert.isTrue(RedissonUtils.tryLockAutomatically(lockDTO), "请勿重复校验三要素"); + + BankCardThreeVerification verificationEntity = threeVerificationMapper.find(verificationDTO); + + if (Objects.nonNull(verificationEntity)) { + if (!AuthStatusEnum.NOT_AUTH.getType().equals(verificationEntity.getStatus())) { + return; + } + verificationEntity.setAuthenticationSource(FactorVerificationSourceTypeEnum.SYS.getType()); + verificationEntity.setStatus(verificationDTO.getStatus()); + threeVerificationMapper.updateEntitySelective(verificationEntity, + UserContextHolder.getLoginUserId()); + } else { + verificationEntity = + BankCardThreeVerification.builder() + .realName(verificationDTO.getRealName()) + .cardNo(verificationDTO.getCardNo()) + .bankAccountNo(verificationDTO.getBankAccountNo()) + .authenticationSource(FactorVerificationSourceTypeEnum.SYS.getType()) + .status(verificationDTO.getStatus()) + .build(); + threeVerificationMapper.saveEntity(verificationEntity); + } + log.info("【MQ】通知认证状态变更,参数:{}", JSONUtil.toJsonStr(verificationDTO)); + MqSendUtils.send(statusChangeRoutingKey(), verificationDTO); + } + + @Override + LockDTO getLock(ThreeFactorVerificationDTO verificationDTO) { + return LockDTO.builder() + .methodName("verify:three") + .tryLockWaitTime(0L) + .arg(verificationDTO.getRealName()) + .arg(verificationDTO.getCardNo()) + .arg(verificationDTO.getBankAccountNo()) + .build(); + } + + @Override + public List list(FactorVerificationQueryDTO queryDTO) { + return threeVerificationMapper.list(queryDTO); + } + + @Override + public List queryListByData(List queryDTOList) { + List resultList = Lists + .newArrayListWithCapacity(queryDTOList.size()); + if (CollectionUtils.isEmpty(queryDTOList)) { + return resultList; + } + List bankCardThreeVerifications = threeVerificationMapper + .findFinishStatusData(); + Map threeVerificationMap = bankCardThreeVerifications + .stream().collect( + Collectors.toMap(k -> k.getRealName() + k.getCardNo() + k.getBankAccountNo(), v -> v, (v1, v2) -> v1)); + + for (FactorVerificationQueryDTO queryDTO : queryDTOList) { + ThreeFactorVerificationDTO threeFactorVerificationDTO = threeVerificationMap + .get(queryDTO.getRealName() + queryDTO.getCardNo() + queryDTO.getBankAccountNo()); + if (threeFactorVerificationDTO != null) { + resultList.add(threeFactorVerificationDTO); + } + } + return resultList; + } + + @Override + public ThreeFactorVerificationDTO findById(Long id) { + ThreeFactorVerificationDTO threeFactorVerificationDTO = null; + BankCardThreeVerification entity = threeVerificationMapper.getById(id); + if (entity != null) { + threeFactorVerificationDTO = ThreeVerificationMapMapper.INSTANCE.toDto(entity); + } + return threeFactorVerificationDTO; + } + @Override + ThreeFactorVerificationDTO realVerification(ThreeFactorVerificationDTO verificationDTO) { + Integer authenticationSource = verificationDTO.getAuthenticationSource(); + SOURCE_SERVICE_MAP.get(authenticationSource).threeVerify(verificationDTO); + //更新状态 + BankCardThreeVerification entity = ThreeVerificationMapMapper.INSTANCE + .toEntity(verificationDTO); + threeVerificationMapper.updateEntitySelective(entity, UserContextHolder.getLoginUserId()); + return verificationDTO; + } + + @Override + public VerificationTypeEnum getType() { + return VerificationTypeEnum.THREE; + } +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/factor/VerifyConfig.java b/src/main/java/com/newyetai/alitaforward/verification/factor/VerifyConfig.java new file mode 100644 index 0000000..92a929b --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/factor/VerifyConfig.java @@ -0,0 +1,18 @@ +package com.newyetai.alitaforward.verification.factor; + +import com.newyetai.alitaforward.verification.source.FactorVerificationSourceService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; + +import java.util.List; + +@Configuration +public class VerifyConfig { + + @Autowired + private void autowiredFactorVerificationSourceService(List sourceServices) { + for (FactorVerificationSourceService sourceService : sourceServices) { + AbstractVerify.SOURCE_SERVICE_MAP.put(sourceService.getSourceType().getType(), sourceService); + } + } +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/factor/four/dao/FourVerificationMapper.java b/src/main/java/com/newyetai/alitaforward/verification/factor/four/dao/FourVerificationMapper.java new file mode 100644 index 0000000..c5ecf4c --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/factor/four/dao/FourVerificationMapper.java @@ -0,0 +1,30 @@ +package com.newyetai.alitaforward.verification.factor.four.dao; + +import com.newyetai.alitaforward.verification.dto.FactorVerificationQueryDTO; +import com.newyetai.alitaforward.verification.dto.FourFactorVerificationDTO; +import com.newyetai.alitaforward.verification.dto.ThreeFactorVerificationDTO; +import com.newyetai.alitaforward.verification.factor.four.entity.BankCardFourVerification; +import com.newyetai.tkmybatis.mybatis.MyMapper; +import java.util.List; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +/** + * @author czy + * @date 2021-06-17 + */ +public interface FourVerificationMapper extends MyMapper { + + /** + * 根据四要素查询数据 + * @param params + * @return + */ + BankCardFourVerification selectInfo(@Param("params") FourFactorVerificationDTO params); + + @Select("select * from bank_card_four_verification where deleted = false and status in (2,3)") + List findFinishStatusData(); + + List list(@Param("params") FactorVerificationQueryDTO factorVerificationQueryDTO); + +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/factor/four/entity/BankCardFourVerification.java b/src/main/java/com/newyetai/alitaforward/verification/factor/four/entity/BankCardFourVerification.java new file mode 100644 index 0000000..5e142b7 --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/factor/four/entity/BankCardFourVerification.java @@ -0,0 +1,51 @@ +package com.newyetai.alitaforward.verification.factor.four.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author czy + * @date 2021-06-17 + */ + +@ApiModel("四要素认证库") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@EqualsAndHashCode(callSuper = true) +@TableName("bank_card_four_verification") +public class BankCardFourVerification extends BaseEntity { + + @ApiModelProperty("姓名") + private String realName; + + @ApiModelProperty("证件号") + private String cardNo; + + @ApiModelProperty("银行卡号") + private String bankAccountNo; + + @ApiModelProperty("手机号") + private String phone; + + @ApiModelProperty("认证状态(1-未认证 2-认证中 3-认证成功 4-认证失败)") + private Integer status; + + @ApiModelProperty("认证来源") + private Integer authenticationSource; + + @ApiModelProperty("调用数据") + private String invokeData; + + @ApiModelProperty("失败原因") + private String failReason; + +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/factor/four/mapper/BankCardFourVerificationMapper.xml b/src/main/java/com/newyetai/alitaforward/verification/factor/four/mapper/BankCardFourVerificationMapper.xml new file mode 100644 index 0000000..2578fd0 --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/factor/four/mapper/BankCardFourVerificationMapper.xml @@ -0,0 +1,44 @@ + + + + + + + + diff --git a/src/main/java/com/newyetai/alitaforward/verification/factor/four/mapstruct/FourVerificationMapMapper.java b/src/main/java/com/newyetai/alitaforward/verification/factor/four/mapstruct/FourVerificationMapMapper.java new file mode 100644 index 0000000..760fbb8 --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/factor/four/mapstruct/FourVerificationMapMapper.java @@ -0,0 +1,62 @@ +package com.newyetai.alitaforward.verification.factor.four.mapstruct; + +import com.newyetai.alitaforward.verification.dto.FourFactorVerificationDTO; +import com.newyetai.alitaforward.verification.factor.four.entity.BankCardFourVerification; +import com.newyetai.sdk.fangxinqian.dto.BankCardFourRequestDTO; +import com.newyetai.sdk.fangxinqian.dto.BankCardThreeRequestDTO; +import java.util.List; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; + +/** + * @author czy + * @date 2021-06-17 + */ +@Mapper +public interface FourVerificationMapMapper { + + FourVerificationMapMapper INSTANCE = Mappers.getMapper( + FourVerificationMapMapper.class); + + /** + * dto to entity + * + * @param fourVerificationDTO + * @return + * @author czy on 2021-06-17 + */ + BankCardFourVerification toEntity( + FourFactorVerificationDTO fourVerificationDTO); + + /** + * dtoList to entityList + * + * @param threeVerificationDTOList + * @return + * @author czy on 2021-06-17 + */ + List toEntityList( + List threeVerificationDTOList); + + /** + * entity to dto + * + * @param threeVerification + * @return + * @author czy on 2021-06-17 + */ + FourFactorVerificationDTO toDto( + BankCardFourVerification threeVerification); + + /** + * entityList to dtoList + * + * @param fourVerificationEntityList + * @return + * @author czy on 2021-06-17 + */ + List toDtoList( + List fourVerificationEntityList); + +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/factor/phoneThree/dao/PhoneThreeVerificationMapper.java b/src/main/java/com/newyetai/alitaforward/verification/factor/phoneThree/dao/PhoneThreeVerificationMapper.java new file mode 100644 index 0000000..7f29d70 --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/factor/phoneThree/dao/PhoneThreeVerificationMapper.java @@ -0,0 +1,30 @@ +package com.newyetai.alitaforward.verification.factor.phoneThree.dao; + +import com.newyetai.alitaforward.verification.dto.FactorVerificationQueryDTO; +import com.newyetai.alitaforward.verification.dto.PhoneThreeFactorVerificationDTO; +import com.newyetai.alitaforward.verification.factor.phoneThree.entity.PhoneThreeVerification; +import com.newyetai.tkmybatis.mybatis.MyMapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** + * @author czy + * @date 2021-06-17 + */ +public interface PhoneThreeVerificationMapper extends MyMapper { + + /** + * 根据三要素查询数据 + * @param params + * @return + */ + PhoneThreeVerification find(@Param("params") PhoneThreeFactorVerificationDTO params); + + @Select("select * from phone_three_verification where deleted = false") + List findFinishStatusData(); + + List list(@Param("params") FactorVerificationQueryDTO factorVerificationQueryDTO); + +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/factor/phoneThree/entity/PhoneThreeVerification.java b/src/main/java/com/newyetai/alitaforward/verification/factor/phoneThree/entity/PhoneThreeVerification.java new file mode 100644 index 0000000..d6be3a8 --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/factor/phoneThree/entity/PhoneThreeVerification.java @@ -0,0 +1,42 @@ +package com.newyetai.alitaforward.verification.factor.phoneThree.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +/** + * @author czy + * @date 2021-06-17 + */ + +@ApiModel("手机号三要素认证库") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@EqualsAndHashCode(callSuper = true) +@TableName("phone_three_verification") +public class PhoneThreeVerification extends BaseEntity { + + private static final long serialVersionUID = 1033289792676234200L; + @ApiModelProperty("姓名") + private String realName; + + @ApiModelProperty("证件号") + private String cardNo; + + @ApiModelProperty("银行卡号") + private String phone; + + @ApiModelProperty("认证状态(1-未认证 2-认证中 3-认证成功 4-认证失败)") + private Integer status; + + @ApiModelProperty("认证来源") + private Integer authenticationSource; + + @ApiModelProperty("失败原因") + private String failReason; + +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/factor/phoneThree/mapper/PhoneThreeVerificationMapper.xml b/src/main/java/com/newyetai/alitaforward/verification/factor/phoneThree/mapper/PhoneThreeVerificationMapper.xml new file mode 100644 index 0000000..ee0e2ee --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/factor/phoneThree/mapper/PhoneThreeVerificationMapper.xml @@ -0,0 +1,44 @@ + + + + + + + + + diff --git a/src/main/java/com/newyetai/alitaforward/verification/factor/phoneThree/mapstruct/PhoneThreeVerificationMapMapper.java b/src/main/java/com/newyetai/alitaforward/verification/factor/phoneThree/mapstruct/PhoneThreeVerificationMapMapper.java new file mode 100644 index 0000000..5267e84 --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/factor/phoneThree/mapstruct/PhoneThreeVerificationMapMapper.java @@ -0,0 +1,21 @@ +package com.newyetai.alitaforward.verification.factor.phoneThree.mapstruct; + +import com.newyetai.alitaforward.verification.dto.PhoneThreeFactorVerificationDTO; +import com.newyetai.alitaforward.verification.factor.phoneThree.entity.PhoneThreeVerification; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * @author czy + * @date 2021-06-17 + */ +@Mapper +public interface PhoneThreeVerificationMapMapper { + + PhoneThreeVerificationMapMapper INSTANCE = Mappers.getMapper( + PhoneThreeVerificationMapMapper.class); + + PhoneThreeFactorVerificationDTO exchange(PhoneThreeVerification verification); + + PhoneThreeVerification exchange(PhoneThreeFactorVerificationDTO verificationDTO); +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/factor/three/dao/ThreeVerificationMapper.java b/src/main/java/com/newyetai/alitaforward/verification/factor/three/dao/ThreeVerificationMapper.java new file mode 100644 index 0000000..2556718 --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/factor/three/dao/ThreeVerificationMapper.java @@ -0,0 +1,29 @@ +package com.newyetai.alitaforward.verification.factor.three.dao; + +import com.newyetai.alitaforward.verification.dto.FactorVerificationQueryDTO; +import com.newyetai.alitaforward.verification.dto.ThreeFactorVerificationDTO; +import com.newyetai.alitaforward.verification.factor.three.entity.BankCardThreeVerification; +import com.newyetai.tkmybatis.mybatis.MyMapper; +import java.util.List; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +/** + * @author czy + * @date 2021-06-17 + */ +public interface ThreeVerificationMapper extends MyMapper { + + /** + * 根据三要素查询数据 + * @param params + * @return + */ + BankCardThreeVerification find(@Param("params") ThreeFactorVerificationDTO params); + + @Select("select * from bank_card_three_verification where deleted = false") + List findFinishStatusData(); + + List list(@Param("params") FactorVerificationQueryDTO factorVerificationQueryDTO); + +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/factor/three/entity/BankCardThreeVerification.java b/src/main/java/com/newyetai/alitaforward/verification/factor/three/entity/BankCardThreeVerification.java new file mode 100644 index 0000000..d48103a --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/factor/three/entity/BankCardThreeVerification.java @@ -0,0 +1,45 @@ +package com.newyetai.alitaforward.verification.factor.three.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +/** + * @author czy + * @date 2021-06-17 + */ + +@ApiModel("三要素认证库") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@EqualsAndHashCode(callSuper = true) +@TableName("bank_card_three_verification") +public class BankCardThreeVerification extends BaseEntity { + + private static final long serialVersionUID = 1178897458908696195L; + @ApiModelProperty("姓名") + private String realName; + + @ApiModelProperty("证件号") + private String cardNo; + + @ApiModelProperty("银行卡号") + private String bankAccountNo; + + @ApiModelProperty("认证状态(1-未认证 2-认证中 3-认证成功 4-认证失败)") + private Integer status; + + @ApiModelProperty("认证来源") + private Integer authenticationSource; + + @ApiModelProperty("调用数据") + private String invokeData; + + @ApiModelProperty("失败原因") + private String failReason; + +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/factor/three/mapper/BankCardThreeVerificationMapper.xml b/src/main/java/com/newyetai/alitaforward/verification/factor/three/mapper/BankCardThreeVerificationMapper.xml new file mode 100644 index 0000000..1b0da1f --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/factor/three/mapper/BankCardThreeVerificationMapper.xml @@ -0,0 +1,50 @@ + + + + + + + + + diff --git a/src/main/java/com/newyetai/alitaforward/verification/factor/three/mapstruct/ThreeVerificationMapMapper.java b/src/main/java/com/newyetai/alitaforward/verification/factor/three/mapstruct/ThreeVerificationMapMapper.java new file mode 100644 index 0000000..6cc6418 --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/factor/three/mapstruct/ThreeVerificationMapMapper.java @@ -0,0 +1,60 @@ +package com.newyetai.alitaforward.verification.factor.three.mapstruct; + +import com.newyetai.alitaforward.verification.dto.ThreeFactorVerificationDTO; +import com.newyetai.alitaforward.verification.factor.three.entity.BankCardThreeVerification; +import java.util.List; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * @author czy + * @date 2021-06-17 + */ +@Mapper +public interface ThreeVerificationMapMapper { + + ThreeVerificationMapMapper INSTANCE = Mappers.getMapper( + ThreeVerificationMapMapper.class); + + /** + * dto to entity + * + * @param threeVerificationDTO + * @return + * @author czy on 2021-06-17 + */ + BankCardThreeVerification toEntity( + ThreeFactorVerificationDTO threeVerificationDTO); + + /** + * dtoList to entityList + * + * @param threeVerificationDTOList + * @return + * @author czy on 2021-06-17 + */ + List toEntityList( + List threeVerificationDTOList); + + /** + * entity to dto + * + * @param threeVerification + * @return + * @author czy on 2021-06-17 + */ + ThreeFactorVerificationDTO toDto( + BankCardThreeVerification threeVerification); + + /** + * entityList to dtoList + * + * @param threeVerificationEntityList + * @return + * @author czy on 2021-06-17 + */ + List toDtoList( + List threeVerificationEntityList); + + +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/factor/two/convert/RealNameTwoVerificationConvert.java b/src/main/java/com/newyetai/alitaforward/verification/factor/two/convert/RealNameTwoVerificationConvert.java new file mode 100644 index 0000000..3b192e2 --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/factor/two/convert/RealNameTwoVerificationConvert.java @@ -0,0 +1,28 @@ +package com.newyetai.alitaforward.verification.factor.two.convert; + +import com.newyetai.alitaforward.verification.dto.RealNameTwoFactorVerificationDTO; +import com.newyetai.alitaforward.verification.factor.two.dto.RealNameTwoVerificationDTO; +import com.newyetai.alitaforward.verification.factor.two.dto.RealNameTwoVerificationOperatorDTO; +import com.newyetai.alitaforward.verification.factor.two.entity.RealNameTwoVerification; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * 二要素认证表 + * + * @author chenyun chenyun.home@outlook.com + * @since 1.0.0 2022-07-22 + */ +@Mapper +public interface RealNameTwoVerificationConvert { + RealNameTwoVerificationConvert INSTANCE = Mappers.getMapper(RealNameTwoVerificationConvert.class); + + RealNameTwoVerification convert(RealNameTwoVerificationDTO dto); + + RealNameTwoVerificationDTO convert(RealNameTwoVerification entity); + RealNameTwoFactorVerificationDTO convertDTO(RealNameTwoVerification entity); + + RealNameTwoVerification convert(RealNameTwoVerificationOperatorDTO dto); + + RealNameTwoVerification convert(RealNameTwoFactorVerificationDTO dto); +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/factor/two/dao/RealNameTwoVerificationMapper.java b/src/main/java/com/newyetai/alitaforward/verification/factor/two/dao/RealNameTwoVerificationMapper.java new file mode 100644 index 0000000..6606b00 --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/factor/two/dao/RealNameTwoVerificationMapper.java @@ -0,0 +1,39 @@ +package com.newyetai.alitaforward.verification.factor.two.dao; + +import com.newyetai.alitaforward.verification.dto.FactorVerificationQueryDTO; +import com.newyetai.alitaforward.verification.dto.RealNameTwoFactorVerificationDTO; +import com.newyetai.alitaforward.verification.factor.two.dto.RealNameTwoVerificationDTO; +import com.newyetai.alitaforward.verification.factor.two.dto.RealNameTwoVerificationPageQueryDTO; +import com.newyetai.alitaforward.verification.factor.two.entity.RealNameTwoVerification; +import com.newyetai.tkmybatis.mybatis.MyMapper; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** + * 二要素认证表 + * + * @author chenyun chenyun.home@outlook.com + * @since 1.0.0 2022-07-22 + */ +@Mapper +public interface RealNameTwoVerificationMapper extends MyMapper { + + /** + * 根据二要素查询数据 + * + * @param params + * @return + */ + RealNameTwoVerification selectInfo(@Param("param") RealNameTwoFactorVerificationDTO params); + + List page( + @Param("param") RealNameTwoVerificationPageQueryDTO queryDTO); + + List list(@Param("param") FactorVerificationQueryDTO queryDTO); + + @Select("select * from real_name_two_verification where deleted = false") + List findFinishStatusData(); +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/factor/two/dto/RealNameTwoVerificationDTO.java b/src/main/java/com/newyetai/alitaforward/verification/factor/two/dto/RealNameTwoVerificationDTO.java new file mode 100644 index 0000000..27e39d4 --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/factor/two/dto/RealNameTwoVerificationDTO.java @@ -0,0 +1,41 @@ +package com.newyetai.alitaforward.verification.factor.two.dto; + +import com.newyetai.common.dto.BaseDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.SuperBuilder; + +/** + * 二要素认证表 + * + * @author chenyun chenyun.home@outlook.com + * @since 1.0.0 2022-07-22 + */ +@ApiModel("二要素认证表") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class RealNameTwoVerificationDTO extends BaseDTO { + private static final long serialVersionUID = 1L; + + @ApiModelProperty("姓名") + private String realName; + + @ApiModelProperty("证件号") + private String cardNo; + + @ApiModelProperty("状态(1待认证 2认证中 3认证成功 4认证失败)") + private Integer status; + + @ApiModelProperty("认证来源(1放心签、2创蓝 3系统)") + private Integer authenticationSource; + + @ApiModelProperty("调用数据") + private String invokeData; + + @ApiModelProperty("失败原因") + private String failReason; +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/factor/two/dto/RealNameTwoVerificationOperatorDTO.java b/src/main/java/com/newyetai/alitaforward/verification/factor/two/dto/RealNameTwoVerificationOperatorDTO.java new file mode 100644 index 0000000..9d708d4 --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/factor/two/dto/RealNameTwoVerificationOperatorDTO.java @@ -0,0 +1,45 @@ +package com.newyetai.alitaforward.verification.factor.two.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 chenyun chenyun.home@outlook.com + * @since 1.0.0 2022-07-22 + */ +@ApiModel("二要素认证表") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class RealNameTwoVerificationOperatorDTO implements Serializable { + private static final long serialVersionUID = 1L; + + private Long id; + + @ApiModelProperty("姓名") + private String realName; + + @ApiModelProperty("证件号") + private String cardNo; + + @ApiModelProperty("状态(1待认证 2认证中 3认证成功 4认证失败)") + private Integer status; + + @ApiModelProperty("认证来源(1放心签、2创蓝 3系统)") + private Integer authenticationSource; + + @ApiModelProperty("调用数据") + private String invokeData; + + @ApiModelProperty("失败原因") + private String failReason; +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/factor/two/dto/RealNameTwoVerificationPageQueryDTO.java b/src/main/java/com/newyetai/alitaforward/verification/factor/two/dto/RealNameTwoVerificationPageQueryDTO.java new file mode 100644 index 0000000..0b59e8c --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/factor/two/dto/RealNameTwoVerificationPageQueryDTO.java @@ -0,0 +1,67 @@ +package com.newyetai.alitaforward.verification.factor.two.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.newyetai.common.dto.PageQueryDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +/** + * 二要素认证表 + * + * @author chenyun chenyun.home@outlook.com + * @since 1.0.0 2022-07-22 + */ +@ApiModel("二要素认证表") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class RealNameTwoVerificationPageQueryDTO extends PageQueryDTO { + private static final long serialVersionUID = 1L; + + @ApiModelProperty("ID") + private Long id; + + @ApiModelProperty("姓名 (模糊匹配)") + private String realNameLike; + + @ApiModelProperty("证件号") + private String cardNo; + + @ApiModelProperty("状态(1待认证 2认证中 3认证成功 4认证失败)") + private Integer status; + + @ApiModelProperty("认证来源(1放心签、2创蓝 3系统)") + private Integer authenticationSource; + + @ApiModelProperty("调用数据") + private String invokeData; + + @ApiModelProperty("失败原因") + private String failReason; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("更新时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeStart; + + @ApiModelProperty("更新时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeEnd; +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/factor/two/dto/RealNameTwoVerificationQueryDTO.java b/src/main/java/com/newyetai/alitaforward/verification/factor/two/dto/RealNameTwoVerificationQueryDTO.java new file mode 100644 index 0000000..f576c59 --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/factor/two/dto/RealNameTwoVerificationQueryDTO.java @@ -0,0 +1,69 @@ +package com.newyetai.alitaforward.verification.factor.two.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.format.annotation.DateTimeFormat; + +import java.io.Serializable; +import java.util.Date; + +/** + * 二要素认证表 + * + * @author chenyun chenyun.home@outlook.com + * @since 1.0.0 2022-07-22 + */ +@ApiModel("二要素认证表") +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class RealNameTwoVerificationQueryDTO implements Serializable { + private static final long serialVersionUID = 1L; + + @ApiModelProperty("ID") + private Long id; + + @ApiModelProperty("姓名 (模糊匹配)") + private String realNameLike; + + @ApiModelProperty("证件号") + private String cardNo; + + @ApiModelProperty("状态(1待认证 2认证中 3认证成功 4认证失败)") + private Integer status; + + @ApiModelProperty("认证来源(1放心签、2创蓝 3系统)") + private Integer authenticationSource; + + @ApiModelProperty("调用数据") + private String invokeData; + + @ApiModelProperty("失败原因") + private String failReason; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("更新时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeStart; + + @ApiModelProperty("更新时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeEnd; +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/factor/two/entity/RealNameTwoVerification.java b/src/main/java/com/newyetai/alitaforward/verification/factor/two/entity/RealNameTwoVerification.java new file mode 100644 index 0000000..5802ab9 --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/factor/two/entity/RealNameTwoVerification.java @@ -0,0 +1,40 @@ +package com.newyetai.alitaforward.verification.factor.two.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * 二要素认证表 + * + * @author chenyun chenyun.home@outlook.com + * @since 1.0.0 2022-07-22 + */ +@TableName("real_name_two_verification") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class RealNameTwoVerification extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** 姓名 */ + private String realName; + /** 证件号 */ + private String cardNo; + /** 状态(1待认证 2认证中 3认证成功 4认证失败) */ + private Integer status; + /** 认证来源(1放心签、2创蓝 3系统) */ + private Integer authenticationSource; + /** 调用数据 */ + private String invokeData; + /** 失败原因 */ + private String failReason; +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/factor/two/mapper/RealNameTwoVerificationMapper.xml b/src/main/java/com/newyetai/alitaforward/verification/factor/two/mapper/RealNameTwoVerificationMapper.xml new file mode 100644 index 0000000..b6cb07e --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/factor/two/mapper/RealNameTwoVerificationMapper.xml @@ -0,0 +1,81 @@ + + + + + + + + + + + + FROM + real_name_two_verification t + WHERE t.deleted = 0 + + AND t.id = #{param.id} + + + + AND t.real_name like #{realNameLike} + + + AND t.card_no = #{param.cardNo} + + + AND t.status = #{param.status} + + + AND t.authentication_source = #{param.authenticationSource} + + + AND t.invoke_data = #{param.invokeData} + + + AND t.fail_reason = #{param.failReason} + + + AND t.create_time >= #{param.createTimeStart} + + + AND t.create_time <= #{param.createTimeEnd} + + + AND t.update_time >= #{param.updateTimeStart} + + + AND t.update_time <= #{param.updateTimeEnd} + + ORDER BY t.id DESC + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/alitaforward/verification/service/BankCardVerificationService.java b/src/main/java/com/newyetai/alitaforward/verification/service/BankCardVerificationService.java new file mode 100644 index 0000000..d01bfc8 --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/service/BankCardVerificationService.java @@ -0,0 +1,14 @@ +package com.newyetai.alitaforward.verification.service; + +import com.newyetai.alitaforward.verification.dto.BankCordVerificationResDTO; + +import java.util.List; + +public interface BankCardVerificationService { + + /** + * 白名单管理-->三、四要素查询合并为银行卡查询 + * @param cardNo + */ + List list(String cardNo,Integer status); +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/service/FourFactorVerificationProvider.java b/src/main/java/com/newyetai/alitaforward/verification/service/FourFactorVerificationProvider.java new file mode 100644 index 0000000..612be2e --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/service/FourFactorVerificationProvider.java @@ -0,0 +1,17 @@ +package com.newyetai.alitaforward.verification.service; + +import com.newyetai.alitaforward.verification.constants.VerificationTypeEnum; +import com.newyetai.alitaforward.verification.dto.FourFactorVerificationDTO; +import com.newyetai.mq.consumer.handler.ITopicMqHandler; + +/** + * @author czy + * @date 2021-06-22 + */ +public interface FourFactorVerificationProvider extends ITopicMqHandler { + + default String getRoutingKey(){ + return VerificationTypeEnum.FOUR.getStatusChangeKey(); + } + +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/service/PhoneThreeFactorVerificationProvider.java b/src/main/java/com/newyetai/alitaforward/verification/service/PhoneThreeFactorVerificationProvider.java new file mode 100644 index 0000000..69be352 --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/service/PhoneThreeFactorVerificationProvider.java @@ -0,0 +1,17 @@ +package com.newyetai.alitaforward.verification.service; + +import com.newyetai.alitaforward.verification.constants.VerificationTypeEnum; +import com.newyetai.alitaforward.verification.dto.PhoneThreeFactorVerificationDTO; +import com.newyetai.mq.consumer.handler.ITopicMqHandler; + +/** + * @author czy + * @date 2021-06-22 + */ +public interface PhoneThreeFactorVerificationProvider extends ITopicMqHandler { + + default String getRoutingKey(){ + return VerificationTypeEnum.PHONE_THREE.getStatusChangeKey(); + } + +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/service/RealNameTwoFactorVerificationProvider.java b/src/main/java/com/newyetai/alitaforward/verification/service/RealNameTwoFactorVerificationProvider.java new file mode 100644 index 0000000..324c65a --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/service/RealNameTwoFactorVerificationProvider.java @@ -0,0 +1,17 @@ +package com.newyetai.alitaforward.verification.service; + +import com.newyetai.alitaforward.verification.constants.VerificationTypeEnum; +import com.newyetai.alitaforward.verification.dto.RealNameTwoFactorVerificationDTO; +import com.newyetai.mq.consumer.handler.ITopicMqHandler; + +/** + * @author czy + * @date 2021-06-22 + */ +public interface RealNameTwoFactorVerificationProvider extends ITopicMqHandler { + + default String getRoutingKey(){ + return VerificationTypeEnum.TWO.getStatusChangeKey(); + } + +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/service/ThreeFactorVerificationProvider.java b/src/main/java/com/newyetai/alitaforward/verification/service/ThreeFactorVerificationProvider.java new file mode 100644 index 0000000..5d1a76c --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/service/ThreeFactorVerificationProvider.java @@ -0,0 +1,17 @@ +package com.newyetai.alitaforward.verification.service; + +import com.newyetai.alitaforward.verification.constants.VerificationTypeEnum; +import com.newyetai.alitaforward.verification.dto.ThreeFactorVerificationDTO; +import com.newyetai.mq.consumer.handler.ITopicMqHandler; + +/** + * @author czy + * @date 2021-06-22 + */ +public interface ThreeFactorVerificationProvider extends ITopicMqHandler { + + default String getRoutingKey(){ + return VerificationTypeEnum.THREE.getStatusChangeKey(); + } + +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/service/impl/BankCardVerificationServiceImpl.java b/src/main/java/com/newyetai/alitaforward/verification/service/impl/BankCardVerificationServiceImpl.java new file mode 100644 index 0000000..ddc75c7 --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/service/impl/BankCardVerificationServiceImpl.java @@ -0,0 +1,35 @@ +package com.newyetai.alitaforward.verification.service.impl; + +import com.newyetai.alitaforward.verification.dao.BankCardVerificationMapper; +import com.newyetai.alitaforward.verification.dto.BankCordVerificationResDTO; +import com.newyetai.alitaforward.verification.service.BankCardVerificationService; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.util.Assert; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + +@Service +public class BankCardVerificationServiceImpl implements BankCardVerificationService { + + @Autowired + BankCardVerificationMapper bankCardVerificationMapper; + /** + * 白名单管理-->三、四要素查询合并为银行卡查询 + * @param cardNo + */ + public List list(String cardNo,Integer status){ + if(StringUtils.isBlank(cardNo)){ + throw new BusinessException("身份证号不能为空"); + } + List bankCordVerificationResDTOList = bankCardVerificationMapper.list(cardNo); + if(status != null){ + return bankCordVerificationResDTOList.stream(). + filter(f -> f.getStatus() != null && f.getStatus() == status).collect(Collectors.toList()); + } + return bankCordVerificationResDTOList; + } +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/source/FactorVerificationSourceService.java b/src/main/java/com/newyetai/alitaforward/verification/source/FactorVerificationSourceService.java new file mode 100644 index 0000000..489fac2 --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/source/FactorVerificationSourceService.java @@ -0,0 +1,34 @@ +package com.newyetai.alitaforward.verification.source; + +import com.newyetai.alitaforward.verification.constants.FactorVerificationSourceTypeEnum; +import com.newyetai.alitaforward.verification.dto.FourFactorVerificationDTO; +import com.newyetai.alitaforward.verification.dto.PhoneThreeFactorVerificationDTO; +import com.newyetai.alitaforward.verification.dto.RealNameTwoFactorVerificationDTO; +import com.newyetai.alitaforward.verification.dto.ThreeFactorVerificationDTO; +import com.newyetai.common.exception.BusinessException; + +/** + * 要素认证源 - 顶层接口 + * + * @author cheny + * @date 2022/08/11 + */ +public interface FactorVerificationSourceService { + + FactorVerificationSourceTypeEnum getSourceType(); + + default RealNameTwoFactorVerificationDTO twoVerify(RealNameTwoFactorVerificationDTO verificationDTO) { + throw new BusinessException("二要素不支持的该认证源:" + getSourceType()); + } + default ThreeFactorVerificationDTO threeVerify(ThreeFactorVerificationDTO verificationDTO){ + throw new BusinessException("银行卡三要素不支持的该认证源:" + getSourceType()); + } + default PhoneThreeFactorVerificationDTO phoneThreeVerify(PhoneThreeFactorVerificationDTO verificationDTO){ + throw new BusinessException("手机号三要素不支持的该认证源:" + getSourceType()); + } + default FourFactorVerificationDTO fourVerify(FourFactorVerificationDTO verificationDTO){ + throw new BusinessException("银行卡四要素不支持的该认证源:" + getSourceType()); + } + + +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/source/cl/ClAuthenticateSourceServiceImpl.java b/src/main/java/com/newyetai/alitaforward/verification/source/cl/ClAuthenticateSourceServiceImpl.java new file mode 100644 index 0000000..f81c61b --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/source/cl/ClAuthenticateSourceServiceImpl.java @@ -0,0 +1,119 @@ +package com.newyetai.alitaforward.verification.source.cl; + +import java.util.Objects; +import java.util.Optional; + +import javax.annotation.Resource; + +import org.springframework.stereotype.Service; + +import com.newyetai.alitaforward.verification.constants.FactorVerificationSourceTypeEnum; +import com.newyetai.alitaforward.verification.dto.FactorVerificationDTO; +import com.newyetai.alitaforward.verification.dto.FourFactorVerificationDTO; +import com.newyetai.alitaforward.verification.dto.PhoneThreeFactorVerificationDTO; +import com.newyetai.alitaforward.verification.dto.RealNameTwoFactorVerificationDTO; +import com.newyetai.alitaforward.verification.dto.ThreeFactorVerificationDTO; +import com.newyetai.alitaforward.verification.source.FactorVerificationSourceService; +import com.newyetai.alitaforward.verification.source.cl.mapstruct.ClMapMapper; +import com.newyetai.common.AlitaResult; +import com.newyetai.common.constant.AuthStatusEnum; +import com.newyetai.sdk.chuanglan.dto.BankCardFourRequestDTO; +import com.newyetai.sdk.chuanglan.dto.BankCardThreeRequestDTO; +import com.newyetai.sdk.chuanglan.dto.ChuangLanResultDTO; +import com.newyetai.sdk.chuanglan.dto.PhoneThreeRequestDTO; +import com.newyetai.sdk.chuanglan.dto.RealNameTwoBaseRequestDTO; +import com.newyetai.sdk.chuanglan.service.ChuangLanService; +import com.newyetai.sdk.common.constant.SdkConstants; + +import cn.hutool.json.JSONUtil; +import lombok.extern.slf4j.Slf4j; + + +/** + * 创蓝认证源 + * + * @author cheny + * @date 2022/08/11 + */ +@Slf4j +@Service +@SuppressWarnings("unchecked") +public class ClAuthenticateSourceServiceImpl implements FactorVerificationSourceService { + + @Override + public RealNameTwoFactorVerificationDTO twoVerify(RealNameTwoFactorVerificationDTO verificationDTO) { + RealNameTwoBaseRequestDTO requestDTO = ClMapMapper.INSTANCE.toTwoRequestDTO(verificationDTO); + log.info("执行创蓝运营商二要素认证:{}", JSONUtil.toJsonStr(requestDTO)); + AlitaResult result = chuangLanService.checkRealNameTwoBase(requestDTO); + handlerResult(result, verificationDTO); + return verificationDTO; + } + + @Override + public PhoneThreeFactorVerificationDTO phoneThreeVerify(PhoneThreeFactorVerificationDTO verificationDTO) { + PhoneThreeRequestDTO phoneThreeRequestDTO = ClMapMapper.INSTANCE + .toPhoneThreeRequestDTO(verificationDTO); + log.info("执行创蓝运营商三要素认证:{}", JSONUtil.toJsonStr(phoneThreeRequestDTO)); + AlitaResult result = chuangLanService.checkPhoneThree(phoneThreeRequestDTO); + handlerResult(result, verificationDTO); + return verificationDTO; + } + + @Override + public ThreeFactorVerificationDTO threeVerify( + ThreeFactorVerificationDTO verificationDTO) { + BankCardThreeRequestDTO bankCardThreeRequestDTO = ClMapMapper.INSTANCE + .toThreeRequestDTO(verificationDTO); + log.info("执行创蓝三要素认证:{}", JSONUtil.toJsonStr(bankCardThreeRequestDTO)); + AlitaResult result = chuangLanService.checkBankCardThree(bankCardThreeRequestDTO); + handlerResult(result, verificationDTO); + return verificationDTO; + } + + @Override + public FourFactorVerificationDTO fourVerify( + FourFactorVerificationDTO verificationDTO) { + //调用放心签 + BankCardFourRequestDTO bankCardFourRequestDTO = ClMapMapper.INSTANCE + .toFourRequestDTO(verificationDTO); + log.info("执行创蓝四要素认证:{}", JSONUtil.toJsonStr(bankCardFourRequestDTO)); + AlitaResult result = chuangLanService.checkBankCardFour(bankCardFourRequestDTO); + handlerResult(result, verificationDTO); + + return verificationDTO; + } + + /** + * 处理结果 + * + * @param result 结果 + * @param verificationDTO 验证dto + */ + private void handlerResult(AlitaResult result, FactorVerificationDTO verificationDTO) { + verificationDTO.setInvokeData(Optional.ofNullable(result.getData()).map(ChuangLanResultDTO::getJsonData).orElse("")); + AuthStatusEnum targetStatus = null; + if (SdkConstants.SDK_INVOKE_NOT_REACH_CODE.equals(result.getCode())) { + // 接口调起失败,未拿到返回结果,视为未调起 + verificationDTO.setFailReason("调用异常,未调起第三方"); + } else { + if (Boolean.TRUE.equals(result.getSuccess()) && Boolean.TRUE.equals(result.getData().getStatus())) { + targetStatus = AuthStatusEnum.AUTH_SUCCESS; + } else { + targetStatus = AuthStatusEnum.AUTH_FAIL; + verificationDTO.setFailReason(result.getMsg()); + } + } + if (Objects.nonNull(targetStatus)) { + verificationDTO.setStatus(targetStatus.getType()); + } + } + + @Resource(name = ChuangLanService.BEAN_ID) + private ChuangLanService chuangLanService; + + + @Override + public FactorVerificationSourceTypeEnum getSourceType() { + return FactorVerificationSourceTypeEnum.CL; + } +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/source/cl/mapstruct/ClMapMapper.java b/src/main/java/com/newyetai/alitaforward/verification/source/cl/mapstruct/ClMapMapper.java new file mode 100644 index 0000000..377111f --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/source/cl/mapstruct/ClMapMapper.java @@ -0,0 +1,76 @@ +package com.newyetai.alitaforward.verification.source.cl.mapstruct; + +import com.newyetai.alitaforward.verification.dto.FourFactorVerificationDTO; +import com.newyetai.alitaforward.verification.dto.PhoneThreeFactorVerificationDTO; +import com.newyetai.alitaforward.verification.dto.RealNameTwoFactorVerificationDTO; +import com.newyetai.alitaforward.verification.dto.ThreeFactorVerificationDTO; +import com.newyetai.sdk.chuanglan.dto.BankCardFourRequestDTO; +import com.newyetai.sdk.chuanglan.dto.BankCardThreeRequestDTO; +import com.newyetai.sdk.chuanglan.dto.PhoneThreeRequestDTO; +import com.newyetai.sdk.chuanglan.dto.RealNameTwoBaseRequestDTO; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +/** + * @author czy + * @date 2021-06-23 + */ +@Mapper +public interface ClMapMapper { + + ClMapMapper INSTANCE = Mappers.getMapper(ClMapMapper.class); + + /** + * dto转创蓝三要素认证请求对象 + * + * @param dto 验证dto + * @return {@link RealNameTwoBaseRequestDTO} + */ + @Mappings(value = { + @Mapping(target = "name", source = "dto.realName"), + @Mapping(target = "idNum", source = "dto.cardNo") + }) + RealNameTwoBaseRequestDTO toTwoRequestDTO(RealNameTwoFactorVerificationDTO dto); + + /** + * dto转创蓝三要素认证请求对象 + * + * @param dto + * @return {@link BankCardThreeRequestDTO} + */ + @Mappings(value = { + @Mapping(target = "name", source = "dto.realName"), + @Mapping(target = "idNum", source = "dto.cardNo"), + @Mapping(target = "cardNo", source = "dto.bankAccountNo") + }) + BankCardThreeRequestDTO toThreeRequestDTO(ThreeFactorVerificationDTO dto); + + /** + * dto转创蓝三要素认证请求对象 + * + * @param dto dto + * @return {@link PhoneThreeRequestDTO} + */ + @Mappings(value = { + @Mapping(target = "name", source = "dto.realName"), + @Mapping(target = "idNum", source = "dto.cardNo"), + @Mapping(target = "mobile", source = "dto.phone") + }) + PhoneThreeRequestDTO toPhoneThreeRequestDTO(PhoneThreeFactorVerificationDTO dto); + + /** + * dto转创蓝四要素认证请求对象 + * + * @param dto + * @return {@link BankCardFourRequestDTO} + */ + @Mappings(value = { + @Mapping(target = "name", source = "dto.realName"), + @Mapping(target = "idNum", source = "dto.cardNo"), + @Mapping(target = "cardNo", source = "dto.bankAccountNo"), + @Mapping(target = "mobile", source = "dto.phone") + }) + BankCardFourRequestDTO toFourRequestDTO(FourFactorVerificationDTO dto); +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/source/fxq/FxqAuthenticateSourceServiceImpl.java b/src/main/java/com/newyetai/alitaforward/verification/source/fxq/FxqAuthenticateSourceServiceImpl.java new file mode 100644 index 0000000..637106c --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/source/fxq/FxqAuthenticateSourceServiceImpl.java @@ -0,0 +1,88 @@ +package com.newyetai.alitaforward.verification.source.fxq; + +import java.util.Objects; + +import javax.annotation.Resource; + +import org.springframework.stereotype.Service; + +import com.newyetai.alitaforward.verification.constants.FactorVerificationSourceTypeEnum; +import com.newyetai.alitaforward.verification.dto.FactorVerificationDTO; +import com.newyetai.alitaforward.verification.dto.FourFactorVerificationDTO; +import com.newyetai.alitaforward.verification.dto.ThreeFactorVerificationDTO; +import com.newyetai.alitaforward.verification.source.FactorVerificationSourceService; +import com.newyetai.alitaforward.verification.source.fxq.mapstruct.FxqMapMapper; +import com.newyetai.common.AlitaResult; +import com.newyetai.common.constant.AuthStatusEnum; +import com.newyetai.sdk.common.constant.SdkConstants; +import com.newyetai.sdk.fangxinqian.dto.BankCardFourRequestDTO; +import com.newyetai.sdk.fangxinqian.dto.BankCardThreeRequestDTO; +import com.newyetai.sdk.fangxinqian.service.FangXinQianService; + +import cn.hutool.json.JSONUtil; +import lombok.extern.slf4j.Slf4j; + +/** + * @author czy + * @date 2021-06-21 + */ +@Slf4j +@Service +public class FxqAuthenticateSourceServiceImpl implements FactorVerificationSourceService { + + @Override + public ThreeFactorVerificationDTO threeVerify( + ThreeFactorVerificationDTO threeFactorVerificationDTO) { + BankCardThreeRequestDTO bankCardThreeRequestDto = + FxqMapMapper.INSTANCE.toThreeRequestDTO(threeFactorVerificationDTO); + log.info("执行放心签三要素认证:{}", JSONUtil.toJsonStr(bankCardThreeRequestDto)); + AlitaResult result = fangXinQianService.checkBankCardThree(bankCardThreeRequestDto); + handlerResult(result, threeFactorVerificationDTO); + return threeFactorVerificationDTO; + } + + @Override + public FourFactorVerificationDTO fourVerify( + FourFactorVerificationDTO fourFactorVerificationDTO) { + //调用放心签 + BankCardFourRequestDTO bankCardFourRequestDTO = FxqMapMapper.INSTANCE + .toFourRequestDTO(fourFactorVerificationDTO); + log.info("执行放心签四要素认证:{}", JSONUtil.toJsonStr(bankCardFourRequestDTO)); + AlitaResult result = fangXinQianService.checkBankCardFour(bankCardFourRequestDTO); + handlerResult(result, fourFactorVerificationDTO); + + return fourFactorVerificationDTO; + } + + /** + * 处理结果 + * + * @param result 结果 + * @param verificationDTO 验证dto + */ + private void handlerResult(AlitaResult result, FactorVerificationDTO verificationDTO) { + AuthStatusEnum targetStatus = null; + if (SdkConstants.SDK_INVOKE_NOT_REACH_CODE.equals(result.getCode())) { + // 接口调起失败,未拿到返回结果,视为未调起 + verificationDTO.setFailReason("调用异常,未调起第三方"); + } else { + if (Boolean.TRUE.equals(result.getSuccess()) && Boolean.TRUE.equals(result.getData())) { + targetStatus = AuthStatusEnum.AUTH_SUCCESS; + } else { + targetStatus = AuthStatusEnum.AUTH_FAIL; + verificationDTO.setFailReason(result.getMsg()); + } + } + if (Objects.nonNull(targetStatus)) { + verificationDTO.setStatus(targetStatus.getType()); + } + } + + @Resource(name = FangXinQianService.BEAN_ID) + private FangXinQianService fangXinQianService; + + @Override + public FactorVerificationSourceTypeEnum getSourceType() { + return FactorVerificationSourceTypeEnum.FXQ; + } +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/source/fxq/mapstruct/FxqMapMapper.java b/src/main/java/com/newyetai/alitaforward/verification/source/fxq/mapstruct/FxqMapMapper.java new file mode 100644 index 0000000..230879f --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/source/fxq/mapstruct/FxqMapMapper.java @@ -0,0 +1,49 @@ +package com.newyetai.alitaforward.verification.source.fxq.mapstruct; + +import com.newyetai.alitaforward.verification.dto.FourFactorVerificationDTO; +import com.newyetai.alitaforward.verification.dto.ThreeFactorVerificationDTO; +import com.newyetai.sdk.fangxinqian.dto.BankCardFourRequestDTO; +import com.newyetai.sdk.fangxinqian.dto.BankCardThreeRequestDTO; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +/** + * @author czy + * @date 2021-06-23 + */ +@Mapper +public interface FxqMapMapper { + + FxqMapMapper INSTANCE = Mappers.getMapper( + FxqMapMapper.class); + + + /** + * dto转放心签三要素认证请求对象 + * + * @param dto + * @return {@link BankCardThreeRequestDTO} + */ + @Mappings(value = { + @Mapping(target = "name", source = "dto.realName"), + @Mapping(target = "identityCode", source = "dto.cardNo"), + @Mapping(target = "bankcardNumber", source = "dto.bankAccountNo") + }) + BankCardThreeRequestDTO toThreeRequestDTO(ThreeFactorVerificationDTO dto); + + /** + * dto转放心签四要素认证请求对象 + * + * @param dto + * @return {@link BankCardFourRequestDTO} + */ + @Mappings(value = { + @Mapping(target = "name", source = "dto.realName"), + @Mapping(target = "identityCode", source = "dto.cardNo"), + @Mapping(target = "bankcardNumber", source = "dto.bankAccountNo"), + @Mapping(target = "phoneNumber", source = "dto.phone") + }) + BankCardFourRequestDTO toFourRequestDTO(FourFactorVerificationDTO dto); +} diff --git a/src/main/java/com/newyetai/business/ability/enums/ProdTypeEnum.java b/src/main/java/com/newyetai/business/ability/enums/ProdTypeEnum.java new file mode 100644 index 0000000..a18635b --- /dev/null +++ b/src/main/java/com/newyetai/business/ability/enums/ProdTypeEnum.java @@ -0,0 +1,67 @@ +package com.newyetai.business.ability.enums; + +/** + * 产品类型 + * + * @author sr on 2021-03-29 + */ +public enum ProdTypeEnum { + + /** + * 新业态-灵活就业 + **/ + XYT(10, "新业态产品"), + /** + * 其他 + **/ + OTHER(11, "其他"), + /** + * 短信 + **/ + SMS_COUNT(12, "短信计次"), + /** + * 三要素 + **/ + BANK_CARD_THREE_COUNT(13, "三要素计次"), + /** + * 电子合同 + **/ + ELECTRONIC_CONTRACT_COUNT(14, "合同计次"), + /** + * 发票 + **/ + INVOICE(15, "开票余额"), + /** + * 工商信息 + **/ + COMPANY_INFO(16, "工商信息"), + /** + * 积分 + **/ + POINT(17, "积分"), + /** + * 通用支付 + */ + OPEN_PAY(18, "通用支付"), + /** + * 无卡发薪 + */ + UPAY(19, "无卡发薪"), + /** + * 平台认证 + */ + PLATFORM_VERIFICATION(20, "平台认证"); + + ProdTypeEnum(Integer type, String desc) { + this.type = type; + this.desc = desc; + } + + private Integer type; + private String desc; + + public Integer getType() { + return type; + } + +} diff --git a/src/main/java/com/newyetai/codegenerator/config/CodeConfiguration.java b/src/main/java/com/newyetai/codegenerator/config/CodeConfiguration.java new file mode 100644 index 0000000..34a6c27 --- /dev/null +++ b/src/main/java/com/newyetai/codegenerator/config/CodeConfiguration.java @@ -0,0 +1,77 @@ +package com.newyetai.codegenerator.config; + +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +import com.newyetai.codegenerator.service.CodeService; +import com.newyetai.codegenerator.service.SnowflakeIdWorker; +import com.newyetai.codegenerator.service.generator.SnowFlakeCodeGenerator; +import com.newyetai.codegenerator.service.impl.CodeServiceImpl; +import com.newyetai.codegenerator.util.CodeUtils; +import com.newyetai.common.CommonConfiguration; +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.util.EnvironmentUtils; +import com.newyetai.common.util.RequestUtils; + +import lombok.extern.slf4j.Slf4j; + +/** + * 发号器配置类 + * @author sr on 2021-03-23 + */ +@Configuration +@AutoConfigureAfter(CommonConfiguration.class) +@Slf4j +public class CodeConfiguration { + + public static final String PROP_WORID_PREFIX = "code.snowflake.workid"; + + /** + * 默认编号生成器 + * @return + * @author sr on 2021-03-23 + */ + @Bean + public SnowFlakeCodeGenerator snowFlakeCodeGenerator() { + // 机器id + String hostIp = RequestUtils.getHostIp(); + log.info("hostIp:" + hostIp); + String workIdStr = EnvironmentUtils.getProperty( + String.join(CommonConstants.POINT, PROP_WORID_PREFIX, hostIp)); + Long workId = 99l; + try { + if (StringUtils.isNoneBlank(workIdStr)) { + workId = Long.valueOf(workIdStr); + } + } catch (Exception e) { + } + SnowflakeIdWorker idWorker = new SnowflakeIdWorker(workId, 0); + return new SnowFlakeCodeGenerator(idWorker); + } + + /** + * 编号service(根据类型分发不同的生成器) + * @return + * @author sr on 2021-03-23 + */ + @Bean + public CodeService codeService() { + CodeService codeService = new CodeServiceImpl(); + CodeUtils.setCodeService(codeService); + return codeService; + } + + +} diff --git a/src/main/java/com/newyetai/codegenerator/constant/CodeConstants.java b/src/main/java/com/newyetai/codegenerator/constant/CodeConstants.java new file mode 100644 index 0000000..f336d76 --- /dev/null +++ b/src/main/java/com/newyetai/codegenerator/constant/CodeConstants.java @@ -0,0 +1,26 @@ +package com.newyetai.codegenerator.constant; + +/** + * 编号常量类 + * @author sr on 2019-09-15 + */ +public class CodeConstants { + + /** 生成器类型:默认(不可用) **/ +// public static final String GENERATOR_TYPE_DEFAULT = "DEFAULT"; + public static final String GENERATOR_TYPE_SNOW_FLAKE = "SnowFlake"; + + /** id默认长度 **/ + public static final int ID_DEFAULT_LENGTH = 5; + + /** id默认补位字符 **/ + public static final char ID_DEFAULT_PAD = '0'; + /** id默认日期格式化 **/ + public static final DateFormatterEnum ID_DEFAULT_FORMATTER = DateFormatterEnum.YEAR; + + /** -----异常信息----- **/ + public static final String CODE_GENERATE_ERROR = "编号生成失败"; + /** -----异常信息----- **/ + + +} diff --git a/src/main/java/com/newyetai/codegenerator/constant/DateFormatterEnum.java b/src/main/java/com/newyetai/codegenerator/constant/DateFormatterEnum.java new file mode 100644 index 0000000..4b638f0 --- /dev/null +++ b/src/main/java/com/newyetai/codegenerator/constant/DateFormatterEnum.java @@ -0,0 +1,32 @@ +package com.newyetai.codegenerator.constant; + +import java.time.format.DateTimeFormatter; + +/** + * 日期formatter枚举 + * @author sr on 2019-12-03 + */ +public enum DateFormatterEnum { + + /** 年:yyyy **/ + YEAR(DateTimeFormatter.ofPattern("yyyy")), + /** 年月:yyyyMM **/ + YM(DateTimeFormatter.ofPattern("yyyyMM")), + /** 年月:yyMM **/ + YM2(DateTimeFormatter.ofPattern("yyMM")), + /** 年月日:yyyyMMdd **/ + YMD(DateTimeFormatter.ofPattern("yyyyMMdd")), + /** 年月日:yyMMdd **/ + YMD2(DateTimeFormatter.ofPattern("yyMMdd")); + + private DateTimeFormatter formatter; + + private DateFormatterEnum(DateTimeFormatter formatter){ + this.formatter = formatter; + } + + public DateTimeFormatter getDateTimeFormatter() { + return this.formatter; + } + +} diff --git a/src/main/java/com/newyetai/codegenerator/exception/CodeGeneratorException.java b/src/main/java/com/newyetai/codegenerator/exception/CodeGeneratorException.java new file mode 100644 index 0000000..70221c5 --- /dev/null +++ b/src/main/java/com/newyetai/codegenerator/exception/CodeGeneratorException.java @@ -0,0 +1,26 @@ +package com.newyetai.codegenerator.exception; + +/** + * 编号生成器异常 + * @author sr on 2019-12-03 + */ +public class CodeGeneratorException extends RuntimeException{ + + /** **/ + private static final long serialVersionUID = 3558280270933232655L; + + + public CodeGeneratorException() {} + + public CodeGeneratorException(String message) { + super(message); + } + + public CodeGeneratorException(String message, Throwable cause) { + super(message, cause); + } + + public CodeGeneratorException(Throwable cause) { + super(cause); + } +} diff --git a/src/main/java/com/newyetai/codegenerator/pojo/CodeParam.java b/src/main/java/com/newyetai/codegenerator/pojo/CodeParam.java new file mode 100644 index 0000000..ea67bac --- /dev/null +++ b/src/main/java/com/newyetai/codegenerator/pojo/CodeParam.java @@ -0,0 +1,25 @@ +package com.newyetai.codegenerator.pojo; + +import com.newyetai.codegenerator.constant.CodeConstants; + +import lombok.Builder; +import lombok.Data; +import lombok.Builder.Default; + +/** + * 编码生成参数对象 + * @author sr on 2019-12-05 + */ +@Data +@Builder +public class CodeParam { + + /** 生成器类型 **/ + @Default + private String generatorType = CodeConstants.GENERATOR_TYPE_SNOW_FLAKE; + + /** 编码类型 **/ + private String type; + + +} diff --git a/src/main/java/com/newyetai/codegenerator/service/CodeGenerator.java b/src/main/java/com/newyetai/codegenerator/service/CodeGenerator.java new file mode 100644 index 0000000..c023518 --- /dev/null +++ b/src/main/java/com/newyetai/codegenerator/service/CodeGenerator.java @@ -0,0 +1,42 @@ +package com.newyetai.codegenerator.service; + +import java.util.List; + +import com.newyetai.codegenerator.pojo.CodeParam; + +/** + * 编号生成器 默认一套实现,如需重定义中间时间format和id长度,重写规则 重写规则,注意去发号器对应的数据库表(leaf_alloc)中添加对应type+时间(biz_tag)的记录 + * + * @author sr on 2019-09-15 + */ +public interface CodeGenerator { + + /** + * 自定义特定业务类型,即前缀 + * + * @return + * @author sr on 2019-09-19 + */ + String getType(); + + + /** + * 根据生成规则获取编号 + * + * @param codeParam + * @return + * @author sr on 2020-07-13 + */ + String getCode(T codeParam); + + /** + * 批量根据生成规则获取编号 + * + * @param codeParam + * @return + * @author sr on 2020-07-13 + */ + List batchCode(T codeParam, Integer batchNum); + + +} diff --git a/src/main/java/com/newyetai/codegenerator/service/CodeService.java b/src/main/java/com/newyetai/codegenerator/service/CodeService.java new file mode 100644 index 0000000..6fb3649 --- /dev/null +++ b/src/main/java/com/newyetai/codegenerator/service/CodeService.java @@ -0,0 +1,33 @@ +package com.newyetai.codegenerator.service; + +import java.util.List; + +import com.newyetai.codegenerator.pojo.CodeParam; + +/** + * 编号service(根据类型分发不同的生成器) + * + * @author sr on 2019-09-15 + */ +public interface CodeService { + + /** + * 根据生成规则获取编号 + * + * @param codeParam + * @return + * @author sr on 2020-07-13 + */ + String getCode(CodeParam codeParam); + + /** + * 批量根据生成规则获取编号 + * + * @param codeParam + * @param batchNum 批次数(1-1000) + * @return + * @author sr on 2020-07-13 + */ + List batchCode(CodeParam codeParam, Integer batchNum); + +} diff --git a/src/main/java/com/newyetai/codegenerator/service/SnowflakeIdWorker.java b/src/main/java/com/newyetai/codegenerator/service/SnowflakeIdWorker.java new file mode 100644 index 0000000..434212d --- /dev/null +++ b/src/main/java/com/newyetai/codegenerator/service/SnowflakeIdWorker.java @@ -0,0 +1,160 @@ +package com.newyetai.codegenerator.service; + +/** + * Twitter_Snowflake
+ * SnowFlake的结构如下(每部分用-分开):
+ * 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000
+ * 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0
+ * 41位时间戳(毫秒级),注意,41位时间戳不是存储当前时间的时间戳,而是存储时间戳的差值(当前时间戳 - 开始时间戳) 得到的值),这里的的开始时间戳,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下下面程序IdWorker类的startTime属性)。41位的时间戳,可以使用69年,年T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69
+ * 10位的数据机器位,可以部署在1024个节点,包括5位datacenterId和5位workerId
+ * 12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间戳)产生4096个ID序号
+ * 加起来刚好64位,为一个Long型。
+ * SnowFlake的优点是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分),并且效率较高,经测试,SnowFlake每秒能够产生26万ID左右。 + */ +public class SnowflakeIdWorker { + + // ==============================Fields=========================================== + /** 开始时间戳 (2015-01-01) */ + private final long twepoch = 1420041600000L; + + /** 能容忍的系统时钟回拨时间(2秒) */ + private final long timeOffset = 2000L; + + /** 机器id所占的位数 */ + private final long workerIdBits = 5L; + + /** 数据标识id所占的位数 */ + private final long datacenterIdBits = 5L; + + /** 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) */ + private final long maxWorkerId = -1L ^ (-1L << workerIdBits); + + /** 支持的最大数据标识id,结果是31 */ + private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); + + /** 序列在id中占的位数 */ + private final long sequenceBits = 12L; + + /** 机器ID向左移12位 */ + private final long workerIdShift = sequenceBits; + + /** 数据标识id向左移17位(12+5) */ + private final long datacenterIdShift = sequenceBits + workerIdBits; + + /** 时间戳向左移22位(5+5+12) */ + private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; + + /** 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095) */ + private final long sequenceMask = -1L ^ (-1L << sequenceBits); + + /** 工作机器ID(0~31) */ + private long workerId; + + /** 数据中心ID(0~31) */ + private long datacenterId; + + /** 毫秒内序列(0~4095) */ + private long sequence = 0L; + + /** 上次生成ID的时间戳 */ + private long lastTimestamp = -1L; + + // ==============================Constructors===================================== + /** + * 构造函数 + * @param workerId 工作ID (0~31) + * @param datacenterId 数据中心ID (0~31) + */ + public SnowflakeIdWorker(long workerId, long datacenterId) { + if (workerId > maxWorkerId || workerId < 0) { + throw new IllegalArgumentException( + String.format("worker Id can't be greater than %d or less than 0", maxWorkerId)); + } + if (datacenterId > maxDatacenterId || datacenterId < 0) { + throw new IllegalArgumentException( + String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId)); + } + this.workerId = workerId; + this.datacenterId = datacenterId; + } + + // ==============================Methods========================================== + /** + * 获得下一个ID (该方法是线程安全的) + * @return SnowflakeId + */ + public synchronized long nextId() { + long timestamp = timeGen(); + + // 当前时间戳小于上一次ID生成的时间戳 + if (timestamp < lastTimestamp) { + long offset = lastTimestamp - timestamp; + // 系统时钟回退在容忍范围内,例如出现过闰秒 + if (offset < timeOffset) { + timestamp = lastTimestamp; + } + // 系统时钟回退超出容忍范围,抛出异常 + else { + throw new RuntimeException(String + .format("Clock moved backwards. Refusing to generate id for %d milliseconds", offset)); + } + } + + // 如果是同一时间生成的,则进行毫秒内序列 + if (lastTimestamp == timestamp) { + sequence = (sequence + 1) & sequenceMask; + // 毫秒内序列溢出 + if (sequence == 0) { + // 阻塞到下一个毫秒,获得新的时间戳 + timestamp = tilNextMillis(lastTimestamp); + } + } + // 时间戳改变,毫秒内序列重置 + else { + sequence = 0L; + } + + // 上次生成ID的时间戳 + lastTimestamp = timestamp; + + // 移位并通过或运算拼到一起组成64位的ID + return ((timestamp - twepoch) << timestampLeftShift) // + | (datacenterId << datacenterIdShift) // + | (workerId << workerIdShift) // + | sequence; + } + + /** + * 阻塞到下一个毫秒,直到获得新的时间戳 + * @param lastTimestamp 上次生成ID的时间戳 + * @return 当前时间戳 + */ + protected long tilNextMillis(long lastTimestamp) { + long timestamp = timeGen(); + while (timestamp <= lastTimestamp) { + timestamp = timeGen(); + } + return timestamp; + } + + /** + * 返回以毫秒为单位的当前时间 + * @return 当前时间(毫秒) + */ + protected long timeGen() { + return System.currentTimeMillis(); + } + + // ==============================Test============================================= + /** 测试 */ + public static void main(String[] args) { + + System.out.println("1000011111010000000111110011100110011110000000000000000001100".length()); + // SnowflakeIdWorker idWorker = new SnowflakeIdWorker(0, 0); + // for (int i = 0; i < 1000; i++) { + // long id = idWorker.nextId(); + // System.out.println(Long.toBinaryString(id)); + // System.out.println(id); + // } + } +} diff --git a/src/main/java/com/newyetai/codegenerator/service/generator/SnowFlakeCodeGenerator.java b/src/main/java/com/newyetai/codegenerator/service/generator/SnowFlakeCodeGenerator.java new file mode 100644 index 0000000..b11beb2 --- /dev/null +++ b/src/main/java/com/newyetai/codegenerator/service/generator/SnowFlakeCodeGenerator.java @@ -0,0 +1,47 @@ +package com.newyetai.codegenerator.service.generator; + +import java.util.List; + +import com.google.common.collect.Lists; +import com.newyetai.codegenerator.constant.CodeConstants; +import com.newyetai.codegenerator.pojo.CodeParam; +import com.newyetai.codegenerator.service.CodeGenerator; +import com.newyetai.codegenerator.service.SnowflakeIdWorker; + +import lombok.extern.slf4j.Slf4j; + +/** + * 默认编号生成器 + * + * @author sr on 2019-09-15 + */ +@Slf4j +public class SnowFlakeCodeGenerator implements CodeGenerator { + + private SnowflakeIdWorker snowflakeIdWorker; + + public SnowFlakeCodeGenerator(SnowflakeIdWorker snowflakeIdWorker) { + this.snowflakeIdWorker = snowflakeIdWorker; + } + + + @Override + public String getType() { + return CodeConstants.GENERATOR_TYPE_SNOW_FLAKE; + } + + @Override + public String getCode(CodeParam codeParam) { + return codeParam.getType() + snowflakeIdWorker.nextId(); + } + + @Override + public List batchCode(CodeParam codeParam, Integer batchNum) { + List ids = Lists.newArrayListWithCapacity(batchNum); + for (int i = 0; i < batchNum; i++) { + ids.add(this.getCode(codeParam)); + } + return ids; + } + +} diff --git a/src/main/java/com/newyetai/codegenerator/service/impl/CodeServiceImpl.java b/src/main/java/com/newyetai/codegenerator/service/impl/CodeServiceImpl.java new file mode 100644 index 0000000..6a3e8d1 --- /dev/null +++ b/src/main/java/com/newyetai/codegenerator/service/impl/CodeServiceImpl.java @@ -0,0 +1,48 @@ +package com.newyetai.codegenerator.service.impl; + +import java.util.List; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; + +import com.google.common.collect.Maps; +import com.newyetai.codegenerator.constant.CodeConstants; +import com.newyetai.codegenerator.pojo.CodeParam; +import com.newyetai.codegenerator.service.CodeGenerator; +import com.newyetai.codegenerator.service.CodeService; + +/** + * 编号service实现类 + * + * @author sr on 2019-09-15 + */ +public class CodeServiceImpl implements CodeService { + + private Map> codeGenerators = Maps.newHashMap(); + + @SuppressWarnings({"unchecked", "rawtypes"}) + @Autowired + private void codeGenerateResolver(List resolvers) { + resolvers.forEach(resolver -> codeGenerators.put(resolver.getType(), resolver)); + } + + private CodeGenerator getResolver(String type) { + CodeGenerator resolver = codeGenerators.get(type); + if (resolver == null) { + resolver = codeGenerators.get(CodeConstants.GENERATOR_TYPE_SNOW_FLAKE); + } + return resolver; + } + + @Override + public String getCode(CodeParam codeParam) { + return getResolver(codeParam.getGeneratorType()).getCode(codeParam); + } + + @Override + public List batchCode(CodeParam codeParam, Integer batchNum) { + return getResolver(codeParam.getGeneratorType()).batchCode(codeParam, batchNum); + } + + +} diff --git a/src/main/java/com/newyetai/codegenerator/util/CodeUtils.java b/src/main/java/com/newyetai/codegenerator/util/CodeUtils.java new file mode 100644 index 0000000..ffed798 --- /dev/null +++ b/src/main/java/com/newyetai/codegenerator/util/CodeUtils.java @@ -0,0 +1,48 @@ +package com.newyetai.codegenerator.util; + +import java.util.List; + +import com.newyetai.codegenerator.pojo.CodeParam; +import com.newyetai.codegenerator.service.CodeService; +import com.newyetai.component.constants.CodeTypeEnum; + +/** + * 发号器工具类 + * @author sr on 2021-03-23 + */ +public abstract class CodeUtils { + + private static CodeService codeService; + + public static void setCodeService(CodeService codeService) { + CodeUtils.codeService = codeService; + } + + public static String getCode(CodeTypeEnum codeTypeEnum) { + return codeService.getCode(codeTypeEnum.getCodeParam()); + } + + /** + * 根据生成规则获取编号 + * + * @param codeParam + * @return + * @author sr on 2021-03-23 + */ + public static String getCode(CodeParam codeParam) { + return codeService.getCode(codeParam); + } + + /** + * 批量根据生成规则获取编号 + * + * @param codeParam + * @param batchNum + * @return + * @author sr on 2021-03-23 + */ + public static List batchCode(CodeParam codeParam, Integer batchNum) { + return codeService.batchCode(codeParam, batchNum); + } + +} diff --git a/src/main/java/com/newyetai/codesetting/constant/CodeSettingConstants.java b/src/main/java/com/newyetai/codesetting/constant/CodeSettingConstants.java new file mode 100644 index 0000000..006a6ff --- /dev/null +++ b/src/main/java/com/newyetai/codesetting/constant/CodeSettingConstants.java @@ -0,0 +1,37 @@ +package com.newyetai.codesetting.constant; + +public interface CodeSettingConstants { + /** + * 编码配置数据类型 + */ + public static final String CODE_SETTING_DATA_TYPE = "code_setting_data_type"; + + public class CodeSettingDataType { + + public static final String STRING = "1"; + + public static final String NUMBER = "2"; + + public static final String DATE = "3"; + + public static final String BOOL = "4"; + + public static final String RADIO = "5"; + + public static final String CHECKBOX = "6"; + + public static final String FILE = "7"; + + } + + /** + * 编码配置模块:机构配置 + **/ + public static final String CODE_SETTING_TYPE_CONFIG = "1"; + + /** + * 编码配置默认级别 + **/ + public static final String CODE_SETTING_LEVEL_DEFAULT = "1,2,3,4"; + +} diff --git a/src/main/java/com/newyetai/codesetting/controller/CodeSettingController.java b/src/main/java/com/newyetai/codesetting/controller/CodeSettingController.java new file mode 100644 index 0000000..a05d327 --- /dev/null +++ b/src/main/java/com/newyetai/codesetting/controller/CodeSettingController.java @@ -0,0 +1,67 @@ +package com.newyetai.codesetting.controller; + +import com.newyetai.codesetting.dto.CodeSettingDTO; +import com.newyetai.codesetting.dto.CodeSettingOperatorDTO; +import com.newyetai.codesetting.dto.CodeSettingPageQueryDTO; +import com.newyetai.codesetting.dto.CodeSettingQueryDTO; +import com.newyetai.codesetting.service.CodeSettingService; +import com.newyetai.common.AlitaResult; +import com.newyetai.tkmybatis.pojo.Page; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 编码表 + * + * @author chenyun chenyun.home@outlook.com + * @since 1.0.0 2023-01-04 + */ +@Api(tags = "编码表") +@RestController +@RequestMapping("code_setting") +public class CodeSettingController { + + @Autowired + private CodeSettingService codeSettingService; + + @PostMapping + @ApiOperation("编码表-创建") + public AlitaResult create(@RequestBody CodeSettingOperatorDTO operatorDTO) { + return AlitaResult.success(codeSettingService.create(operatorDTO)); + } + + @PutMapping + @ApiOperation("编码表-修改") + public AlitaResult modify(@RequestBody CodeSettingOperatorDTO operatorDTO) { + return AlitaResult.success(codeSettingService.modify(operatorDTO)); + } + + @DeleteMapping("{id}") + @ApiOperation("编码表-删除") + public AlitaResult delete(@PathVariable("id") Long id) { + return AlitaResult.success(codeSettingService.delete(id)); + } + + @GetMapping("{id}") + @ApiOperation("编码表-查询单个") + public AlitaResult findById(@PathVariable("id") Long id) { + return AlitaResult.success(codeSettingService.findById(id)); + } + + @GetMapping("list") + @ApiOperation("编码表-列表查询") + public AlitaResult> list(CodeSettingQueryDTO queryDTO) { + return AlitaResult.success(codeSettingService.list(queryDTO)); + } + + @GetMapping("page") + @ApiOperation("编码表-分页查询") + public AlitaResult> page(CodeSettingPageQueryDTO queryDTO) { + codeSettingService.page(queryDTO); + return AlitaResult.success(queryDTO.getPageResult()); + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/codesetting/convert/CodeSettingConvert.java b/src/main/java/com/newyetai/codesetting/convert/CodeSettingConvert.java new file mode 100644 index 0000000..8ebc5fb --- /dev/null +++ b/src/main/java/com/newyetai/codesetting/convert/CodeSettingConvert.java @@ -0,0 +1,25 @@ +package com.newyetai.codesetting.convert; + +import com.newyetai.codesetting.dto.CodeSettingDTO; +import com.newyetai.codesetting.dto.CodeSettingOperatorDTO; +import com.newyetai.codesetting.entity.CodeSetting; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * 编码表 + * + * @author chenyun chenyun.home@outlook.com + * @since 1.0.0 2023-01-04 + */ +@Mapper +public interface CodeSettingConvert { + CodeSettingConvert INSTANCE = Mappers.getMapper(CodeSettingConvert.class); + + CodeSetting convert(CodeSettingDTO dto); + + CodeSettingDTO convert(CodeSetting entity); + + CodeSetting convert(CodeSettingOperatorDTO dto); + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/codesetting/dao/CodeSettingMapper.java b/src/main/java/com/newyetai/codesetting/dao/CodeSettingMapper.java new file mode 100644 index 0000000..33df0b1 --- /dev/null +++ b/src/main/java/com/newyetai/codesetting/dao/CodeSettingMapper.java @@ -0,0 +1,35 @@ +package com.newyetai.codesetting.dao; + +import com.newyetai.codesetting.dto.CodeSettingDTO; +import com.newyetai.codesetting.dto.CodeSettingPageQueryDTO; +import com.newyetai.codesetting.dto.CodeSettingQueryDTO; +import com.newyetai.codesetting.entity.CodeSetting; +import com.newyetai.tkmybatis.mybatis.MyMapper; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** + * 编码表 + * + * @author chenyun chenyun.home@outlook.com + * @since 1.0.0 2023-01-04 + */ +@Mapper +public interface CodeSettingMapper extends MyMapper { + + List page(@Param("param") CodeSettingPageQueryDTO queryDTO); + + List list(@Param("param") CodeSettingQueryDTO queryDTO); + + /** + * 根据类型查询 + * + * @param type + * @return + */ + @Select("select * from xs_code_setting where type = #{type} and deleted = 0") + List queryByType(String type); +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/codesetting/dto/CodeSettingDTO.java b/src/main/java/com/newyetai/codesetting/dto/CodeSettingDTO.java new file mode 100644 index 0000000..b53d11c --- /dev/null +++ b/src/main/java/com/newyetai/codesetting/dto/CodeSettingDTO.java @@ -0,0 +1,46 @@ +package com.newyetai.codesetting.dto; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.component.action.dto.ActionDetailDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.SuperBuilder; + +/** + * 编码表 + * + * @author chenyun chenyun.home@outlook.com + * @since 1.0.0 2023-01-04 + */ +@ApiModel("编码表") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class CodeSettingDTO extends BaseDTO { + private static final long serialVersionUID = 1L; + + @ApiModelProperty("编码") + private String code; + + @ApiModelProperty("名称") + private String name; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("类型 模板编码、配置编码") + private String type; + + @ApiModelProperty("数据类型") + private String dataType; + + @ApiModelProperty("级别 平台、渠道、定制机构、普通机构") + private String level; + + @ApiModelProperty("数据值") + private String dataFormat; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/codesetting/dto/CodeSettingOperatorDTO.java b/src/main/java/com/newyetai/codesetting/dto/CodeSettingOperatorDTO.java new file mode 100644 index 0000000..a316768 --- /dev/null +++ b/src/main/java/com/newyetai/codesetting/dto/CodeSettingOperatorDTO.java @@ -0,0 +1,60 @@ +package com.newyetai.codesetting.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.NotEmpty; +import java.io.Serializable; + +/** + * 编码表 + * + * @author chenyun chenyun.home@outlook.com + * @since 1.0.0 2023-01-04 + */ +@ApiModel("编码表") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class CodeSettingOperatorDTO implements Serializable { + + private static final long serialVersionUID = 8836210011277521607L; + private Long id; + + @ApiModelProperty("编码") + @NotEmpty(message = "配置项编码不能为空") + @Length(min = 1, max = 64, message = "配置项编码长度超限") + private String code; + + @ApiModelProperty("名称") + @NotEmpty(message = "配置项名称不能为空") + @Length(min = 1, max = 128, message = "配置项名称长度超限") + private String name; + + @ApiModelProperty("备注") +// @NotEmpty(message = "备注不能为空") + private String remark; + + @ApiModelProperty("数据值") + private String dataFormat; + + @ApiModelProperty("类型 模板编码、配置编码") + @NotEmpty(message = "配置类型不能为空") + private String type; + + @ApiModelProperty("数据类型") + @NotEmpty(message = "配置参数类型不能为空") + private String dataType; + + @ApiModelProperty("级别 平台、渠道、定制机构、普通机构") + @NotEmpty(message = "配置应用级别不能为空") + private String level; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/codesetting/dto/CodeSettingPageQueryDTO.java b/src/main/java/com/newyetai/codesetting/dto/CodeSettingPageQueryDTO.java new file mode 100644 index 0000000..0c4376d --- /dev/null +++ b/src/main/java/com/newyetai/codesetting/dto/CodeSettingPageQueryDTO.java @@ -0,0 +1,77 @@ +package com.newyetai.codesetting.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.newyetai.common.annotation.trimAndUpper.TrimAndUpper; +import com.newyetai.common.dto.PageQueryDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +/** + * 编码表 + * + * @author chenyun chenyun.home@outlook.com + * @since 1.0.0 2023-01-04 + */ + +@ApiModel("编码表") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class CodeSettingPageQueryDTO extends PageQueryDTO { + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键ID") + private Long id; + + @ApiModelProperty("编码") + private String code; + + @ApiModelProperty("编码 (模糊匹配)") + @TrimAndUpper(TrimAndUpper.ExecuteType.TRIM) + private String codeLike; + + @ApiModelProperty("名称 (模糊匹配)") + @TrimAndUpper(TrimAndUpper.ExecuteType.TRIM) + private String nameLike; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("类型 模板编码、配置编码") + @TrimAndUpper(TrimAndUpper.ExecuteType.TRIM) + private String type; + + @ApiModelProperty("数据类型") + private String dataType; + + @ApiModelProperty("级别 平台、渠道、定制机构、普通机构") + private String level; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("修改时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeStart; + + @ApiModelProperty("修改时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeEnd; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/codesetting/dto/CodeSettingQueryDTO.java b/src/main/java/com/newyetai/codesetting/dto/CodeSettingQueryDTO.java new file mode 100644 index 0000000..caead13 --- /dev/null +++ b/src/main/java/com/newyetai/codesetting/dto/CodeSettingQueryDTO.java @@ -0,0 +1,74 @@ +package com.newyetai.codesetting.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.format.annotation.DateTimeFormat; + +import java.io.Serializable; +import java.util.Date; + +/** + * 编码表 + * + * @author chenyun chenyun.home@outlook.com + * @since 1.0.0 2023-01-04 + */ +@ApiModel("编码表") +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class CodeSettingQueryDTO implements Serializable { + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键ID") + private Long id; + + @ApiModelProperty("编码") + private String code; + + @ApiModelProperty("编码 (模糊匹配)") + private String codeLike; + + @ApiModelProperty("名称 (模糊匹配)") + private String nameLike; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("类型 模板编码、配置编码") + private String type; + + @ApiModelProperty("数据类型") + private String dataType; + + @ApiModelProperty("级别 平台、渠道、定制机构、普通机构") + private String level; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("修改时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeStart; + + @ApiModelProperty("修改时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeEnd; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/codesetting/entity/CodeSetting.java b/src/main/java/com/newyetai/codesetting/entity/CodeSetting.java new file mode 100644 index 0000000..d3511b4 --- /dev/null +++ b/src/main/java/com/newyetai/codesetting/entity/CodeSetting.java @@ -0,0 +1,56 @@ +package com.newyetai.codesetting.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * 编码表 + * + * @author chenyun chenyun.home@outlook.com + * @since 1.0.0 2023-01-04 + */ +@TableName("xs_code_setting") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class CodeSetting extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * 编码 + */ + private String code; + /** + * 名称 + */ + private String name; + /** + * 备注 + */ + private String remark; + /** + * 类型 模板编码、配置编码 + */ + private String type; + /** + * 数据类型 + */ + private String dataType; + /** + * 数据格式编号 + */ + private String dataFormat; + /** + * 级别 平台、渠道、定制机构、普通机构 + */ + private String level; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/codesetting/mapper/CodeSettingMapper.xml b/src/main/java/com/newyetai/codesetting/mapper/CodeSettingMapper.xml new file mode 100644 index 0000000..f0a6569 --- /dev/null +++ b/src/main/java/com/newyetai/codesetting/mapper/CodeSettingMapper.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + FROM + xs_code_setting t + WHERE t.deleted = 0 + + AND t.id = #{param.id} + + + AND t.code = #{param.code} + + + + AND t.code like #{codeLike} + + + + AND t.name like #{nameLike} + + + AND t.remark = #{param.remark} + + + AND t.type = #{param.type} + + + AND t.data_type = #{param.dataType} + + + AND FIND_IN_SET(CONCAT(#{param.level},""),t.level) + + + AND t.create_time >= #{param.createTimeStart} + + + AND t.create_time <= #{param.createTimeEnd} + + + AND t.update_time >= #{param.updateTimeStart} + + + AND t.update_time <= #{param.updateTimeEnd} + + ORDER BY t.id DESC + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/codesetting/service/CodeSettingService.java b/src/main/java/com/newyetai/codesetting/service/CodeSettingService.java new file mode 100644 index 0000000..b66f8b5 --- /dev/null +++ b/src/main/java/com/newyetai/codesetting/service/CodeSettingService.java @@ -0,0 +1,96 @@ +package com.newyetai.codesetting.service; + +import com.newyetai.codesetting.dto.CodeSettingDTO; +import com.newyetai.codesetting.dto.CodeSettingOperatorDTO; +import com.newyetai.codesetting.dto.CodeSettingPageQueryDTO; +import com.newyetai.codesetting.dto.CodeSettingQueryDTO; +import com.newyetai.codesetting.entity.CodeSetting; +import org.springframework.validation.annotation.Validated; + +import javax.validation.Valid; +import javax.validation.groups.Default; +import java.util.List; + +/** + * 编码表 + * + * @author chenyun chenyun.home@outlook.com + * @since 1.0.0 2023-01-04 + */ +@Validated(Default.class) +public interface CodeSettingService { + + /** + * 编码表 - 创建 + * + * @param operatorDto 操作dto + * @return {@link CodeSettingDTO} + */ + CodeSettingDTO create(@Valid CodeSettingOperatorDTO operatorDto); + + /** + * 校验编码是否存在 + * + * @param code 代码 + * @param codeSettingId 编码ID + * @return boolean true: 存在重复编码 + */ + boolean checkCode(String code, Long codeSettingId); + + /** + * 编码表 - 修改 + * + * @param operatorDto 操作dto + * @return {@link CodeSettingDTO} + */ + CodeSettingDTO modify(@Valid CodeSettingOperatorDTO operatorDto); + + /** + * 编码表 - 删除 + * + * @param id id + * @return {@link CodeSettingDTO} + */ + CodeSettingDTO delete(Long id); + + /** + * 编码表 - 根据ID查询单个 + * + * @param id id + * @return {@link CodeSettingDTO} + */ + CodeSettingDTO findById(Long id); + + /** + * 编码表 - 列表查询 + * + * @param queryDTO 列表查询dto + * @return {@link List}<{@link CodeSettingDTO}> + */ + List list(CodeSettingQueryDTO queryDTO); + + /** + * 编码表 - 分页查询 + * + * @param queryDTO 分页查询dto + * @return {@link CodeSettingDTO} + */ + List page(CodeSettingPageQueryDTO queryDTO); + + /** + * 根据type和code查询 + * + * @param codeSettingType + * @param orgType + * @return + */ + List queryCode(String codeSettingType, String orgType); + + /** + * 根据code查询 + * + * @param code + * @return + */ + CodeSettingDTO getByCode(String code); +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/codesetting/service/impl/CodeSettingServiceImpl.java b/src/main/java/com/newyetai/codesetting/service/impl/CodeSettingServiceImpl.java new file mode 100644 index 0000000..eaf0aff --- /dev/null +++ b/src/main/java/com/newyetai/codesetting/service/impl/CodeSettingServiceImpl.java @@ -0,0 +1,119 @@ +package com.newyetai.codesetting.service.impl; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import javax.annotation.Resource; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.ArrayUtils; +import org.springframework.stereotype.Service; + +import com.newyetai.codesetting.convert.CodeSettingConvert; +import com.newyetai.codesetting.dao.CodeSettingMapper; +import com.newyetai.codesetting.dto.CodeSettingDTO; +import com.newyetai.codesetting.dto.CodeSettingOperatorDTO; +import com.newyetai.codesetting.dto.CodeSettingPageQueryDTO; +import com.newyetai.codesetting.dto.CodeSettingQueryDTO; +import com.newyetai.codesetting.entity.CodeSetting; +import com.newyetai.codesetting.service.CodeSettingService; +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.config.dao.ConfigMapper; + +import lombok.extern.slf4j.Slf4j; + +/** + * 编码表 + * + * @author chenyun chenyun.home@outlook.com + * @since 1.0.0 2023-01-04 + */ +@Slf4j +@Service +public class CodeSettingServiceImpl implements CodeSettingService { + + @Resource + private CodeSettingMapper codeSettingMapper; + + @Resource + private ConfigMapper configMapper; + + @Override + public CodeSettingDTO create(CodeSettingOperatorDTO operatorDto) { + Assert.isTrue(!checkCode(operatorDto.getCode(), null), "配置项编码已存在"); + CodeSetting codeSetting = CodeSettingConvert.INSTANCE.convert(operatorDto); + codeSettingMapper.saveEntity(codeSetting); + return CodeSettingConvert.INSTANCE.convert(codeSetting); + } + + @Override + public boolean checkCode(String code, Long codeSettingId) { + return codeSettingMapper.existsEntity(CodeSetting.builder().code(code).build()); + } + + @Override + public CodeSettingDTO modify(CodeSettingOperatorDTO operatorDto) { + CodeSettingDTO codeSettingDto = this.findById(operatorDto.getId()); + if (Objects.isNull(codeSettingDto)) { + return null; + } + Assert.isTrue(!checkCode(operatorDto.getCode(), operatorDto.getId()), "配置项编码已存在"); + CodeSetting codeSetting = CodeSettingConvert.INSTANCE.convert(operatorDto); + codeSettingMapper.updateEntity(codeSetting); + return this.findById(operatorDto.getId()); + } + + @Override + public CodeSettingDTO delete(Long id) { + CodeSettingDTO codeSettingDto = this.findById(id); + if (Objects.isNull(codeSettingDto)) { + return null; + } + CodeSetting codeSetting = CodeSetting.builder().build(); + codeSetting.setId(id); + codeSettingMapper.deleteEntity(codeSetting, UserContextHolder.getLoginUserId()); + // 删除配置项的时候,同步删除配置项下的配置 + configMapper.batchDelete(codeSettingDto.getCode(), UserContextHolder.getExistLoginUserId()); + return codeSettingDto; + } + + @Override + public CodeSettingDTO findById(Long id) { + CodeSetting codeSetting = codeSettingMapper.getById(id); + if (Objects.isNull(codeSetting)) { + return null; + } + return CodeSettingConvert.INSTANCE.convert(codeSetting); + } + + @Override + public List list(CodeSettingQueryDTO queryDTO) { + return codeSettingMapper.list(queryDTO); + } + + @Override + public List page(CodeSettingPageQueryDTO queryDTO) { + return codeSettingMapper.page(queryDTO); + } + + @Override + public List queryCode(String codeSettingType, String orgType) { + List codeSettings = codeSettingMapper.queryByType(codeSettingType); + return codeSettings.stream() + .filter(codeSetting -> ArrayUtils + .contains(codeSetting.getLevel().split(CommonConstants.COMMA), orgType)) + .map(CodeSettingConvert.INSTANCE::convert).collect(Collectors.toList()); + } + + @Override + public CodeSettingDTO getByCode(String code) { + List list = this.list(CodeSettingQueryDTO.builder().code(code).build()); + if (CollectionUtils.isEmpty(list)) { + return null; + } + return list.get(0); + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/common/AlitaResult.java b/src/main/java/com/newyetai/common/AlitaResult.java new file mode 100644 index 0000000..74054a0 --- /dev/null +++ b/src/main/java/com/newyetai/common/AlitaResult.java @@ -0,0 +1,254 @@ +package com.newyetai.common; + +import java.io.Serializable; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.newyetai.sdk.common.constant.SdkConstants; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 用于 ajax 请求的响应工具类 + * + * @author guhong + * @date 2019/8/19 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class AlitaResult implements Serializable { + + /** */ + private static final long serialVersionUID = 5933105804003541576L; + + /** 未登录 * */ + public static final String UN_LOGIN_CODE = "401"; + /** 无权限 * */ + public static final String NO_AUTHORITY_CODE = "402"; + /** 无查询信息 * */ + public static final String NO_RESULT_CODE = "405"; + /** 登录用户多机构 * */ + public static final String DUPLICATE_ORG_CODE = "600"; + /** 登录用户多用户 * */ + public static final String DUPLICATE_USER_CODE = "601"; + /** 用户未实名 * */ + public static final String UN_AUTH_CODE = "602"; + /** 用户更换token **/ + public static final String CHANGE_TOKEN_CODE = "603"; + /** 用户未绑定手机号 **/ + public static final String UN_BINDING_PHONE = "604"; + /** 登录用户相关异常 **/ + public static final String LOGIN_ERROR_CODE = "666"; + /** 系统异常 * */ + public static final String SYSTEM_ERROR_CODE = "999"; + /** 业务异常 **/ + public static final String BUSINESS_ERROR_CODE = "700"; + /** 校验异常 * */ + public static final String VALIDATION_ERROR_CODE = "555"; + /** 操作成功 * */ + public static final String SUCCESS_CODE = "200"; + + public static final String CHANG_TOKEN_MSG = "token变更"; + + /** 链路id **/ + private String requestId; + /** 响应信息 */ + private String msg; + /** 响应code */ + private String code; + /** 是否成功 */ + private Boolean success; + /** 操作成功,响应数据 */ + private T data; + /** 操作失败结果 **/ + private Object errorData; + + /** 临时json **/ + @JsonIgnore + private String tempJson; + + public AlitaResult(String code, String msg, boolean success, T data) { + this.msg = msg; + this.code = code; + this.success = success; + this.data = data; + } + + public AlitaResult(String code, String msg, Serializable errorData) { + this.msg = msg; + this.code = code; + this.success = false; + this.errorData = errorData; + } + + /** + * 创建一个成功的响应对象 + * + * @return + */ + public static AlitaResult success() { + return success(null); + } + + /** + * 创建一个成功的响应对象 + * + * @param data + * @return + */ + public static AlitaResult success(T data) { + return new AlitaResult(SUCCESS_CODE, "请求成功", true, data); + } + + /** + * 创建一个成功的响应对象 + * + * @param msg + * @return + */ + public static AlitaResult success(String msg, T data) { + return new AlitaResult(SUCCESS_CODE, msg, true, data); + } + + /** + * 创建一个失败的响应对象 + * + * @param msg + * @return + */ + public static AlitaResult error(String msg) { + return new AlitaResult(SYSTEM_ERROR_CODE, msg, false, null); + } + + /** + * 创建一个失败的响应对象 + * + * @param code + * @param msg + * @return + */ + public static AlitaResult error(String code, String msg) { + return new AlitaResult(code, msg, false, null); + } + + /** + * 创建一个失败的响应对象 + * + * @param code + * @param msg + * @return + */ + public static AlitaResult error(String code, String msg, T data) { + return new AlitaResult(code, msg, false, data); + } + + /** + * 创建一个失败的响应对象 + * + * @param msg + * @return + */ + public static AlitaResult error(String msg, T data) { + return new AlitaResult(SYSTEM_ERROR_CODE, msg, false, data); + } + + /** + * 创建业务异常对象 + * + * @param + * @param msg + * @return + * @author sr on 2020-07-02 + */ + public static AlitaResult bizError(String msg) { + return new AlitaResult(BUSINESS_ERROR_CODE, msg, false, null); + } + + /** + * 创建一个未登录响应对象 + * + * @return + */ + public static AlitaResult unLogin() { + return new AlitaResult(UN_LOGIN_CODE, "请先登录", false, null); + } + + /** + * 创建未实名响应对象 + * @param + * @return + * @author sr on 2021-06-30 + */ + public static AlitaResult unAuth() { + return new AlitaResult(UN_AUTH_CODE, "请先实名", false, null); + } + + /** + * 创建未绑定手机号响应对象 + * @param + * @return + * @author sr on 2021-06-30 + */ + public static AlitaResult unBinding() { + return new AlitaResult(UN_BINDING_PHONE, "请先绑定手机号", false, null); + } + + /** + * 创建一个未登录响应对象 + * + * @param loginUrl 登录地址 + * @return + * @author sr on 2019-12-29 + */ + public static AlitaResult unLogin(String loginUrl) { + return new AlitaResult(UN_LOGIN_CODE, "请先登录", false, loginUrl); + } + + /** + * 更换token + * @param + * @param token + * @return + * @author sr on 2021-08-02 + */ + public static AlitaResult changeToken(Serializable token) { + return new AlitaResult(AlitaResult.CHANGE_TOKEN_CODE, CHANG_TOKEN_MSG, token); + } + + /** + * 创建一个未登录响应对象 + * + * @return + * @author sr on 2019-12-29 + */ + public static AlitaResult noResult() { + return new AlitaResult(NO_RESULT_CODE, "无查询信息", false, null); + } + + /** + * 接口调用失败,未能拿到返回对象 + * + * @param + * @param msg + * @return + * @author sr on 2020-04-10 + */ + public static AlitaResult sdkInvokeNotReachError(String msg) { + return new AlitaResult(SdkConstants.SDK_INVOKE_NOT_REACH_CODE, msg, false, null); + } + + @SuppressWarnings({"hiding", "unchecked"}) + public AlitaResult setRequestId(String requestId){ + this.requestId = requestId; + return (AlitaResult) this; + } + + public AlitaResult setTempJson(String tempJson){ + this.tempJson = tempJson; + return (AlitaResult) this; + } + +} diff --git a/src/main/java/com/newyetai/common/CommonConfiguration.java b/src/main/java/com/newyetai/common/CommonConfiguration.java new file mode 100644 index 0000000..9e0b823 --- /dev/null +++ b/src/main/java/com/newyetai/common/CommonConfiguration.java @@ -0,0 +1,110 @@ +package com.newyetai.common; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.Order; +import org.springframework.core.env.Environment; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.deser.std.StringDeserializer; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.newyetai.common.cache.DefaultCacheProvider; +import com.newyetai.common.cache.ICacheProvider; +import com.newyetai.common.log.ILogProvider; +import com.newyetai.common.log.provider.Slf4jLogProvider; +import com.newyetai.common.log.util.LogUtils; +import com.newyetai.common.service.IMockProvider; +import com.newyetai.common.service.IMockProvider.DefaultMockProvider; +import com.newyetai.common.util.EnvironmentUtils; +import com.newyetai.common.util.MockUtils; +import com.newyetai.component.file.service.IFileStorage; +import com.newyetai.component.file.service.storage.LocalFileStorage; +import com.newyetai.component.file.util.FileStorageUtils; + +import lombok.var; + +/** + * @author sr on 2020-07-24 + */ +@Configuration +public class CommonConfiguration { + + @Bean + EnvironmentUtils environmentUtils(Environment environment) { + return new EnvironmentUtils(environment); + } + + @Bean + @ConditionalOnMissingBean(ICacheProvider.class) + @Order(100) + DefaultCacheProvider defauCacheProvider() { + return new DefaultCacheProvider(); + } + + @Bean + @Order(100) + @ConditionalOnMissingBean(ILogProvider.class) + Slf4jLogProvider slf4jLogProvider() { + return new Slf4jLogProvider(); + } + + @Bean + @Order(200) + LogUtils logUtils(ILogProvider iLogProvider) { + LogUtils logUtils = new LogUtils(); + logUtils.setLogProvider(iLogProvider); + return logUtils; + } + + @Bean + @ConditionalOnMissingBean(IFileStorage.class) + public LocalFileStorage localFileStorage() { + return new LocalFileStorage(); + } + + @Bean + public FileStorageUtils fileStorageUtils(IFileStorage fileStorage) { + return new FileStorageUtils(fileStorage); + } + + @Bean + @ConditionalOnMissingBean(IMockProvider.class) + public IMockProvider defaultMockProvider() { + return new DefaultMockProvider(); + } + + @Bean + public MockUtils mockUtils(IMockProvider mockProvider) { + return new MockUtils(mockProvider); + } + + /** + * requestbody string trim + * @return + * @author sr on 2024-04-19 + */ + @Bean + public SimpleModule stringDeserializerModule() { + final var module = new SimpleModule(); + module.addDeserializer(String.class, new StringDeserializer() { + @Override + public String deserialize(JsonParser p, DeserializationContext ctx) throws java.io.IOException { + final var value = super.deserialize(p, ctx); + if (value == null) { + return null; + } + + final var trimmed = value.trim(); + if (trimmed.isEmpty()) { + return null; + } + + return trimmed; + } + }); + return module; + } + +} diff --git a/src/main/java/com/newyetai/common/CoreConfiguration.java b/src/main/java/com/newyetai/common/CoreConfiguration.java new file mode 100644 index 0000000..fb67569 --- /dev/null +++ b/src/main/java/com/newyetai/common/CoreConfiguration.java @@ -0,0 +1,26 @@ +package com.newyetai.common; + +import org.jasypt.encryption.StringEncryptor; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import com.newyetai.common.trace.DefaultTracer; +import com.newyetai.common.trace.ITracer; +import com.newyetai.common.util.JasyptUtils; + +@Configuration +public class CoreConfiguration { + + @Bean + JasyptUtils jasyptUtils(StringEncryptor stringEncryptor) { + return new JasyptUtils(stringEncryptor); + } + + @Bean + @ConditionalOnMissingBean(value = ITracer.class) + ITracer defaultTracer() { + return new DefaultTracer(); + } + +} diff --git a/src/main/java/com/newyetai/common/actuate/health/dto/HealthDTO.java b/src/main/java/com/newyetai/common/actuate/health/dto/HealthDTO.java new file mode 100644 index 0000000..575c69c --- /dev/null +++ b/src/main/java/com/newyetai/common/actuate/health/dto/HealthDTO.java @@ -0,0 +1,24 @@ +package com.newyetai.common.actuate.health.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 监控健康信息 + * + * @author sr on 2020-07-08 + * @param + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class HealthDTO { + + private String status; + + private T details; + +} diff --git a/src/main/java/com/newyetai/common/annotation/AlitaStopWatch.java b/src/main/java/com/newyetai/common/annotation/AlitaStopWatch.java new file mode 100644 index 0000000..6941de3 --- /dev/null +++ b/src/main/java/com/newyetai/common/annotation/AlitaStopWatch.java @@ -0,0 +1,14 @@ +package com.newyetai.common.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface AlitaStopWatch { + +} diff --git a/src/main/java/com/newyetai/common/annotation/CheckAndMock.java b/src/main/java/com/newyetai/common/annotation/CheckAndMock.java new file mode 100644 index 0000000..ddbadeb --- /dev/null +++ b/src/main/java/com/newyetai/common/annotation/CheckAndMock.java @@ -0,0 +1,56 @@ +package com.newyetai.common.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import com.newyetai.common.constant.ProjectProfileEnum; + +/** + * 校验并mock + * + * @author sr on 2020-05-20 + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface CheckAndMock { + + /** + * 属性前缀 + * + * @return + * @author sr on 2020-05-20 + */ + String propertyPrefix() default ""; + + /** + * 属性配置类 + * + * @return + * @author sr on 2020-05-20 + */ + Class checkAndMockPropertity() default ICheckAndMockPropertity.class; + + /** + * mock实现类(需注入spring上下文,提供与原方法方法名/参数/返回对象一致的方法) + * + * @return + * @author sr on 2020-05-20 + */ + Class mockClass(); + + // String mockBeanId(); + + /** + * 指定环境直接mock + * + * @return + * @author sr on 2020-05-21 + */ + ProjectProfileEnum[] mockIfInProfile() default {}; + + +} diff --git a/src/main/java/com/newyetai/common/annotation/CheckJob.java b/src/main/java/com/newyetai/common/annotation/CheckJob.java new file mode 100644 index 0000000..a7a6058 --- /dev/null +++ b/src/main/java/com/newyetai/common/annotation/CheckJob.java @@ -0,0 +1,27 @@ +package com.newyetai.common.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 校验定时任务是否开启 + * + * @author sr on 2020-05-19 + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface CheckJob { + + /** + * 配置文件是否开启的key,明确指定为false时才关闭 + * + * @return + * @author sr on 2020-05-19 + */ + String value(); + +} diff --git a/src/main/java/com/newyetai/common/annotation/ICheckAndMockPropertity.java b/src/main/java/com/newyetai/common/annotation/ICheckAndMockPropertity.java new file mode 100644 index 0000000..805f4f3 --- /dev/null +++ b/src/main/java/com/newyetai/common/annotation/ICheckAndMockPropertity.java @@ -0,0 +1,34 @@ +package com.newyetai.common.annotation; + +/** + * 需要校验后mock的配置 + * + * @author sr on 2020-05-20 + */ +public interface ICheckAndMockPropertity { + + /** + * 是否开启 + * + * @return + * @author sr on 2020-05-21 + */ + Boolean getEnable(); + + /** + * 次数限制 + * + * @return + * @author sr on 2020-05-21 + */ + Long getNumLimit(); + + /** + * 属性前缀 + * + * @return + * @author sr on 2020-05-21 + */ + String getPropertityPrefix(); + +} diff --git a/src/main/java/com/newyetai/common/annotation/Mask.java b/src/main/java/com/newyetai/common/annotation/Mask.java new file mode 100644 index 0000000..682ccdb --- /dev/null +++ b/src/main/java/com/newyetai/common/annotation/Mask.java @@ -0,0 +1,19 @@ +package com.newyetai.common.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; + +/** + * 掩码 + * @author sr on 2021-11-25 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD, ElementType.METHOD}) +@JacksonAnnotationsInside +public @interface Mask { + +} diff --git a/src/main/java/com/newyetai/common/annotation/MaskAnontationIntrospector.java b/src/main/java/com/newyetai/common/annotation/MaskAnontationIntrospector.java new file mode 100644 index 0000000..4ac8670 --- /dev/null +++ b/src/main/java/com/newyetai/common/annotation/MaskAnontationIntrospector.java @@ -0,0 +1,32 @@ +package com.newyetai.common.annotation; + +import com.fasterxml.jackson.databind.introspect.Annotated; +import com.fasterxml.jackson.databind.introspect.AnnotatedMember; +import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; + +/** + * @author sr on 2021-11-25 + */ +public class MaskAnontationIntrospector extends JacksonAnnotationIntrospector { + + private static final long serialVersionUID = 1L; + + @Override + public Object findSerializer(Annotated a) { + Mask mask = a.getAnnotation(Mask.class); + if (mask != null) { + return MaskSerializer.class; + } + return super.findSerializer(a); + } + + @Override + public boolean hasIgnoreMarker(AnnotatedMember m) { + // 直接不打印该字段,则置为true + /*if (m.hasAnnotation(Mask.class)) { + return true; + }*/ + return super.hasIgnoreMarker(m); + } + +} diff --git a/src/main/java/com/newyetai/common/annotation/MaskSerializer.java b/src/main/java/com/newyetai/common/annotation/MaskSerializer.java new file mode 100644 index 0000000..456c5bf --- /dev/null +++ b/src/main/java/com/newyetai/common/annotation/MaskSerializer.java @@ -0,0 +1,37 @@ +package com.newyetai.common.annotation; + +import java.io.IOException; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; + +/** + * @author sr on 2021-11-25 + */ +public class MaskSerializer extends StdSerializer { + + private static final long serialVersionUID = 1L; + + private String mask = "***"; + + public MaskSerializer() { + super(Object.class); + } + + public MaskSerializer(String mask, int count) { + this(); + } + + public MaskSerializer(MaskSerializer src) { + super(src); + } + + @Override + public void serialize(Object s, JsonGenerator jsonGenerator, + SerializerProvider serializerProvider) throws IOException { + jsonGenerator.writeString(mask); + } + + +} diff --git a/src/main/java/com/newyetai/common/annotation/aspect/AlitaStopWatchAspect.java b/src/main/java/com/newyetai/common/annotation/aspect/AlitaStopWatchAspect.java new file mode 100644 index 0000000..c27cedc --- /dev/null +++ b/src/main/java/com/newyetai/common/annotation/aspect/AlitaStopWatchAspect.java @@ -0,0 +1,49 @@ +package com.newyetai.common.annotation.aspect; + +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.stereotype.Component; +import org.springframework.util.StopWatch; + +import com.newyetai.common.annotation.AlitaStopWatch; +import com.newyetai.common.exception.util.DevopsUtils; +import com.newyetai.common.util.EnvironmentUtils; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Aspect +@Component +public class AlitaStopWatchAspect { + + public static final String DEVOPS_TIME_KEY = "devops.usetime"; + /** 默认十分钟 **/ + public static final Long DEFAULT_DEVOPS_TIME = 10 * 60L; + + + @Around("@annotation(alitaStopWatch)") + public Object around(ProceedingJoinPoint joinPoint, AlitaStopWatch alitaStopWatch) throws Throwable { + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + try { + return joinPoint.proceed(); + } finally { + stopWatch.stop(); + String useTimeStr = EnvironmentUtils.getProperty(DEVOPS_TIME_KEY); + Long maxUseTime = DEFAULT_DEVOPS_TIME; + try { + maxUseTime = Long.parseLong(useTimeStr); + } catch (Exception e) { + } + maxUseTime = 1000 * maxUseTime; + Long actualTime = stopWatch.getTotalTimeMillis(); + String logMsg = joinPoint.getSignature().toShortString() + ",use(ms): " + actualTime; + if (actualTime > maxUseTime) { + DevopsUtils.deal(logMsg); + } + log.info(logMsg); + } + } + +} diff --git a/src/main/java/com/newyetai/common/annotation/aspect/CheckAndMockAspect.java b/src/main/java/com/newyetai/common/annotation/aspect/CheckAndMockAspect.java new file mode 100644 index 0000000..cceccc7 --- /dev/null +++ b/src/main/java/com/newyetai/common/annotation/aspect/CheckAndMockAspect.java @@ -0,0 +1,129 @@ +package com.newyetai.common.annotation.aspect; + +import com.newyetai.common.annotation.CheckAndMock; +import com.newyetai.common.annotation.ICheckAndMockPropertity; +import com.newyetai.common.cache.ICacheProvider; +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.constant.ProjectProfileEnum; +import com.newyetai.common.util.SpringContextHolder; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.annotation.Order; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Component; + +import java.lang.reflect.Method; + +/** + * 校验并mock + * + * @author sr on 2020-05-19 + */ +@Aspect +@Component +@Slf4j +@Order(200) +public class CheckAndMockAspect { + + /** 是否开启属性 **/ + public static final String ENABLE_KEY = "enable"; + /** 次数限制属性 **/ + public static final String NUM_LIMIT_KEY = "numLimit"; + /** 默认次数 **/ + public static final Long DEFALUT_NUM_LIMIT = 3L; + + @Autowired + private Environment environment; + + @Autowired + private ICacheProvider iCacheProvider; + + @Around("@annotation(checkAndMock)") + public Object around(ProceedingJoinPoint joinPoint, CheckAndMock checkAndMock) throws Throwable { + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); + Method method = signature.getMethod(); + ProjectProfileEnum[] profileEnums = checkAndMock.mockIfInProfile(); + Class mockClass = checkAndMock.mockClass(); + String currentProfile = environment.getProperty(CommonConstants.PROFILE_KEY); + + Object[] args = joinPoint.getArgs(); + // 只要配置环境mock,就不校验开关和次数限制 + if (profileEnums.length > 0) { + for (ProjectProfileEnum profileEnum : profileEnums) { + if (profileEnum.getValue().equals(currentProfile)) { + return mock(mockClass, method, args); + } + } + return joinPoint.proceed(); + } + + // 获取属性配置 + String propertyPrefix = checkAndMock.propertyPrefix(); + boolean enable = true; + Long numLimit = null; + if (StringUtils.isNotBlank(propertyPrefix)) { + enable = BooleanUtils.toBoolean( + environment.getProperty(String.join(CommonConstants.POINT, propertyPrefix, ENABLE_KEY))); + try { + numLimit = enable ? Long.parseLong(environment + .getProperty(String.join(CommonConstants.POINT, propertyPrefix, NUM_LIMIT_KEY))) : 0L; + } catch (NumberFormatException e) { + log.info("{} numLimit not right, use default numLimit", propertyPrefix); + } + } else { + try { + ICheckAndMockPropertity properties = + SpringContextHolder.getBean(checkAndMock.checkAndMockPropertity()); + enable = properties.getEnable(); + numLimit = properties.getNumLimit(); + propertyPrefix = properties.getPropertityPrefix(); + } catch (Exception e) { + log.info("ICheckAndMockPropertity not found..."); + enable = false; + } + } + + // 开关关闭,都走mock + if (!enable) { + return mock(mockClass, method, args); + } + // 开关开启,生产无次数限制,本地测试根据配置/默认次数控制 + boolean isProd = ProjectProfileEnum.PROD.getValue().equals(currentProfile); + if (isProd) { + return joinPoint.proceed(); + } + + numLimit = numLimit == null ? DEFALUT_NUM_LIMIT : numLimit; + String key = String.join(CommonConstants.POINT, propertyPrefix, NUM_LIMIT_KEY); + if (iCacheProvider.outLimit(key, numLimit)) { + // 超限,mock + return mock(mockClass, method, args); + } + // 次数限制 + return joinPoint.proceed(); + } + + + /** + * mock调用 + * + * @param clazz + * @param method + * @param objects + * @return + * @throws Throwable + * @author sr on 2020-05-21 + */ + private Object mock(Class clazz, Method method, Object[] objects) throws Throwable { + Object mockBean = SpringContextHolder.getBean(clazz); + Method mockMethod = mockBean.getClass().getMethod(method.getName(), method.getParameterTypes()); + return mockMethod.invoke(mockBean, objects); + } + +} diff --git a/src/main/java/com/newyetai/common/annotation/aspect/CheckJobAspect.java b/src/main/java/com/newyetai/common/annotation/aspect/CheckJobAspect.java new file mode 100644 index 0000000..adff889 --- /dev/null +++ b/src/main/java/com/newyetai/common/annotation/aspect/CheckJobAspect.java @@ -0,0 +1,46 @@ +package com.newyetai.common.annotation.aspect; + +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Component; + +import com.newyetai.common.annotation.CheckJob; +import com.newyetai.common.constant.CommonConstants; + +import lombok.extern.slf4j.Slf4j; + +/** + * 校验定时任务是否开启 + * + * @author sr on 2020-05-19 + */ +@Aspect +@Component +@Slf4j +public class CheckJobAspect { + + /** 配置无效识别符(只有配置false才失效) **/ + private String falseValue = "false"; + + /** 定时任务配置前缀 **/ + public static final String JOB_PROPERTY_PREFIX = "job"; + + @Autowired + private Environment environment; + + @Around("@annotation(checkJob)") + public Object around(ProceedingJoinPoint joinPoint, CheckJob checkJob) throws Throwable { + String propertityKey = checkJob.value(); + boolean disable = falseValue.equals(environment + .getProperty(String.join(CommonConstants.POINT, JOB_PROPERTY_PREFIX, propertityKey))); + if (disable) { + log.info("job:{} not enable...", propertityKey); + return null; + } + return joinPoint.proceed(); + } + +} diff --git a/src/main/java/com/newyetai/common/annotation/trimAndUpper/TrimAndUpper.java b/src/main/java/com/newyetai/common/annotation/trimAndUpper/TrimAndUpper.java new file mode 100644 index 0000000..a9acfdb --- /dev/null +++ b/src/main/java/com/newyetai/common/annotation/trimAndUpper/TrimAndUpper.java @@ -0,0 +1,31 @@ +package com.newyetai.common.annotation.trimAndUpper; + +import java.lang.annotation.*; + +/** + * 用于字符串去空格以及大写 + * + * @author Carlye + * @date 2022/02/16 + */ +@Target(value = { ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER }) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface TrimAndUpper { + + /** + * 执行类型 + * ALL: (所有类型都包含) + * TRIM: (去两边的空格) + * REPLACE_ALL: (去所有的空格) + * UPPER_CASE: (转大写) + * + * @author Carlye + * @date 2022/02/16 + */ + public static enum ExecuteType { + ALL, TRIM, REPLACE_ALL, UPPER_CASE; + } + + ExecuteType value() default ExecuteType.ALL; +} diff --git a/src/main/java/com/newyetai/common/annotation/trimAndUpper/TrimAndUpperAnontationIntrospector.java b/src/main/java/com/newyetai/common/annotation/trimAndUpper/TrimAndUpperAnontationIntrospector.java new file mode 100644 index 0000000..95b88f3 --- /dev/null +++ b/src/main/java/com/newyetai/common/annotation/trimAndUpper/TrimAndUpperAnontationIntrospector.java @@ -0,0 +1,27 @@ +package com.newyetai.common.annotation.trimAndUpper; + +import com.fasterxml.jackson.databind.AnnotationIntrospector; +import com.fasterxml.jackson.databind.introspect.Annotated; +import com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair; + +/** + * @author sr on 2021-11-25 + */ +public class TrimAndUpperAnontationIntrospector extends AnnotationIntrospectorPair { + + + private static final long serialVersionUID = -1755768596246088917L; + + public TrimAndUpperAnontationIntrospector(AnnotationIntrospector p, + AnnotationIntrospector s) { + super(p, s); + } + @Override + public Object findDeserializer(Annotated a) { + TrimAndUpper trim = a.getAnnotation(TrimAndUpper.class); + if (trim != null) { + return TrimAndUpperDeserializer.class; + } + return super.findDeserializer(a); + } +} diff --git a/src/main/java/com/newyetai/common/annotation/trimAndUpper/TrimAndUpperConfig.java b/src/main/java/com/newyetai/common/annotation/trimAndUpper/TrimAndUpperConfig.java new file mode 100644 index 0000000..821912c --- /dev/null +++ b/src/main/java/com/newyetai/common/annotation/trimAndUpper/TrimAndUpperConfig.java @@ -0,0 +1,59 @@ +package com.newyetai.common.annotation.trimAndUpper; + +import com.fasterxml.jackson.databind.AnnotationIntrospector; +import com.fasterxml.jackson.databind.DeserializationConfig; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.cfg.BaseSettings; +import com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair; +import java.lang.reflect.Field; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.format.FormatterRegistry; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.util.ReflectionUtils; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; + +@Configuration +public class TrimAndUpperConfig { + + @Autowired + public void addFormatters(FormatterRegistry registry) { + TrimAndUpperFormatterFactory trimAndUpperCaseFormatterFactory = new TrimAndUpperFormatterFactory(); + registry.addFormatterForFieldAnnotation(trimAndUpperCaseFormatterFactory); + } + + @Autowired + public void init(RequestMappingHandlerAdapter handlerAdapter){ + for (HttpMessageConverter messageConverter : handlerAdapter.getMessageConverters()) { + try { + if (messageConverter instanceof MappingJackson2HttpMessageConverter){ + MappingJackson2HttpMessageConverter converter1 = (MappingJackson2HttpMessageConverter)messageConverter; + ObjectMapper objectMapper = converter1.getObjectMapper(); + DeserializationConfig deserializationConfig = objectMapper.getDeserializationConfig(); + + Field _base = ReflectionUtils.findField(DeserializationConfig.class, "_base"); + ReflectionUtils.makeAccessible(_base); + BaseSettings baseSettings = (BaseSettings)ReflectionUtils.getField(_base, deserializationConfig); + + AnnotationIntrospector annotationIntrospector = baseSettings.getAnnotationIntrospector(); + if (annotationIntrospector instanceof AnnotationIntrospectorPair){ + AnnotationIntrospectorPair annotationIntrospectorOld = (AnnotationIntrospectorPair)baseSettings.getAnnotationIntrospector(); + + Field _primary = ReflectionUtils.findField(AnnotationIntrospectorPair.class, "_primary"); + ReflectionUtils.makeAccessible(_primary); + AnnotationIntrospector _primaryObj = (AnnotationIntrospector)ReflectionUtils.getField(_primary, annotationIntrospectorOld); + + Field _secondary = ReflectionUtils.findField(AnnotationIntrospectorPair.class, "_secondary"); + ReflectionUtils.makeAccessible(_secondary); + AnnotationIntrospector _secondaryObj = (AnnotationIntrospector)ReflectionUtils.getField(_secondary, annotationIntrospectorOld); + + converter1.getObjectMapper().setAnnotationIntrospector(new TrimAndUpperAnontationIntrospector(_primaryObj,_secondaryObj)); + } + } + } catch (Exception e) { + //doNothing + } + } + } +} diff --git a/src/main/java/com/newyetai/common/annotation/trimAndUpper/TrimAndUpperDeserializer.java b/src/main/java/com/newyetai/common/annotation/trimAndUpper/TrimAndUpperDeserializer.java new file mode 100644 index 0000000..78e910b --- /dev/null +++ b/src/main/java/com/newyetai/common/annotation/trimAndUpper/TrimAndUpperDeserializer.java @@ -0,0 +1,66 @@ +package com.newyetai.common.annotation.trimAndUpper; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.BeanProperty; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.deser.ContextualDeserializer; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.google.common.collect.Maps; +import com.newyetai.common.annotation.trimAndUpper.TrimAndUpper.ExecuteType; +import java.io.IOException; +import java.util.Map; +import java.util.Objects; +import org.apache.commons.lang3.StringUtils; + +public class TrimAndUpperDeserializer extends StdDeserializer implements ContextualDeserializer { + + private static final Map INSTANCE_MAP = Maps.newHashMap(); + private static final long serialVersionUID = 3463447204376923373L; + + static { + for (ExecuteType value : ExecuteType.values()) { + INSTANCE_MAP.put(value,new TrimAndUpperDeserializer(value)); + } + } + + private ExecuteType executeType; + + public TrimAndUpperDeserializer(){ + super(String.class); + } + + public TrimAndUpperDeserializer(ExecuteType executeType){ + super(String.class); + this.executeType = executeType; + } + + @Override + public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException { + String s = jsonParser.getText(); + if (!(StringUtils.isEmpty(s) || Objects.isNull(executeType))) { + if (ExecuteType.ALL.equals(executeType) || ExecuteType.TRIM.equals(executeType)) { + s = StringUtils.replace(StringUtils.trim(s)," ",""); + } + if (ExecuteType.ALL.equals(executeType) || ExecuteType.TRIM.equals(executeType)) { + s = StringUtils.upperCase(s); + } + } + return s; + } + + @Override + public JsonDeserializer createContextual(DeserializationContext prov, BeanProperty property) throws JsonMappingException { + ExecuteType executeType = null; + TrimAndUpper ann = null; + if (property != null) { + ann = property.getAnnotation(TrimAndUpper.class); + } + if (ann != null) { + executeType = ann.value(); + } + return INSTANCE_MAP.get(executeType); + } +} diff --git a/src/main/java/com/newyetai/common/annotation/trimAndUpper/TrimAndUpperFormatterFactory.java b/src/main/java/com/newyetai/common/annotation/trimAndUpper/TrimAndUpperFormatterFactory.java new file mode 100644 index 0000000..2af7c78 --- /dev/null +++ b/src/main/java/com/newyetai/common/annotation/trimAndUpper/TrimAndUpperFormatterFactory.java @@ -0,0 +1,77 @@ +package com.newyetai.common.annotation.trimAndUpper; + +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import com.newyetai.common.annotation.trimAndUpper.TrimAndUpper.ExecuteType; +import org.apache.commons.lang3.StringUtils; +import org.springframework.format.AnnotationFormatterFactory; +import org.springframework.format.Formatter; +import org.springframework.format.Parser; +import org.springframework.format.Printer; + +import java.text.ParseException; +import java.util.*; + +public class TrimAndUpperFormatterFactory implements + AnnotationFormatterFactory { + + private static final Map TRIMMER_FORMATTER_MAP; + + static { + ExecuteType[] values = ExecuteType.values(); + Map map = Maps.newHashMap(); + for (ExecuteType type : values) { + map.put(type, new TrimAndUpperCaseFormatter(type)); + } + TRIMMER_FORMATTER_MAP = Collections.unmodifiableMap(map); + } + + @Override + public Set> getFieldTypes() { + return Sets.newHashSet(String.class); + } + + @Override + public Printer getPrinter(TrimAndUpper trimAndUpper, Class aClass) { + return TRIMMER_FORMATTER_MAP.get(trimAndUpper.value()); + } + + @Override + public Parser getParser(TrimAndUpper trimAndUpper, Class aClass) { + return TRIMMER_FORMATTER_MAP.get(trimAndUpper.value()); + } + + private static class TrimAndUpperCaseFormatter implements Formatter { + + private TrimAndUpper.ExecuteType executeType; + + public TrimAndUpperCaseFormatter(TrimAndUpper.ExecuteType executeType) { + this.executeType = executeType; + } + + @Override + public String parse(String value, Locale locale) throws ParseException { + if (StringUtils.isEmpty(value) || Objects.isNull(executeType)) { + return value; + } + // 去所有空格 + if (ExecuteType.ALL.equals(executeType) || ExecuteType.REPLACE_ALL.equals(executeType)) { + value = StringUtils.replace(value, " ", ""); + } + // 转大写 + if (ExecuteType.ALL.equals(executeType) || ExecuteType.UPPER_CASE.equals(executeType)) { + value = StringUtils.upperCase(value); + } + //去两边空格 + if (ExecuteType.ALL.equals(executeType) || ExecuteType.TRIM.equals(executeType)) { + value = StringUtils.trim(value); + } + return value; + } + + @Override + public String print(String value, Locale locale) { + return value; + } + } +} diff --git a/src/main/java/com/newyetai/common/cache/DefaultCacheProvider.java b/src/main/java/com/newyetai/common/cache/DefaultCacheProvider.java new file mode 100644 index 0000000..288b023 --- /dev/null +++ b/src/main/java/com/newyetai/common/cache/DefaultCacheProvider.java @@ -0,0 +1,31 @@ +package com.newyetai.common.cache; + +import java.util.Map; + +import org.apache.commons.collections.MapUtils; + +import com.google.common.collect.Maps; + +/** + * @author sr on 2020-07-07 + */ +public class DefaultCacheProvider implements ICacheProvider { + + private Map numLimitMap = Maps.newConcurrentMap(); + + @Override + public boolean outLimit(final String key, Long maxNumLimit) { + Long currentNumLimit = null; + final Object lockKey = key.intern(); + synchronized (lockKey) { + currentNumLimit = MapUtils.getLong(numLimitMap, key, 0L); + if (currentNumLimit >= maxNumLimit) { + return true; + } + currentNumLimit++; + numLimitMap.put(key, currentNumLimit); + } + return false; + } + +} diff --git a/src/main/java/com/newyetai/common/cache/ICacheProvider.java b/src/main/java/com/newyetai/common/cache/ICacheProvider.java new file mode 100644 index 0000000..83a28cc --- /dev/null +++ b/src/main/java/com/newyetai/common/cache/ICacheProvider.java @@ -0,0 +1,18 @@ +package com.newyetai.common.cache; + +/** + * @author sr on 2020-07-07 + */ +public interface ICacheProvider { + + /** + * 是否超限 + * + * @param key + * @param maxNumLimit + * @return + * @author sr on 2020-07-07 + */ + boolean outLimit(String key, Long maxNumLimit); + +} diff --git a/src/main/java/com/newyetai/common/cache/RedisCacheProvier.java b/src/main/java/com/newyetai/common/cache/RedisCacheProvier.java new file mode 100644 index 0000000..20da121 --- /dev/null +++ b/src/main/java/com/newyetai/common/cache/RedisCacheProvier.java @@ -0,0 +1,32 @@ +package com.newyetai.common.cache; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.core.annotation.Order; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; + +/** + * @author sr on 2020-07-07 + */ +@Service +@ConditionalOnClass(RedisTemplate.class) +@Order(1) +public class RedisCacheProvier implements ICacheProvider{ + + @SuppressWarnings("rawtypes") + @Autowired(required = false) + private RedisTemplate redisTemplate; + + @SuppressWarnings("unchecked") + @Override + public boolean outLimit(String key, Long maxNumLimit) { + Long currentNumLimit = redisTemplate.opsForValue().increment(key); + if (currentNumLimit > maxNumLimit) { + redisTemplate.opsForValue().decrement(key); + return true; + } + return false; + } + +} diff --git a/src/main/java/com/newyetai/common/constant/AuthStatusEnum.java b/src/main/java/com/newyetai/common/constant/AuthStatusEnum.java new file mode 100644 index 0000000..8700dbe --- /dev/null +++ b/src/main/java/com/newyetai/common/constant/AuthStatusEnum.java @@ -0,0 +1,52 @@ +package com.newyetai.common.constant; + +import com.google.common.collect.Maps; +import java.util.Map; +import javax.validation.constraints.NotNull; + +/** + * 系统枚举 + * + * @author sr on 2020-06-02 + */ +public enum AuthStatusEnum { + + /** + * 待认证 + **/ + NOT_AUTH(1, "待认证"), + /** + * 认证中 + **/ + AUTHING(2, "认证中"), + /** + * 认证成功 + **/ + AUTH_SUCCESS(3, "认证成功"), + /** + * 认证失败 + **/ + AUTH_FAIL(4, "认证失败"); + + /** + * 状态类型 + */ + private Integer type; + /** + * 状态名称 + */ + private String name; + + AuthStatusEnum(Integer type, String name) { + this.type = type; + this.name = name; + } + + public Integer getType() { + return type; + } + + public String getName() { + return name; + } +} diff --git a/src/main/java/com/newyetai/common/constant/CacheConstants.java b/src/main/java/com/newyetai/common/constant/CacheConstants.java new file mode 100644 index 0000000..83bf196 --- /dev/null +++ b/src/main/java/com/newyetai/common/constant/CacheConstants.java @@ -0,0 +1,12 @@ +package com.newyetai.common.constant; + +/** + * 缓存常量 + * + * @author sr on 2020-04-03 + */ +public interface CacheConstants { + + String CACHE_NAME_DICT = "dict"; + +} diff --git a/src/main/java/com/newyetai/common/constant/CommonConstants.java b/src/main/java/com/newyetai/common/constant/CommonConstants.java new file mode 100644 index 0000000..3f9a7c7 --- /dev/null +++ b/src/main/java/com/newyetai/common/constant/CommonConstants.java @@ -0,0 +1,66 @@ +package com.newyetai.common.constant; + +/** + * 公共常量 + * @author sr on 2019-12-03 + */ +public interface CommonConstants { + + /** _(下划线) **/ + String UNDERLINE = "_"; + /** # **/ + String POUND = "#"; + /** & **/ + String AND = "&"; + /** ,(逗号) **/ + String COMMA = ","; + /** :(冒号) **/ + String COLON = ":"; + /** ;(分号) **/ + String SEMICOLON = ";"; + /** . **/ + String POINT = "."; + /** = **/ + String EQUAL = "="; + /** ? **/ + String QUESTION = "?"; + /** -(连字号) **/ + String HYPHEN = "-"; + /** ...(省略号) **/ + String ELLIPSIS = "..."; + + /** 金额精度:两位 **/ + int AMOUNT_SCALE = 2; + + /** 金额小数位 **/ + int AMOUNT_FRACTION = 2; + /** 金额整数位 **/ + int AMOUNT_INTEGER = 14; + + + /** 项目环境配置key **/ + String PROFILE_KEY = "spring.profiles.active"; + /** 项目名称 **/ + String APPLICATION_NAME_KEY = "spring.application.name"; + /** security是否使用本地方法 **/ + String USELOCAL_KEY = "security.useLocal"; + + /** + * 表字段去空格 + */ + String TRIM_TABLE_FIELDS_ENBALE_KEY = "trim.table.fields"; + + /** 开关键 **/ + String ENABLE_KEY = "enable"; + + String FALSE_STR = "false"; + + /** 配置值:是 **/ + String CONFIG_TRUE = "1"; + /** 配置值:否 **/ + String CONFIG_FALSE = "0"; + + /** 平台机构id **/ + Long PLATFORM_ORG_ID = 1L; + +} diff --git a/src/main/java/com/newyetai/common/constant/CommonMqConstants.java b/src/main/java/com/newyetai/common/constant/CommonMqConstants.java new file mode 100644 index 0000000..25a99ee --- /dev/null +++ b/src/main/java/com/newyetai/common/constant/CommonMqConstants.java @@ -0,0 +1,18 @@ +package com.newyetai.common.constant; + +public interface CommonMqConstants { + + /** 用户中心系统mq前缀 **/ + String FORWARD_MQ_PREFIX = SystemCodeEnum.ALITA_FORWARD.getName() + CommonConstants.POINT; + + + /** + * 保存异常和发送叮 + */ + String SAVE_EXCEPTION_AND_SEND_DING = CommonMqConstants.FORWARD_MQ_PREFIX + "save_exception_and_send_ding"; + + + /** 操作记录 **/ + String ACTION_LOG = SystemCodeEnum.ALITA_TASK_NAME + CommonConstants.POINT + "action_log"; + +} diff --git a/src/main/java/com/newyetai/common/constant/CookieConstants.java b/src/main/java/com/newyetai/common/constant/CookieConstants.java new file mode 100644 index 0000000..7c3767e --- /dev/null +++ b/src/main/java/com/newyetai/common/constant/CookieConstants.java @@ -0,0 +1,18 @@ +package com.newyetai.common.constant; + +/** + * @author Jerry.li + * @description Cookie相关常量 + * @date 2020/5/11 + */ +public class CookieConstants { + + /** + * 登录Cookie名称前缀 + */ + public static final String LOGIN_COOKIE_NAME_PREFIX = "xs_ck_"; + + /** 属性配置键:cookie域名 **/ + public static final String PROP_KEY_COOKIE_DOMAIN = "cookie.domain"; + +} diff --git a/src/main/java/com/newyetai/common/constant/ExceptionMsgs.java b/src/main/java/com/newyetai/common/constant/ExceptionMsgs.java new file mode 100644 index 0000000..77c6579 --- /dev/null +++ b/src/main/java/com/newyetai/common/constant/ExceptionMsgs.java @@ -0,0 +1,21 @@ +package com.newyetai.common.constant; + +/** + * 异常错误信息 + * + * @author on 2019-11-05 + */ +public interface ExceptionMsgs { + + String ENTITY_HAS_EXISTS = "数据已存在"; + + String ENTITY_NONE_EXISTS = "数据不存在"; + + String ENTITY_MULTIPLE_EXISTS = "数据存在多条"; + + String UPDATE_DATA_NOT_EXIST = "操作失败,请检查数据"; + + + + +} diff --git a/src/main/java/com/newyetai/common/constant/ExceptionRecordConstants.java b/src/main/java/com/newyetai/common/constant/ExceptionRecordConstants.java new file mode 100644 index 0000000..3195e4c --- /dev/null +++ b/src/main/java/com/newyetai/common/constant/ExceptionRecordConstants.java @@ -0,0 +1,10 @@ +package com.newyetai.common.constant; + +public interface ExceptionRecordConstants { + + /** + * 接口记录系统类型 + */ + String SOURCE_HYG = "1"; + String SOURCE_XINPAI = "2"; +} diff --git a/src/main/java/com/newyetai/common/constant/GenderEnum.java b/src/main/java/com/newyetai/common/constant/GenderEnum.java new file mode 100644 index 0000000..4363507 --- /dev/null +++ b/src/main/java/com/newyetai/common/constant/GenderEnum.java @@ -0,0 +1,48 @@ +package com.newyetai.common.constant; + +/** + * 性别枚举 + * + */ +public enum GenderEnum { + + MALE(1, "男"), + FEMALE(2, "女"), + OTHER(3, "其它"); + + private final Integer type; + + private final String desc; + + GenderEnum(Integer type, String desc) { + this.type = type; + this.desc = desc; + } + + public Integer getType() { + return type; + } + + public String getDesc() { + return desc; + } + + public static Integer formatFemale(Integer value){ + // 通过sql 身份证号处理性别条件:0女,1男 + if(GenderEnum.FEMALE.getType().equals(value)){ + return 0; + } + return value; + } + + public static String getVal(Integer val){ + if(GenderEnum.MALE.getType().equals(val)){ + return GenderEnum.MALE.desc; + } else if(GenderEnum.FEMALE.getType().equals(val)){ + return GenderEnum.FEMALE.desc; + } + return GenderEnum.OTHER.desc; + } + + +} diff --git a/src/main/java/com/newyetai/common/constant/ProjectProfileEnum.java b/src/main/java/com/newyetai/common/constant/ProjectProfileEnum.java new file mode 100644 index 0000000..3f65e7e --- /dev/null +++ b/src/main/java/com/newyetai/common/constant/ProjectProfileEnum.java @@ -0,0 +1,30 @@ +package com.newyetai.common.constant; + +/** + * 项目环境枚举 + * @author sr on 2020-05-20 + */ +public enum ProjectProfileEnum { + + /** 开发 **/ + DEV("dev"), + /** 测试 **/ + TEST("test"), + /** 测试 * */ + UAT("uat"), + /** 生产 **/ + PROD("prod"), + /** 福安 **/ + FUAN("fuan"); + + private String value; + + ProjectProfileEnum(String value){ + this.value = value; + } + + public String getValue() { + return this.value; + } + +} diff --git a/src/main/java/com/newyetai/common/constant/SystemCodeEnum.java b/src/main/java/com/newyetai/common/constant/SystemCodeEnum.java new file mode 100644 index 0000000..06ddbc3 --- /dev/null +++ b/src/main/java/com/newyetai/common/constant/SystemCodeEnum.java @@ -0,0 +1,152 @@ +package com.newyetai.common.constant; + +import com.google.common.collect.Maps; + +import javax.validation.constraints.NotNull; +import java.util.Map; + +/** + * 系统枚举 + * + * @author sr on 2020-06-02 + */ +public enum SystemCodeEnum { + + /** + * 业务系统,纽业态灵活就业平台 + **/ + ALITA_TASK(1, SystemCodeEnum.ALITA_TASK_NAME), + /** + * 结算系统,运营中台 + **/ + ALITA_SETTLEMENT(2, SystemCodeEnum.ALITA_SETTLEMENT_NAME), + /** + * 用户中心 + **/ + ALITA_USER_CENTER(3, SystemCodeEnum.ALITA_USER_CENTER_NAME), + /** + * 支付系统 + **/ + ALITA_PAY(4, SystemCodeEnum.ALITA_PAY_NAME), + /** + * 在线培训 + **/ + ALITA_CLASS(5, SystemCodeEnum.ALITA_CLASS_NAME), + /** + * 转发器 + **/ + ALITA_FORWARD(6, SystemCodeEnum.ALITA_FORWARD_NAME), + /** + * 风控 + **/ + ALITA_RISK_CONTROL(7, SystemCodeEnum.ALITA_RISK_CONTROL_NAME), + /** + * 网关 + **/ + ALITA_GATEWAY(8, SystemCodeEnum.ALITA_GATEWAY_NAME), + /** + * 发号器 + **/ + ALITA_LEAF(9, SystemCodeEnum.ALITA_LEAF_NAME), + /** + * 基础框架 + **/ + ALITA_FRAMEWORK(10, SystemCodeEnum.ALITA_FRAMEWORK_NAME), + /** + * CMS + **/ + ALITA_CMS(11, SystemCodeEnum.ALITA_CMS_NAME), + /** + * 监管者 + **/ + ALITA_REGULATOR(12, SystemCodeEnum.ALITA_REGULATOR_NAME), + /** + * 招聘系统 + **/ + ALITA_RECRUIT(13, SystemCodeEnum.ALITA_RECRUIT_NAME), + + /** + * 招聘系统小程序 + */ + ALITA_RECRUIT_MINI_PROGRAM(14, SystemCodeEnum.ALITA_RECRUIT_MINI_PROGRAM_NAME), + + /** + * 无卡发薪系统 + */ + ALITA_UPAY_PROGRAM(15, SystemCodeEnum.ALITA_UPAY_NAME), + + /** 长三角招聘 **/ + ALITA_JOB(16, SystemCodeEnum.ALITA_JOB_NAME), + /** **/ + ALITA_BJY(17, SystemCodeEnum.ALITA_BJY_NAME), + ; + + public static final String ALITA_TASK_NAME = "alita-task"; + public static final String ALITA_SETTLEMENT_NAME = "alita-settlement"; + public static final String ALITA_USER_CENTER_NAME = "alita-user-center"; + public static final String ALITA_PAY_NAME = "alita-pay"; + public static final String ALITA_CLASS_NAME = "alita-class"; + public static final String ALITA_FORWARD_NAME = "alita-forward"; + public static final String ALITA_RISK_CONTROL_NAME = "alita-risk-control"; + public static final String ALITA_GATEWAY_NAME = "alita-gateway"; + public static final String ALITA_LEAF_NAME = "alita-leaf"; + public static final String ALITA_FRAMEWORK_NAME = "alita-framework"; + public static final String ALITA_CMS_NAME = "alita-cms"; + public static final String ALITA_REGULATOR_NAME = "alita-regulator"; + public static final String ALITA_RECRUIT_NAME = "alita-recruit"; + public static final String ALITA_UPAY_NAME = "alita-upay"; + public static final String ALITA_JOB_NAME = "alita-job"; + public static final String ALITA_BJY_NAME = "alita-bjy"; + + public static final String ALITA_RECRUIT_MINI_PROGRAM_NAME = "alita-recruit-mini-program"; + + /** + * 系统名称map + **/ + private static Map systemNameMap; + + static { + SystemCodeEnum[] systemCodeEnums = SystemCodeEnum.values(); + systemNameMap = Maps.newHashMapWithExpectedSize(systemCodeEnums.length); + for (SystemCodeEnum systemCodeEnum : systemCodeEnums) { + systemNameMap.put(systemCodeEnum.getName(), systemCodeEnum); + } + } + + /** + * 应用编号 + */ + private Integer code; + /** + * 应用名称 + */ + private String name; + + SystemCodeEnum(Integer code, String name) { + this.code = code; + this.name = name; + } + + public Integer getCode() { + return code; + } + + public String getName() { + return name; + } + + /** + * 根据应用名称获取应用编码 + * + * @param name + * @return + */ + public static Integer getCodeByName(@NotNull String name) { + SystemCodeEnum systemCodeEnum = systemNameMap.get(name); + if (systemCodeEnum == null) { + return null; + } + return systemCodeEnum.getCode(); + } + +} diff --git a/src/main/java/com/newyetai/common/constant/TradeAccountTypeConstants.java b/src/main/java/com/newyetai/common/constant/TradeAccountTypeConstants.java new file mode 100644 index 0000000..49782e9 --- /dev/null +++ b/src/main/java/com/newyetai/common/constant/TradeAccountTypeConstants.java @@ -0,0 +1,69 @@ +package com.newyetai.common.constant; + +import java.util.Arrays; +import java.util.Objects; + +/** + * 交易账户类型常量 + * @author sr on 2020-08-19 + */ +public interface TradeAccountTypeConstants { + + /** 交易账号类型:银行卡 **/ + String TRADE_ACCOUNT_TYPE_BANK = TradeAccountTypeEnum.BANK.getType().toString(); + /** 交易账号类型:子账号 **/ + String TRADE_ACCOUNT_TYPE_SUB_ACCOUNT = TradeAccountTypeEnum.SUB_ACCOUNT.getType().toString(); + /** 交易账号类型:支付宝账号 **/ + String TRADE_ACCOUNT_TYPE_ALIPAY_ACCOUNT = TradeAccountTypeEnum.ALIPAY_ACCOUNT.getType().toString(); + /** 交易账号类型:支付宝用户ID **/ + String TRADE_ACCOUNT_TYPE_ALIPAY_USERID = TradeAccountTypeEnum.ALIPAY_USERID.getType().toString(); + /** 交易账号类型:微信OPENID **/ + String TRADE_ACCOUNT_TYPE_WECHAT_OPENID = TradeAccountTypeEnum.WECHAT_OPENID.getType().toString(); + /** 交易账号类型:平台机构 **/ + String TRADE_ACCOUNT_TYPE_PLATFORM_ORG = TradeAccountTypeEnum.PLATFORM_ORG.getType().toString(); + + /** + * 交易账号类型:其他 + */ + String TRADE_ACCOUNT_TYPE_OTHER = TradeAccountTypeEnum.OTHER.getType().toString(); + + /** + * 帐户类型枚举 + * + * @author Carlye + * @date 2021/08/17 + */ + public enum TradeAccountTypeEnum{ + BANK(1,"银行卡"), + SUB_ACCOUNT(2,"内部子账户"), + ALIPAY_ACCOUNT(3,"支付宝账号"), + ALIPAY_USERID(4,"支付宝用户ID"), + WECHAT_OPENID(5,"微信支付"), + PLATFORM_ORG(6,"平台机构"), + OTHER(99,"其他"); + + private final Integer type; + + private final String desc; + + TradeAccountTypeEnum(Integer type,String desc){ + this.type = type; + this.desc = desc; + } + + public Integer getType() { + return type; + } + + public String getDesc() { + return desc; + } + + public static TradeAccountTypeEnum find(Integer type){ + if (Objects.isNull(type)){ + return null; + } + return Arrays.stream(TradeAccountTypeEnum.values()).filter(e->e.getType().equals(type)).findFirst().orElse(null); + } + } +} diff --git a/src/main/java/com/newyetai/common/controller/TestController.java b/src/main/java/com/newyetai/common/controller/TestController.java new file mode 100644 index 0000000..3dd8187 --- /dev/null +++ b/src/main/java/com/newyetai/common/controller/TestController.java @@ -0,0 +1,55 @@ +package com.newyetai.common.controller; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import com.google.common.collect.Lists; +import com.newyetai.common.AlitaResult; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.common.util.RequestUtils; +import com.newyetai.commonexport.dto.CommonExportPropertiesDTO; +import com.newyetai.commonexport.service.ExportService; +import com.newyetai.component.file.entity.FileRecord; +import com.newyetai.recruit.talent.dto.TalentDTO; +import com.newyetai.recruit.talent.dto.TalentExportDTO; +import com.newyetai.usercenter.user.dto.UserDTO; + +@RestController +public class TestController { + + @Autowired + private ExportService exportService; + + @GetMapping("anon/hostIp") + public AlitaResult hostIp() { + return AlitaResult.success(RequestUtils.getHostIp()); + } + + @GetMapping("anon/trim") + public AlitaResult gettrim(UserDTO userDTO) { + return AlitaResult.success(JsonUtils.toJsonString(userDTO)); + } + + + @PostMapping("anon/trim") + public AlitaResult posttrim(@RequestBody UserDTO userDTO) { + return AlitaResult.success(JsonUtils.toJsonString(userDTO)); + } + + + @GetMapping("anon/download") + public AlitaResult export() { + List talentExportDTOs = Lists.newArrayList(TalentExportDTO.builder() + .realName("张三").age(12).companyName("上海有限公司").cardNo("23223232").build()); + return AlitaResult + .success(exportService.export(CommonExportPropertiesDTO.builder() + .fileName("人才信息清单").sheetName("人才信息清单").datas(talentExportDTOs).build())); + } + + +} diff --git a/src/main/java/com/newyetai/common/dto/BaseDTO.java b/src/main/java/com/newyetai/common/dto/BaseDTO.java new file mode 100644 index 0000000..ea5cd75 --- /dev/null +++ b/src/main/java/com/newyetai/common/dto/BaseDTO.java @@ -0,0 +1,56 @@ +package com.newyetai.common.dto; + +import java.io.Serializable; +import java.util.Date; + +import javax.validation.constraints.NotNull; + +import org.springframework.format.annotation.DateTimeFormat; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonFormat.Shape; +import com.newyetai.common.validation.Update; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + + +/** + * 基础dto + * + * @author sr on 2019-12-07 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class BaseDTO implements Serializable,IBaseDTO { + + /** **/ + private static final long serialVersionUID = 3305990673475531178L; + + @ApiModelProperty("id") + @NotNull(message = "id不能为空", groups = {Update.class}) + private Long id; + @ApiModelProperty("是否逻辑删除(0否1是)") + private Boolean deleted; + @ApiModelProperty("创建人") + private Long createBy; + @ApiModelProperty("创建时间") + // requestparam + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + // requestbody+serial + @JsonFormat(shape = Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTime; + @ApiModelProperty("修改人") + private Long updateBy; + @ApiModelProperty("修改时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTime; + private Long proxyBy; + +} diff --git a/src/main/java/com/newyetai/common/dto/BaseOperateDTO.java b/src/main/java/com/newyetai/common/dto/BaseOperateDTO.java new file mode 100644 index 0000000..17d9563 --- /dev/null +++ b/src/main/java/com/newyetai/common/dto/BaseOperateDTO.java @@ -0,0 +1,41 @@ +package com.newyetai.common.dto; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.newyetai.common.util.UserContextHolder; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 基础操作对象 + * + * @author sr on 2020-08-26 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class BaseOperateDTO implements Serializable, IOperateDTO{ + + /** **/ + private static final long serialVersionUID = -3075506470200622050L; + + /** 操作机构ID **/ + @JsonIgnore + private Long operateOrgId; + + /** 操作用户ID **/ + @JsonIgnore + private Long operateUserId; + + public Long getOperateOrgId() { + return operateOrgId == null ? UserContextHolder.getLoginOrgId() : operateOrgId; + } + + public Long getOperateUserId() { + return operateUserId == null ? UserContextHolder.getLoginUserId() : operateUserId; + } + +} diff --git a/src/main/java/com/newyetai/common/dto/ButtonDTO.java b/src/main/java/com/newyetai/common/dto/ButtonDTO.java new file mode 100644 index 0000000..db20b20 --- /dev/null +++ b/src/main/java/com/newyetai/common/dto/ButtonDTO.java @@ -0,0 +1,13 @@ +package com.newyetai.common.dto; + +import java.io.Serializable; + +/** + * @author sr on 2020-04-22 + */ +public class ButtonDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = -8606784819452806185L; + +} diff --git a/src/main/java/com/newyetai/common/dto/CasTokenDTO.java b/src/main/java/com/newyetai/common/dto/CasTokenDTO.java new file mode 100644 index 0000000..d280daa --- /dev/null +++ b/src/main/java/com/newyetai/common/dto/CasTokenDTO.java @@ -0,0 +1,27 @@ +package com.newyetai.common.dto; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class CasTokenDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = -6818144396647084889L; + + private String token; + + /** 当前token用户id **/ + private Long userId; + + /** 是否新注册 **/ + private Boolean register; + +} diff --git a/src/main/java/com/newyetai/common/dto/ColumnDTO.java b/src/main/java/com/newyetai/common/dto/ColumnDTO.java new file mode 100644 index 0000000..e115301 --- /dev/null +++ b/src/main/java/com/newyetai/common/dto/ColumnDTO.java @@ -0,0 +1,37 @@ +package com.newyetai.common.dto; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Builder.Default; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2020-04-22 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class ColumnDTO implements Serializable{ + /** **/ + private static final long serialVersionUID = 1L; + + private static final int DEFAULT_WIDTH = 160; + + /** 标题,如:总条数 **/ + private String title; + /** 下标(同key),如:totalCount **/ + private String dataIndex; + /** 属性,如:totalCount **/ + private String key; + /** 宽度 **/ + @Default + private int width = DEFAULT_WIDTH; + /** 对齐方式 **/ + @Default + private String align = "center"; + +} diff --git a/src/main/java/com/newyetai/common/dto/DisplayedComponentDTO.java b/src/main/java/com/newyetai/common/dto/DisplayedComponentDTO.java new file mode 100644 index 0000000..798375d --- /dev/null +++ b/src/main/java/com/newyetai/common/dto/DisplayedComponentDTO.java @@ -0,0 +1,32 @@ +package com.newyetai.common.dto; + +import java.io.Serializable; +import java.util.List; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 展示定制的组件 + * + * @author sr on 2020-04-22 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class DisplayedComponentDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + /** 消息 **/ + private MessageDTO message; + /** 列配置 **/ + private List columns; + /** 展示数据 **/ + private List data; + /** 按钮 **/ + private List buttons; + +} diff --git a/src/main/java/com/newyetai/common/dto/ExceptionRecordDTO.java b/src/main/java/com/newyetai/common/dto/ExceptionRecordDTO.java new file mode 100644 index 0000000..04d3512 --- /dev/null +++ b/src/main/java/com/newyetai/common/dto/ExceptionRecordDTO.java @@ -0,0 +1,31 @@ +package com.newyetai.common.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ExceptionRecordDTO implements Serializable { + + /** + * 入参json + */ + private String paramJson; + /** + * 响应json + */ + private String resultJson; + /** + * 调用接口地址 + */ + private String url; + /** + * 系统 1 慧用工、2、3、4待定 + */ + private String sys; +} diff --git a/src/main/java/com/newyetai/common/dto/ExportHeadDetailInfoDTO.java b/src/main/java/com/newyetai/common/dto/ExportHeadDetailInfoDTO.java new file mode 100644 index 0000000..c2a45b6 --- /dev/null +++ b/src/main/java/com/newyetai/common/dto/ExportHeadDetailInfoDTO.java @@ -0,0 +1,27 @@ +package com.newyetai.common.dto; + +import java.io.Serializable; +import java.util.List; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@AllArgsConstructor +@NoArgsConstructor +@Data +@Builder +public class ExportHeadDetailInfoDTO implements Serializable { + + private static final long serialVersionUID = 2399902503017038944L; + /** + * 表头 + */ + private String head; + + /** + * 下拉列表 + */ + private List explicitList; +} diff --git a/src/main/java/com/newyetai/common/dto/ExportHeadInfoDTO.java b/src/main/java/com/newyetai/common/dto/ExportHeadInfoDTO.java new file mode 100644 index 0000000..beac722 --- /dev/null +++ b/src/main/java/com/newyetai/common/dto/ExportHeadInfoDTO.java @@ -0,0 +1,59 @@ +package com.newyetai.common.dto; + +import org.apache.commons.compress.utils.Lists; + +import java.io.Serializable; +import java.util.List; +import java.util.Objects; + +import cn.hutool.core.date.DateUtil; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@AllArgsConstructor +@NoArgsConstructor +@Data +@Builder +public class ExportHeadInfoDTO implements Serializable { + + private static final long serialVersionUID = -3123297330700623056L; + + + /** + * 文件名称 + */ + private String fileName; + + /** + * 表头 + */ + private List heads; + + /** + * 数据列 + */ + private List datas; + + public String getFileName() { + if (Objects.isNull(fileName)){ + fileName = DateUtil.today() + "_动态模板"; + } + return fileName; + } + + public List getHeads() { + if (Objects.isNull(heads)){ + heads = Lists.newArrayList(); + } + return heads; + } + + public List getDatas() { + if (Objects.isNull(datas)){ + datas = Lists.newArrayList(); + } + return datas; + } +} diff --git a/src/main/java/com/newyetai/common/dto/IBaseDTO.java b/src/main/java/com/newyetai/common/dto/IBaseDTO.java new file mode 100644 index 0000000..716037c --- /dev/null +++ b/src/main/java/com/newyetai/common/dto/IBaseDTO.java @@ -0,0 +1,12 @@ +package com.newyetai.common.dto; + +/** + * 基础对象 + * @author sr on 2024-04-18 + */ +public interface IBaseDTO { + + Long getId(); + + +} diff --git a/src/main/java/com/newyetai/common/dto/IDisplayed.java b/src/main/java/com/newyetai/common/dto/IDisplayed.java new file mode 100644 index 0000000..609a5ad --- /dev/null +++ b/src/main/java/com/newyetai/common/dto/IDisplayed.java @@ -0,0 +1,23 @@ +package com.newyetai.common.dto; + +/** + * 展示信息 + * + * @author sr on 2020-07-14 + */ +public interface IDisplayed{ + /** + * 是否展示 + * @return + * @author sr on 2020-07-14 + */ + Boolean getDisplayed(); + + /** + * 展示组件 + * @return + * @author sr on 2020-07-14 + */ + DisplayedComponentDTO getDisplayedComponentDto(); + +} diff --git a/src/main/java/com/newyetai/common/dto/IOperateDTO.java b/src/main/java/com/newyetai/common/dto/IOperateDTO.java new file mode 100644 index 0000000..e2058df --- /dev/null +++ b/src/main/java/com/newyetai/common/dto/IOperateDTO.java @@ -0,0 +1,26 @@ +package com.newyetai.common.dto; + +/** + * 操作对象 + * + * @author sr on 2020-08-26 + */ +public interface IOperateDTO { + + /** + * 设置操作机构id + * + * @param orgId + * @author sr on 2020-08-31 + */ + void setOperateOrgId(Long orgId); + + /** + * 设置操作用户id + * + * @param userId + * @author sr on 2020-08-31 + */ + void setOperateUserId(Long userId); + +} diff --git a/src/main/java/com/newyetai/common/dto/IPage.java b/src/main/java/com/newyetai/common/dto/IPage.java new file mode 100644 index 0000000..62adb43 --- /dev/null +++ b/src/main/java/com/newyetai/common/dto/IPage.java @@ -0,0 +1,43 @@ +package com.newyetai.common.dto; + +import java.util.List; + +/** + * 分页对象 + * + * @author sr on 2020-08-26 + */ +public interface IPage { + + /** + * 第几页 + * + * @return + * @author sr on 2020-08-26 + */ + Integer getPageNo(); + + /** + * 页宽 + * + * @return + * @author sr on 2020-08-26 + */ + Integer getPageSize(); + + + /** + * 获取是否需要分页属性 + * + * @return {@link Boolean} + */ + Boolean getNeedPage(); + + /** + * 设置分页结果 + * + * @author sr on 2020-08-26 + */ + void setPageResult(int totalCount, List results); + +} diff --git a/src/main/java/com/newyetai/common/dto/MessageDTO.java b/src/main/java/com/newyetai/common/dto/MessageDTO.java new file mode 100644 index 0000000..7f69b2c --- /dev/null +++ b/src/main/java/com/newyetai/common/dto/MessageDTO.java @@ -0,0 +1,28 @@ +package com.newyetai.common.dto; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.Builder.Default; + +/** + * @author sr on 2020-04-22 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class MessageDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 3623225038987713421L; + /** 类型:success/info/warning/error **/ + @Default + private String type = "info"; + /** 内容 **/ + private String content; + +} diff --git a/src/main/java/com/newyetai/common/dto/OrgBaseDTO.java b/src/main/java/com/newyetai/common/dto/OrgBaseDTO.java new file mode 100644 index 0000000..11b43b0 --- /dev/null +++ b/src/main/java/com/newyetai/common/dto/OrgBaseDTO.java @@ -0,0 +1,24 @@ +package com.newyetai.common.dto; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 机构基础 + * + * @author sr on 2019-12-22 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@SuperBuilder +public class OrgBaseDTO extends BaseDTO { + + /** **/ + private static final long serialVersionUID = -2595043832455614748L; + + private Long orgId; + +} diff --git a/src/main/java/com/newyetai/common/dto/PageQueryDTO.java b/src/main/java/com/newyetai/common/dto/PageQueryDTO.java new file mode 100644 index 0000000..0e8df7f --- /dev/null +++ b/src/main/java/com/newyetai/common/dto/PageQueryDTO.java @@ -0,0 +1,98 @@ +package com.newyetai.common.dto; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.newyetai.tkmybatis.pojo.Page; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; +import java.util.Optional; + +/** + * 分页查询对象 + * + * @author sr on 2020-08-03 + */ +@AllArgsConstructor +@NoArgsConstructor +public class PageQueryDTO extends BaseOperateDTO implements Serializable, IPage { + + /** + * + **/ + private static final long serialVersionUID = -6370476082571087349L; + + /** + * 第几页 + **/ + private Integer pageNo = 1; + /** + * 页宽 + **/ + private Integer pageSize = 20; + /** + * 是否需要分页 + **/ + private Boolean needPage = Boolean.TRUE; + /** + * 分页结果 + **/ + @JsonIgnore + private Page pageResult; + + @Override + public Integer getPageNo() { + return Optional.ofNullable(pageNo).orElse(1); + } + + @Override + public Integer getPageSize() { + return Optional.ofNullable(pageSize).orElse(20); + } + + @Override + public Boolean getNeedPage() { + return Optional.ofNullable(this.needPage).orElse(Boolean.TRUE); + } + + @Override + public void setPageResult(int totalCount, List results) { + pageResult = new Page(getPageNo(), getPageSize()); + pageResult.setPageResult(totalCount, results); + } + + public void setPageNo(Integer pageNo) { + this.pageNo = pageNo; + } + + public void setPageSize(Integer pageSize) { + if (pageSize != null && pageSize >1000) { + this.pageSize = 1000; + } else { + this.pageSize = pageSize; + } + } + + public void setNeedPage(Boolean needPage) { + this.needPage = needPage; + } + + public Page getPageResult() { + return pageResult; + } + + public void setPageResult(Page pageResult) { + this.pageResult = pageResult; + } + + public PageQueryDTO disablePage() { + this.setNeedPage(Boolean.FALSE); + return this; + } + + public Integer getStartPage() { + return (getPageNo() - 1) * getPageSize(); + } + +} diff --git a/src/main/java/com/newyetai/common/easyexcel/DynamicExportTemplateCellWriteHandler.java b/src/main/java/com/newyetai/common/easyexcel/DynamicExportTemplateCellWriteHandler.java new file mode 100644 index 0000000..fd90a43 --- /dev/null +++ b/src/main/java/com/newyetai/common/easyexcel/DynamicExportTemplateCellWriteHandler.java @@ -0,0 +1,157 @@ +package com.newyetai.common.easyexcel; + +import com.google.common.collect.Maps; + + +import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.metadata.data.CellData; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.write.handler.AbstractCellWriteHandler; +import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; +import com.alibaba.excel.write.metadata.holder.WriteTableHolder; +import com.newyetai.common.dto.ExportHeadDetailInfoDTO; +import com.newyetai.common.dto.ExportHeadInfoDTO; + +import org.apache.poi.hssf.util.HSSFColor; +import org.apache.poi.ss.usermodel.BorderStyle; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.DataValidation; +import org.apache.poi.ss.usermodel.DataValidationConstraint; +import org.apache.poi.ss.usermodel.DataValidationHelper; +import org.apache.poi.ss.usermodel.FillPatternType; +import org.apache.poi.ss.usermodel.Font; +import org.apache.poi.ss.usermodel.HorizontalAlignment; +import org.apache.poi.ss.usermodel.IndexedColors; +import org.apache.poi.ss.usermodel.Name; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.VerticalAlignment; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.util.CellRangeAddressList; +import org.apache.poi.xssf.usermodel.XSSFCellStyle; +import org.apache.poi.xssf.usermodel.XSSFColor; +import org.apache.poi.xssf.usermodel.XSSFDataValidation; + +import java.awt.*; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import cn.hutool.core.collection.CollUtil; + +public class DynamicExportTemplateCellWriteHandler extends AbstractCellWriteHandler { + + private Map exportHeadIndexMap = null; + + private Integer hiddenSheetIndex = 1; + + + + @Override + public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { + super.afterCellDispose(writeSheetHolder, writeTableHolder, cellDataList, cell, head, relativeRowIndex, isHead); + int rowIndex = cell.getRowIndex(); + int columnIndex = cell.getColumnIndex(); + Workbook workbook = writeSheetHolder.getParentWriteWorkbookHolder().getWorkbook(); + Sheet sheet = writeSheetHolder.getSheet(); + if (rowIndex == 0) { + Row row = cell.getRow(); + row.setHeight((short) (33 * 20)); + ExportHeadInfoDTO exportInfo = (ExportHeadInfoDTO) ImportDataContext.get("exportInfo"); + + XSSFCellStyle cellStyle = (XSSFCellStyle) workbook.createCellStyle(); + cellStyle.setBorderBottom(BorderStyle.THIN); //下边框 + cellStyle.setBottomBorderColor(IndexedColors.BLACK.index); + cellStyle.setBorderLeft(BorderStyle.THIN);//左边框 + cellStyle.setLeftBorderColor(IndexedColors.BLACK.index); + cellStyle.setBorderTop(BorderStyle.THIN);//上边框 + cellStyle.setTopBorderColor(IndexedColors.BLACK.index); + cellStyle.setBorderRight(BorderStyle.THIN);//右边框 + cellStyle.setRightBorderColor(IndexedColors.BLACK.index); + + cellStyle.setAlignment(HorizontalAlignment.CENTER); + cellStyle.setVerticalAlignment(VerticalAlignment.CENTER); + + Color color = new Color(91, 155, 213); + cellStyle.setFillForegroundColor(new XSSFColor(color,null)); + cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); + + Font font = workbook.createFont(); + cellStyle.setFont(font); + + font.setFontName("Calibri"); + font.setColor(HSSFColor.HSSFColorPredefined.WHITE.getIndex()); + cell.setCellStyle(cellStyle); + if (Objects.isNull(exportHeadIndexMap)) { + List heads = exportInfo.getHeads(); + exportHeadIndexMap = Maps.newHashMap(); + for (int i = 0; i < heads.size(); i++) { + ExportHeadDetailInfoDTO exportHead = heads.get(i); + exportHeadIndexMap.put(i, exportHead); + } + } + + ExportHeadDetailInfoDTO exportHeadDetailInfoDTO = exportHeadIndexMap.get(columnIndex); + String name; + if (Objects.isNull(exportHeadDetailInfoDTO)) { + name = cell.getStringCellValue(); + } else { + name = exportHeadDetailInfoDTO.getHead(); + } + int length = ((name.getBytes(StandardCharsets.UTF_8).length + cell.toString().length()) * 3) / 5 + 5; + sheet.setColumnWidth(columnIndex, length * 290); + + List explicitList = Objects.isNull(exportHeadDetailInfoDTO) ? null : exportHeadDetailInfoDTO.getExplicitList(); + // 设置下拉属性 +// if (CollUtil.isNotEmpty(explicitList)) { +// DataValidationHelper helper = sheet.getDataValidationHelper(); +// DataValidationConstraint constraint = helper.createExplicitListConstraint(explicitList.toArray(new String[]{})); +// //设置生效的起始行、终止行、起始列、终止列 +// CellRangeAddressList cellAddressList = new CellRangeAddressList(1, +// 65535, columnIndex, columnIndex); +// DataValidation validation = helper.createValidation(constraint, cellAddressList); +// //适配xls和xlsx +// if (validation instanceof HSSFDataValidation) { +// validation.setSuppressDropDownArrow(false); +// } else { +// validation.setSuppressDropDownArrow(true); +// validation.setShowErrorBox(true); +// } +// sheet.addValidationData(validation); +// } + + if (CollUtil.isNotEmpty(explicitList)){ + String hiddenName = "hidden" + hiddenSheetIndex; + //1.创建隐藏的sheet页。 起个名字吧!叫"hidden"! + Sheet hiddenSheet = workbook.createSheet(hiddenName); + //2.循环赋值(为了防止下拉框的行数与隐藏域的行数相对应,将隐藏域加到结束行之后) + for (int i = 0; i < explicitList.size(); i++) { + hiddenSheet.createRow(65535 + i).createCell(columnIndex).setCellValue(explicitList.get(i)); + } + Name category1Name = workbook.createName(); + category1Name.setNameName(hiddenName); + //3 A1:A代表隐藏域创建第N列createCell(N)时。以A1列开始A行数据获取下拉数组 + category1Name.setRefersToFormula(hiddenName + "!A1:A" + (explicitList.size() + 65535)); + // + DataValidationHelper helper = sheet.getDataValidationHelper(); + DataValidationConstraint constraint = helper.createFormulaListConstraint(hiddenName); + CellRangeAddressList addressList = new CellRangeAddressList(1, 65535, columnIndex, columnIndex); + DataValidation dataValidation = helper.createValidation(constraint, addressList); + if (dataValidation instanceof XSSFDataValidation) { + // 数据校验 + dataValidation.setSuppressDropDownArrow(true); + dataValidation.setShowErrorBox(true); + } else { + dataValidation.setSuppressDropDownArrow(false); + } + // 作用在目标sheet上 + sheet.addValidationData(dataValidation); + // 设置hiddenSheet隐藏 + workbook.setSheetHidden(hiddenSheetIndex, true); + hiddenSheetIndex++; + } + } + + } +} diff --git a/src/main/java/com/newyetai/common/easyexcel/ExcelUtil.java b/src/main/java/com/newyetai/common/easyexcel/ExcelUtil.java new file mode 100644 index 0000000..fee3b3b --- /dev/null +++ b/src/main/java/com/newyetai/common/easyexcel/ExcelUtil.java @@ -0,0 +1,77 @@ +package com.newyetai.common.easyexcel; + +import com.google.common.collect.Lists; + +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; +import com.newyetai.common.dto.ExportHeadDetailInfoDTO; +import com.newyetai.common.dto.ExportHeadInfoDTO; + +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletResponse; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; + +public class ExcelUtil { + + + private ExcelUtil() { + } + + + /** + * 动态导出excel模板 + * + * @param reqDto 点播dto + */ + public static void dynamicExportTemplate(ExportHeadInfoDTO reqDto) { + if (CollUtil.isEmpty(reqDto.getHeads())) { + return; + } + ImportDataContext.set("exportInfo", reqDto); + + ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + HttpServletResponse response = attr.getResponse(); + if (Objects.isNull(response)) { + return; + } + String fileName = reqDto.getFileName() + ".xlsx"; + + response.setContentType("application/vnd.ms-excel;charset=UTF-8"); + response.setCharacterEncoding("UTF-8"); + String fileNamePrefix = StrUtil.subBefore(fileName, ".", true); + String fileNameSuffix = StrUtil.subAfter(fileName, ".", true); + try { + String fileNamePrefix2 = URLEncoder.encode(fileNamePrefix, "UTF-8").replaceAll("\\+", "%20"); + response.setHeader("Content-Disposition", "attachment;" + fileNamePrefix2 + "." + fileNameSuffix); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + throw new IllegalArgumentException("下载文件异常"); + } + response.addHeader("Param", "no-cache"); + response.addHeader("Cache-Control", "no-cache"); + + try (OutputStream out = response.getOutputStream();) { + ExcelWriter writer = EasyExcel.write(out).registerWriteHandler(new DynamicExportTemplateCellWriteHandler()).build(); + List objects = Lists.newArrayList(); + objects.add(reqDto.getHeads().stream().map(ExportHeadDetailInfoDTO::getHead).collect(Collectors.toList())); + objects.addAll(reqDto.getDatas()); + writer.write(objects, EasyExcel.writerSheet("sheet").build()); + writer.finish(); + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/main/java/com/newyetai/common/easyexcel/ImportDataContext.java b/src/main/java/com/newyetai/common/easyexcel/ImportDataContext.java new file mode 100644 index 0000000..931a605 --- /dev/null +++ b/src/main/java/com/newyetai/common/easyexcel/ImportDataContext.java @@ -0,0 +1,35 @@ +package com.newyetai.common.easyexcel; + +import com.google.common.collect.Maps; + +import java.util.Map; +import java.util.Objects; + +public class ImportDataContext { + public static final ThreadLocal> THREAD_LOCAL_MAP = new ThreadLocal<>(); + + public static Object get(String key) { + Map stringObjectMap = THREAD_LOCAL_MAP.get(); + if (Objects.isNull(stringObjectMap)) { + THREAD_LOCAL_MAP.set(Maps.newHashMap()); + return null; + } + return stringObjectMap.get(key); + } + + public static void set(String key,Object value) { + Map stringObjectMap = THREAD_LOCAL_MAP.get(); + if (Objects.isNull(stringObjectMap)) { + THREAD_LOCAL_MAP.set(Maps.newHashMap()); + } + THREAD_LOCAL_MAP.get().put(key,value); + } + + public static void putAll(Map extraInfoMap){ + Map stringObjectMap = THREAD_LOCAL_MAP.get(); + if (Objects.isNull(stringObjectMap)) { + THREAD_LOCAL_MAP.set(Maps.newHashMap()); + } + THREAD_LOCAL_MAP.get().putAll(extraInfoMap); + } +} diff --git a/src/main/java/com/newyetai/common/entity/BaseEntity.java b/src/main/java/com/newyetai/common/entity/BaseEntity.java new file mode 100644 index 0000000..4673504 --- /dev/null +++ b/src/main/java/com/newyetai/common/entity/BaseEntity.java @@ -0,0 +1,67 @@ +package com.newyetai.common.entity; + +import java.io.Serializable; +import java.util.Date; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.newyetai.common.dto.IBaseDTO; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author Rey(leijiaping @ newyetai.com) + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public abstract class BaseEntity implements Serializable, Cloneable, IBaseDTO { + + private static final long serialVersionUID = -723338960662087915L; + + /** + * 主键 + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + /** + * 是否逻辑删除(0否1是) + */ + @TableField(value = "deleted", fill = FieldFill.INSERT) + @Builder.Default + private Boolean deleted = Boolean.FALSE; + /** + * 创建人 + */ + @TableField(value = "create_by", fill = FieldFill.INSERT) + private Long createBy; + /** + * 创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + @TableField(value = "create_time", fill = FieldFill.INSERT) + private Date createTime; + /** + * 修改人 + */ + @TableField(value = "update_by", fill = FieldFill.UPDATE) + private Long updateBy; + /** + * 修改时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + @TableField(value = "update_time", fill = FieldFill.UPDATE) + private Date updateTime; + /** + * 代理人 + */ + private Long proxyBy; +} diff --git a/src/main/java/com/newyetai/common/entity/OrgBaseEntity.java b/src/main/java/com/newyetai/common/entity/OrgBaseEntity.java new file mode 100644 index 0000000..173e640 --- /dev/null +++ b/src/main/java/com/newyetai/common/entity/OrgBaseEntity.java @@ -0,0 +1,27 @@ +package com.newyetai.common.entity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 机构基础实体 + * @author sr on 2019-10-19 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class OrgBaseEntity extends BaseEntity { + + /** **/ + private static final long serialVersionUID = 2559571969035017003L; + + /** 机构id **/ + private Long orgId; + + +} diff --git a/src/main/java/com/newyetai/common/exception/AlitaException.java b/src/main/java/com/newyetai/common/exception/AlitaException.java new file mode 100644 index 0000000..1cff84a --- /dev/null +++ b/src/main/java/com/newyetai/common/exception/AlitaException.java @@ -0,0 +1,30 @@ +package com.newyetai.common.exception; + + +/** + * 项目所有自定义异常父类 + * + * @author guhong + */ +public class AlitaException extends RuntimeException { + + /** + * + */ + private static final long serialVersionUID = 3121871576733025786L; + + public AlitaException() {} + + public AlitaException(String message) { + super(message); + } + + public AlitaException(String message, Throwable cause) { + super(message, cause); + } + + public AlitaException(Throwable cause) { + super(cause); + } + +} diff --git a/src/main/java/com/newyetai/common/exception/BusinessException.java b/src/main/java/com/newyetai/common/exception/BusinessException.java new file mode 100644 index 0000000..ffc72ab --- /dev/null +++ b/src/main/java/com/newyetai/common/exception/BusinessException.java @@ -0,0 +1,30 @@ +package com.newyetai.common.exception; + +/** + * 业务异常 + * + * @author guhong + * @date 2019/8/19 + */ +public class BusinessException extends AlitaException { + + /** + * + */ + private static final long serialVersionUID = -3097174055942519169L; + + public BusinessException() {} + + public BusinessException(String message) { + super(message); + } + + public BusinessException(String message, Throwable cause) { + super(message, cause); + } + + public BusinessException(Throwable cause) { + super(cause); + } + +} diff --git a/src/main/java/com/newyetai/common/exception/ChangeTokenException.java b/src/main/java/com/newyetai/common/exception/ChangeTokenException.java new file mode 100644 index 0000000..92983fe --- /dev/null +++ b/src/main/java/com/newyetai/common/exception/ChangeTokenException.java @@ -0,0 +1,24 @@ +package com.newyetai.common.exception; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.dto.CasTokenDTO; + +/** + * 更新token + * @author sr on 2021-07-05 + */ +public class ChangeTokenException extends WithResultException{ + + /** **/ + private static final long serialVersionUID = -8897274199463229506L; + + + public ChangeTokenException(CasTokenDTO casTokenDTO) { + super(AlitaResult.changeToken(casTokenDTO)); + } + + public CasTokenDTO getCasTokenDTO(){ + return (CasTokenDTO) getResult().getErrorData(); + } + +} diff --git a/src/main/java/com/newyetai/common/exception/DevopsException.java b/src/main/java/com/newyetai/common/exception/DevopsException.java new file mode 100644 index 0000000..378266e --- /dev/null +++ b/src/main/java/com/newyetai/common/exception/DevopsException.java @@ -0,0 +1,24 @@ +package com.newyetai.common.exception; + +import com.newyetai.common.exception.util.DevopsUtils; + +/** + * 运维业务异常 + * @author sr on 2022-03-01 + */ +public class DevopsException extends BusinessException{ + + /** **/ + private static final long serialVersionUID = 1L; + + public DevopsException(String message) { + super(message); + DevopsUtils.deal(message); + } + + public DevopsException(String message, Throwable cause) { + super(message, cause); + DevopsUtils.deal(message); + } + +} diff --git a/src/main/java/com/newyetai/common/exception/ExistException.java b/src/main/java/com/newyetai/common/exception/ExistException.java new file mode 100644 index 0000000..3fc21f7 --- /dev/null +++ b/src/main/java/com/newyetai/common/exception/ExistException.java @@ -0,0 +1,24 @@ +package com.newyetai.common.exception; + +/** + * 已存在业务异常 + * @author sr on 2022-03-01 + */ +public class ExistException extends BusinessException{ + + /** **/ + private static final long serialVersionUID = 1L; + + public ExistException() { + super(); + } + + public ExistException(String message) { + super(message); + } + + public ExistException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/src/main/java/com/newyetai/common/exception/IDevopsProvider.java b/src/main/java/com/newyetai/common/exception/IDevopsProvider.java new file mode 100644 index 0000000..3d2d219 --- /dev/null +++ b/src/main/java/com/newyetai/common/exception/IDevopsProvider.java @@ -0,0 +1,7 @@ +package com.newyetai.common.exception; + +public interface IDevopsProvider { + + void deal(String msg); + +} diff --git a/src/main/java/com/newyetai/common/exception/NoneLoginException.java b/src/main/java/com/newyetai/common/exception/NoneLoginException.java new file mode 100644 index 0000000..3ffd182 --- /dev/null +++ b/src/main/java/com/newyetai/common/exception/NoneLoginException.java @@ -0,0 +1,26 @@ +package com.newyetai.common.exception; + +/** + * 用户未登录异常 + * + * @author guhong + * @date 2019/8/19 + */ +public class NoneLoginException extends AlitaException { + + public static final String ERROR_MSG = "用户未登录"; + + /** + * + */ + private static final long serialVersionUID = -7013134475760472324L; + + public NoneLoginException(String msg, Throwable t) { + super(msg, t); + } + + public NoneLoginException() { + super(ERROR_MSG); + } + +} diff --git a/src/main/java/com/newyetai/common/exception/WithResultException.java b/src/main/java/com/newyetai/common/exception/WithResultException.java new file mode 100644 index 0000000..f7e28ab --- /dev/null +++ b/src/main/java/com/newyetai/common/exception/WithResultException.java @@ -0,0 +1,30 @@ +package com.newyetai.common.exception; + +import com.newyetai.common.AlitaResult; + +/** + * 更新token + * @author sr on 2021-07-05 + */ +public class WithResultException extends AlitaException{ + + /** **/ + private static final long serialVersionUID = -8897274199463229506L; + + private AlitaResult result; + + public WithResultException(AlitaResult result) { + super(result.getMsg()); + this.result = result; + } + + public WithResultException(AlitaResult result, Throwable cause) { + super(result.getMsg(), cause); + this.result = result; + } + + public AlitaResult getResult(){ + return result; + } + +} diff --git a/src/main/java/com/newyetai/common/exception/controller/ExceptionLogController.java b/src/main/java/com/newyetai/common/exception/controller/ExceptionLogController.java new file mode 100644 index 0000000..99e0d08 --- /dev/null +++ b/src/main/java/com/newyetai/common/exception/controller/ExceptionLogController.java @@ -0,0 +1,33 @@ +package com.newyetai.common.exception.controller; + +import com.newyetai.common.exception.dao.ExceptionLogMapper; +import io.swagger.annotations.Api; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 异常日志查看 + * + * @author on 2019-11-05 + */ +@RestController +@RequestMapping("/anon/exception") +@Api(tags = "异常日志查看") +public class ExceptionLogController { + + @Autowired + private ExceptionLogMapper exceptionLogMapper; + + @GetMapping("/{id}") + public String getExceptionMsg(@PathVariable Long id) { + try { + return exceptionLogMapper.selectById(id).getMsg(); + } catch (Exception e) { + return "未找到对应id错误"; + } + } + +} diff --git a/src/main/java/com/newyetai/common/exception/dao/ExceptionLogMapper.java b/src/main/java/com/newyetai/common/exception/dao/ExceptionLogMapper.java new file mode 100644 index 0000000..18bf335 --- /dev/null +++ b/src/main/java/com/newyetai/common/exception/dao/ExceptionLogMapper.java @@ -0,0 +1,13 @@ +package com.newyetai.common.exception.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.newyetai.common.exception.entity.ExceptionLog; + +/** + * 异常日志 + * + * @author on 2019-11-05 + */ +public interface ExceptionLogMapper extends BaseMapper { + +} diff --git a/src/main/java/com/newyetai/common/exception/entity/ExceptionLog.java b/src/main/java/com/newyetai/common/exception/entity/ExceptionLog.java new file mode 100644 index 0000000..158e4d5 --- /dev/null +++ b/src/main/java/com/newyetai/common/exception/entity/ExceptionLog.java @@ -0,0 +1,41 @@ +package com.newyetai.common.exception.entity; + +import java.io.Serializable; +import java.util.Date; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 错误日志 + * @author sr on 2019-10-28 + */ +@TableName("xs_exception_log") +@Data +@NoArgsConstructor +public class ExceptionLog implements Serializable{ + + /** **/ + private static final long serialVersionUID = 3730091070919812549L; + + /** 主键 **/ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** 创建时间 **/ + private Date createTime; + + /** 错误信息 **/ + private String msg; + + public ExceptionLog(Date createTime, String msg) { + super(); + this.createTime = createTime; + this.msg = msg; + } + +} diff --git a/src/main/java/com/newyetai/common/exception/handle/GlobalControllerExceptionHandler.java b/src/main/java/com/newyetai/common/exception/handle/GlobalControllerExceptionHandler.java new file mode 100644 index 0000000..dbec692 --- /dev/null +++ b/src/main/java/com/newyetai/common/exception/handle/GlobalControllerExceptionHandler.java @@ -0,0 +1,188 @@ +package com.newyetai.common.exception.handle; + +import java.util.List; +import java.util.Set; +import java.util.StringJoiner; + +import javax.validation.ConstraintViolation; +import javax.validation.ConstraintViolationException; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.beans.propertyeditors.StringTrimmerEditor; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.validation.FieldError; +import org.springframework.validation.ObjectError; +import org.springframework.web.HttpRequestMethodNotSupportedException; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.WebDataBinder; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.InitBinder; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.constant.SystemCodeEnum; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.NoneLoginException; +import com.newyetai.common.exception.WithResultException; +import com.newyetai.common.log.dto.ExceptionLogDTO; +import com.newyetai.common.log.util.LogUtils; +import com.newyetai.common.util.SpringContextHolder; +import com.newyetai.common.util.TracerUtils; + +/** + * 全局异常处理 + * + * @author guhong + * @date 2019/8/19 + */ +@RestControllerAdvice +public class GlobalControllerExceptionHandler { + + private static final Logger LOGGER = LoggerFactory + .getLogger(GlobalControllerExceptionHandler.class); + + @Value("${spring.application.name:}") + private String applicationName; + + /** + * 业务异常 + * + * @param ex + */ + @ExceptionHandler(value = {BusinessException.class}) + public AlitaResult handleBusinessException(BusinessException ex) { + String traceId = TracerUtils.getTraceId(); + String msg; + if (StringUtils.isNotBlank(ex.getMessage()) && ex.getMessage().contains(traceId)) { + msg = ex.getMessage(); + }else { + msg = String.format("[%s]操作失败:%s", traceId, ex.getMessage()); + } + + LOGGER.debug(msg, ex); + AlitaResult alitaResult = AlitaResult.error(AlitaResult.BUSINESS_ERROR_CODE, msg); + alitaResult.setRequestId(traceId); + return alitaResult; + } + + /** + * 处理未登录异常 + * + * @param ex + */ + @ExceptionHandler(value = {NoneLoginException.class}) + public AlitaResult handleNoneLoginException(NoneLoginException ex) { + AlitaResult alitaResult = AlitaResult.unLogin(); + alitaResult.setRequestId(TracerUtils.getTraceId()); + return alitaResult; + } + + /** + * 处理更换token + * + * @param ex + */ + @ExceptionHandler(value = {WithResultException.class}) + public AlitaResult handleChangeTokenException(WithResultException ex) { + AlitaResult result = ex.getResult(); + result.setRequestId(TracerUtils.getTraceId()); + return result; + } + + /** + * 处理校验异常 + * + * @param ex + */ + @ExceptionHandler(value = { + MethodArgumentNotValidException.class, + BindException.class}) + public AlitaResult handleValidationException(Exception ex) { + BindingResult result; + if (ex instanceof MethodArgumentNotValidException) { + result = ((MethodArgumentNotValidException) ex).getBindingResult(); + } else { + result = ((BindException) ex).getBindingResult(); + } + if (!result.hasErrors()) { + return AlitaResult.error("操作失败"); + } + + StringJoiner joiner = new StringJoiner(","); + List errors = result.getAllErrors(); + + errors.forEach(error -> { + if (error instanceof FieldError) { + joiner.add(((FieldError) error).getField() + "-" + error.getDefaultMessage()); + } else { + joiner.add(error.getDefaultMessage()); + } + }); + + String msg = String.format("数据异常:%s", joiner.toString()); + LOGGER.error(msg); + AlitaResult alitaResult = AlitaResult.error(AlitaResult.VALIDATION_ERROR_CODE, msg); + alitaResult.setRequestId(TracerUtils.getTraceId()); + return alitaResult; + } + + /** + * 处理未知的错误 + * + * @param ex + */ + @ExceptionHandler(value = {ConstraintViolationException.class}) + @Transactional(rollbackFor = RuntimeException.class) + public AlitaResult handleConstraintViolationException(ConstraintViolationException ex) { + Set> constraintViolations = ex.getConstraintViolations(); + StringJoiner joiner = new StringJoiner(CommonConstants.COMMA); + constraintViolations.stream().forEach(error -> joiner.add(error.getMessage())); + String msg = String.format("数据异常:%s", joiner.toString()); + LOGGER.error(msg); + AlitaResult alitaResult = AlitaResult.error(AlitaResult.VALIDATION_ERROR_CODE, msg); + alitaResult.setRequestId(TracerUtils.getTraceId()); + return alitaResult; + } + + /** + * 处理未知的错误 + * + * @param ex + */ + @ExceptionHandler(value = {Exception.class}) + @Transactional(rollbackFor = RuntimeException.class) + public AlitaResult handleUnknownException(Exception ex) { + String msg = null; + if (ex instanceof HttpRequestMethodNotSupportedException) { + msg = "请求错误:" + ((HttpRequestMethodNotSupportedException) ex).getSupportedMethods()[0] + + SpringContextHolder.getRequest().getRequestURI(); + } else { + LOGGER.error("",ex); + ExceptionLogDTO exceptionLogDTO = ExceptionLogDTO.builder().traceId(TracerUtils.getTraceId()) + .msg(ExceptionUtils.getStackTrace(ex)).build(); + LogUtils.log(exceptionLogDTO); + msg = String.format("系统异常[%s#%s],请稍后重试.", + SystemCodeEnum.getCodeByName(applicationName), exceptionLogDTO.getErrNo() + ); + LOGGER.error("系统异常,错误号:{}", exceptionLogDTO.getErrNo()); + } + + AlitaResult alitaResult = AlitaResult.error(msg); + alitaResult.setRequestId(TracerUtils.getTraceId()); + return alitaResult; + } + + @InitBinder + public void initBinder(WebDataBinder binder) { + binder.registerCustomEditor(String.class, new StringTrimmerEditor(" \t\r\n\f", true)); + } + + +} diff --git a/src/main/java/com/newyetai/common/exception/util/Assert.java b/src/main/java/com/newyetai/common/exception/util/Assert.java new file mode 100644 index 0000000..828cddd --- /dev/null +++ b/src/main/java/com/newyetai/common/exception/util/Assert.java @@ -0,0 +1,133 @@ +package com.newyetai.common.exception.util; + +import com.google.common.base.Supplier; +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.util.JsonUtils; + +import lombok.extern.slf4j.Slf4j; + +import java.util.Collection; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.lang.Nullable; +import org.springframework.util.CollectionUtils; + +/** + * 断言 + * + * @author sr on 2020-09-02 + */ +@Slf4j +public class Assert { + + private Assert() { + } + + private static void dealLog(String message, Object... logData) { + if (logData.length > 0) { + log.info(new StringBuilder().append(message).append(CommonConstants.COLON) + .append(JsonUtils.toJsonString(logData)).toString()); + } + } + + /** + * true正常,fasle抛BusinessException + * + * @param expression + * @param message + * @author sr on 2020-09-02 + */ + public static void isTrue(boolean expression, String message, Object... logData) { + if (!expression) { + dealLog(message, logData); + throw new BusinessException(message); + } + } + + /** + * true正常,fasle抛BusinessException + * + * @param expression 表达式 + * @param message 消息 + */ + public static void isTrue(boolean expression, Supplier message) { + if (!expression) { + throw new BusinessException(message.get()); + } + } + + + /** + * true正常,fasle抛指定异常 + * @param expression + * @param e + * @author sr on 2021-06-18 + */ + public static void isTrue(boolean expression, RuntimeException e) { + if (!expression) { + throw e; + } + } + + /** + * null正常,notNull抛BusinessException + * + * @param object + * @param message + * @author sr on 2020-09-02 + */ + public static void isNull(@Nullable Object object, String message, Object... logData) { + if (object != null) { + dealLog(message, logData); + throw new BusinessException(message); + } + } + + /** + * notNull正常,null抛BusinessException + * + * @param object + * @param message + * @author sr on 2020-09-02 + */ + public static void notNull(@Nullable Object object, String message, Object... logData) { + if (object == null) { + dealLog(message, logData); + throw new BusinessException(message); + } + } + + /** + * notNull正常,null抛BusinessException + * + * @param object 对象 + * @param message 消息 + */ + public static void notNull(@Nullable Object object, Supplier message) { + if (object == null) { + throw new BusinessException(message.get()); + } + } + + /** + * notBlank正常,blank抛BusinessException + * + * @param str + * @param message + * @author sr on 2021-01-06 + */ + public static void notBlank(String str, String message, Object... logData) { + if (StringUtils.isBlank(str)) { + dealLog(message, logData); + throw new BusinessException(message); + } + } + + public static void notEmpty(@Nullable Collection collection, String message) { + if (CollectionUtils.isEmpty(collection)) { + throw new BusinessException(message); + } +} + +} diff --git a/src/main/java/com/newyetai/common/exception/util/DevopsUtils.java b/src/main/java/com/newyetai/common/exception/util/DevopsUtils.java new file mode 100644 index 0000000..04cf682 --- /dev/null +++ b/src/main/java/com/newyetai/common/exception/util/DevopsUtils.java @@ -0,0 +1,33 @@ +package com.newyetai.common.exception.util; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.newyetai.common.exception.IDevopsProvider; + +import lombok.extern.slf4j.Slf4j; + +/** + * 运维工具类 + * @author sr on 2022-03-01 + */ +@Component +@Slf4j +public class DevopsUtils { + + private static IDevopsProvider devopsProvider; + + @Autowired(required = false) + public void setDevopsProvider(IDevopsProvider devopsProvider) { + DevopsUtils.devopsProvider = devopsProvider; + } + + public static void deal(String msg) { + if (devopsProvider == null) { + log.error("no devops provider, error:{}", msg); + return ; + } + devopsProvider.deal(msg); + } + +} diff --git a/src/main/java/com/newyetai/common/exception/util/ExceptionUtils.java b/src/main/java/com/newyetai/common/exception/util/ExceptionUtils.java new file mode 100644 index 0000000..b83de79 --- /dev/null +++ b/src/main/java/com/newyetai/common/exception/util/ExceptionUtils.java @@ -0,0 +1,48 @@ +package com.newyetai.common.exception.util; + +import com.newyetai.common.exception.BusinessException; +import lombok.extern.slf4j.Slf4j; + +/** + * 异常工具类 + * @author sr on 2019-10-14 + */ +@Slf4j +public class ExceptionUtils { + + /** + * @Description 抛异常 + * @Author chenyun.huang + * @Date 2020/3/27 15:06 + **/ + public static void throwBusinessException(String msg) { + ExceptionUtils.throwBusinessException(true,msg); + } + + /** + * 根据判断抛异常 + * @param isThrow + * @param msg 异常信息 + * @author sr on 2019-10-14 + */ + public static void throwBusinessException(boolean isThrow, String msg) { + if (isThrow) { + throw new BusinessException(msg); + } + } + + /** + * 根据判断抛异常 + * @param isThrow + * @param errorMsg 异常信息 + * @param logMsg 日志信息(info级) + * @author sr on 2019-12-18 + */ + public static void throwBusinessException(boolean isThrow, String errorMsg, String logMsg) { + if (isThrow) { + log.info(logMsg); + throw new BusinessException(errorMsg); + } + } + +} diff --git a/src/main/java/com/newyetai/common/exception/util/UUIDUtils.java b/src/main/java/com/newyetai/common/exception/util/UUIDUtils.java new file mode 100644 index 0000000..804f6d0 --- /dev/null +++ b/src/main/java/com/newyetai/common/exception/util/UUIDUtils.java @@ -0,0 +1,24 @@ +package com.newyetai.common.exception.util; + +import java.util.UUID; + +import com.newyetai.common.util.RandomUtils; + +/** + * uuid工具类 + * {@link RandomUtils} + * @author sr on 2019-12-10 + */ +@Deprecated +public class UUIDUtils { + + /** + * 生成uuid,去掉- + * @return + * @author sr on 2019-12-10 + */ + public static String generateUUID() { + return RandomUtils.generateUUID(); + } + +} diff --git a/src/main/java/com/newyetai/common/freemarker/constant/BusinessModelFileEnum.java b/src/main/java/com/newyetai/common/freemarker/constant/BusinessModelFileEnum.java new file mode 100644 index 0000000..11d86f3 --- /dev/null +++ b/src/main/java/com/newyetai/common/freemarker/constant/BusinessModelFileEnum.java @@ -0,0 +1,60 @@ +package com.newyetai.common.freemarker.constant; + +/** + * @author sr on 2020-04-13 + */ +public enum BusinessModelFileEnum { + + /** 常量 **/ + CONSTANT("Constants.java", "constant", "Constant.ftl"), + /** 控制层 **/ + CONTROLLER_FILE_SUFFIX("Controller.java", "controller", "Controller.ftl"), + /** dao **/ + DAO_FILE_SUFFIX("Mapper.java", "dao", "Dao.ftl"), + /** dto **/ + DTO_FILE_SUFFIX("DTO.java", "dto", "DTO.ftl"), + /** operateDto **/ + OPERATE_DTO_FILE_SUFFIX("OperateDTO.java", "dto", "OperateDTO.ftl"), + /** queryDto **/ + QUERY_DTO_FILE_SUFFIX("QueryDTO.java", "dto", "QueryDTO.ftl"), + /** entity **/ + ENTITY_FILE_SUFFIX(".java", "entity", "entity.ftl"), + /** mapper **/ + MAPPER_FILE_SUFFIX("Mapper.xml", "mapper", "Mapper.ftl"), + /** mapstruct **/ + MAPSTRUCT_FILE_SUFFIX("MapMapper.java", "mapstruct", "MapMapper.ftl"), + /** service **/ + SERVICE_FILE_SUFFIX("Service.java", "service", "Service.ftl"), + /** serviceImpl **/ + SERVICE_IMPL_FILE_SUFFIX("ServiceImpl.java", "service.impl", "ServiceImpl.ftl"), + /** util **/ + UTIL_FILE_SUFFIX("Utils.java", "util", "Util.ftl"); + + + + /** 生成文件后缀 **/ + private String generatefileSuffix; + /** 包名 **/ + private String packageName; + /** 模版文件后缀 **/ + private String ftlFile; + + private BusinessModelFileEnum(String fileSuffix, String packageName, String ftlFile) { + this.generatefileSuffix = fileSuffix; + this.packageName = packageName; + this.ftlFile = ftlFile; + } + + public String getGeneratefileSuffix() { + return generatefileSuffix; + } + + public String getPackageName() { + return packageName; + } + + public String getFtlFile() { + return ftlFile; + } + +} diff --git a/src/main/java/com/newyetai/common/freemarker/constant/FreemarkerConstants.java b/src/main/java/com/newyetai/common/freemarker/constant/FreemarkerConstants.java new file mode 100644 index 0000000..270998a --- /dev/null +++ b/src/main/java/com/newyetai/common/freemarker/constant/FreemarkerConstants.java @@ -0,0 +1,11 @@ +package com.newyetai.common.freemarker.constant; + +/** + * @author sr on 2020-04-10 + */ +public interface FreemarkerConstants { + + /** 数据库表名前缀 **/ + String TABLE_PREFIX = "xs_"; + +} diff --git a/src/main/java/com/newyetai/common/freemarker/dto/BusinessModelCreateDTO.java b/src/main/java/com/newyetai/common/freemarker/dto/BusinessModelCreateDTO.java new file mode 100644 index 0000000..1a65f21 --- /dev/null +++ b/src/main/java/com/newyetai/common/freemarker/dto/BusinessModelCreateDTO.java @@ -0,0 +1,39 @@ +package com.newyetai.common.freemarker.dto; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2020-04-10 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class BusinessModelCreateDTO implements Serializable { + + /** **/ + private static final long serialVersionUID = 3962743989033667188L; + + /** + * 文件输出路径-绝对路径,如/work/eclipse/workspace/alita-base/common/src/main/java/com/newyetai/common/freemarker/ + **/ + private String exportDir; + /** 包路径,如com.newyetai.dict **/ + private String packageName; + /** 是否创建业务路径,默认创建 **/ + private Boolean createBusinessPath; + /** 数据库表名:为空,则默认xs_entityName(snake小写) **/ + private String tableName; + /** 作者名 **/ + private String author; + /** 实体名,如Dict **/ + private String entityName; + /** 实体名描述,如数据字典 **/ + private String entityNameDescription; + +} diff --git a/src/main/java/com/newyetai/common/freemarker/util/CodeGenerateUtils.java b/src/main/java/com/newyetai/common/freemarker/util/CodeGenerateUtils.java new file mode 100644 index 0000000..0f06279 --- /dev/null +++ b/src/main/java/com/newyetai/common/freemarker/util/CodeGenerateUtils.java @@ -0,0 +1,88 @@ +package com.newyetai.common.freemarker.util; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileOutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; + +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.freemarker.constant.BusinessModelFileEnum; +import com.newyetai.common.freemarker.constant.FreemarkerConstants; +import com.newyetai.common.freemarker.dto.BusinessModelCreateDTO; +import com.newyetai.common.util.StrUtils; + +import freemarker.template.Template; +import lombok.extern.slf4j.Slf4j; + +/** + * @author sr on 2020-04-13 + */ +@Slf4j +public class CodeGenerateUtils { + + public static void generateModelFile(BusinessModelCreateDTO businessModelCreateDto) { + for (BusinessModelFileEnum businessModelFileEnum : BusinessModelFileEnum.values()) { + generateModelFile(businessModelCreateDto, businessModelFileEnum); + } + } + + public static boolean generateModelFile(BusinessModelCreateDTO businessModelCreateDto, + BusinessModelFileEnum businessModelFileEnum) { + // 文件输出路径/包名路径/实体名+文件后缀 + String entityName = businessModelCreateDto.getEntityName(); + String entityNameLowerCase = StrUtils.toLowerCamel(entityName); + String entityNameSnake = StrUtils.toSnake(entityNameLowerCase); + String packageName = businessModelCreateDto.getPackageName(); + String tableName = businessModelCreateDto.getTableName(); + String path = String.join(StringUtils.EMPTY, + packageNameToPath(businessModelFileEnum.getPackageName()), File.separator, + entityName, businessModelFileEnum.getGeneratefileSuffix()); + if (!Boolean.FALSE.equals(businessModelCreateDto.getCreateBusinessPath())) { + path = String.join(StringUtils.EMPTY, entityName.toLowerCase(), File.separator, path); + packageName = String.join(CommonConstants.POINT, packageName, entityName.toLowerCase()); + } + final String templateName = businessModelFileEnum.getFtlFile(); + File file = new File(businessModelCreateDto.getExportDir(), path); + if (!file.getParentFile().exists()) { + file.getParentFile().mkdirs(); + } + Map dataMap = new HashMap<>(); + try { + dataMap.put("packageName", packageName); + dataMap.put("author", businessModelCreateDto.getAuthor()); + dataMap.put("entityName", entityName); + dataMap.put("entityNameLowerCamel", entityNameLowerCase); + dataMap.put("entityNameSnake", entityNameSnake); + dataMap.put("entityNameDescription", businessModelCreateDto.getEntityNameDescription()); + dataMap.put("tableName", + StringUtils.isBlank(tableName) ? FreemarkerConstants.TABLE_PREFIX + entityNameSnake + : tableName); + + generateFileByTemplate(templateName, file, dataMap); + } catch (Exception e) { + e.printStackTrace(); + log.info("generateFile fail:{}", e.getMessage()); + return false; + } + log.info("generateFile suc:{}", file.getPath()); + return true; + } + + public static void generateFileByTemplate(final String templateName, File file, + Map dataMap) throws Exception { + Template template = FreeMarkerTemplateUtils.getTemplate(templateName); + FileOutputStream fos = new FileOutputStream(file); + Writer out = new BufferedWriter(new OutputStreamWriter(fos, "utf-8"), 10240); + template.process(dataMap, out); + } + + public static String packageNameToPath(String packageName) { + return packageName.replace('.', File.separatorChar); + } + +} diff --git a/src/main/java/com/newyetai/common/freemarker/util/FreeMarkerTemplateUtils.java b/src/main/java/com/newyetai/common/freemarker/util/FreeMarkerTemplateUtils.java new file mode 100644 index 0000000..3148cac --- /dev/null +++ b/src/main/java/com/newyetai/common/freemarker/util/FreeMarkerTemplateUtils.java @@ -0,0 +1,66 @@ +package com.newyetai.common.freemarker.util; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.Map; + +import freemarker.cache.ClassTemplateLoader; +import freemarker.cache.NullCacheStorage; +import freemarker.template.Configuration; +import freemarker.template.Template; +import freemarker.template.TemplateException; +import freemarker.template.TemplateExceptionHandler; +import lombok.extern.slf4j.Slf4j; + +/** + * @author sr on 2020-04-13 + */ +@Slf4j +public class FreeMarkerTemplateUtils { + + private FreeMarkerTemplateUtils() {} + + private static final Configuration CONFIGURATION = new Configuration(Configuration.VERSION_2_3_22); + + static { + //这里比较重要,用来指定加载模板所在的路径 + CONFIGURATION + .setTemplateLoader(new ClassTemplateLoader(FreeMarkerTemplateUtils.class, "/ftls")); + CONFIGURATION.setDefaultEncoding("UTF-8"); + CONFIGURATION.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); + CONFIGURATION.setCacheStorage(NullCacheStorage.INSTANCE); + } + + public static Template getTemplate(String templateName) throws IOException { + try { + return CONFIGURATION.getTemplate(templateName); + } catch (IOException e) { + throw e; + } + } + + /** + * 字符串模版占位符替换 + * @param templateStr + * @param params + * @return + * @author sr on 2020-12-21 + */ + public static String formatString(String templateStr, Map params) { + try { + Template template = new Template("formatString", templateStr, FreeMarkerTemplateUtils.CONFIGURATION); + StringWriter result = new StringWriter(); + template.process(params, result); + return result.toString(); + } catch (IOException | TemplateException e) { + log.error("内容占位符替换失败:{}", e.getMessage()); + } + return null; + } + + + public static void clearCache() { + CONFIGURATION.clearTemplateCache(); + } + +} diff --git a/src/main/java/com/newyetai/common/function/TransactionAfterCommit.java b/src/main/java/com/newyetai/common/function/TransactionAfterCommit.java new file mode 100644 index 0000000..0e72dfb --- /dev/null +++ b/src/main/java/com/newyetai/common/function/TransactionAfterCommit.java @@ -0,0 +1,38 @@ +package com.newyetai.common.function; + +import org.springframework.transaction.support.TransactionSynchronizationAdapter; +import org.springframework.transaction.support.TransactionSynchronizationManager; + +@FunctionalInterface +public interface TransactionAfterCommit { + + void afterCommit(); + + /** + * 事务提交后的回调操作 + * + * @param transactionAfterCommit 事务提交后 + */ + static void doSomeThingAfterCommit(TransactionAfterCommit transactionAfterCommit) { + TransactionSynchronizationManager + .registerSynchronization(new TransactionSynchronizationAdapter() { + @Override + public void afterCommit() { + transactionAfterCommit.afterCommit(); + } + }); + } + + static void doSomeThingAfterCompletion(TransactionAfterCommit transactionAfterCommit) { + TransactionSynchronizationManager + .registerSynchronization(new TransactionSynchronizationAdapter() { + @Override + public void afterCompletion(int status) { + transactionAfterCommit.afterCommit(); + } + }); + } + + + +} diff --git a/src/main/java/com/newyetai/common/functions/SFunction.java b/src/main/java/com/newyetai/common/functions/SFunction.java new file mode 100644 index 0000000..4678050 --- /dev/null +++ b/src/main/java/com/newyetai/common/functions/SFunction.java @@ -0,0 +1,31 @@ +package com.newyetai.common.functions; + +import java.io.Serializable; +import java.lang.invoke.SerializedLambda; +import java.lang.reflect.Method; +import java.util.function.Function; + +/** + * @author chenyun + * @description 序列化的Function + * @date 2020/9/16 13:38 + */ +@FunctionalInterface +public interface SFunction extends Function, Serializable { + + /** + * 解析function为SerializedLambda + * + * @return + */ + default SerializedLambda serialized() { + try { + Method replaceMethod = getClass().getDeclaredMethod("writeReplace"); + replaceMethod.setAccessible(true); + return (SerializedLambda) replaceMethod.invoke(this); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + +} diff --git a/src/main/java/com/newyetai/common/log/ILogProvider.java b/src/main/java/com/newyetai/common/log/ILogProvider.java new file mode 100644 index 0000000..52023fb --- /dev/null +++ b/src/main/java/com/newyetai/common/log/ILogProvider.java @@ -0,0 +1,12 @@ +package com.newyetai.common.log; + +/** + * 日志提供者 + * + * @author sr on 2020-10-29 + */ +public interface ILogProvider { + + void log(Object object); + +} diff --git a/src/main/java/com/newyetai/common/log/aspect/ControllerLogAspect.java b/src/main/java/com/newyetai/common/log/aspect/ControllerLogAspect.java new file mode 100644 index 0000000..38b2d88 --- /dev/null +++ b/src/main/java/com/newyetai/common/log/aspect/ControllerLogAspect.java @@ -0,0 +1,169 @@ +package com.newyetai.common.log.aspect; + +import com.google.common.collect.Lists; +import com.newyetai.common.AlitaResult; +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.dto.IOperateDTO; +import com.newyetai.common.log.dto.OperationLogDTO; +import com.newyetai.common.log.util.LogUtils; +import com.newyetai.common.util.*; +import com.newyetai.security.config.SecurityProperties; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.dto.IUserDetail; +import lombok.extern.slf4j.Slf4j; + +import org.apache.commons.lang3.StringUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.util.StopWatch; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletRequest; +import java.io.PrintWriter; +import java.io.Serializable; +import java.io.StringWriter; +import java.util.Date; +import java.util.List; +import java.util.Objects; + + +/** + * controller日志 + * + * @author sr on 2020-07-30 + */ +@Component +@Aspect +@Slf4j +public class ControllerLogAspect { + + private static final String ANON_LOGIN_URI = "/anon/user/find_user_detail_dto"; + + + + @Autowired + private SecurityProperties securityProperties; + + + @Around("@within(org.springframework.web.bind.annotation.RestController)") + public Object around(ProceedingJoinPoint joinPoint) throws Throwable { + Object result = null; + Throwable currentThrowable = null; + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + // 记录mongo日志 + IUserDetail userDto = UserContextHolder.getLoginUser(); + OperationLogDTO operationLog = new OperationLogDTO(); + HttpServletRequest request = SpringContextHolder.getRequest(); + String requestUri = request.getRequestURL().toString(); + String traceId = TracerUtils.getTraceId(); + operationLog.setTraceId(traceId); + operationLog.setSpanId(TracerUtils.getSpanId()); + operationLog.setParentId(TracerUtils.getParentId()); + operationLog.setLoginUser(userDto); + operationLog.setIp(RequestUtils.getIpAddress(request)); + operationLog.setSystemName(EnvironmentUtils.getApplicationName()); + operationLog.setRequestMethod(request.getMethod()); + operationLog.setRequestTime(new Date()); + operationLog.setRequestUri(requestUri); + List argList = Lists.newArrayList(); + for (Object object : joinPoint.getArgs()) { + // 移除参数分页对象,结果会返回,会记录 + if (object instanceof Page) { + continue; + } + // 文件对象 + if (object instanceof MultipartFile) { + long fileDes = ((MultipartFile) object).getSize(); + argList.add("multipartFile size:" + fileDes); + continue; + } + + if (!(object instanceof Serializable)) { + continue; + } + + //封装参数 + if (Objects.nonNull(userDto) && Objects.nonNull(object) && object instanceof IOperateDTO) { + //前置请求封装数据 + ((IOperateDTO) object).setOperateOrgId(userDto.getOrgId()); + ((IOperateDTO) object).setOperateUserId(userDto.getId()); + } + argList.add(object); + } + operationLog.setRequestBody(parseString(argList)); + try { + result = joinPoint.proceed(); + if (result instanceof AlitaResult) { + ((AlitaResult) result).setRequestId(traceId); + } + return result; + } catch (Throwable t) { + currentThrowable = t; + throw t; + } finally { + stopWatch.stop(); + try { + boolean canLog = canLog(requestUri); + if (canLog && !requestUri.contains(ANON_LOGIN_URI)) { + operationLog.setUseTime(stopWatch.getTotalTimeMillis()); + if (currentThrowable != null) { + operationLog.setResult("调用异常,异常信息:" + currentThrowable); + } else { + if (result != null && result.getClass().equals(byte[].class)) { + operationLog.setResult("byte数组。。。"); + } else { + operationLog.setResult(parseString(result)); + } + } + LogUtils.log(operationLog); + } + } catch (Exception e) { + log.info("controller log:{}, error:{}", operationLog, e.getMessage()); + } + + } + } + + private String parseString(Object object) { + try { + return JsonUtils.toJsonString(object, false); + } catch (Exception e) { + return getStackTrace(e); + } + } + + /** + * 获取异常的堆栈信息 + * + * @param t + * @return + */ + public static String getStackTrace(Throwable t) { + StringWriter sw = new StringWriter(); + + try (PrintWriter pw = new PrintWriter(sw)) { + t.printStackTrace(pw); + return sw.toString(); + } catch (Exception e) { + return t.getMessage(); + } + } + + public boolean canLog(String requestUri) { + String notLogs = securityProperties.getNotLogs(); + if (StringUtils.isBlank(notLogs)) { + return true; + } + for (String notlog : notLogs.split(CommonConstants.COMMA)) { + if (requestUri.contains(notlog)) { + return false; + } + } + return true; + } + +} diff --git a/src/main/java/com/newyetai/common/log/dto/ExceptionLogDTO.java b/src/main/java/com/newyetai/common/log/dto/ExceptionLogDTO.java new file mode 100644 index 0000000..3946007 --- /dev/null +++ b/src/main/java/com/newyetai/common/log/dto/ExceptionLogDTO.java @@ -0,0 +1,68 @@ +package com.newyetai.common.log.dto; + +import java.io.Serializable; +import java.util.Date; + +import org.apache.commons.lang3.StringUtils; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonFormat.Shape; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 异常日志 + * + * @author sr on 2020-12-09 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class ExceptionLogDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = -3544344864494146694L; + + private String id; + + /** 错误号 **/ + private String errNo; + + /** 年月 **/ + private String ym; + + /** 序号 **/ + private Long seqId; + + /** 链路id **/ + private String traceId; + + /** 创建时间 **/ + @JsonFormat(shape = Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTime; + + /** 错误信息 **/ + private String msg; + + /** + * ym + seqId(5位补零) + * @return + * @author sr on 2020-12-09 + */ + public String getErrNo() { + if (errNo == null) { + if (seqId != null) { + this.errNo = ym + StringUtils.leftPad(String.valueOf(this.seqId), 5, "0"); + } else if (traceId != null) { + this.errNo = traceId; + } + + } + return errNo; + } + +} diff --git a/src/main/java/com/newyetai/common/log/dto/OperationLogDTO.java b/src/main/java/com/newyetai/common/log/dto/OperationLogDTO.java new file mode 100644 index 0000000..4dad37a --- /dev/null +++ b/src/main/java/com/newyetai/common/log/dto/OperationLogDTO.java @@ -0,0 +1,59 @@ +package com.newyetai.common.log.dto; + +import java.io.Serializable; +import java.util.Date; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 操作日志 + * @author sr on 2020-10-26 + */ +@Data +@NoArgsConstructor +public class OperationLogDTO implements Serializable { + + /** **/ + private static final long serialVersionUID = -6817430348970835175L; + + /** 链路id **/ + private String traceId; + + /** spanid **/ + private String spanId; + + /** 上一级链路id **/ + private String parentId; + + /** 系统名称 **/ + private String systemName; + + /** ip **/ + private String ip; + + /** 请求地址 **/ + private String requestUri; + + /** 请求类型 **/ + private String requestMethod; + + /** 请求参数 **/ + private Object requestBody; + + /** 请求时间 **/ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date requestTime; + + /** 请求耗时(ms) **/ + private Long useTime; + + /** 请求结果 **/ + private Object result; + + /** 当前登录用户信息:属性见上下文用户对象 **/ + private Object loginUser; + +} diff --git a/src/main/java/com/newyetai/common/log/provider/Slf4jLogProvider.java b/src/main/java/com/newyetai/common/log/provider/Slf4jLogProvider.java new file mode 100644 index 0000000..f8a8de5 --- /dev/null +++ b/src/main/java/com/newyetai/common/log/provider/Slf4jLogProvider.java @@ -0,0 +1,23 @@ +package com.newyetai.common.log.provider; + +import com.newyetai.common.log.ILogProvider; +import com.newyetai.common.util.JsonUtils; + +import lombok.extern.slf4j.Slf4j; + +/** + * @author sr on 2021-01-21 + */ +@Slf4j +public class Slf4jLogProvider implements ILogProvider { + + @Override + public void log(Object object) { + try { + log.info("class:{}, obj:{}", object.getClass(), JsonUtils.toJsonString(object)); + } catch (Exception e) { + log.error("cant log:{}", e.getMessage()); + } + } + +} diff --git a/src/main/java/com/newyetai/common/log/util/LogUtils.java b/src/main/java/com/newyetai/common/log/util/LogUtils.java new file mode 100644 index 0000000..8301b55 --- /dev/null +++ b/src/main/java/com/newyetai/common/log/util/LogUtils.java @@ -0,0 +1,27 @@ +package com.newyetai.common.log.util; + +import com.newyetai.common.log.ILogProvider; +import com.newyetai.common.log.provider.Slf4jLogProvider; + +/** + * @author sr on 2020-10-29 + */ +public class LogUtils { + + private static ILogProvider logProvider = new Slf4jLogProvider(); + + public void setLogProvider(ILogProvider logProvider) { + LogUtils.logProvider = logProvider; + } + + /** + * 记录日志 + * + * @param object + * @author sr on 2020-10-29 + */ + public static void log(Object object) { + logProvider.log(object); + } + +} diff --git a/src/main/java/com/newyetai/common/sensitive/SensitiveInfoUtils.java b/src/main/java/com/newyetai/common/sensitive/SensitiveInfoUtils.java new file mode 100644 index 0000000..17a565f --- /dev/null +++ b/src/main/java/com/newyetai/common/sensitive/SensitiveInfoUtils.java @@ -0,0 +1,213 @@ +package com.newyetai.common.sensitive; + +import org.apache.commons.lang3.StringUtils; + + +/** + * 脱敏基本工具类 + * + * @author qpc + */ +public class SensitiveInfoUtils { + + /** + * [中文姓名] 只显示第一个汉字,其他隐藏为2个星号<例子:李**> + */ + public static String chineseName(final String fullName) { + if (StringUtils.isBlank(fullName)) { + return ""; + } + final String name = StringUtils.left(fullName, 1); + return StringUtils.rightPad(name, StringUtils.length(fullName), "*"); + } + + /** + * [中文姓名] 只显示第一个汉字,其他隐藏为2个星号<例子:李**> + */ + public static String chineseName(final String familyName, final String givenName) { + if (StringUtils.isBlank(familyName) || StringUtils.isBlank(givenName)) { + return ""; + } + return chineseName(familyName + givenName); + } + + /** + * [身份证号] 显示最后四位,其他隐藏。共计18位或者15位。<例子:*************5762> + */ + public static String idCardNum(final String id) { + if (StringUtils.isBlank(id)) { + return ""; + } + return StringUtils.left(id, 3).concat(StringUtils + .removeStart(StringUtils.leftPad(StringUtils.right(id, 3), StringUtils.length(id), "*"), + "***")); + } + + /** + * 将字符串中某一段替换成* + *

+ * 比如 呵呵哈哈哈或或 , start:0 end:1 则变成 *呵哈哈哈或或 + * + * @param start + * @param end + * @return + */ + public static String exchangeHashKey(String origin, int start, int end) { + if (org.apache.commons.lang3.StringUtils.isBlank(origin)) { + return null; + } + char[] chars = origin.toCharArray(); + int startIndex = start - 1; + for (int i = 0; i < chars.length; i++) { + if (i >= startIndex && i < end) { + chars[i] = '*'; + } + } + return new String(chars); + } + + /** + * 【身份证号】前三位 和后三位 + * + * @param front + * @param end + */ + public static String idCardNum(String idCardNum, int front, int end) { + //身份证不能为空 + if (StringUtils.isEmpty(idCardNum)) { + return ""; + } + //需要截取的长度不能大于身份证号长度 + if ((front + end) > idCardNum.length()) { + return ""; + } + //需要截取的不能小于0 + if (front < 0 || end < 0) { + return ""; + } + //计算*的数量 + int asteriskCount = idCardNum.length() - (front + end); + StringBuffer asteriskStr = new StringBuffer(); + for (int i = 0; i < asteriskCount; i++) { + asteriskStr.append("*"); + } + String regex = "(\\w{" + front + "})(\\w+)(\\w{" + end + "})"; + return idCardNum.replaceAll(regex, "$1" + asteriskStr + "$3"); + } + + /** + * 【固定电话 前四位,后两位 + * + * @param num + * @return + */ + public static String fixedPhone(String num) { + if (StringUtils.isBlank(num)) { + return ""; + } + return StringUtils.left(num, 4).concat(StringUtils.removeStart(StringUtils.leftPad(StringUtils.right(num, 2), StringUtils.length(num), "*"), "****")); + } + + /** + * [手机号码] 前三位,后四位,其他隐藏<例子:138******1234> + */ + public static String mobilePhone2(final String num) { + if (StringUtils.isBlank(num)) { + return ""; + } + return StringUtils.left(num, 3).concat(StringUtils + .removeStart(StringUtils.leftPad(StringUtils.right(num, 4), StringUtils.length(num), "*"), + "***")); + + } + + /** + * 【手机号码】前三位,后两位,其他隐藏,比如135******10 + * + * @param num + * @return + */ + public static String mobilePhone(String num) { + if (StringUtils.isBlank(num)) { + return ""; + } + return StringUtils.left(num, 3).concat(StringUtils.removeStart(StringUtils.leftPad(StringUtils.right(num, 2), StringUtils.length(num), "*"), "***")); + } + + /** + * [地址] 只显示到地区,不显示详细地址;我们要对个人信息增强保护<例子:北京市海淀区****> + * + * @param sensitiveSize 敏感信息长度 + */ + public static String address(final String address, final int sensitiveSize) { + if (StringUtils.isBlank(address)) { + return ""; + } + if (address.length() <= sensitiveSize) { + return address; + } + final int length = StringUtils.length(address); + return StringUtils.rightPad(StringUtils.left(address, length - sensitiveSize), length, "*"); + } + + /** + * [电子邮箱] 邮箱前缀仅显示第一个字母,前缀其他隐藏,用星号代替,@及后面的地址显示<例子:g**@163.com> + */ + public static String email(final String email) { + if (StringUtils.isBlank(email)) { + return ""; + } + final int index = StringUtils.indexOf(email, "@"); + if (index <= 1) { + return email; + } else { + return StringUtils.rightPad(StringUtils.left(email, 1), index, "*") + .concat(StringUtils.mid(email, index, StringUtils.length(email))); + } + } + + /** + * [银行卡号] 前六位,后四位,其他用星号隐藏每位1个星号<例子:6222600**********1234> + */ + public static String bankCard(final String cardNum) { + if (StringUtils.isBlank(cardNum)) { + return ""; + } + + return StringUtils.left(cardNum, 6).concat(StringUtils + .removeStart(StringUtils.leftPad(StringUtils.right(cardNum, 4), StringUtils.length(cardNum), "*"), + "***")); + + } + + /** + * [公司开户银行联号] 公司开户银行联行号,显示前两位,其他用星号隐藏,每位1个星号<例子:12********> + */ + public static String shopsCode(final String code) { + if (StringUtils.isBlank(code)) { + return ""; + } + return StringUtils.rightPad(StringUtils.left(code, 2), StringUtils.length(code), "*"); + } + + /** + * 【密码】密码的全部字符都用*代替,比如:****** + * + * @param password + * @return + */ + public static String password(String password) { + if (StringUtils.isBlank(password)) { + return ""; + } + String pwd = StringUtils.left(password, 0); + return StringUtils.rightPad(pwd, StringUtils.length(password), "*"); + } + + + public static void main(String[] args) { + String bankCard = "6214851215669289"; + System.out.println(bankCard(bankCard)); + } + +} diff --git a/src/main/java/com/newyetai/common/sensitive/SensitiveType.java b/src/main/java/com/newyetai/common/sensitive/SensitiveType.java new file mode 100644 index 0000000..27e254e --- /dev/null +++ b/src/main/java/com/newyetai/common/sensitive/SensitiveType.java @@ -0,0 +1,64 @@ +package com.newyetai.common.sensitive; + + +/** + * 脱敏类型枚举 + * + * @author qpc + */ +public enum SensitiveType { + /** + * 中文名 + */ + CHINESE_NAME, + /** + * 身份证号 + */ + ID_CARD, + /** + * 座机号 + */ + FIXED_PHONE, + /** + * 手机号 + */ + MOBILE_PHONE, + /** + * 密码 + */ + PASSWORD, + /** + * 地址 + */ + ADDRESS, + /** + * 电子邮件 + */ + EMAIL, + /** + * 银行卡 + */ + BANK_CARD, + /** + * 公司开户银行联号 + */ + SHOPS_CODE, + /** + * 自定义正则过滤 + */ + RGE_EXP, + + /** + * 空值 + */ + NULL, + /** + * 自定义处理 + */ + SELF, + + /** + * 公司名称 + */ + COMPANY_NAME +} diff --git a/src/main/java/com/newyetai/common/sensitive/jackson/SensitiveInfo.java b/src/main/java/com/newyetai/common/sensitive/jackson/SensitiveInfo.java new file mode 100644 index 0000000..7df1f56 --- /dev/null +++ b/src/main/java/com/newyetai/common/sensitive/jackson/SensitiveInfo.java @@ -0,0 +1,48 @@ +package com.newyetai.common.sensitive.jackson; + +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.newyetai.common.sensitive.SensitiveType; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * 脱敏AOP注解 + */ +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotationsInside +@JsonSerialize(using = SensitiveInfoSerialize.class) +public @interface SensitiveInfo { + SensitiveType value() default SensitiveType.RGE_EXP; + + /** + * 前缀(保留多少位) + * + * @return int + */ + int prefix() default -1; + + + /** + * 后缀(保留多少位) + * + * @return int + */ + int suffix() default -1; + + /** + * 自定义正则匹配规则 + */ + String regExp() default ""; + + /** + * 正则替换字符 + */ + String regStr() default "*"; + + /** + * 自定义处理标识 + */ + String tag() default "self"; +} diff --git a/src/main/java/com/newyetai/common/sensitive/jackson/SensitiveInfoObjectSerialize.java b/src/main/java/com/newyetai/common/sensitive/jackson/SensitiveInfoObjectSerialize.java new file mode 100644 index 0000000..5dbc2af --- /dev/null +++ b/src/main/java/com/newyetai/common/sensitive/jackson/SensitiveInfoObjectSerialize.java @@ -0,0 +1,84 @@ +package com.newyetai.common.sensitive.jackson; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.BeanProperty; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.ContextualSerializer; +import com.newyetai.common.sensitive.SensitiveType; +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; +import java.util.Objects; + + +/** + * jackson的脱敏实现 + * + * @author doobo + */ +@Slf4j +public class SensitiveInfoObjectSerialize extends JsonSerializer implements ContextualSerializer { + + private SensitiveType type; + + public SensitiveInfoObjectSerialize() { + } + + public SensitiveInfoObjectSerialize(final SensitiveInfo sensitiveInfo) { + this.type = sensitiveInfo.value(); + } + + @Override + public void serialize(final Object s, final JsonGenerator jsonGenerator, + final SerializerProvider serializerProvider) throws IOException, JsonProcessingException { + try { + if (this.type == SensitiveType.NULL && !isBaseType(s.getClass())) { + jsonGenerator.writeObject(null); + return; + } + jsonGenerator.writeObject(s); + } catch (Exception e) { + log.error("脱敏数据处理异常", e); + jsonGenerator.writeObject(s); + } + } + + @Override + public JsonSerializer createContextual(final SerializerProvider serializerProvider, + final BeanProperty beanProperty) throws JsonMappingException { + // 为空直接跳过 + if (beanProperty != null) { + // 非 String 类直接跳过 + if (Objects.equals(beanProperty.getType().getRawClass(), Object.class)) { + SensitiveInfo sensitiveInfo = beanProperty.getAnnotation(SensitiveInfo.class); + if (sensitiveInfo == null) { + sensitiveInfo = beanProperty.getContextAnnotation(SensitiveInfo.class); + } + if (sensitiveInfo != null && sensitiveInfo.value() == SensitiveType.NULL) { + return new SensitiveInfoObjectSerialize(sensitiveInfo); + } + } + return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty); + } + return serializerProvider.findNullValueSerializer(null); + } + + /** + * 判断object是否为基本类型 + * + * @param cls + */ + public boolean isBaseType(Class cls) { + return cls.equals(int.class) || + cls.equals(byte.class) || + cls.equals(long.class) || + cls.equals(double.class) || + cls.equals(float.class) || + cls.equals(char.class) || + cls.equals(short.class) || + cls.equals(boolean.class); + } +} diff --git a/src/main/java/com/newyetai/common/sensitive/jackson/SensitiveInfoSerialize.java b/src/main/java/com/newyetai/common/sensitive/jackson/SensitiveInfoSerialize.java new file mode 100644 index 0000000..a50b705 --- /dev/null +++ b/src/main/java/com/newyetai/common/sensitive/jackson/SensitiveInfoSerialize.java @@ -0,0 +1,125 @@ +package com.newyetai.common.sensitive.jackson; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.BeanProperty; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.ContextualSerializer; +import com.newyetai.common.sensitive.SensitiveInfoUtils; +import com.newyetai.common.sensitive.SensitiveType; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; + +import java.io.IOException; +import java.util.Objects; + +/** + * jackson的脱敏实现 + * + * @author doobo + */ +@Slf4j +public class SensitiveInfoSerialize extends JsonSerializer implements ContextualSerializer { + + private SensitiveType type; + + private SensitiveInfo sensitiveInfo; + + public SensitiveInfoSerialize() { + } + + public SensitiveInfoSerialize(final SensitiveInfo sensitiveInfo) { + this.type = sensitiveInfo.value(); + this.sensitiveInfo = sensitiveInfo; + } + + private int getOrDefault(int value, int defaultValue) { + return value < 0 ? defaultValue : value; + } + + @Override + public void serialize(final String s, final JsonGenerator jsonGenerator, + final SerializerProvider serializerProvider) throws IOException, JsonProcessingException { + try { + //有正则优先使用正则 + if (StringUtils.isNotBlank(sensitiveInfo.regExp())) { + jsonGenerator.writeString(s.replaceAll(sensitiveInfo.regExp(), sensitiveInfo.regStr())); + return; + } + switch (this.type) { + case CHINESE_NAME: { + jsonGenerator.writeString(SensitiveInfoUtils.chineseName(s)); + break; + } + case ID_CARD: + case MOBILE_PHONE: { + jsonGenerator.writeString(SensitiveInfoUtils.idCardNum(s + , getOrDefault(sensitiveInfo.prefix(), 3), getOrDefault(sensitiveInfo.suffix(), 4))); + break; + } + case FIXED_PHONE: { + jsonGenerator.writeString(SensitiveInfoUtils.fixedPhone(s)); + break; + } + case PASSWORD: { + jsonGenerator.writeString(SensitiveInfoUtils.password(s)); + break; + } + case ADDRESS: { + jsonGenerator.writeString(SensitiveInfoUtils.address(s, getOrDefault(sensitiveInfo.prefix(), 8))); + break; + } + case EMAIL: { + jsonGenerator.writeString(SensitiveInfoUtils.email(s)); + break; + } + case BANK_CARD: { + jsonGenerator.writeString(SensitiveInfoUtils.bankCard(s)); + break; + } + case SHOPS_CODE: { + jsonGenerator.writeString(SensitiveInfoUtils.shopsCode(s)); + break; + } + case NULL: { + jsonGenerator.writeString((String) null); + break; + } + case COMPANY_NAME: { + jsonGenerator.writeString(SensitiveInfoUtils.exchangeHashKey(s + , getOrDefault(sensitiveInfo.prefix(), 0), getOrDefault(sensitiveInfo.suffix(), 3))); + break; + } + default: { + jsonGenerator.writeString(s); + } + } + } catch (Exception e) { + log.error("脱敏数据处理异常", e); + jsonGenerator.writeString(s); + } + } + + @Override + public JsonSerializer createContextual(final SerializerProvider serializerProvider, + final BeanProperty beanProperty) throws JsonMappingException { + // 为空直接跳过 + if (beanProperty != null) { + SensitiveInfo sensitiveInfo = beanProperty.getAnnotation(SensitiveInfo.class); + // 非 String 类直接跳过 + if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) { + if (sensitiveInfo != null) { + // 如果能得到注解,就将注解的 value 传入 SensitiveInfoSerialize + return new SensitiveInfoSerialize(sensitiveInfo); + } + } + if (sensitiveInfo != null && sensitiveInfo.value() == SensitiveType.NULL) { + return new SensitiveInfoObjectSerialize(sensitiveInfo); + } + return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty); + } + return serializerProvider.findNullValueSerializer(null); + } +} diff --git a/src/main/java/com/newyetai/common/sensitive/service/AbstractSensitiveService.java b/src/main/java/com/newyetai/common/sensitive/service/AbstractSensitiveService.java new file mode 100644 index 0000000..cde5ce3 --- /dev/null +++ b/src/main/java/com/newyetai/common/sensitive/service/AbstractSensitiveService.java @@ -0,0 +1,69 @@ +package com.newyetai.common.sensitive.service; + +import com.newyetai.common.sensitive.SensitiveInfoUtils; + +/** + * 默认脱敏工具抽象类 + * 使用时,可继承并重写(覆盖)相关方法 + */ +public abstract class AbstractSensitiveService implements SensitiveService { + @Override + public String chineseName(String fullName) { + return SensitiveInfoUtils.chineseName(fullName); + } + + @Override + public String chineseName(String familyName, String givenName) { + return SensitiveInfoUtils.chineseName(familyName, givenName); + } + + @Override + public String idCardNum(String id) { + return SensitiveInfoUtils.idCardNum(id); + } + + @Override + public String idCardNum(String idCardNum, int front, int end) { + return SensitiveInfoUtils.idCardNum(idCardNum, front, end); + } + + @Override + public String fixedPhone(String num) { + return SensitiveInfoUtils.fixedPhone(num); + } + + @Override + public String mobilePhone2(String num) { + return SensitiveInfoUtils.mobilePhone2(num); + } + + @Override + public String mobilePhone(String num) { + return SensitiveInfoUtils.mobilePhone(num); + } + + @Override + public String address(String address, int sensitiveSize) { + return SensitiveInfoUtils.address(address, sensitiveSize); + } + + @Override + public String email(String email) { + return SensitiveInfoUtils.email(email); + } + + @Override + public String bankCard(String cardNum) { + return SensitiveInfoUtils.bankCard(cardNum); + } + + @Override + public String shopsCode(String code) { + return SensitiveInfoUtils.shopsCode(code); + } + + @Override + public String password(String password) { + return SensitiveInfoUtils.password(password); + } +} diff --git a/src/main/java/com/newyetai/common/sensitive/service/SensitiveService.java b/src/main/java/com/newyetai/common/sensitive/service/SensitiveService.java new file mode 100644 index 0000000..08a7656 --- /dev/null +++ b/src/main/java/com/newyetai/common/sensitive/service/SensitiveService.java @@ -0,0 +1,69 @@ +package com.newyetai.common.sensitive.service; + +/** + * 脱敏服务 + */ +public interface SensitiveService { + + /** + * [中文姓名] 只显示第一个汉字,其他隐藏为2个星号<例子:李**> + */ + String chineseName(final String fullName); + + /** + * [中文姓名] 只显示第一个汉字,其他隐藏为2个星号<例子:李**> + */ + String chineseName(final String familyName, final String givenName); + + /** + * [身份证号] 显示最后四位,其他隐藏。共计18位或者15位。<例子:*************5762> + */ + String idCardNum(final String id); + + /** + * 【身份证号】前三位 和后三位 + */ + String idCardNum(String idCardNum, int front, int end); + + /** + * 【固定电话 前四位,后两位 + */ + String fixedPhone(String num); + + /** + * [手机号码] 前三位,后四位,其他隐藏<例子:138******1234> + */ + String mobilePhone2(final String num); + + /** + * 【手机号码】前三位,后两位,其他隐藏,比如135******10 + */ + String mobilePhone(String num); + + /** + * [地址] 只显示到地区,不显示详细地址;我们要对个人信息增强保护<例子:北京市海淀区****> + * + * @param sensitiveSize 敏感信息长度 + */ + String address(final String address, final int sensitiveSize); + + /** + * [电子邮箱] 邮箱前缀仅显示第一个字母,前缀其他隐藏,用星号代替,@及后面的地址显示<例子:g**@163.com> + */ + String email(final String email); + + /** + * [银行卡号] 前六位,后四位,其他用星号隐藏每位1个星号<例子:6222600**********1234> + */ + String bankCard(final String cardNum); + + /** + * [公司开户银行联号] 公司开户银行联行号,显示前两位,其他用星号隐藏,每位1个星号<例子:12********> + */ + String shopsCode(final String code); + + /** + * 【密码】密码的全部字符都用*代替,比如:****** + */ + String password(String password); +} diff --git a/src/main/java/com/newyetai/common/sensitive/service/SensitiveServiceUtils.java b/src/main/java/com/newyetai/common/sensitive/service/SensitiveServiceUtils.java new file mode 100644 index 0000000..05ec278 --- /dev/null +++ b/src/main/java/com/newyetai/common/sensitive/service/SensitiveServiceUtils.java @@ -0,0 +1,32 @@ +package com.newyetai.common.sensitive.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * 脱敏服务工具类 + */ +@Component +public class SensitiveServiceUtils { + + /** + * 脱敏工具 + */ + private static SensitiveService sensitiveService; + + @Autowired(required = false) + public void setSensitiveService(SensitiveService sensitiveService) { + SensitiveServiceUtils.sensitiveService = sensitiveService; + } + + /** + * 获取脱敏工具类 + */ + public static SensitiveService getSensitiveService() { + if (SensitiveServiceUtils.sensitiveService == null) { + SensitiveServiceUtils.sensitiveService = new AbstractSensitiveService() { + }; + } + return SensitiveServiceUtils.sensitiveService; + } +} diff --git a/src/main/java/com/newyetai/common/service/IMockProvider.java b/src/main/java/com/newyetai/common/service/IMockProvider.java new file mode 100644 index 0000000..b029280 --- /dev/null +++ b/src/main/java/com/newyetai/common/service/IMockProvider.java @@ -0,0 +1,36 @@ +package com.newyetai.common.service; + + +public interface IMockProvider{ + + void mockPlatUser() ; + + void mockUser(Long userId, Long orgId); + + void clearUser(); + + + + + public class DefaultMockProvider implements IMockProvider{ + + @Override + public void mockPlatUser() { + // TODO Auto-generated method stub + } + + @Override + public void mockUser(Long userId, Long orgId) { + // TODO Auto-generated method stub + + } + + @Override + public void clearUser() { + // TODO Auto-generated method stub + + } + + } +} + diff --git a/src/main/java/com/newyetai/common/trace/DefaultTracer.java b/src/main/java/com/newyetai/common/trace/DefaultTracer.java new file mode 100644 index 0000000..f1fe43e --- /dev/null +++ b/src/main/java/com/newyetai/common/trace/DefaultTracer.java @@ -0,0 +1,12 @@ +package com.newyetai.common.trace; + +import com.newyetai.common.util.RandomUtils; + +public class DefaultTracer implements ITracer{ + + @Override + public String getTraceId() { + return RandomUtils.generateUUID(); + } + +} diff --git a/src/main/java/com/newyetai/common/trace/ITracer.java b/src/main/java/com/newyetai/common/trace/ITracer.java new file mode 100644 index 0000000..a6e6944 --- /dev/null +++ b/src/main/java/com/newyetai/common/trace/ITracer.java @@ -0,0 +1,15 @@ +package com.newyetai.common.trace; + +public interface ITracer { + + String getTraceId(); + + default String getSpanId() { + return null; + } + + default String getParentId() { + return null; + } + +} diff --git a/src/main/java/com/newyetai/common/util/AESUtils.java b/src/main/java/com/newyetai/common/util/AESUtils.java new file mode 100644 index 0000000..586a757 --- /dev/null +++ b/src/main/java/com/newyetai/common/util/AESUtils.java @@ -0,0 +1,50 @@ +package com.newyetai.common.util; + +import java.nio.charset.StandardCharsets; +import java.security.Security; + +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; + +import org.springframework.util.Base64Utils; + + +/** + * @author sr on 2024-02-22 + */ +public class AESUtils { + + public static final String TRANSFORM_ECB_5 = "AES/ECB/PKCS5Padding"; + public static final String TRANSFORM_ECB_7 = "AES/ECB/PKCS7Padding"; + public static final String TRANSFORM_ECB = "AES/ECB/NoPadding"; + + static { + Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); + } + + public static Cipher getCipher(String transform) throws Exception { + if (TRANSFORM_ECB_7.equals(transform)) { + return Cipher.getInstance(transform, "BC"); + } else { + return Cipher.getInstance(transform); + } + } + + public static String encrypt(String input, String key, String transform) throws Exception { + Cipher cipher = getCipher(transform); + SecretKey keySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES"); + cipher.init(Cipher.ENCRYPT_MODE, keySpec); + return Base64Utils.encodeToString(cipher.doFinal(input.getBytes(StandardCharsets.UTF_8))); + } + + public static String decrypt(String input, String key, String transform) + throws Exception { + Cipher cipher = getCipher(transform); + SecretKey keySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES"); + cipher.init(Cipher.DECRYPT_MODE, keySpec); + return new String(cipher.doFinal(Base64Utils.decode(input.getBytes(StandardCharsets.UTF_8))), + StandardCharsets.UTF_8); + } + +} diff --git a/src/main/java/com/newyetai/common/util/BaseDtoUtils.java b/src/main/java/com/newyetai/common/util/BaseDtoUtils.java new file mode 100644 index 0000000..a736b07 --- /dev/null +++ b/src/main/java/com/newyetai/common/util/BaseDtoUtils.java @@ -0,0 +1,36 @@ +package com.newyetai.common.util; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.common.entity.BaseEntity; + +/** + * 基础dto工具类 + * @author sr on 2019-12-07 + */ +public class BaseDtoUtils { + + /** + * 创建回写dto数据 + * @param entity + * @param dto + * @author sr on 2019-12-07 + */ + public static void createCopy(BaseEntity entity, BaseDTO dto) { + dto.setId(entity.getId()); + dto.setDeleted(entity.getDeleted()); + dto.setCreateTime(entity.getCreateTime()); + dto.setCreateBy(entity.getCreateBy()); + } + + /** + * 修改回写dto数据 + * @param entity + * @param dto + * @author sr on 2019-12-07 + */ + public static void updateCopy(BaseEntity entity, BaseDTO dto) { + dto.setUpdateTime(entity.getUpdateTime()); + dto.setUpdateBy(entity.getUpdateBy()); + } + +} diff --git a/src/main/java/com/newyetai/common/util/BigDecimalUtils.java b/src/main/java/com/newyetai/common/util/BigDecimalUtils.java new file mode 100644 index 0000000..d3c5ed0 --- /dev/null +++ b/src/main/java/com/newyetai/common/util/BigDecimalUtils.java @@ -0,0 +1,72 @@ +package com.newyetai.common.util; + +import com.newyetai.common.exception.util.Assert; +import java.math.BigDecimal; +import java.math.RoundingMode; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; + +/** + * @author sr on 2020-08-14 + */ +@Slf4j +public class BigDecimalUtils { + + /** + * 保留两位小数 + * + * @return + */ + public static BigDecimal keepTwo(BigDecimal amount) { + if (amount == null) { + return BigDecimal.ZERO; + } + return amount.setScale(2, RoundingMode.DOWN); + } + + /** + * 转BigDecimal(转换失败,默认值null) + * @param amountStr + * @return + * @author sr on 2020-08-14 + */ + public static BigDecimal parse(String amountStr) { + return parse(amountStr, null); + } + + /** + * 转BigDecimal + * + * @param amountStr + * @param defaultValue 转换失败默认值 + * @return + * @author sr on 2020-08-14 + */ + public static BigDecimal parse(String amountStr, BigDecimal defaultValue) { + if (StringUtils.isBlank(amountStr)) { + return defaultValue; + } + try { + return new BigDecimal(amountStr); + } catch (NumberFormatException e) { + log.info("bigDecimal parse error", e); + return defaultValue; + } + } + + /** + * 见N+1进N 例如见厘进分 + * 0.0321->0.04 + * 0.0310->0.04 + * 0.0301->0.03 + * -0.991->-0.990 + * @param decimal + * @return + */ + public static BigDecimal rounding(BigDecimal decimal, int n){ + Assert.isTrue(n > 0, "小数位必须大于0"); + Assert.notNull(decimal, "金额不能为空"); + return decimal.setScale(n + 1, RoundingMode.DOWN).setScale(n, RoundingMode.UP); + } + +} diff --git a/src/main/java/com/newyetai/common/util/CookieUtils.java b/src/main/java/com/newyetai/common/util/CookieUtils.java new file mode 100644 index 0000000..7c34081 --- /dev/null +++ b/src/main/java/com/newyetai/common/util/CookieUtils.java @@ -0,0 +1,110 @@ +package com.newyetai.common.util; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; + +import com.google.common.base.Strings; +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.constant.CookieConstants; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * @author Jerry.li + * @description Cookie工具类 + * @date 2020/4/2 + */ +@Slf4j +public class CookieUtils { + + /** + * 获取登录token存储cookie的key + * + * @return + * @author sr on 2020-06-11 + */ + public static String getLoginTokenCookieKey() { + String profile = EnvironmentUtils.getProperty(CommonConstants.PROFILE_KEY); + return CookieConstants.LOGIN_COOKIE_NAME_PREFIX + + (Strings.isNullOrEmpty(profile) ? null : profile.substring(0, 1)); + } + + /** + * 获取指定key的值 + * + * @param key + * @param cookies + * @return + */ + public static String getCookieValue(String key, Cookie[] cookies) { + String value = null; + if (null != cookies && !StringUtils.isEmpty(key)) { + for (Cookie cookie : cookies) { + String cookieName = cookie.getName(); + if (key.equals(cookieName)) { + value = cookie.getValue(); + break; + } + } + } + return value; + } + + /** + * 创建Cookie + * + * @param name + * @param value + * @param domain + * @param path + * @param maxAge 单位:秒 -1: 代表关闭浏览器时就清除cookie 0:创建完cookie,使用后马上就删除 + * @return + */ + public static Cookie createCookie(String name, String value, String domain, String path, + int maxAge) { + Cookie cookie = new Cookie(name, value); + try { + if (StringUtils.isNotEmpty(domain)) { + cookie.setDomain(domain); + } + path = StringUtils.isEmpty(path) ? "/" : path; + cookie.setPath(path); + cookie.setHttpOnly(false); + cookie.setMaxAge(maxAge); + return cookie; + } catch (Exception e) { + log.error("------创建Cookie时,系统异常:{0}", e); + return null; + } + } + + /** + * 移除Cookie + * + * @param name 需要移除的cookie名称 + * @param domain 指定某个域名,不指定就是清空当前tomcat应用下的所有cookie + * @param request + * @param response + */ + public static void removeCookie(String name, String domain, HttpServletRequest request, + HttpServletResponse response) { + Cookie[] cookies = request.getCookies(); + if (!StringUtils.isEmpty(name) && null != cookies) { + for (Cookie cookie : cookies) { + if (name.equals(cookie.getName())) { + Cookie tempCookie = new Cookie(name, ""); + tempCookie.setMaxAge(0); + tempCookie.setPath("/"); + if (!StringUtils.isEmpty(domain)) { + tempCookie.setDomain(domain); + } + response.addCookie(tempCookie); + break; + } + } + } + } + +} diff --git a/src/main/java/com/newyetai/common/util/DateUtils.java b/src/main/java/com/newyetai/common/util/DateUtils.java new file mode 100644 index 0000000..6fba5a9 --- /dev/null +++ b/src/main/java/com/newyetai/common/util/DateUtils.java @@ -0,0 +1,335 @@ +package com.newyetai.common.util; + +import lombok.extern.slf4j.Slf4j; +import net.bytebuddy.dynamic.scaffold.MethodGraph.Linked; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.time.FastDateFormat; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.*; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; + +/** + * 日期工具类 + * @author sr on 2020-08-14 + */ +@Slf4j +public class DateUtils { + + public static final String YYYY_MM_DD = "yyyy-MM-dd"; + public static final String YYYY_MM = "yyyy-MM"; + + public static final String YYYY = "yyyy"; + public static final String DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss"; + public static final FastDateFormat YMDHMS_FORMAT = + FastDateFormat.getInstance(DATETIME_PATTERN); + + public static final String DATETIME_PATTERN_NO_SS = "yyyy-MM-dd HH:mm"; + public static final FastDateFormat YMDHM_FORMAT = + FastDateFormat.getInstance(DATETIME_PATTERN_NO_SS); + + /** yyyy-MM-dd **/ + public static final FastDateFormat YMD_FORMAT = FastDateFormat.getInstance("yyyy-MM-dd"); + /** yyMMdd **/ + public static final FastDateFormat YMD_FORMAT2 = FastDateFormat.getInstance("yyyyMMdd"); + + /** yyMM **/ + public static final DateTimeFormatter YM_FORMAT = DateTimeFormatter.ofPattern("yyMM"); + /** yyyyMM **/ + public static final DateTimeFormatter YM_FORMAT2 = DateTimeFormatter.ofPattern("yyyyMM"); + /** yyyy-MM-dd HH:mm:ss **/ + public static final DateTimeFormatter DATETIME_FORMAT = + DateTimeFormatter.ofPattern(DATETIME_PATTERN); + + /** + * @param date + * @return yyyy-MM-dd HH:mm:ss + * @author sr on 2020-08-14 + */ + public static String format(Date date) { + return YMDHMS_FORMAT.format(date); + } + + /** + * @param date + * @return yyyy-MM-dd HH:mm + * @author sr on 2020-08-14 + */ + public static String formatSplitSecond(Date date) { + return YMDHM_FORMAT.format(date); + } + + /** + * @param dateStr yyyy-MM-dd HH:mm:ss + * @return + * @author sr on 2020-08-14 + */ + public static Date parse(String dateStr) { + if (StringUtils.isBlank(dateStr)) { + return null; + } + try { + return YMDHMS_FORMAT.parse(dateStr); + } catch (ParseException e) { + log.error("parse date error", e); + return null; + } + } + + /** + * @param date + * @return yyyy-MM-dd + * @author sr on 2020-08-14 + */ + public static String formatToDay(Date date) { + return YMD_FORMAT.format(date); + } + + /** + * @param dateStr yyyy-MM-dd + * @return + * @author sr on 2020-08-14 + */ + public static Date parseToDay(String dateStr) { + if (StringUtils.isBlank(dateStr)) { + return null; + } + try { + return YMD_FORMAT.parse(dateStr); + } catch (ParseException e) { + log.error("parse date error", e); + return null; + } + } + + /** + * @param date + * @return yyMMdd + * @author sr on 2022-09-22 + */ + public static String formatToDay2(Date date) { + return YMD_FORMAT2.format(date); + } + + /** + * @param dateStr yyMMdd + * @return + * @author sr on 2022-09-22 + */ + public static Date parseToDay2(String dateStr) { + if (StringUtils.isBlank(dateStr)) { + return null; + } + try { + return YMD_FORMAT2.parse(dateStr); + } catch (ParseException e) { + log.error("parse date error", e); + return null; + } + } + + + /** + * 获取当前年月(yyMM) + * @return + * @author sr on 2020-12-09 + */ + public static String getCurrentYm() { + LocalDate localDate = LocalDate.now(); + return localDate.format(DateUtils.YM_FORMAT); + } + + /** + * 获取当前年月日(yyyy-MM-dd) + * @return yyyy-MM-dd + * @author sr on 2023-12-07 + */ + public static String getCurrentYmd() { + return formatToDay(new Date()); + } + + public static LocalDate getLocalDate(Date date) { + if (date == null) { + return LocalDate.now(); + } else { + return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); + } + } + + public static LocalDateTime getLocalDateTime(Date date) { + if (date == null) { + return LocalDateTime.now(); + } else { + return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); + } + } + + public static Date toDate(LocalDateTime date) { + ZonedDateTime startZdt = date.atZone(ZoneId.systemDefault()); + return Date.from(startZdt.toInstant()); + } + + /** + * 获取指定日期开始时间字符串(yyyy-MM-dd 00:00:00) + * @param date 为空取当前时间 + * @return + * @author sr on 2021-04-19 + */ + public static String getStartDateTimeStr(Date date) { + LocalDateTime localDateTime = LocalDateTime.of(getLocalDate(date), LocalTime.MIN); + return DATETIME_FORMAT.format(localDateTime); + } + + /** + * 获取当前日期开始时间 + * @return + * @author sr on 2021-04-19 + */ + public static Date getCurrentStartDateTime() { + return getStartDateTime(null); + } + + /** + * 获取指定日期开始时间 + * @param date 为空取当前时间 + * @return + * @author sr on 2021-04-19 + */ + public static Date getStartDateTime(Date date) { + return toDate(LocalDateTime.of(getLocalDate(date), LocalTime.MIN)); + } + + /** + * 获取指定日期开始时间字符串(yyyy-MM-dd 23:59:59) + * @param date 为空取当前时间 + * @return + * @author sr on 2021-04-19 + */ + public static String getEndDateTimeStr(Date date) { + LocalDateTime localDateTime = LocalDateTime.of(getLocalDate(date), LocalTime.MAX); + return DATETIME_FORMAT.format(localDateTime); + } + + + /** + * 获取当前日期结束时间 + * @return + * @author sr on 2021-04-19 + */ + public static Date getCurrentEndDateTime() { + return getEndDateTime(null); + } + + /** + * 获取指定日期结束时间 + * @param date 为空取当前时间 + * @return + * @author sr on 2021-04-19 + */ + public static Date getEndDateTime(Date date) { + return toDate(LocalDateTime.of(getLocalDate(date), LocalTime.MAX)); + } + + /** + * 两个日期间相差的天数 这里不包含起始日期,如果想要结果包含起始日期,则需要再结果上+1 + * @return + */ + public static int getDifferenceDayCount(Date date1, Date date2) { + + LocalDate startDate = DateUtils.getLocalDate(date1); + LocalDate endDate = DateUtils.getLocalDate(date2); + //取正数 + return Math.abs((int) (endDate.toEpochDay() - startDate.toEpochDay())); + } + + /** + * 日期添加月 + * @param date + * @param month + * @return + * @author sr on 2023-03-02 + */ + public static Date addMonth(Date date, int month) { + Calendar c = Calendar.getInstance(); + c.setTime(date); + c.add(Calendar.MONTH, month); + return c.getTime(); + } + + /** + * 添加天 + * @param date + * @param amount + * @return + * @author sr on 2023-12-22 + */ + public static Date addDays(Date date, int amount) { + return add(date, Calendar.DAY_OF_MONTH, amount); + } + + /** + * 日期变化 + * @param date + * @param calendarField {@link Linked Calendar} + * @param amount + * @return + * @author sr on 2023-12-22 + */ + public static Date add(Date date, int calendarField, int amount) { + if (date == null) { + throw new IllegalArgumentException("The date must not be null"); + } + Calendar c = Calendar.getInstance(); + c.setTime(date); + c.add(calendarField, amount); + return c.getTime(); + } + + /** + * 根据日期格式不同计算两个时间内的日期、月份、年 + * @param beginTime 开始时间 + * @param endTime 结束时间 + * @param dateFormat 日期格式 + * @return + */ + public static List getDateBetween(Date beginTime, Date endTime,String dateFormat) { + List result = new ArrayList<>(); + try { + //格式化日期 + SimpleDateFormat sdf = new SimpleDateFormat(dateFormat); + Calendar min = Calendar.getInstance(); + min.setTime(beginTime); + + Calendar max = Calendar.getInstance(); + max.setTime(endTime); + + if(YYYY_MM_DD.equals(dateFormat)){ + while (min.before(max) || min.equals(max)) { + result.add(sdf.format(min.getTime())); + min.add(Calendar.DATE, 1); + } + }else if(YYYY_MM.equals(dateFormat)){ + while (min.before(max) || min.equals(max)) { + result.add(sdf.format(min.getTime())); + min.add(Calendar.MONTH, 1); + } + }else { + while (min.before(max) || min.equals(max)) { + result.add(String.valueOf(min.get(Calendar.YEAR))); + min.add(Calendar.YEAR, 1); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } + + +} diff --git a/src/main/java/com/newyetai/common/util/DisplayedComponentUtils.java b/src/main/java/com/newyetai/common/util/DisplayedComponentUtils.java new file mode 100644 index 0000000..26bb44f --- /dev/null +++ b/src/main/java/com/newyetai/common/util/DisplayedComponentUtils.java @@ -0,0 +1,57 @@ +package com.newyetai.common.util; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import com.newyetai.common.dto.ColumnDTO; +import com.newyetai.common.dto.DisplayedComponentDTO; +import com.newyetai.common.dto.MessageDTO; + +/** + * @author sr on 2020-04-22 + */ +public class DisplayedComponentUtils { + + /** + * 数组转列配置(index 0标题,1属性key) + * + * @param columnArray + * @return + * @author sr on 2020-04-22 + */ + public static ColumnDTO toColumnDTO(String[] columnArray) { + return ColumnDTO.builder().title(columnArray[0]).key(columnArray[1]).dataIndex(columnArray[1]).build(); + } + + /** + * 批量数组转列配置(index 0标题,1属性key) + * + * @param columnArrays + * @return + * @author sr on 2020-04-22 + */ + public static List toColumnDtos(List columnArrays) { + return columnArrays.stream().map(DisplayedComponentUtils::toColumnDTO) + .collect(Collectors.toList()); + } + + /** + * 创建展示对象 + * + * @param + * @param msg + * @param columnArrays (index 0标题,1属性key) + * @param data + * @return + * @author sr on 2020-04-22 + */ + public static DisplayedComponentDTO create(String msg, List columnArrays, + List data) { + MessageDTO messageDto = MessageDTO.builder().content(msg).build(); + return new DisplayedComponentDTO(messageDto, toColumnDtos(columnArrays), data, + Collections.emptyList()); + } + + +} diff --git a/src/main/java/com/newyetai/common/util/EnumUtil.java b/src/main/java/com/newyetai/common/util/EnumUtil.java new file mode 100644 index 0000000..3ae4493 --- /dev/null +++ b/src/main/java/com/newyetai/common/util/EnumUtil.java @@ -0,0 +1,43 @@ +package com.newyetai.common.util; + +import com.newyetai.common.constant.SystemCodeEnum; +import com.newyetai.common.functions.SFunction; + +import java.lang.invoke.SerializedLambda; +import java.util.Arrays; + +/** + * @author chenyun + * @description 枚举工具类 + * @date 2020/9/16 13:36 + */ +public class EnumUtil { + + private EnumUtil() { + } + + /** + * @param function 转换函数 + * @param r 转换的值 + * @param + * @param + * @return + */ + public static , R> E resolve(SFunction function, R r) { + SerializedLambda serialized = function.serialized(); + try { + Class aClass = (Class) Class.forName(serialized.getImplClass().replace("/", ".")); + return (E) Arrays.stream(aClass.getEnumConstants()) + .filter(e -> { + R apply = function.apply(e); + return apply != null && apply.equals(r); + }) + .findFirst() + .orElse(null); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + return null; + } + +} diff --git a/src/main/java/com/newyetai/common/util/EnvironmentUtils.java b/src/main/java/com/newyetai/common/util/EnvironmentUtils.java new file mode 100644 index 0000000..0184099 --- /dev/null +++ b/src/main/java/com/newyetai/common/util/EnvironmentUtils.java @@ -0,0 +1,74 @@ +package com.newyetai.common.util; + +import org.springframework.core.env.Environment; + +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.constant.SystemCodeEnum; +import com.newyetai.common.exception.util.Assert; + +/** + * 环境变量工具类 + * + * @author sr on 2020-06-11 + */ +public class EnvironmentUtils{ + + private static Environment ENVIRONMENT; + + public EnvironmentUtils(Environment environment) { + EnvironmentUtils.ENVIRONMENT = environment; + getSystemCode(); + } + + private static Integer systemCode; + private static String applicationName; + + /** + * 获取环境变量 + * + * @param key + * @return + * @author sr on 2020-06-17 + */ + public static String getProperty(String key) { + return ENVIRONMENT.getProperty(key); + } + + /** + * 获取项目名 + * + * @return + * @author sr on 2020-06-17 + */ + public static String getApplicationName() { + if (applicationName == null) { + applicationName = ENVIRONMENT.getProperty(CommonConstants.APPLICATION_NAME_KEY); + } + return applicationName; + } + + /** + * 获取系统编码 + * + * @return + * @author sr on 2020-06-17 + */ + public static Integer getSystemCode() { + if (systemCode == null) { + systemCode = SystemCodeEnum.getCodeByName(getApplicationName()); + } + Assert.notNull(systemCode, "系统标识不能为空"); + return systemCode; + } + + /** + * 获取环境 + * + * @return + * @author sr on 2020-07-22 + */ + public static String getProfile() { + return EnvironmentUtils.getProperty(CommonConstants.PROFILE_KEY); + } + +} diff --git a/src/main/java/com/newyetai/common/util/IdcardUtils.java b/src/main/java/com/newyetai/common/util/IdcardUtils.java new file mode 100644 index 0000000..d1431c4 --- /dev/null +++ b/src/main/java/com/newyetai/common/util/IdcardUtils.java @@ -0,0 +1,161 @@ +package com.newyetai.common.util; + +import com.newyetai.common.exception.BusinessException; + +import org.apache.commons.lang3.StringUtils; + +import lombok.extern.slf4j.Slf4j; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @author : yzq + * create at: 2020/10/28 14:39 + * @description: 身份证工具类 + */ + +@Slf4j +public class IdcardUtils { + + // 非法的年龄,用于处理异常。 + private static final int invalidAge = -1; + + //身份证提取正则 + private static Pattern idCardPattern = Pattern.compile("\\d{17}[\\d|x|X]|\\d{15}"); + + /** + * 根据身份证号码计算年龄 + * + * @param idNumber 考虑到了15位身份证,但不一定存在 + */ + public static int getAgeByIDNumber(String idNumber) { + String dateStr; + if (idNumber.length() == 15) { + dateStr = "19" + idNumber.substring(6, 12); + } else if (idNumber.length() == 18) { + dateStr = idNumber.substring(6, 14); + } else {//默认是合法身份证号,但不排除有意外发生 + return invalidAge; + } + + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd"); + try { + Date birthday = simpleDateFormat.parse(dateStr); + return getAgeByDate(birthday); + } catch (ParseException e) { + return invalidAge; + } + + } + + /** + * 根据出生日期获取年龄 + * + * @param birthday + * @return + */ + public static int getAgeByDate(Date birthday) { + Calendar calendar = Calendar.getInstance(); + if (calendar.getTimeInMillis() - birthday.getTime() < 0L) { + return invalidAge; + } + + int yearNow = calendar.get(Calendar.YEAR); + int monthNow = calendar.get(Calendar.MONTH); + int dayOfMonthNow = calendar.get(Calendar.DAY_OF_MONTH); + + calendar.setTime(birthday); + + int yearBirthday = calendar.get(Calendar.YEAR); + int monthBirthday = calendar.get(Calendar.MONTH); + int dayOfMonthBirthday = calendar.get(Calendar.DAY_OF_MONTH); + + int age = yearNow - yearBirthday; + + if (monthNow <= monthBirthday) { + if (monthNow == monthBirthday) { + if (dayOfMonthNow < dayOfMonthBirthday) { + age--; + } + } else { + age--; + } + } + + return age; + } + + /** + * 根据身份证号判断性别 + * + * @param idNumber + * @return + */ + public static String judgeGender(String idNumber) { + + if (idNumber.length() != 18 && idNumber.length() != 15) { + return ""; + } + int gender = 0; + if (idNumber.length() == 18) { + //如果身份证号18位,取身份证号倒数第二位 + char c = idNumber.charAt(idNumber.length() - 2); + gender = Integer.parseInt(String.valueOf(c)); + } else { + //如果身份证号15位,取身份证号最后一位 + char c = idNumber.charAt(idNumber.length() - 1); + gender = Integer.parseInt(String.valueOf(c)); + } + + if (gender % 2 == 1) { + return "男"; + } else { + return "女"; + } + } + + public static Integer getGender(String idNumber) { + if (idNumber.length() != 18 && idNumber.length() != 15) { + return null; + } + int gender = 0; + if (idNumber.length() == 18) { + //如果身份证号18位,取身份证号倒数第二位 + char c = idNumber.charAt(idNumber.length() - 2); + gender = Integer.parseInt(String.valueOf(c)); + } else { + //如果身份证号15位,取身份证号最后一位 + char c = idNumber.charAt(idNumber.length() - 1); + gender = Integer.parseInt(String.valueOf(c)); + } + + if (gender % 2 == 1) { + return 1; + } else { + return 2; + } + } + + + + /** + * @description: 提取身份证号 + * @return: 身份证号 + */ + public static String extractCardNo(String str){ + if (StringUtils.isBlank(str)) { + return null; + } + Matcher matcher = idCardPattern.matcher(str); + if (matcher.find()) { + return matcher.group(); + } + return null; + } + +} diff --git a/src/main/java/com/newyetai/common/util/JasyptUtils.java b/src/main/java/com/newyetai/common/util/JasyptUtils.java new file mode 100644 index 0000000..6ddfe92 --- /dev/null +++ b/src/main/java/com/newyetai/common/util/JasyptUtils.java @@ -0,0 +1,54 @@ +package com.newyetai.common.util; + +import org.jasypt.encryption.StringEncryptor; + +import com.newyetai.common.exception.util.Assert; + +import lombok.extern.slf4j.Slf4j; + +/** + * 配置信息加解密工具 + * @author sr on 2021-11-11 + */ +@Slf4j +public class JasyptUtils { + + private static StringEncryptor stringEncryptor; + + public JasyptUtils(StringEncryptor stringEncryptor) { + Assert.isNull(JasyptUtils.stringEncryptor, "已存在加密对象"); + JasyptUtils.stringEncryptor = stringEncryptor; + } + + /** + * 加密 + * @param str + * @return + * @author sr on 2021-11-11 + */ + public static String encrypt(String str) { + try { + return stringEncryptor.encrypt(str); + } catch (Exception e) { + log.info("加密失败:", e); + return null; + } + + } + + /** + * 解密 + * @param encodedStr + * @return + * @author sr on 2021-11-11 + */ + public static String decrypt(String encodedStr) { + try { + return stringEncryptor.decrypt(encodedStr); + } catch (Exception e) { + log.info("解密失败:", e); + return null; + } + } + +} diff --git a/src/main/java/com/newyetai/common/util/JsonUtils.java b/src/main/java/com/newyetai/common/util/JsonUtils.java new file mode 100644 index 0000000..9ae49ee --- /dev/null +++ b/src/main/java/com/newyetai/common/util/JsonUtils.java @@ -0,0 +1,178 @@ +package com.newyetai.common.util; + +import java.text.SimpleDateFormat; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.newyetai.common.annotation.MaskAnontationIntrospector; +import com.newyetai.tkmybatis.pojo.Page; + +/** + * json 工具类 + * + * @author on 2019-11-05 + * + */ +public class JsonUtils { + + /** 序列化所有(带mask) **/ + private static ObjectMapper simpleDateMapper; + /** 序列化不为null(带mask) **/ + private static ObjectMapper simpleDateNoEmptyMapper; + + /** 默认(不带mask) **/ + private static ObjectMapper defaultMapper; + + static { + simpleDateMapper = buildObjectMapper(); + simpleDateMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); + simpleDateMapper.setAnnotationIntrospector(new MaskAnontationIntrospector()); + simpleDateNoEmptyMapper = buildObjectMapper(); + simpleDateNoEmptyMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); + // 配置mapper忽略空属性 默认不忽略 + simpleDateNoEmptyMapper.setSerializationInclusion(Include.NON_EMPTY); + simpleDateNoEmptyMapper.setAnnotationIntrospector(new MaskAnontationIntrospector()); + defaultMapper = buildObjectMapper(); + + } + + /** + * (mask)对象转json字符串(null也序列化) + * @param object + * @return + * @author sr on 2020-08-14 + */ + public static String toJsonString(Object object) { + return toJsonString(simpleDateMapper, object); + } + + /** + * (mask)对象转json字符串(null不序列化) + * @param object + * @return + * @author sr on 2021-10-21 + */ + public static String toNoEmptyJson(Object object) { + return toJsonString(simpleDateNoEmptyMapper, object); + } + + /** + * (mask)对象转json字符串 + * @param object + * @param nullable null是否序列化 + * + */ + public static String toJsonString(Object object, boolean nullable) { + ObjectMapper objectMapper; + if (nullable) { + objectMapper = simpleDateMapper; + } else { + objectMapper = simpleDateNoEmptyMapper; + } + return toJsonString(objectMapper, object); + } + + /** + * 对象转json字符串 + * @param objectMapper + * @param object + * @return + * @author sr on 2021-10-21 + */ + public static String toJsonString(ObjectMapper objectMapper, Object object) { + // 为了使JSON视觉上的可读性,增加一行如下代码,注意,在生产中不需要这样,因为这样会增大Json的内容 + // mapper.configure(SerializationFeature.INDENT_OUTPUT, true); + String jsonString = null; + try { + jsonString = objectMapper.writeValueAsString(object); + } catch (Exception e) { + throw new RuntimeException(e); + } + return jsonString; + } + + /** + * 对象转json字符串(默认) + * @param object + * @return + * @author sr on 2024-04-09 + */ + public static String toDefaultJsonString(Object object) { + return toJsonString(defaultMapper, object); + } + + /** + * json字符串转指定对象 + */ + public static T toObject(String json, Class clazz) { + ObjectMapper mapper = defaultMapper; + try { + return mapper.readValue(json, clazz); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static T toObject(String json, TypeReference valueTypeRef) { + ObjectMapper mapper = defaultMapper; + try { + return mapper.readValue(json, valueTypeRef); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * json字符串转指定对象 + */ + @SuppressWarnings("unchecked") + public static Map toMap(String json) { + ObjectMapper mapper = defaultMapper; + try { + JavaType javaType = mapper.getTypeFactory().constructParametricType(LinkedHashMap.class, + new Class[] {String.class, Object.class}); + return (Map) mapper.readValue(json, javaType); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @SuppressWarnings("unchecked") + public static List toList(String json, Class clazz) { + ObjectMapper mapper = defaultMapper; + try { + JavaType javaType = mapper.getTypeFactory().constructCollectionType(List.class, clazz); + return (List) mapper.readValue(json, javaType); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static ObjectMapper buildObjectMapper() { + ObjectMapper mapper = new ObjectMapper(); + // 当反序列化json时,未知属性会引起的反序列化被打断,这里我们禁用未知属性打断反序列化功能, + // 因为,例如json里有10个属性,而我们的bean中只定义了2个属性,其它8个属性将被忽略 + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + return mapper; + } + + /** + * object转指定类型对象 + * + * @param + * @param object + * @param clazz + * @return + * @author sr on 2020-05-25 + */ + public static T objToClassObj(Object object, Class clazz) { + return defaultMapper.convertValue(object, clazz); + } + +} diff --git a/src/main/java/com/newyetai/common/util/ListUtil.java b/src/main/java/com/newyetai/common/util/ListUtil.java new file mode 100644 index 0000000..de54304 --- /dev/null +++ b/src/main/java/com/newyetai/common/util/ListUtil.java @@ -0,0 +1,56 @@ +package com.newyetai.common.util; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.function.Function; + +import org.apache.commons.collections.CollectionUtils; + +public class ListUtil { + + private ListUtil() {} + + /** + * Collection 转 Map + * + * @param collection 集合对象 + * @param func 处理函数 + * @param 原始类型 + * @param 目标类型 + * @return + */ + public static Map> toMap(Collection collection, Function func) { + Map> resMap; + if (CollectionUtils.isEmpty(collection)) { + return Maps.newHashMap(); + } + int size = collection.size(); + resMap = Maps.newHashMapWithExpectedSize(size); + for (T obj : collection) { + R apply = func.apply(obj); + List ts = resMap.get(apply); + if (ts == null) { + ts = Lists.newArrayList(); + } + ts.add(obj); + resMap.put(apply, ts); + } + return resMap; + } + + + /** + * 获取首个记录 + * @param + * @param list + * @return 可为null + * @author sr on 2021-08-10 + */ + public static T first(List list) { + return CollectionUtils.isEmpty(list) ? null : list.get(0); + } +} diff --git a/src/main/java/com/newyetai/common/util/MockUtils.java b/src/main/java/com/newyetai/common/util/MockUtils.java new file mode 100644 index 0000000..ee64b62 --- /dev/null +++ b/src/main/java/com/newyetai/common/util/MockUtils.java @@ -0,0 +1,25 @@ +package com.newyetai.common.util; + +import com.newyetai.common.service.IMockProvider; + +public class MockUtils { + +public static IMockProvider mockProvider; + + public MockUtils(IMockProvider mockProvider) { + MockUtils.mockProvider = mockProvider; + } + + public static void mockPlatUser() { + mockProvider.mockPlatUser(); + } + + public static void mockUser(Long userId, Long orgId) { + mockProvider.mockUser(userId, orgId); + } + + public static void clearUser() { + mockProvider.clearUser(); + } + +} diff --git a/src/main/java/com/newyetai/common/util/ParameterizedTypeImpl.java b/src/main/java/com/newyetai/common/util/ParameterizedTypeImpl.java new file mode 100644 index 0000000..9f079a6 --- /dev/null +++ b/src/main/java/com/newyetai/common/util/ParameterizedTypeImpl.java @@ -0,0 +1,62 @@ +package com.newyetai.common.util; + +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.Arrays; + +/** + * copy fastjson + * + * @author sr on 2020-09-02 + */ +public class ParameterizedTypeImpl implements ParameterizedType { + + private final Type[] actualTypeArguments; + private final Type ownerType; + private final Type rawType; + + public ParameterizedTypeImpl(Type[] actualTypeArguments, Type ownerType, Type rawType) { + this.actualTypeArguments = actualTypeArguments; + this.ownerType = ownerType; + this.rawType = rawType; + } + + public Type[] getActualTypeArguments() { + return actualTypeArguments; + } + + public Type getOwnerType() { + return ownerType; + } + + public Type getRawType() { + return rawType; + } + + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + ParameterizedTypeImpl that = (ParameterizedTypeImpl) o; + + // Probably incorrect - comparing Object[] arrays with Arrays.equals + if (!Arrays.equals(actualTypeArguments, that.actualTypeArguments)) + return false; + if (ownerType != null ? !ownerType.equals(that.ownerType) : that.ownerType != null) + return false; + return rawType != null ? rawType.equals(that.rawType) : that.rawType == null; + + } + + @Override + public int hashCode() { + int result = actualTypeArguments != null ? Arrays.hashCode(actualTypeArguments) : 0; + result = 31 * result + (ownerType != null ? ownerType.hashCode() : 0); + result = 31 * result + (rawType != null ? rawType.hashCode() : 0); + return result; + } +} diff --git a/src/main/java/com/newyetai/common/util/ProductConfig.java b/src/main/java/com/newyetai/common/util/ProductConfig.java new file mode 100644 index 0000000..932ed29 --- /dev/null +++ b/src/main/java/com/newyetai/common/util/ProductConfig.java @@ -0,0 +1,35 @@ +package com.newyetai.common.util; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.math.BigDecimal; + +@NoArgsConstructor +@AllArgsConstructor +@Data +@ApiModel("限额") +public class ProductConfig implements Serializable { + + private static final long serialVersionUID = 3619751184797118876L; + + @ApiModelProperty("产品id") + private Long productId; + + @ApiModelProperty("年龄上限") + private Integer maxAge; + + @ApiModelProperty("年龄下限") + private Integer minAge; + + @ApiModelProperty("限制额度-月") + private BigDecimal limitAmountMonth; + + @ApiModelProperty("限制额度-年") + private BigDecimal limitAmountYear; + +} diff --git a/src/main/java/com/newyetai/common/util/RandomUtils.java b/src/main/java/com/newyetai/common/util/RandomUtils.java new file mode 100644 index 0000000..3071ff8 --- /dev/null +++ b/src/main/java/com/newyetai/common/util/RandomUtils.java @@ -0,0 +1,50 @@ +package com.newyetai.common.util; + +import java.util.UUID; + +import org.apache.commons.lang3.RandomStringUtils; + +/** + * 随机工具类型 + * @author sr on 2020-01-02 + */ +public class RandomUtils { + + /** + * 随机六位数 + * @return + * @author sr on 2020-01-02 + */ + public static int nextSixInt() { + return org.apache.commons.lang3.RandomUtils.nextInt(100000, 1000000); + } + + /** + * 随机六位验证码 + * @return + * @author sr on 2020-01-02 + */ + public static String nextSixVerificationCode() { + return Integer.toString(RandomUtils.nextSixInt()); + } + + /** + * 生成指定长度的随机字符串 + * @param len 指定长度 + * @return + */ + public static String getRandomString(int len) { + return RandomStringUtils.randomAlphabetic(len); + } + + /** + * 生成uuid,去掉- + * @return + * @author sr on 2019-12-10 + */ + public static String generateUUID() { + String uuid = UUID.randomUUID().toString(); + return uuid.replace("-", ""); + } + +} diff --git a/src/main/java/com/newyetai/common/util/ReflectionUtils.java b/src/main/java/com/newyetai/common/util/ReflectionUtils.java new file mode 100644 index 0000000..74d46e0 --- /dev/null +++ b/src/main/java/com/newyetai/common/util/ReflectionUtils.java @@ -0,0 +1,53 @@ +package com.newyetai.common.util; + +import lombok.extern.slf4j.Slf4j; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import org.apache.commons.lang3.StringUtils; + +/** + * @author Jerry.li + * @description 反射工具类 + * @date 2020/4/21 + */ +@Slf4j +public class ReflectionUtils { + + /** + * 获取对象属性字段数组 + * @param object 对象 + * @return fieldNames + */ + public static String[] getFiledNames(Object object) { + Field[] fields = object.getClass().getDeclaredFields(); + String[] fieldNames = new String[fields.length]; + for (int i = 0; i < fields.length; i++) { + fieldNames[i] = fields[i].getName(); + } + return fieldNames; + } + + /*** + * 根据属性名称获取对象属性值 + * @param fieldName 字段名称 + * @param object 对象 + * @return Object + */ + public static Object getValueByFieldName(String fieldName, Object object) { + try { + // 序列化字段返回null + if (StringUtils.equalsIgnoreCase(fieldName,"serialVersionUID")){ + return null; + } + String firstLetter = fieldName.substring(0, 1).toUpperCase(); + String getter = "get" + firstLetter + fieldName.substring(1); + Method method = object.getClass().getMethod(getter); + return method.invoke(object); + } catch (Exception e) { + log.error("------ReflectionUtils getValueByFieldName error: {0}", e); + return null; + } + } + +} diff --git a/src/main/java/com/newyetai/common/util/RequestUtils.java b/src/main/java/com/newyetai/common/util/RequestUtils.java new file mode 100644 index 0000000..53be174 --- /dev/null +++ b/src/main/java/com/newyetai/common/util/RequestUtils.java @@ -0,0 +1,179 @@ +package com.newyetai.common.util; + +import java.net.InetAddress; +import java.net.UnknownHostException; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.lang3.StringUtils; + +import com.google.common.base.Strings; +import com.google.common.net.InternetDomainName; + +import lombok.extern.slf4j.Slf4j; + +/** + * @author Jerry.li + * @description 网络请求工具类 + * @date 2020/4/16 + */ +@Slf4j +public class RequestUtils { + + /** ajax请求key **/ + public static final String AJAX_REQUEST_HEADER_KEY = "x-requested-with"; + /** ajax请求value **/ + public static final String AJAX_REQUEST_HEADER_VALUE = "XMLHttpRequest"; + /** feign请求key **/ + public static final String FEIGN_REQUEST_HEADER_KEY = "feign-requested"; + /** feign请求value **/ + public static final String FEIGN_REQUEST_HEADER_VALUE = "feignHttpRequest"; + /** 域名分割符 **/ + public static final String DOMAIN_SEPARATOR = "://"; + /** 路径分割符 **/ + public static final String PATH_SEPARATOR = "/"; + + /** origin_host **/ + public static final String ORIGIN_HOST_HEADER_KEY = "origin_host"; + + /** + * 判断是否是ajax请求 + */ + public static boolean isAjaxRequest(HttpServletRequest request) { + String xReq = request.getHeader(AJAX_REQUEST_HEADER_KEY); + return !Strings.isNullOrEmpty(xReq) && AJAX_REQUEST_HEADER_VALUE.equalsIgnoreCase(xReq); + } + + /** + * 判断是否是feign请求 + */ + public static boolean isFeignRequest(HttpServletRequest request) { + String xReq = request.getHeader(FEIGN_REQUEST_HEADER_KEY); + return !Strings.isNullOrEmpty(xReq) && FEIGN_REQUEST_HEADER_VALUE.equalsIgnoreCase(xReq); + } + + /** + * 获取请求域名(不带协议) + * + * @param request + * @return + * @author sr on 2020-03-10 + */ + public static String getDomain(HttpServletRequest request) { + String hostHeader = request.getHeader(RequestUtils.ORIGIN_HOST_HEADER_KEY); + StringBuffer url = request.getRequestURL(); + log.debug("request url:{}", url); + if (StringUtils.isNoneBlank(hostHeader)) { + log.debug("get request head origin_host:{}", hostHeader); + return hostHeader; + } + int start = url.length() - request.getRequestURI().length(); + int subStart = + url.indexOf(RequestUtils.DOMAIN_SEPARATOR) + RequestUtils.DOMAIN_SEPARATOR.length(); + return url.delete(start, url.length()).substring(subStart); + } + + /** + * 获取请求根域名 + * + * @param request + * @return + * @author sr on 2020-06-10 + */ + public static String getRootDomain(HttpServletRequest request) { + String domainStr = getDomain(request); + try { + String rootDomain = InternetDomainName.from(domainStr).topPrivateDomain().toString(); + return rootDomain; + } catch (IllegalArgumentException e) { + log.debug("{}-rootDomain error:{}", domainStr, e.getMessage()); + return null; + } + } + + + /** + * 获取带协议的域名地址 + * + * @param request + * @return + * @author sr on 2020-03-15 + */ + public static String getHttpDomain(HttpServletRequest request) { + StringBuffer url = request.getRequestURL(); + int start = url.length() - request.getRequestURI().length(); + return url.delete(start, url.length()).toString(); + } + + /** + * 替换域名 + * + * @param urlString + * @param domain + * @author sr on 2020-03-10 + */ + public static String replaceDomain(String urlString, String domain) { + StringBuilder urlBuilder = new StringBuilder(urlString); + int start = urlBuilder.indexOf(DOMAIN_SEPARATOR) + DOMAIN_SEPARATOR.length(); + int endIndex = urlBuilder.indexOf(PATH_SEPARATOR, + urlBuilder.indexOf(DOMAIN_SEPARATOR) + DOMAIN_SEPARATOR.length()); + if (endIndex <= 0) { + endIndex = urlString.length(); + } + return urlBuilder.replace(start, endIndex, domain).toString(); + } + + /** + * 获取请求用户IP地址 + * + * @param request + * @return + */ + public static String getIpAddress(HttpServletRequest request) { + String ipAddress = request.getHeader("x-forwarded-for"); + String unknown = "unknown"; + if (ipAddress == null || ipAddress.length() == 0 || unknown.equalsIgnoreCase(ipAddress)) { + ipAddress = request.getHeader("Proxy-Client-IP"); + } + if (ipAddress == null || ipAddress.length() == 0 || unknown.equalsIgnoreCase(ipAddress)) { + ipAddress = request.getHeader("WL-Proxy-Client-IP"); + } + if (ipAddress == null || ipAddress.length() == 0 || unknown.equalsIgnoreCase(ipAddress)) { + ipAddress = request.getRemoteAddr(); + String localhost = "127.0.0.1"; + if (localhost.equals(ipAddress) || "0:0:0:0:0:0:0:1".equals(ipAddress)) { + //根据网卡获取本机配置的IP地址 + InetAddress inetAddress; + try { + inetAddress = InetAddress.getLocalHost(); + ipAddress = inetAddress.getHostAddress(); + } catch (UnknownHostException e) { + log.error("------获取请求用户IP地址时,异常: {0}", e); + } + } + } + + //对于通过多个代理的情况,第一个IP为客户端真实的IP地址,多个IP按照','分割 + if (null != ipAddress && ipAddress.length() > 15) { + //"***.***.***.***".length() = 15 + if (ipAddress.indexOf(',') != -1) { + ipAddress = ipAddress.substring(0, ipAddress.indexOf(',')); + } + } + return ipAddress; + } + + public static String getHostIp() { + try { + String hostname = System.getenv("HOSTNAME"); + String hostIp = InetAddress.getByName(hostname).getHostAddress(); + if ("127.0.0.1".equals(hostIp) || "0:0:0:0:0:0:0:1".equals(hostIp)) { + return InetAddress.getLocalHost().getHostAddress(); + } + return hostIp; + } catch (UnknownHostException e) { + } + return "127.0.0.1"; + } + +} diff --git a/src/main/java/com/newyetai/common/util/ResponseUtils.java b/src/main/java/com/newyetai/common/util/ResponseUtils.java new file mode 100644 index 0000000..59ac99a --- /dev/null +++ b/src/main/java/com/newyetai/common/util/ResponseUtils.java @@ -0,0 +1,27 @@ +package com.newyetai.common.util; + +import java.io.IOException; +import java.io.PrintWriter; + +import javax.servlet.http.HttpServletResponse; + +import lombok.extern.slf4j.Slf4j; + +/** + * @author Jerry.li + * @description 响应工具类 + * @date 2020/4/16 + */ +@Slf4j +public class ResponseUtils { + + public static void printJson(HttpServletResponse response, Object data) { + response.setContentType("application/json;charset=utf-8"); + try (PrintWriter out = response.getWriter();) { + out.print(JsonUtils.toJsonString(data)); + out.flush(); + } catch (IOException ex) { + log.error("------响应异常", ex); + } + } +} diff --git a/src/main/java/com/newyetai/common/util/SensitiveWordUtils.java b/src/main/java/com/newyetai/common/util/SensitiveWordUtils.java new file mode 100644 index 0000000..4387247 --- /dev/null +++ b/src/main/java/com/newyetai/common/util/SensitiveWordUtils.java @@ -0,0 +1,71 @@ +package com.newyetai.common.util; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.core.io.ClassPathResource; + +import com.newyetai.common.constant.CommonConstants; + +import toolgood.words.IllegalWordsSearch; +import toolgood.words.IllegalWordsSearchResult; + +public class SensitiveWordUtils { + + static IllegalWordsSearch search; + + static { + List list = new ArrayList<>(); + try (BufferedReader bufferedReader = new BufferedReader( + new InputStreamReader(new ClassPathResource("config" + File.separator + "sensi_words.txt").getInputStream()))) { + for (String line = bufferedReader.readLine(); line != null; line = + bufferedReader.readLine()) { + list.add(line); + } + } catch (IOException e) { + throw new RuntimeException("sensi_words.txt加载失败"); + } + search = new IllegalWordsSearch(); + search.SetKeywords(list); + } + + /** + * 校验字符串敏感词是否通过 + * + * @param str + * @return + * @author sr on 2024-06-28 + */ + public static boolean check(String str) { + //todo 先全通过 + return true; +// if (StringUtils.isBlank(str)) { +// return true; +// } +// return !search.ContainsAny(str); + } + + public static String findFirst(String str) { + IllegalWordsSearchResult result = search.FindFirst(str); + if (result != null) { + return result.Keyword; + } + return null; + } + + public static String findAll(String str) { + List results = search.FindAll(str); + if (results != null) { + return results.stream().map(r -> r.Keyword).collect(Collectors.joining(CommonConstants.COMMA)); + } + return null; + } + + +} diff --git a/src/main/java/com/newyetai/common/util/SpringContextHolder.java b/src/main/java/com/newyetai/common/util/SpringContextHolder.java new file mode 100644 index 0000000..bd5af8d --- /dev/null +++ b/src/main/java/com/newyetai/common/util/SpringContextHolder.java @@ -0,0 +1,101 @@ +package com.newyetai.common.util; + +import java.io.Serializable; +import java.util.Optional; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +/** + * spring上下文工具类 + * + * @author sr on 2020-05-20 + */ +@Component +public class SpringContextHolder implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + SpringContextHolder.applicationContext = applicationContext; + } + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + /** + * 获取bean + * + * @param + * @param beanId + * @return + * @author sr on 2020-05-20 + */ + @SuppressWarnings("unchecked") + public static T getBean(String beanId) { + return (T) applicationContext.getBean(beanId); + } + + public static T getBean(Class clazz) { + return applicationContext.getBean(clazz); + } + + public static Optional getRequestAttributes() { + return Optional + .ofNullable((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()); + } + + /** + * 获取当前线程的request + */ + public static HttpServletRequest getRequest() { + return getRequestAttributes().map(ServletRequestAttributes :: getRequest).orElse(null); + } + + /** + * 获取当前线程的response + */ + public static HttpServletResponse getResponse() { + return getRequestAttributes().map(ServletRequestAttributes :: getResponse).orElse(null); + } + + /** + * 获取HttpSession + */ + public static HttpSession getHttpSession() { + return getRequest().getSession(); + } + + /** + * 把值放入session + */ + public static void setSessionAttribute(String key, Serializable entity) { + getHttpSession().setAttribute(key, entity); + } + + public static Object getSessionAttribute(String key) { + return getHttpSession().getAttribute(key); + } + + /** + * 把值放入当前request + */ + public static void setRequestAttribute(String key, Object entity) { + getRequest().setAttribute(key, entity); + } + + public static Object getRequestAttribute(String key) { + return getRequest().getAttribute(key); + } + +} diff --git a/src/main/java/com/newyetai/common/util/StrUtils.java b/src/main/java/com/newyetai/common/util/StrUtils.java new file mode 100644 index 0000000..5026a47 --- /dev/null +++ b/src/main/java/com/newyetai/common/util/StrUtils.java @@ -0,0 +1,101 @@ +package com.newyetai.common.util; + +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.commons.lang3.StringUtils; + +import java.util.TreeMap; + +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.exception.BusinessException; + +/** + * @author sr on 2021-02-03 + */ +public class StrUtils { + + /** + * 大驼峰转小驼峰(AaBb -> aaBb) + * + * @param upperCamel + * @return + * @author sr on 2021-02-03 + */ + public static String toLowerCamel(String upperCamel) { + StringBuilder sb = + new StringBuilder(Character.toString(Character.toLowerCase(upperCamel.charAt(0)))); + return sb.append(upperCamel.substring(1)).toString(); + } + + /** + * 驼峰转蛇形(AaBb -> aa_bb) + * + * @param upperCamel + * @return + * @author sr on 2021-02-03 + */ + public static String toSnake(String camel) { + StringBuilder stringBuilder = new StringBuilder(); + boolean first = true; + for (char c : camel.toCharArray()) { + char nc = Character.toLowerCase(c); + if (Character.isUpperCase(c) && !first) { + stringBuilder.append('_').append(nc); + } else { + stringBuilder.append(nc); + first = false; + } + } + return stringBuilder.toString(); + } + + /** + * 构建升序参数字符串(xx=**&xx=**) + * @param paramData + * @return + * @author sr on 2022-02-10 + */ + public static String buildAscQueryValue(Object paramData) { + Map paramDataMap = null; + if (paramData instanceof Map) { + paramDataMap = paramDataMap; + } else { + try { + paramDataMap = JsonUtils.objToClassObj(paramData, Map.class); + } catch (Exception e) { + throw new BusinessException("参数对象格式错误"); + } + } + if (paramDataMap == null || paramDataMap.isEmpty()) { + return null; + } + Map parameters = new TreeMap(); + for (Entry entry : paramDataMap.entrySet()) { + Object value = entry.getValue(); + if (value != null) { + parameters.put(entry.getKey(), value); + } + } + if (parameters.isEmpty()) { + return null; + } + StringBuilder paramstr = new StringBuilder(); + for (Entry entry : parameters.entrySet()) { + paramstr.append(entry.getKey()).append(CommonConstants.EQUAL) + .append(entry.getValue()).append(CommonConstants.AND); + } + return paramstr.substring(0, paramstr.length() - 1); + } + + /** + * 不为空/空字符串/"null"字符串 + * @param str + * @return + * @author sr on 2022-02-10 + */ + public static boolean isNotNull(String str) { + return StringUtils.isNotBlank(str) && !"null".equals(str); + } + +} diff --git a/src/main/java/com/newyetai/common/util/TracerUtils.java b/src/main/java/com/newyetai/common/util/TracerUtils.java new file mode 100644 index 0000000..8e52e71 --- /dev/null +++ b/src/main/java/com/newyetai/common/util/TracerUtils.java @@ -0,0 +1,38 @@ +package com.newyetai.common.util; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.newyetai.common.trace.ITracer; + +import lombok.extern.slf4j.Slf4j; + +/** + * 链路工具类 + * + * @author sr on 2020-10-29 + */ +@Component +@Slf4j +public class TracerUtils { + + private static ITracer tracer; + + @Autowired + public void setTracer(ITracer tracer) { + TracerUtils.tracer = tracer; + } + + public static String getTraceId() { + return tracer.getTraceId(); + } + + public static String getSpanId() { + return tracer.getSpanId(); + } + + public static String getParentId() { + return tracer.getParentId(); + } + +} diff --git a/src/main/java/com/newyetai/common/util/TreeHelper.java b/src/main/java/com/newyetai/common/util/TreeHelper.java new file mode 100644 index 0000000..158eb2b --- /dev/null +++ b/src/main/java/com/newyetai/common/util/TreeHelper.java @@ -0,0 +1,73 @@ +package com.newyetai.common.util; + +import com.google.common.base.Objects; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * 树型结构工具类 + * + * @author sr on 2019-12-11 + */ +public class TreeHelper { + + private TreeHelper() { + } + + + /** + * 构建树型数据 + * + * @param parentId 父id + * @param nodeList 节点列表 + * @return {@link List} + */ + public static > List buildTree(I parentId, List nodeList) { + // 根节点列表 + List list = Lists.newArrayList(); + Map treeMap = nodeList.stream() + .collect(Collectors.toMap(TreeNode::getId, treeNode -> treeNode)); + + nodeList.forEach(node -> { + if (Objects.equal(parentId, node.getParentId())) { + list.add(node); + } + // 父节点 + TreeNode parentNode = treeMap.get(node.getParentId()); + if (parentNode != null) { + parentNode.addChildren(node); + } + }); + return list; + } + + + /** + * 返回子节点Ids + * + * @param parentId 父id + * @param nodeList 节点列表 + * @return {@link Set} + */ + public static > Set childrenNodeIds(Long parentId, List nodeList) { + // 根节点列表 + Set set = Sets.newHashSet(parentId); + + nodeList.sort((a, b) -> a.getParentId().compareTo(b.getParentId())); + + nodeList.forEach(node -> { + if (set.contains(node.getParentId())) { + set.add(node.getId()); + } + }); + set.remove(parentId); + return set; + } + +} diff --git a/src/main/java/com/newyetai/common/util/TreeNode.java b/src/main/java/com/newyetai/common/util/TreeNode.java new file mode 100644 index 0000000..af0ce91 --- /dev/null +++ b/src/main/java/com/newyetai/common/util/TreeNode.java @@ -0,0 +1,37 @@ +package com.newyetai.common.util; + +import java.io.Serializable; + +/** + * 树型结构 + * + * @param + * @author sr on 2019-12-11 + */ +public interface TreeNode { + + /** + * id + * + * @return + * @author sr on 2019-12-11 + */ + I getId(); + + /** + * 父id + * + * @return + * @author sr on 2019-12-11 + */ + I getParentId(); + + /** + * 添加子节点 + * + * @param node + * @author sr on 2019-12-11 + */ + void addChildren(T node); + +} diff --git a/src/main/java/com/newyetai/common/util/UserContextHolder.java b/src/main/java/com/newyetai/common/util/UserContextHolder.java new file mode 100644 index 0000000..83a6653 --- /dev/null +++ b/src/main/java/com/newyetai/common/util/UserContextHolder.java @@ -0,0 +1,206 @@ +package com.newyetai.common.util; + +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.exception.NoneLoginException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.usercenter.dto.IUserDetail; +import com.newyetai.usercenter.user.constant.UserTypeEnum; + +import lombok.extern.slf4j.Slf4j; + +/** + * 项目上下文 + * + * @author on 2019-11-05 + */ +@Slf4j +public class UserContextHolder { + + private static final ThreadLocal contextHolder = new ThreadLocal(); + + /** + * 清除 + * + * @author sr on 2020-07-30 + */ + public static void clearContext() { + contextHolder.remove(); + } + + /** + * 设置 + * + * @param context + * @author sr on 2020-07-30 + */ + public static void setContext(IUserDetail context) { + contextHolder.set(context); + } + + /** + * 获取当前登录用户 + * + * @param auth + * @return + * @author sr on 2020-06-16 + */ + public static IUserDetail getLoginUser() { + return contextHolder.get(); + } + + /** + * 获取当前登录用户ID + */ + public static Long getLoginUserId() { + IUserDetail userDTO = getLoginUser(); + return userDTO == null ? null : userDTO.getId(); + } + + /** + * 获取当前登录机构ID + */ + public static Long getLoginOrgId() { + IUserDetail userDTO = getLoginUser(); + return userDTO == null ? null : userDTO.getOrgId(); + } + + /** + * 获取登录用户(未登录抛异常) + * + * @return + * @author sr on 2019-10-11 + */ + public static IUserDetail getExistLoginUser() { + IUserDetail userDTO = getLoginUser(); + if (userDTO == null) { + throw new NoneLoginException(); + } + return userDTO; + } + + /** + * 获取登录用户id(未登录抛异常) + * + * @return + * @author sr on 2019-10-11 + */ + public static Long getExistLoginUserId() { + return getExistLoginUser().getId(); + } + + /** + * 获取登录机构id(未登录抛异常) + * + * @return + * @author sr on 2019-10-11 + */ + public static Long getExistLoginOrgId() { + return getExistLoginUser().getOrgId(); + } + + /** + * 获取机构类型 + * + * @return + * @author sr on 2019-10-22 + */ + public static String getOrgType() { + IUserDetail userDTO = getLoginUser(); + return userDTO == null ? null : userDTO.getOrgType(); + } + + /** + * 获取用户类型 + * + * @return + * @author sr on 2020-06-17 + */ + public static Integer getUserType() { + IUserDetail userDTO = getLoginUser(); + return userDTO == null ? null : userDTO.getType(); + } + + /** + * 获取用户类型(未登录抛异常) + * + * @return + * @author sr on 2020-06-17 + */ + public static Integer getExistUserType() { + return getExistLoginUser().getType(); + } + + /** + * 获取登录超管用户id(超管未登录抛异常) + * + * @return + * @author sr on 2019-10-17 + */ + public static Long getExistLoginSuperiorId() { + IUserDetail userDTO = getExistLoginUser(); + Assert.isTrue(userDTO.getSupeiror(), "只有平台管理员能访问"); + return userDTO.getId(); + } + + /** + * 是否超管用户 + * + * @return + * @author sr on 2020-03-12 + */ + public static boolean isSuperior() { + IUserDetail userDTO = getLoginUser(); + return userDTO != null && userDTO.getSupeiror(); + } + + /** + * 是否企业管理员 + * @return + * @author sr on 2021-06-22 + */ + public static boolean isAdministrator() { + return isAdministrator(getLoginUser()); + } + + /** + * 是否企业管理员 + * @param userDTO + * @return + * @author sr on 2021-06-29 + */ + public static boolean isAdministrator(IUserDetail userDTO) { + return userDTO != null && UserTypeEnum.ORG.getType().equals(userDTO.getType()) + && userDTO.getAdministrator(); + } + + /** + * + * 校验平台机构访问 + * + * @author sr on 2020-12-28 + */ + public static void checkPlatformOrg() { + Assert.isTrue(CommonConstants.PLATFORM_ORG_ID.equals(getLoginOrgId()), "只有平台机构能访问"); + } + + /** + * 获取除超管以外的机构ID + * + * @return + */ + public static Long getOrgIdNotSupper() { + IUserDetail userDTO = getExistLoginUser(); + return userDTO.getSupeiror() ? null : userDTO.getOrgId(); + } + + /** + * 获取用户状态 + * @return + * @author sr on 2021-06-30 + */ + public static Integer getStatus() { + IUserDetail userDTO = getLoginUser(); + return userDTO == null ? null : userDTO.getStatus(); + } + +} diff --git a/src/main/java/com/newyetai/common/validate/EnumValidator.java b/src/main/java/com/newyetai/common/validate/EnumValidator.java new file mode 100644 index 0000000..f483028 --- /dev/null +++ b/src/main/java/com/newyetai/common/validate/EnumValidator.java @@ -0,0 +1,30 @@ +package com.newyetai.common.validate; + +import com.newyetai.mybatis.handle.BaseEnum; + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * enum验证器 + * + * @author Carlye + * @date 2021/01/14 + */ +@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@Constraint(validatedBy = EnumValidatorAdapter.class) +public @interface EnumValidator { + + Class> value(); + + String message(); + + Class[] groups() default {}; + + Class[] payload() default {}; +} diff --git a/src/main/java/com/newyetai/common/validate/EnumValidatorAdapter.java b/src/main/java/com/newyetai/common/validate/EnumValidatorAdapter.java new file mode 100644 index 0000000..99ef1e7 --- /dev/null +++ b/src/main/java/com/newyetai/common/validate/EnumValidatorAdapter.java @@ -0,0 +1,30 @@ +package com.newyetai.common.validate; + + +import com.newyetai.mybatis.handle.BaseEnum; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; +import java.util.Arrays; +import java.util.Objects; + +/** + * enum验证器适配器 + * + * @author Carlye + * @date 2021/01/14 + */ +public class EnumValidatorAdapter implements ConstraintValidator { + private BaseEnum[] enumConstants; + + @Override + public void initialize(EnumValidator constraintAnnotation) { + Class> clazz = constraintAnnotation.value(); + enumConstants = clazz.getEnumConstants(); + } + + @Override + public boolean isValid(Object s, ConstraintValidatorContext constraintValidatorContext) { + return Objects.nonNull(enumConstants) && Objects.nonNull(s) && Arrays.stream(enumConstants).anyMatch(e -> s.equals(e.getValue())); + } +} diff --git a/src/main/java/com/newyetai/common/validation/Check.java b/src/main/java/com/newyetai/common/validation/Check.java new file mode 100644 index 0000000..cc0cc4f --- /dev/null +++ b/src/main/java/com/newyetai/common/validation/Check.java @@ -0,0 +1,9 @@ +package com.newyetai.common.validation; + +/** + * 校验 + * + * @author on 2019-11-05 + */ +public interface Check { +} diff --git a/src/main/java/com/newyetai/common/validation/Create.java b/src/main/java/com/newyetai/common/validation/Create.java new file mode 100644 index 0000000..a323a9b --- /dev/null +++ b/src/main/java/com/newyetai/common/validation/Create.java @@ -0,0 +1,10 @@ +package com.newyetai.common.validation; + +/** + * 新增校验 + * + * @author on 2019-11-05 + */ +public interface Create { + +} diff --git a/src/main/java/com/newyetai/common/validation/Delete.java b/src/main/java/com/newyetai/common/validation/Delete.java new file mode 100644 index 0000000..3e031f3 --- /dev/null +++ b/src/main/java/com/newyetai/common/validation/Delete.java @@ -0,0 +1,10 @@ +package com.newyetai.common.validation; + +/** + * 删除校验 + * + * @author on 2019-11-05 + */ +public interface Delete { + +} diff --git a/src/main/java/com/newyetai/common/validation/Send.java b/src/main/java/com/newyetai/common/validation/Send.java new file mode 100644 index 0000000..8e211f7 --- /dev/null +++ b/src/main/java/com/newyetai/common/validation/Send.java @@ -0,0 +1,7 @@ +package com.newyetai.common.validation; + +/** + * @author on 2019-11-05 + */ +public interface Send { +} diff --git a/src/main/java/com/newyetai/common/validation/Update.java b/src/main/java/com/newyetai/common/validation/Update.java new file mode 100644 index 0000000..7f8ad02 --- /dev/null +++ b/src/main/java/com/newyetai/common/validation/Update.java @@ -0,0 +1,10 @@ +package com.newyetai.common.validation; + +/** + * 更新校验 + * + * @author on 2019-11-05 + */ +public interface Update { + +} diff --git a/src/main/java/com/newyetai/common/validation/annotation/BigDecimalRange.java b/src/main/java/com/newyetai/common/validation/annotation/BigDecimalRange.java new file mode 100644 index 0000000..8dddf0d --- /dev/null +++ b/src/main/java/com/newyetai/common/validation/annotation/BigDecimalRange.java @@ -0,0 +1,52 @@ +package com.newyetai.common.validation.annotation; + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.*; + +@Target({TYPE, ANNOTATION_TYPE,FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@Constraint(validatedBy = {BigDecimalRangeValidator.class}) +public @interface BigDecimalRange { + + String message() default ""; + + /** + * 提示信息前缀 + * @return 错误提示 + */ + String messagePrefix() default "金额数值"; + + /** + * 最小值 (包含) + * @return 最小值 + */ + String minValue() default ""; + + /** + * 最大值 (包含) + * @return 最大值 + */ + String maxValue() default ""; + + /** + * 校验长度 + * + * @return int 长度 -1:不校验 + */ + int length() default -1; + + /** + * 校验小数点位数 + * @return int 小数点位数校验 -1:不校验 + */ + int scala() default -1; + + Class[] groups() default {}; + + Class[] payload() default {}; +} diff --git a/src/main/java/com/newyetai/common/validation/annotation/BigDecimalRangeValidator.java b/src/main/java/com/newyetai/common/validation/annotation/BigDecimalRangeValidator.java new file mode 100644 index 0000000..3fa6769 --- /dev/null +++ b/src/main/java/com/newyetai/common/validation/annotation/BigDecimalRangeValidator.java @@ -0,0 +1,124 @@ +package com.newyetai.common.validation.annotation; + +import lombok.Data; +import org.apache.commons.lang3.StringUtils; +import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorContextImpl; +import org.springframework.validation.annotation.Validated; + +import javax.validation.*; +import java.math.BigDecimal; +import java.util.Objects; +import java.util.Set; + +/** + * 金额数字范围验证器 + * + * @author Carlye + * @date 2021/03/16 + */ +public class BigDecimalRangeValidator implements ConstraintValidator { + + private BigDecimal minValue; + private BigDecimal maxValue; + private int scala; + private int length; + private String messagePrefix; + + @Override + public void initialize(BigDecimalRange constraintAnnotation) { + try { + minValue = new BigDecimal(constraintAnnotation.minValue()); + } catch (Exception e) { + //doNothing + minValue = null; + } + + try { + maxValue = new BigDecimal(constraintAnnotation.maxValue()); + } catch (Exception e) { + //doNothing + maxValue = null; + } + scala = constraintAnnotation.scala(); + length = constraintAnnotation.length(); + messagePrefix = constraintAnnotation.messagePrefix(); + } + + @Override + public boolean isValid(BigDecimal checkValue, + ConstraintValidatorContext context) { + String messageSuffix = "超出范围"; + boolean checkResult = true; + if (Objects.isNull(checkValue)) { + messageSuffix = "不能为空"; + checkResult = false; + } else if (scala >= 0) { //需要对位数进行校验 + //原值输出BigDecimal + String checkValueStr = checkValue.toPlainString(); + if (StringUtils.substringAfter(checkValueStr, ".").length() != scala) { + messageSuffix = "需要保留" + scala + "位小数"; + checkResult = false; + } + } else if (length >= 0) { + //原值输出BigDecimal + String checkValueStr = checkValue.toPlainString(); + if (checkValueStr.length() > length) { + messageSuffix = "超过最大位数限制(" + length + ")"; + checkResult = false; + } + } else if (Objects.nonNull(minValue) && minValue.compareTo(checkValue) > 0) { + messageSuffix = String.join("", "最小值为", minValue.stripTrailingZeros().toPlainString()); + checkResult = false; + } else if (Objects.nonNull(maxValue) && maxValue.compareTo(checkValue) < 0) { + messageSuffix = String.join("", "最大值为", maxValue.stripTrailingZeros().toPlainString()); + checkResult = false; + } + if (!checkResult) { + //改变默认提示信息 + if (ConstraintValidatorContextImpl.class.isAssignableFrom(context.getClass())) { + //禁用默认提示信息 + context.disableDefaultConstraintViolation(); + //设置提示语(在message前面加上key) + context.buildConstraintViolationWithTemplate(String.join("", messagePrefix, messageSuffix)).addConstraintViolation(); + } + } + return checkResult; + } + + public static void main(String[] args) { + BigDecimal bigDecimal = BigDecimal.valueOf(0.90988); + System.out.println(bigDecimal.toPlainString()); + System.out.println(StringUtils.substringAfter(bigDecimal.toPlainString(), ".")); + } + + + @Data + private static class ValidTest { + + @BigDecimalRange(messagePrefix = "火红的萨", maxValue = "0.999", minValue = "0.001") + private BigDecimal checkV; + + + @Validated + public static void test(@Valid ValidTest validTest) { + System.out.println(validTest); + } + + public static void main(String[] args) { + BigDecimal bigDecimal = BigDecimal.valueOf(0.0001); + System.out.println(String.valueOf(bigDecimal)); + Validator validator = Validation.buildDefaultValidatorFactory() + .getValidator(); + ValidTest validTest = new ValidTest(); + validTest.setCheckV(BigDecimal.valueOf(-1)); + Set> validate = validator.validate(validTest); + StringBuilder validateError = new StringBuilder(); + for (ConstraintViolation constraintViolation : validate) { + validateError.append(constraintViolation.getMessage()).append(";"); + } + + System.out.println(validateError); + } + + } +} diff --git a/src/main/java/com/newyetai/common/validation/annotation/Expression.java b/src/main/java/com/newyetai/common/validation/annotation/Expression.java new file mode 100644 index 0000000..21fd21a --- /dev/null +++ b/src/main/java/com/newyetai/common/validation/annotation/Expression.java @@ -0,0 +1,50 @@ +package com.newyetai.common.validation.annotation; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; + +import com.newyetai.common.validation.constants.ValidProviderEnum; + +/** + * 表达式校验器注解 + * @author sr on 2021-05-25 + */ +@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) +@Retention(RUNTIME) +@Documented +@Constraint(validatedBy = {ExpressionValidator.class}) +public @interface Expression { + + String message() default "{javax.validation.constraints.Expression.message}"; + + /** + * springEl表达式,内置参数value(待校验值),返回值类型boolean + * @return + * @author sr on 2021-05-25 + */ + String expressionStr() default ""; + + /** + * {@link ValidProviderEnum} + * @return + * @author sr on 2021-07-07 + */ + ValidProviderEnum type() default ValidProviderEnum.NONE; + + Class[] groups() default {}; + + Class[] payload() default {}; + +} diff --git a/src/main/java/com/newyetai/common/validation/annotation/ExpressionValidator.java b/src/main/java/com/newyetai/common/validation/annotation/ExpressionValidator.java new file mode 100644 index 0000000..3e14776 --- /dev/null +++ b/src/main/java/com/newyetai/common/validation/annotation/ExpressionValidator.java @@ -0,0 +1,42 @@ +package com.newyetai.common.validation.annotation; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.expression.spel.support.StandardEvaluationContext; + +import com.newyetai.common.validation.constants.ValidProviderEnum; + +public class ExpressionValidator implements ConstraintValidator{ + + //SPEL解析 + private static ExpressionParser parser = new SpelExpressionParser(); + + private org.springframework.expression.Expression spelExpression ; + private ValidProviderEnum validProviderEnum; + + @Override + public void initialize(Expression expression) { + String expressionStr = expression.expressionStr(); + if (StringUtils.isNotBlank(expressionStr)) { + spelExpression = parser.parseExpression(expressionStr); + } + validProviderEnum = expression.type(); + } + + + @Override + public boolean isValid(Object value, ConstraintValidatorContext context) { + if (spelExpression != null) { + StandardEvaluationContext spelContext = new StandardEvaluationContext(); + spelContext.setVariable("value", value); + return spelExpression.getValue(spelContext, Boolean.class); + } + return validProviderEnum.getFunction().apply(value); + } + + +} diff --git a/src/main/java/com/newyetai/common/validation/annotation/IdCard.java b/src/main/java/com/newyetai/common/validation/annotation/IdCard.java new file mode 100644 index 0000000..0d405fc --- /dev/null +++ b/src/main/java/com/newyetai/common/validation/annotation/IdCard.java @@ -0,0 +1,52 @@ +package com.newyetai.common.validation.annotation; + + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; +import javax.validation.constraints.Pattern.Flag; + +/** + * 身份证号 + * + * @author on 2019-11-05 + */ +@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) +@Retention(RUNTIME) +@Documented +@Constraint(validatedBy = {IdCardValidator.class}) +@Inherited +public @interface IdCard { + + /** + * @return the error message template + */ + String message() default "身份证号码格式错误"; + + /** + * @return the groups the constraint belongs to + */ + Class[] groups() default {}; + + /** + * @return array of {@code Flag}s considered when resolving the regular expression + */ + Flag[] flags() default {}; + + /** + * @return the payload associated to the constraint + */ + Class[] payload() default {}; +} diff --git a/src/main/java/com/newyetai/common/validation/annotation/IdCardValidator.java b/src/main/java/com/newyetai/common/validation/annotation/IdCardValidator.java new file mode 100644 index 0000000..36d7c67 --- /dev/null +++ b/src/main/java/com/newyetai/common/validation/annotation/IdCardValidator.java @@ -0,0 +1,29 @@ +package com.newyetai.common.validation.annotation; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +import org.apache.commons.lang3.StringUtils; + +import com.newyetai.common.validation.util.ValidateUtils; + +/** + * 身份证号校验器 + * + * @author on 2019-11-05 + */ +public class IdCardValidator implements ConstraintValidator { + + @Override + public void initialize(IdCard constraintAnnotation) { + + } + + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + if (StringUtils.isBlank(value)) { + return true; + } + return ValidateUtils.isIdCard(value); + } +} diff --git a/src/main/java/com/newyetai/common/validation/annotation/Phone.java b/src/main/java/com/newyetai/common/validation/annotation/Phone.java new file mode 100644 index 0000000..78af3f5 --- /dev/null +++ b/src/main/java/com/newyetai/common/validation/annotation/Phone.java @@ -0,0 +1,59 @@ +package com.newyetai.common.validation.annotation; + + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; +import javax.validation.constraints.Pattern.Flag; + + +/** + * 电话号码 + * + * @author on 2019-11-05 + */ +@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) +@Retention(RUNTIME) +@Documented +@Constraint(validatedBy = {PhoneValidator.class}) +@Inherited +// @Pattern(regexp=ValidateUtil.mobileReg, message = MaterialConstant.PHONE_FORMAT_ERROR) +public @interface Phone { + + /** + * @return the error message template + */ + // @AliasFor(annotation = Pattern.class, attribute = "message") + String message() default "电话号码格式错误"; + + /** + * @return the groups the constraint belongs to + */ + // @AliasFor(annotation = Pattern.class, attribute = "groups") + Class[] groups() default {}; + + /** + * @return array of {@code Flag}s considered when resolving the regular expression + */ + // @AliasFor(annotation = Pattern.class, attribute = "flags") + Flag[] flags() default {}; + + /** + * @return the payload associated to the constraint + */ + // @AliasFor(annotation = Pattern.class, attribute = "payload") + Class[] payload() default {}; +} + diff --git a/src/main/java/com/newyetai/common/validation/annotation/PhoneValidator.java b/src/main/java/com/newyetai/common/validation/annotation/PhoneValidator.java new file mode 100644 index 0000000..7976b08 --- /dev/null +++ b/src/main/java/com/newyetai/common/validation/annotation/PhoneValidator.java @@ -0,0 +1,28 @@ +package com.newyetai.common.validation.annotation; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +import org.apache.commons.lang3.StringUtils; + +import com.newyetai.common.validation.util.ValidateUtils; + +/** + * 电话号码校验器 + * + * @author on 2019-11-05 + */ +public class PhoneValidator implements ConstraintValidator { + + @Override + public void initialize(Phone constraintAnnotation) {} + + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + if (StringUtils.isBlank(value)) { + return true; + } + return ValidateUtils.isPhone(value) || ValidateUtils.isFixedTelephone(value); + } + +} diff --git a/src/main/java/com/newyetai/common/validation/annotation/TableColumn.java b/src/main/java/com/newyetai/common/validation/annotation/TableColumn.java new file mode 100644 index 0000000..e36b727 --- /dev/null +++ b/src/main/java/com/newyetai/common/validation/annotation/TableColumn.java @@ -0,0 +1,23 @@ +package com.newyetai.common.validation.annotation; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * @author on 2019-11-05 + */ +@Target(FIELD) +@Retention(RUNTIME) +@Documented +@Inherited +public @interface TableColumn { + + String name(); + + int sort(); +} diff --git a/src/main/java/com/newyetai/common/validation/constants/ValidProviderEnum.java b/src/main/java/com/newyetai/common/validation/constants/ValidProviderEnum.java new file mode 100644 index 0000000..6e99b10 --- /dev/null +++ b/src/main/java/com/newyetai/common/validation/constants/ValidProviderEnum.java @@ -0,0 +1,46 @@ +package com.newyetai.common.validation.constants; + +import java.util.Map; +import java.util.function.Function; + +import com.google.common.collect.Maps; +import com.newyetai.common.validation.util.ValidateUtils; + + +public enum ValidProviderEnum { + + NONE("none", (v) -> false), + CARD_NO("cardNo", (v) -> ValidateUtils.isIdCard((String) v)), + PHONE("phone", (v) -> ValidateUtils.isPhone((String) v)), + USERNAME("username", (v) -> ValidateUtils.matchUsername((String) v)), + PASSWORD("password", (v) -> ValidateUtils.matchPassword((String) v)), + REAL_NAME("realName", (v) -> ValidateUtils.checkRealName((String) v)), + ; + + private static Map validMap ; + private String type; + private Function function; + + ValidProviderEnum(String type, Function function) { + this.type = type; + this.function = function; + } + + static { + ValidProviderEnum[] enums = ValidProviderEnum.values(); + validMap = Maps.newHashMapWithExpectedSize(enums.length); + for (ValidProviderEnum providerEnum : enums) { + validMap.put(providerEnum.getType(), providerEnum); + } + } + + public String getType() { + return this.type; + } + + public Function getFunction() { + return this.function; + } + + +} diff --git a/src/main/java/com/newyetai/common/validation/util/ValidateUtils.java b/src/main/java/com/newyetai/common/validation/util/ValidateUtils.java new file mode 100644 index 0000000..24acf57 --- /dev/null +++ b/src/main/java/com/newyetai/common/validation/util/ValidateUtils.java @@ -0,0 +1,249 @@ +package com.newyetai.common.validation.util; + +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.exception.util.Assert; +import org.apache.commons.lang3.StringUtils; + +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.Validator; +import java.util.Set; +import java.util.regex.Pattern; + +/** + * @author on 2019-11-05 + */ +public class ValidateUtils { + + + /** + * 用户安全码校验正则 + */ + public static final String SECURITY_CODE_PATTERN = "^[A-Za-z\\d!@#$%^&*]{6,32}$"; + + public static Pattern numberPattern = Pattern.compile("^[-\\+]?[\\d]*$"); + + public static Pattern mobilePattern = Pattern.compile("^[1][0-9]{10}$"); + + public static Pattern fixedTelephone = Pattern.compile("^[0]\\d{2,3}\\d{7,8}"); + + public static final Pattern USERNAME_PATTERN = Pattern.compile("^[a-zA-Z0-9]{4,32}$"); + public static final Pattern PASSWORD_PATTERN = Pattern.compile("[A-Za-z\\d!@#$%^&*]{6,32}$"); + /** + * 正则 邮箱 + */ + private static Pattern EMAIL_REG = Pattern.compile("^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$"); + /** + * 昵称校验 + */ + private static Pattern NICK_NAME_REG = Pattern.compile("^[\\u4e00-\\u9fffa-zA-Z0-9]{2,32}$"); + + /** 姓名 **/ + private static final Pattern REAL_NAME_REG = Pattern.compile( + "^(([a-zA-Z+\\.?\\·?a-zA-Z+]{2,30}$)|([\\u4e00-\\u9fff+\\·?\\u4e00-\\u9fff+]{2,30}$))"); + + public static Validator validator = Validation.buildDefaultValidatorFactory() + .getValidator(); + + /** + * 身份证号权重因子、对应验证码 + */ + // 前十七位加权因子 + public static final int[] idCardWi = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}; + // 这是除以11后,可能产生的11位余数对应的验证码 + public static final String[] idCardY = {"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"}; + + // 定义判别用户身份证号的正则表达式(15位或者18位,最后一位可以为字母) + // 假设18位身份证号码:41000119910101123X 410001 19910101 123X + // ^开头 + // [1-9] 第一位1-9中的一个 4 + // \\d{5} 五位数字 10001(前六位省市县地区) + // (18|19|20) 19(现阶段可能取值范围18xx-20xx年) + // \\d{2} 91(年份) + // ((0[1-9])|(10|11|12)) 01(月份) + // (([0-2][1-9])|10|20|30|31)01(日期) + // \\d{3} 三位数字 123(第十七位奇数代表男,偶数代表女) + // [0-9Xx] 0123456789Xx其中的一个 X(第十八位为校验值) + // $结尾 + + // 假设15位身份证号码:410001910101123 410001 910101 123 + // ^开头 + // [1-9] 第一位1-9中的一个 4 + // \\d{5} 五位数字 10001(前六位省市县地区) + // \\d{2} 91(年份) + // ((0[1-9])|(10|11|12)) 01(月份) + // (([0-2][1-9])|10|20|30|31)01(日期) + // \\d{3} 三位数字 123(第十五位奇数代表男,偶数代表女),15位身份证不含X + // $结尾 + private static Pattern idCardPattern = Pattern.compile( + "(^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$)|" + + "(^[1-9]\\d{5}\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}$)"); + + /** + * 手机号码校验 + * + * @param mobile + * @return + */ + public static boolean isPhone(String mobile) { + if (StringUtils.isBlank(mobile)) { + return false; + } + return mobilePattern.matcher(mobile).matches(); + } + + /** + * 固定电话校验 + * + * @param phone + * @return + */ + public static boolean isFixedTelephone(String phone) { + if (StringUtils.isBlank(phone)) { + return false; + } + phone = phone.replace("-", ""); + return fixedTelephone.matcher(phone).matches(); + } + + /** + * 身份证校验 + * + * @param idCard + * @return + */ + public static boolean isIdCard(String idCard) { + if (StringUtils.isBlank(idCard)) { + return false; + } + boolean matches = idCardPattern.matcher(idCard).matches(); + // 判断第18位校验值 + if (matches) { + if (idCard.length() == 18) { + try { + char[] charArray = idCard.toCharArray(); + int sum = 0; + for (int i = 0; i < idCardWi.length; i++) { + int current = Integer.parseInt(String.valueOf(charArray[i])); + int count = current * idCardWi[i]; + sum += count; + } + char idCardLast = charArray[17]; + int idCardMod = sum % 11; + if (idCardY[idCardMod].toUpperCase().equals(String.valueOf(idCardLast).toUpperCase())) { + return true; + } else { + return false; + } + + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + } + return matches; + } + + /** + * 校验对象,校验未通过返回异常信息 + * @param object + * @param groups + * @return null 校验通过;否则 返回异常信息 + * @author sr on 2021-05-25 + */ + public static String validate(Object object, Class... groups) { + Set> constraintViolations = validator.validate(object, groups); + if (constraintViolations.isEmpty()) { + return null; + } + StringBuilder errMsg = new StringBuilder(); + constraintViolations.forEach(constraintViolation -> errMsg + .append(constraintViolation.getMessage()).append(CommonConstants.COMMA)); + return errMsg.toString(); + } + + /** + * 校验对象,校验未通过抛BusinessException + * @param object + * @param groups + * @author sr on 2021-05-25 + */ + public static void validateBiz(Object object, Class... groups) { + String errMsg = validate(object, groups); + Assert.isNull(errMsg, errMsg); + } + + /** + * 校验对象,校验未通过抛BusinessException + * @param object + * @param errMsg 自定义异常信息 + * @param groups + * @author sr on 2021-06-10 + */ + public static void validateBiz(Object object, String errMsg, Class... groups) { + String originErrMsg = validate(object, groups); + Assert.isNull(originErrMsg, errMsg); + } + + /** + * 账号是否合规 + * @param userName + * @return + * @author sr on 2021-07-07 + */ + public static boolean matchUsername(String userName) { + if (StringUtils.isBlank(userName)) { + return false; + } + return USERNAME_PATTERN.matcher(userName).matches(); + } + + /** + * 密码是否合规 + * @param password + * @return + * @author sr on 2021-07-07 + */ + public static boolean matchPassword(String password) { + if (StringUtils.isBlank(password)) { + return false; + } + return PASSWORD_PATTERN.matcher(password).matches(); + } + + /** + * 邮箱是否合规 + * @param email + * @return + * @author sr on 2021-07-07 + */ + public static boolean checkEmail(String email) { + if (StringUtils.isBlank(email)) { + return false; + } + return EMAIL_REG.matcher(email).matches(); + } + + public static boolean checkNickName(String nickname) { + if (StringUtils.isBlank(nickname)) { + return false; + } + return NICK_NAME_REG.matcher(nickname).matches(); + } + + /** + * 检查中文姓名 + * + * @param realname 中文名 + * @return boolean + */ + public static boolean checkRealName(String realname) { + if (StringUtils.isBlank(realname)) { + return false; + } + return REAL_NAME_REG.matcher(realname).matches(); + } + +} diff --git a/src/main/java/com/newyetai/commonexport/dto/CommonExportDynamicDTO.java b/src/main/java/com/newyetai/commonexport/dto/CommonExportDynamicDTO.java new file mode 100644 index 0000000..7c85eb5 --- /dev/null +++ b/src/main/java/com/newyetai/commonexport/dto/CommonExportDynamicDTO.java @@ -0,0 +1,34 @@ +package com.newyetai.commonexport.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class CommonExportDynamicDTO implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 文件名 + */ + private String fileName; + + /** + * 表头列表 + */ + private List head; + + /** + * List : 数据 + */ + private List> datas; + + +} diff --git a/src/main/java/com/newyetai/commonexport/dto/CommonExportMapDTO.java b/src/main/java/com/newyetai/commonexport/dto/CommonExportMapDTO.java new file mode 100644 index 0000000..11ada32 --- /dev/null +++ b/src/main/java/com/newyetai/commonexport/dto/CommonExportMapDTO.java @@ -0,0 +1,64 @@ +package com.newyetai.commonexport.dto; + +import com.alibaba.excel.write.style.column.AbstractHeadColumnWidthStyleStrategy; +import com.alibaba.excel.write.style.column.SimpleColumnWidthStyleStrategy; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.apache.commons.lang3.StringUtils; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +/** + * 导出多个sheet实体类 + * + * @param + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class CommonExportMapDTO implements Serializable { + private static final long serialVersionUID = -8482074133630026236L; + + private static final String FILE_SUFFIX = ".xlsx"; + + /** + * 文件名 + */ + private String fileName; + + /** + * 文件后缀 + */ + private String fileSuffix; + + /** + * 列宽度策略 + */ + private AbstractHeadColumnWidthStyleStrategy columnWidthStyleStrategy; + + /** + * key : sheetName + * List : 数据 + */ + private Map> datas; + + public String getFileSuffix() { + if (StringUtils.isEmpty(fileSuffix)) { + this.fileSuffix = FILE_SUFFIX; + } + return this.fileSuffix; + } + + public AbstractHeadColumnWidthStyleStrategy getColumnWidthStyleStrategy() { + if (this.columnWidthStyleStrategy == null) { + this.columnWidthStyleStrategy = new SimpleColumnWidthStyleStrategy(20); + } + return this.columnWidthStyleStrategy; + } + +} diff --git a/src/main/java/com/newyetai/commonexport/dto/CommonExportPropertiesDTO.java b/src/main/java/com/newyetai/commonexport/dto/CommonExportPropertiesDTO.java new file mode 100644 index 0000000..43f2f08 --- /dev/null +++ b/src/main/java/com/newyetai/commonexport/dto/CommonExportPropertiesDTO.java @@ -0,0 +1,67 @@ +package com.newyetai.commonexport.dto; + +import com.alibaba.excel.write.style.column.AbstractHeadColumnWidthStyleStrategy; +import com.alibaba.excel.write.style.column.SimpleColumnWidthStyleStrategy; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.apache.commons.lang3.StringUtils; + +import java.io.Serializable; +import java.util.List; + +/** + * @author chenyun + * @description 公共导出DTO + * @date 2020/10/21 14:03 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class CommonExportPropertiesDTO implements Serializable { + private static final long serialVersionUID = -8482074133630026236L; + + private static final String FILE_SUFFIX = ".xlsx"; + + /** + * 文件名 + */ + private String fileName; + + /** + * 文件后缀 + */ + private String fileSuffix; + + /** + * 列宽度策略 + */ + private AbstractHeadColumnWidthStyleStrategy columnWidthStyleStrategy; + + /** + * sheet 名称 + */ + private String sheetName; + + /** + * 导出头 + */ + private List datas; + + public String getFileSuffix() { + if (StringUtils.isEmpty(fileSuffix)) { + this.fileSuffix = FILE_SUFFIX; + } + return this.fileSuffix; + } + + public AbstractHeadColumnWidthStyleStrategy getColumnWidthStyleStrategy() { + if (this.columnWidthStyleStrategy == null) { + this.columnWidthStyleStrategy = new SimpleColumnWidthStyleStrategy(20); + } + return this.columnWidthStyleStrategy; + } + +} diff --git a/src/main/java/com/newyetai/commonexport/service/ExportService.java b/src/main/java/com/newyetai/commonexport/service/ExportService.java new file mode 100644 index 0000000..13558d3 --- /dev/null +++ b/src/main/java/com/newyetai/commonexport/service/ExportService.java @@ -0,0 +1,23 @@ +package com.newyetai.commonexport.service; + +import com.newyetai.commonexport.dto.CommonExportDynamicDTO; +import com.newyetai.commonexport.dto.CommonExportMapDTO; +import com.newyetai.commonexport.dto.CommonExportPropertiesDTO; +import com.newyetai.component.file.entity.FileRecord; + +import java.util.List; + +public interface ExportService { + + /** + * 公共导出方法 + * + * @param commonExportPropertiesDTO 导出实体 + * @return FileRecord + */ + FileRecord export(CommonExportPropertiesDTO commonExportPropertiesDTO); + + + FileRecord export(CommonExportMapDTO commonExportMapDTO); + +} diff --git a/src/main/java/com/newyetai/commonexport/service/impl/ExportByDtoServiceImpl.java b/src/main/java/com/newyetai/commonexport/service/impl/ExportByDtoServiceImpl.java new file mode 100644 index 0000000..b0ef4fc --- /dev/null +++ b/src/main/java/com/newyetai/commonexport/service/impl/ExportByDtoServiceImpl.java @@ -0,0 +1,81 @@ +package com.newyetai.commonexport.service.impl; + +import java.io.ByteArrayOutputStream; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import org.apache.poi.ss.formula.functions.T; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.commonexport.dto.CommonExportMapDTO; +import com.newyetai.commonexport.dto.CommonExportPropertiesDTO; +import com.newyetai.commonexport.service.ExportService; +import com.newyetai.component.file.config.FileProperties; +import com.newyetai.component.file.entity.FileRecord; +import com.newyetai.component.file.service.FileService; + +import cn.hutool.core.collection.CollUtil; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class ExportByDtoServiceImpl implements ExportService { + + @Autowired + private FileProperties fileProperties; + + @Autowired + private FileService fileService; + + public FileRecord export(CommonExportPropertiesDTO commonExportPropertiesDTO) { + CommonExportMapDTO objectCommonExportMapDTO = new CommonExportMapDTO<>(); + objectCommonExportMapDTO.setFileName(commonExportPropertiesDTO.getFileName()); + objectCommonExportMapDTO.setColumnWidthStyleStrategy( + commonExportPropertiesDTO.getColumnWidthStyleStrategy()); + objectCommonExportMapDTO.setFileSuffix(commonExportPropertiesDTO.getFileSuffix()); + objectCommonExportMapDTO.setDatas(new HashMap>() { + { + put(commonExportPropertiesDTO.getSheetName(), commonExportPropertiesDTO.getDatas()); + } + }); + return this.export(objectCommonExportMapDTO); + } + + @Override + public FileRecord export(CommonExportMapDTO commonExportMapDTO) { + Map datas = commonExportMapDTO.getDatas(); + if (CollUtil.isEmpty(datas)) { + return null; + } + Optional first = datas.values().stream().findFirst(); + if (!first.isPresent() || CollUtil.isEmpty(first.get())) { + return null; + } + Class aClass = first.get().get(0).getClass(); + // 临时文件名 + String targetFileName = commonExportMapDTO.getFileName() + commonExportMapDTO.getFileSuffix(); + //3.调用excelUtil 生成临时文件 + try { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + ExcelWriter writer = EasyExcel.write(os, aClass) + .registerWriteHandler(commonExportMapDTO.getColumnWidthStyleStrategy()).build(); + + datas.forEach((key, value) -> writer.write(value, EasyExcel.writerSheet(key).build())); + writer.finish(); + byte[] excelByte = os.toByteArray(); + return fileService.uploadTemp(targetFileName, excelByte); + } catch ( + Exception e) { + log.info("导出文件异常", e); + throw new BusinessException("导出文件异常"); + } + } + + +} diff --git a/src/main/java/com/newyetai/component/action/annotation/ActionField.java b/src/main/java/com/newyetai/component/action/annotation/ActionField.java new file mode 100644 index 0000000..71a25de --- /dev/null +++ b/src/main/java/com/newyetai/component/action/annotation/ActionField.java @@ -0,0 +1,19 @@ +package com.newyetai.component.action.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 操作记录 + * @author sr on 2022-02-18 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD}) +public @interface ActionField { + + String alias() default ""; + String dictCode() default ""; + +} diff --git a/src/main/java/com/newyetai/component/action/annotation/ActionModel.java b/src/main/java/com/newyetai/component/action/annotation/ActionModel.java new file mode 100644 index 0000000..6d816f4 --- /dev/null +++ b/src/main/java/com/newyetai/component/action/annotation/ActionModel.java @@ -0,0 +1,17 @@ +package com.newyetai.component.action.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 操作记录对象 + * @author sr on 2022-02-18 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +public @interface ActionModel { + + String type(); +} diff --git a/src/main/java/com/newyetai/component/action/constant/ActionConstants.java b/src/main/java/com/newyetai/component/action/constant/ActionConstants.java new file mode 100644 index 0000000..605d43b --- /dev/null +++ b/src/main/java/com/newyetai/component/action/constant/ActionConstants.java @@ -0,0 +1,9 @@ +package com.newyetai.component.action.constant; + +/** + * @author sr on 2022-02-18 + */ +public interface ActionConstants { + + +} diff --git a/src/main/java/com/newyetai/component/action/constant/ActionTypeEnum.java b/src/main/java/com/newyetai/component/action/constant/ActionTypeEnum.java new file mode 100644 index 0000000..b72b610 --- /dev/null +++ b/src/main/java/com/newyetai/component/action/constant/ActionTypeEnum.java @@ -0,0 +1,20 @@ +package com.newyetai.component.action.constant; + +/** + * 操作类型枚举 + * @author sr on 2022-02-21 + */ +public enum ActionTypeEnum { + ; + + ActionTypeEnum(String type) { + this.type = type; + } + + private String type; + + public String getType() { + return type; + } + +} diff --git a/src/main/java/com/newyetai/component/action/controller/ActionController.java b/src/main/java/com/newyetai/component/action/controller/ActionController.java new file mode 100644 index 0000000..23e2031 --- /dev/null +++ b/src/main/java/com/newyetai/component/action/controller/ActionController.java @@ -0,0 +1,43 @@ +package com.newyetai.component.action.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.newyetai.common.AlitaResult; +import com.newyetai.component.action.dto.ActionDTO; +import com.newyetai.component.action.dto.ActionQueryDTO; +import com.newyetai.component.action.service.ActionService; +import com.newyetai.tkmybatis.pojo.Page; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +import java.util.List; + +/** + * @author sr on 2022-02-18 + */ +@RestController +@RequestMapping("action") +@Api(tags = "操作记录") +public class ActionController { + + @Autowired + private ActionService actionService; + + @GetMapping("/page") + @ApiOperation("分页查询") + public AlitaResult> page(ActionQueryDTO actionQueryDTO){ + actionService.page(actionQueryDTO); + return AlitaResult.success(actionQueryDTO.getPageResult()); + } + + @GetMapping("/list") + @ApiOperation("分页查询") + public AlitaResult> list(ActionQueryDTO actionQueryDTO){ + return AlitaResult.success(actionService.list(actionQueryDTO)); + } + +} diff --git a/src/main/java/com/newyetai/component/action/controller/ActionDetailController.java b/src/main/java/com/newyetai/component/action/controller/ActionDetailController.java new file mode 100644 index 0000000..fd1875e --- /dev/null +++ b/src/main/java/com/newyetai/component/action/controller/ActionDetailController.java @@ -0,0 +1,42 @@ +package com.newyetai.component.action.controller; + +import com.newyetai.common.AlitaResult; +import com.newyetai.component.action.dto.ActionDetailDTO; +import com.newyetai.component.action.dto.ActionDetailQueryDTO; +import com.newyetai.component.action.service.ActionDetailService; +import com.newyetai.tkmybatis.pojo.Page; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + * @author sr on 2022-02-18 + */ +@RestController +@RequestMapping("action_detail") +@Api(tags = "操作记录明细") +public class ActionDetailController { + + @Autowired + private ActionDetailService actionDetailService; + + @GetMapping("/page") + @ApiOperation("分页查询") + public AlitaResult> page(ActionDetailQueryDTO actionDetailQueryDTO){ + actionDetailService.page(actionDetailQueryDTO); + return AlitaResult.success(actionDetailQueryDTO.getPageResult()); + } + + + @GetMapping("/list") + @ApiOperation("根据关联业务id查询日志") + public AlitaResult> list(ActionDetailQueryDTO actionDetailQueryDTO){ + return AlitaResult.success(actionDetailService.list(actionDetailQueryDTO)); + } + +} diff --git a/src/main/java/com/newyetai/component/action/dao/ActionDetailMapper.java b/src/main/java/com/newyetai/component/action/dao/ActionDetailMapper.java new file mode 100644 index 0000000..32ead78 --- /dev/null +++ b/src/main/java/com/newyetai/component/action/dao/ActionDetailMapper.java @@ -0,0 +1,28 @@ +package com.newyetai.component.action.dao; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.newyetai.component.action.dto.ActionDetailDTO; +import com.newyetai.component.action.dto.ActionDetailQueryDTO; +import com.newyetai.component.action.entity.ActionDetail; +import com.newyetai.tkmybatis.mybatis.MyMapper; + +/** + * 操作记录明细 + * + * @author sr on 2022-02-18 + */ +public interface ActionDetailMapper extends MyMapper { + + /** + * 查询 + * + * @param actionDetailQueryDTO + * @return + * @author sr on 2022-02-18 + */ + List listActionDetailDTO(@Param("param") ActionDetailQueryDTO actionDetailQueryDTO); + +} diff --git a/src/main/java/com/newyetai/component/action/dao/ActionMapper.java b/src/main/java/com/newyetai/component/action/dao/ActionMapper.java new file mode 100644 index 0000000..585b32e --- /dev/null +++ b/src/main/java/com/newyetai/component/action/dao/ActionMapper.java @@ -0,0 +1,28 @@ +package com.newyetai.component.action.dao; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.newyetai.component.action.dto.ActionDTO; +import com.newyetai.component.action.dto.ActionQueryDTO; +import com.newyetai.component.action.entity.Action; +import com.newyetai.tkmybatis.mybatis.MyMapper; + +/** + * 操作记录 + * + * @author sr on 2022-02-18 + */ +public interface ActionMapper extends MyMapper { + + /** + * 查询 + * + * @param actionQueryDTO + * @return + * @author sr on 2022-02-18 + */ + List listActionDTO(@Param("param") ActionQueryDTO actionQueryDTO); + +} diff --git a/src/main/java/com/newyetai/component/action/dto/ActionCreateDTO.java b/src/main/java/com/newyetai/component/action/dto/ActionCreateDTO.java new file mode 100644 index 0000000..1d97d1e --- /dev/null +++ b/src/main/java/com/newyetai/component/action/dto/ActionCreateDTO.java @@ -0,0 +1,42 @@ +package com.newyetai.component.action.dto; + +import java.io.Serializable; +import java.util.List; + +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import com.newyetai.common.dto.BaseOperateDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2022-02-18 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "操作记录创建") +public class ActionCreateDTO extends BaseOperateDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("关联类型") + @NotBlank(message = "关联类型不能为空") + private String unionType; + @ApiModelProperty("关联id") + @NotNull(message = "关联id不能为空") + private Long unionId; + @ApiModelProperty("明细") + @Valid + private List detailDtos; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/action/dto/ActionDTO.java b/src/main/java/com/newyetai/component/action/dto/ActionDTO.java new file mode 100644 index 0000000..fbf2f6a --- /dev/null +++ b/src/main/java/com/newyetai/component/action/dto/ActionDTO.java @@ -0,0 +1,37 @@ +package com.newyetai.component.action.dto; + +import com.newyetai.common.dto.BaseDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +import java.util.List; + +/** + * @author sr on 2022-02-18 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@ApiModel(description = "操作记录") +public class ActionDTO extends BaseDTO { + + /** **/ + private static final long serialVersionUID = 1L; + @ApiModelProperty("关联类型") + private String unionType; + @ApiModelProperty("关联id") + private Long unionId; + @ApiModelProperty("处理人") + private String createName; + @ApiModelProperty("子节点") + private List childNode; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/action/dto/ActionDetailCreateDTO.java b/src/main/java/com/newyetai/component/action/dto/ActionDetailCreateDTO.java new file mode 100644 index 0000000..90f6714 --- /dev/null +++ b/src/main/java/com/newyetai/component/action/dto/ActionDetailCreateDTO.java @@ -0,0 +1,46 @@ +package com.newyetai.component.action.dto; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import io.swagger.annotations.ApiModel; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import com.newyetai.common.validation.Update; + +import com.newyetai.common.dto.BaseOperateDTO; + +/** + * @author sr on 2022-02-18 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "操作记录明细创建") +public class ActionDetailCreateDTO extends BaseOperateDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("属性") + @NotBlank(message = "属性不能为空") + private String field; + @ApiModelProperty("属性别名") + private String fieldAlias; + @ApiModelProperty("属性字典编码") + private String fieldDictCode; + @ApiModelProperty("旧值") + private String oldValue; + @ApiModelProperty("新值") + private String newValue; + @ApiModelProperty("差异") + private String diff; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/action/dto/ActionDetailDTO.java b/src/main/java/com/newyetai/component/action/dto/ActionDetailDTO.java new file mode 100644 index 0000000..a92b98f --- /dev/null +++ b/src/main/java/com/newyetai/component/action/dto/ActionDetailDTO.java @@ -0,0 +1,43 @@ +package com.newyetai.component.action.dto; + +import com.newyetai.common.dto.BaseDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2022-02-18 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@ApiModel(description = "操作记录明细") +public class ActionDetailDTO extends BaseDTO { + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("操作记录id") + private Long actionId; + @ApiModelProperty("属性") + private String field; + @ApiModelProperty("属性别名") + private String fieldAlias; + @ApiModelProperty("属性字典编码") + private String fieldDictCode; + @ApiModelProperty("旧值") + private String oldValue; + @ApiModelProperty("新值") + private String newValue; + @ApiModelProperty("差异") + private String diff; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/action/dto/ActionDetailQueryDTO.java b/src/main/java/com/newyetai/component/action/dto/ActionDetailQueryDTO.java new file mode 100644 index 0000000..0dd564c --- /dev/null +++ b/src/main/java/com/newyetai/component/action/dto/ActionDetailQueryDTO.java @@ -0,0 +1,33 @@ +package com.newyetai.component.action.dto; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import io.swagger.annotations.ApiModel; + +import com.newyetai.common.dto.PageQueryDTO; + +/** + * @author sr on 2022-02-18 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "操作记录明细查询条件") +public class ActionDetailQueryDTO extends PageQueryDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("操作记录id") + private Long actionId; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/action/dto/ActionQueryDTO.java b/src/main/java/com/newyetai/component/action/dto/ActionQueryDTO.java new file mode 100644 index 0000000..de91fb3 --- /dev/null +++ b/src/main/java/com/newyetai/component/action/dto/ActionQueryDTO.java @@ -0,0 +1,33 @@ +package com.newyetai.component.action.dto; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import io.swagger.annotations.ApiModel; + +import com.newyetai.common.dto.PageQueryDTO; + +/** + * @author sr on 2022-02-18 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "操作记录查询条件") +public class ActionQueryDTO extends PageQueryDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("关联业务id") + private Long unionId; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/action/entity/Action.java b/src/main/java/com/newyetai/component/action/entity/Action.java new file mode 100644 index 0000000..ee97925 --- /dev/null +++ b/src/main/java/com/newyetai/component/action/entity/Action.java @@ -0,0 +1,32 @@ +package com.newyetai.component.action.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 操作记录 + * + * @author sr on 2022-02-18 + */ +@TableName("uc_action") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +public class Action extends BaseEntity { + + /** **/ + private static final long serialVersionUID = 1L; + /** 关联类型 **/ + private String unionType; + /** 关联id **/ + private Long unionId; + +} diff --git a/src/main/java/com/newyetai/component/action/entity/ActionDetail.java b/src/main/java/com/newyetai/component/action/entity/ActionDetail.java new file mode 100644 index 0000000..938e7d1 --- /dev/null +++ b/src/main/java/com/newyetai/component/action/entity/ActionDetail.java @@ -0,0 +1,41 @@ +package com.newyetai.component.action.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 操作记录明细 + * + * @author sr on 2022-02-18 + */ +@TableName("uc_action_detail") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +public class ActionDetail extends BaseEntity { + + /** **/ + private static final long serialVersionUID = 1L; + /** 操作记录id **/ + private Long actionId; + /** 属性 **/ + private String field; + /** 属性别名 **/ + private String fieldAlias; + /** 属性字典编码 **/ + private String fieldDictCode; + /** 旧值 **/ + private String oldValue; + /** 新值 **/ + private String newValue; + /** 差异 **/ + private String diff; +} diff --git a/src/main/java/com/newyetai/component/action/mapper/ActionDetailMapper.xml b/src/main/java/com/newyetai/component/action/mapper/ActionDetailMapper.xml new file mode 100644 index 0000000..047fc79 --- /dev/null +++ b/src/main/java/com/newyetai/component/action/mapper/ActionDetailMapper.xml @@ -0,0 +1,20 @@ + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/action/mapper/ActionMapper.xml b/src/main/java/com/newyetai/component/action/mapper/ActionMapper.xml new file mode 100644 index 0000000..bc2565e --- /dev/null +++ b/src/main/java/com/newyetai/component/action/mapper/ActionMapper.xml @@ -0,0 +1,19 @@ + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/action/mapstruct/ActionDetailMapMapper.java b/src/main/java/com/newyetai/component/action/mapstruct/ActionDetailMapMapper.java new file mode 100644 index 0000000..c9f773c --- /dev/null +++ b/src/main/java/com/newyetai/component/action/mapstruct/ActionDetailMapMapper.java @@ -0,0 +1,37 @@ +package com.newyetai.component.action.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.newyetai.component.action.dto.ActionDetailCreateDTO; +import com.newyetai.component.action.dto.ActionDetailDTO; +import com.newyetai.component.action.entity.ActionDetail; + +/** + * @author sr on 2022-02-18 + */ +@Mapper +public interface ActionDetailMapMapper { + + ActionDetailMapMapper INSTANCE = + Mappers.getMapper(ActionDetailMapMapper.class); + + /** + * dto to entity + * + * @param actionDetailDto + * @return + * @author sr on 2022-02-18 + */ + ActionDetail toEntity( + ActionDetailDTO actionDetailDto); + + + /** + * @param ActionDetailCreateDTO + * @return + * @author sr on 2022-02-18 + */ + ActionDetail toEntity(ActionDetailCreateDTO ActionDetailCreateDTO); + +} diff --git a/src/main/java/com/newyetai/component/action/mapstruct/ActionMapMapper.java b/src/main/java/com/newyetai/component/action/mapstruct/ActionMapMapper.java new file mode 100644 index 0000000..0bf5038 --- /dev/null +++ b/src/main/java/com/newyetai/component/action/mapstruct/ActionMapMapper.java @@ -0,0 +1,37 @@ +package com.newyetai.component.action.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.newyetai.component.action.dto.ActionCreateDTO; +import com.newyetai.component.action.dto.ActionDTO; +import com.newyetai.component.action.entity.Action; + +/** + * @author sr on 2022-02-18 + */ +@Mapper +public interface ActionMapMapper { + + ActionMapMapper INSTANCE = + Mappers.getMapper(ActionMapMapper.class); + + /** + * dto to entity + * + * @param actionDto + * @return + * @author sr on 2022-02-18 + */ + Action toEntity( + ActionDTO actionDto); + + + /** + * @param actionCreateDTO + * @return + * @author sr on 2022-02-18 + */ + Action toEntity(ActionCreateDTO actionCreateDTO); + +} diff --git a/src/main/java/com/newyetai/component/action/service/ActionDetailService.java b/src/main/java/com/newyetai/component/action/service/ActionDetailService.java new file mode 100644 index 0000000..e81a13c --- /dev/null +++ b/src/main/java/com/newyetai/component/action/service/ActionDetailService.java @@ -0,0 +1,42 @@ +package com.newyetai.component.action.service; + +import java.util.List; + +import com.newyetai.component.action.dto.ActionDetailDTO; +import com.newyetai.component.action.dto.ActionDetailQueryDTO; + +/** + * 操作记录明细 + * + * @author sr on 2022-02-18 + */ +public interface ActionDetailService { + + /** + * 查询 + * + * @param actionDetailQueryDTO + * @return + * @author sr on 2022-02-18 + */ + List list(ActionDetailQueryDTO actionDetailQueryDTO); + + /** + * 分页查询 + * + * @param actionDetailQueryDTO + * @return + * @author sr on 2022-02-18 + */ + void page(ActionDetailQueryDTO actionDetailQueryDTO); + + /** + * 单个查询 + * + * @param actionDetailQueryDTO + * @return + * @author sr on 2022-02-18 + */ + ActionDetailDTO find(ActionDetailQueryDTO actionDetailQueryDTO); + +} diff --git a/src/main/java/com/newyetai/component/action/service/ActionService.java b/src/main/java/com/newyetai/component/action/service/ActionService.java new file mode 100644 index 0000000..a681d81 --- /dev/null +++ b/src/main/java/com/newyetai/component/action/service/ActionService.java @@ -0,0 +1,55 @@ +package com.newyetai.component.action.service; + +import java.util.List; + +import org.springframework.validation.annotation.Validated; + +import com.newyetai.component.action.dto.ActionCreateDTO; +import com.newyetai.component.action.dto.ActionDTO; +import com.newyetai.component.action.dto.ActionQueryDTO; + +/** + * 操作记录 + * + * @author sr on 2022-02-18 + */ +public interface ActionService { + + /** + * 新增 + * + * @param actionOperateDTO + * @return + * @author sr on 2022-02-18 + */ + Long create(@Validated ActionCreateDTO actionOperateDTO); + + + /** + * 查询 + * + * @param actionQueryDTO + * @return + * @author sr on 2022-02-18 + */ + List list(ActionQueryDTO actionQueryDTO); + + /** + * 分页查询 + * + * @param actionQueryDTO + * @return + * @author sr on 2022-02-18 + */ + void page(ActionQueryDTO actionQueryDTO); + + /** + * 单个查询 + * + * @param actionQueryDTO + * @return + * @author sr on 2022-02-18 + */ + ActionDTO find(ActionQueryDTO actionQueryDTO); + +} diff --git a/src/main/java/com/newyetai/component/action/service/impl/ActionDetailServiceImpl.java b/src/main/java/com/newyetai/component/action/service/impl/ActionDetailServiceImpl.java new file mode 100644 index 0000000..7d32ff2 --- /dev/null +++ b/src/main/java/com/newyetai/component/action/service/impl/ActionDetailServiceImpl.java @@ -0,0 +1,40 @@ +package com.newyetai.component.action.service.impl; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.newyetai.common.util.ListUtil; +import com.newyetai.component.action.dao.ActionDetailMapper; +import com.newyetai.component.action.dto.ActionDetailDTO; +import com.newyetai.component.action.dto.ActionDetailQueryDTO; +import com.newyetai.component.action.service.ActionDetailService; + +/** + * @author sr on 2022-02-18 + */ +@Service +public class ActionDetailServiceImpl implements ActionDetailService { + + @Autowired + private ActionDetailMapper actionDetailMapper; + + @Override + public List list(ActionDetailQueryDTO actionDetailQueryDTO) { + actionDetailQueryDTO.disablePage(); + return actionDetailMapper.listActionDetailDTO(actionDetailQueryDTO); + } + + @Override + public void page(ActionDetailQueryDTO actionDetailQueryDTO) { + actionDetailMapper.listActionDetailDTO(actionDetailQueryDTO); + } + + @Override + public ActionDetailDTO find(ActionDetailQueryDTO actionDetailQueryDTO) { + List actionDetailDTOs = this.list(actionDetailQueryDTO); + return actionDetailDTOs.isEmpty() ? null : ListUtil.first(actionDetailDTOs); + } + +} diff --git a/src/main/java/com/newyetai/component/action/service/impl/ActionServiceImpl.java b/src/main/java/com/newyetai/component/action/service/impl/ActionServiceImpl.java new file mode 100644 index 0000000..4c45872 --- /dev/null +++ b/src/main/java/com/newyetai/component/action/service/impl/ActionServiceImpl.java @@ -0,0 +1,101 @@ +package com.newyetai.component.action.service.impl; + +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.common.constant.CommonMqConstants; +import com.newyetai.common.util.ListUtil; +import com.newyetai.common.util.MockUtils; +import com.newyetai.component.action.dao.ActionDetailMapper; +import com.newyetai.component.action.dao.ActionMapper; +import com.newyetai.component.action.dto.ActionCreateDTO; +import com.newyetai.component.action.dto.ActionDTO; +import com.newyetai.component.action.dto.ActionDetailCreateDTO; +import com.newyetai.component.action.dto.ActionDetailQueryDTO; +import com.newyetai.component.action.dto.ActionQueryDTO; +import com.newyetai.component.action.entity.Action; +import com.newyetai.component.action.entity.ActionDetail; +import com.newyetai.component.action.mapstruct.ActionDetailMapMapper; +import com.newyetai.component.action.mapstruct.ActionMapMapper; +import com.newyetai.component.action.service.ActionService; +import com.newyetai.mq.consumer.handler.ITopicMqHandler; +import com.newyetai.mq.dto.TopicMqMessage; + +/** + * @author sr on 2022-02-18 + */ +@Service +public class ActionServiceImpl implements ActionService , ITopicMqHandler{ + + @Autowired + private ActionMapper actionMapper; + + @Autowired + private ActionDetailMapper actionDetailMapper; + + @Override + @Transactional + public Long create(ActionCreateDTO actionCreateDTO) { + Action action = ActionMapMapper.INSTANCE.toEntity(actionCreateDTO); + actionMapper.saveEntity(action); + Long actionId = action.getId(); + List detailCreateDtos = actionCreateDTO.getDetailDtos(); + if (CollectionUtils.isEmpty(detailCreateDtos)) { + return actionId; + } + List details = detailCreateDtos.stream().map(dto -> { + ActionDetail actionDetail = ActionDetailMapMapper.INSTANCE.toEntity(dto); + actionDetail.setActionId(actionId); + return actionDetail; + }).collect(Collectors.toList()); + actionDetailMapper.saveEntites(details); + return actionId; + } + + + @Override + public List list(ActionQueryDTO actionQueryDTO) { + actionQueryDTO.disablePage(); + List dtoList = actionMapper.listActionDTO(actionQueryDTO); + dtoList.forEach(f ->{ + f.setChildNode(actionDetailMapper.listActionDetailDTO(ActionDetailQueryDTO.builder().actionId(f.getId()).build())); + }); + return dtoList; + } + + @Override + public void page(ActionQueryDTO actionQueryDTO) { + actionMapper.listActionDTO(actionQueryDTO); + } + + @Override + public ActionDTO find(ActionQueryDTO actionQueryDTO) { + List actionDTOs = this.list(actionQueryDTO); + return actionDTOs.isEmpty() ? null : ListUtil.first(actionDTOs); + } + + + @Override + public String getRoutingKey() { + return CommonMqConstants.ACTION_LOG; + } + + + @Override + public void onMessage(TopicMqMessage message) { + Long userId = message.getOperateUserId(); + if (userId != null) { + MockUtils.mockUser(userId, message.getOperateOrgId()); + } else { + MockUtils.mockPlatUser(); + } + ((ActionService) AopContext.currentProxy()).create(message.getData()); + } + +} diff --git a/src/main/java/com/newyetai/component/action/util/ActionUtils.java b/src/main/java/com/newyetai/component/action/util/ActionUtils.java new file mode 100644 index 0000000..06d59d4 --- /dev/null +++ b/src/main/java/com/newyetai/component/action/util/ActionUtils.java @@ -0,0 +1,110 @@ +package com.newyetai.component.action.util; + +import java.lang.reflect.Field; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.StringUtils; + +import com.google.common.collect.Lists; +import com.newyetai.common.constant.CommonMqConstants; +import com.newyetai.common.util.StrUtils; +import com.newyetai.component.action.annotation.ActionField; +import com.newyetai.component.action.annotation.ActionModel; +import com.newyetai.component.action.dto.ActionCreateDTO; +import com.newyetai.component.action.dto.ActionDetailCreateDTO; +import com.newyetai.component.dict.util.DictUtils; +import com.newyetai.mq.util.MqSendUtils; +import com.newyetai.mybatisplus.util.MybatisPlusUtils; + +import lombok.extern.slf4j.Slf4j; + +/** + * @author sr on 2022-02-18 + */ +@Slf4j +public class ActionUtils { + + public static void diff(Long objId, Object oldObj, Object newObj) { + if (oldObj == null || newObj == null) { + log.info("记录对象不能为空"); + return; + } + Class objClass = oldObj.getClass(); + if (objClass != newObj.getClass()) { + log.info("记录对象类型需一致"); + return; + } + if (objId == null) { + log.info("记录id不能为空"); + return; + } + try { + Field[] fields = objClass.getDeclaredFields(); + List detailCreateDTOs = Lists.newArrayList(); + for (Field field : fields) { + ActionField actionLog = field.getAnnotation(ActionField.class); + if (actionLog == null) { + continue; + } + field.setAccessible(true); + String fieldAlias = actionLog.alias(); + String fieldName = field.getName(); + try { + Object oldValue = MybatisPlusUtils.dealEnumField(field.get(oldObj)); + Object newValue = MybatisPlusUtils.dealEnumField(field.get(newObj)); + String oldValueStr = oldValue == null ? null : oldValue.toString(); + String newValueStr = newValue == null ? null : newValue.toString(); + + if(StringUtils.isBlank(oldValueStr) && StringUtils.isBlank(newValueStr)){ + continue; + } + String dictCode = actionLog.dictCode(); + String diff = null; + if (StringUtils.isNotBlank(dictCode)) { + Map dictNameMap = DictUtils.getCodeNameMap(dictCode); + diff = formatDiff(fieldAlias, MapUtils.getString(dictNameMap, oldValueStr, oldValueStr), + MapUtils.getString(dictNameMap, newValueStr, newValueStr)); + } else { + dictCode = null; + diff = formatDiff(fieldAlias, oldValueStr, newValueStr); + } + ActionDetailCreateDTO detailCreateDTO = ActionDetailCreateDTO.builder() + .field(fieldName) + .fieldAlias(fieldAlias) + .fieldDictCode(dictCode) + .oldValue(oldValueStr) + .newValue(newValueStr) + .diff(diff) + .build(); + detailCreateDTOs.add(detailCreateDTO); + } catch (IllegalArgumentException | IllegalAccessException e) { + log.info("获取记录对象属性失败", e); + return; + } + } + ActionModel actionModel = objClass.getAnnotation(ActionModel.class); + String unionType = null; + if (actionModel != null) { + unionType = actionModel.type(); + } + unionType = + Optional.ofNullable(unionType) + .orElseGet(() -> StrUtils.toSnake(objClass.getSimpleName())); + ActionCreateDTO actionCreateDTO = + ActionCreateDTO.builder().unionType(unionType).unionId(objId).detailDtos(detailCreateDTOs) + .build(); + MqSendUtils.send(CommonMqConstants.ACTION_LOG, actionCreateDTO); + } catch (Exception e) { + log.info("记录操作失败", e); + } + } + + private static String formatDiff(String fieldAlias, String oldValueStr, String newValueStr) { + return String.join("", fieldAlias, ",旧值为\"", oldValueStr, "\",新值为\"", newValueStr, "\""); + } + + +} diff --git a/src/main/java/com/newyetai/component/asyntasknotice/constant/AsyncTaskFlowStatusEnum.java b/src/main/java/com/newyetai/component/asyntasknotice/constant/AsyncTaskFlowStatusEnum.java new file mode 100644 index 0000000..94f5841 --- /dev/null +++ b/src/main/java/com/newyetai/component/asyntasknotice/constant/AsyncTaskFlowStatusEnum.java @@ -0,0 +1,29 @@ +package com.newyetai.component.asyntasknotice.constant; + + +/** + * 异步任务流程状态 + * + * @author sr on 2024-02-06 + */ +public enum AsyncTaskFlowStatusEnum { + + /** 开启 **/ + START(1), + /** 结束 **/ + END(2), + ; + + + private Integer status; + + AsyncTaskFlowStatusEnum(Integer status) { + this.status = status; + } + + public Integer getStatus() { + return status; + } + + +} diff --git a/src/main/java/com/newyetai/component/asyntasknotice/constant/AsyncTaskNoticeStatusEnum.java b/src/main/java/com/newyetai/component/asyntasknotice/constant/AsyncTaskNoticeStatusEnum.java new file mode 100644 index 0000000..913dbf5 --- /dev/null +++ b/src/main/java/com/newyetai/component/asyntasknotice/constant/AsyncTaskNoticeStatusEnum.java @@ -0,0 +1,30 @@ +package com.newyetai.component.asyntasknotice.constant; + + +/** + * 异步任务通知状态 + * @author sr on 2024-02-06 + */ +public enum AsyncTaskNoticeStatusEnum { + + /** 未读 **/ + INIT(1), + /** 已读 **/ + READ(2), + ; + + + + + private Integer status; + + AsyncTaskNoticeStatusEnum(Integer status) { + this.status = status; + } + + public Integer getStatus() { + return status; + } + + +} diff --git a/src/main/java/com/newyetai/component/asyntasknotice/constant/AsyncTaskTypeEnum.java b/src/main/java/com/newyetai/component/asyntasknotice/constant/AsyncTaskTypeEnum.java new file mode 100644 index 0000000..97c9302 --- /dev/null +++ b/src/main/java/com/newyetai/component/asyntasknotice/constant/AsyncTaskTypeEnum.java @@ -0,0 +1,21 @@ +package com.newyetai.component.asyntasknotice.constant; + +/** + * 异步任务类型 + * @author sr on 2024-02-06 + */ +public enum AsyncTaskTypeEnum { + + COMMON_IMPORT("common_import") + ; + + private String type; + + AsyncTaskTypeEnum(String type) { + this.type = type; + } + + public String getType() { + return type; + } +} diff --git a/src/main/java/com/newyetai/component/asyntasknotice/controller/AsyncTaskNoticeController.java b/src/main/java/com/newyetai/component/asyntasknotice/controller/AsyncTaskNoticeController.java new file mode 100644 index 0000000..e1d82c5 --- /dev/null +++ b/src/main/java/com/newyetai/component/asyntasknotice/controller/AsyncTaskNoticeController.java @@ -0,0 +1,49 @@ +package com.newyetai.component.asyntasknotice.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeDTO; +import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeQueryDTO; +import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeReadDTO; +import com.newyetai.component.asyntasknotice.service.AsyncTaskNoticeService; +import com.newyetai.component.commonimport.dto.ImportMainCreateDTO; +import com.newyetai.tkmybatis.pojo.Page; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +/** + * @author sr on 2024-02-06 + */ +@RestController +@RequestMapping("async_task_notice") +@Api(tags = "异步任务通知") +public class AsyncTaskNoticeController { + + @Autowired + private AsyncTaskNoticeService asyncTaskNoticeService; + + @GetMapping("/page") + @ApiOperation("分页查询") + public AlitaResult> page(AsyncTaskNoticeQueryDTO asyncTaskNoticeQueryDTO){ + asyncTaskNoticeQueryDTO.setCreateBy(UserContextHolder.getExistLoginUserId()); + asyncTaskNoticeService.page(asyncTaskNoticeQueryDTO); + return AlitaResult.success(asyncTaskNoticeQueryDTO.getPageResult()); + } + + + @PostMapping("/read") + @ApiOperation("创建") + public AlitaResult read(AsyncTaskNoticeReadDTO readDTO){ + return AlitaResult.success(asyncTaskNoticeService.read(readDTO)); + } +} diff --git a/src/main/java/com/newyetai/component/asyntasknotice/dao/AsyncTaskNoticeMapper.java b/src/main/java/com/newyetai/component/asyntasknotice/dao/AsyncTaskNoticeMapper.java new file mode 100644 index 0000000..b28578c --- /dev/null +++ b/src/main/java/com/newyetai/component/asyntasknotice/dao/AsyncTaskNoticeMapper.java @@ -0,0 +1,33 @@ +package com.newyetai.component.asyntasknotice.dao; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeDTO; +import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeFinishDTO; +import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeQueryDTO; +import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeReadDTO; +import com.newyetai.component.asyntasknotice.entity.AsyncTaskNotice; +import com.newyetai.tkmybatis.mybatis.MyMapper; + +/** + * 异步任务通知 + * + * @author sr on 2024-02-06 + */ +public interface AsyncTaskNoticeMapper extends MyMapper { + + /** + * 查询 + * + * @param asyncTaskNoticeQueryDTO + * @return + * @author sr on 2024-02-06 + */ + List listAsyncTaskNoticeDTO(@Param("param") AsyncTaskNoticeQueryDTO asyncTaskNoticeQueryDTO); + + int finish(@Param("param") AsyncTaskNoticeFinishDTO finishDTO); + + int read(@Param("param") AsyncTaskNoticeReadDTO readDTO); +} diff --git a/src/main/java/com/newyetai/component/asyntasknotice/dto/AsyncTaskNoticeCreateDTO.java b/src/main/java/com/newyetai/component/asyntasknotice/dto/AsyncTaskNoticeCreateDTO.java new file mode 100644 index 0000000..e885932 --- /dev/null +++ b/src/main/java/com/newyetai/component/asyntasknotice/dto/AsyncTaskNoticeCreateDTO.java @@ -0,0 +1,41 @@ +package com.newyetai.component.asyntasknotice.dto; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import com.newyetai.common.dto.BaseOperateDTO; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2024-02-06 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "异步任务通知创建") +public class AsyncTaskNoticeCreateDTO extends BaseOperateDTO{ + + /** **/ + private static final long serialVersionUID = 1L; + + /** 关联类型:common_import等**/ + @NotBlank(message = "关联类型不能为空") + private String unionType; + /** 关联id**/ + @NotNull(message = "关联id不能为空") + private Long unionId; + /** 内容**/ + @NotBlank(message = "内容不能为空") + private String content; + /** 业务状态**/ + private String bizStatusStr; + /** 业务参数**/ + private String bizParamData; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/asyntasknotice/dto/AsyncTaskNoticeDTO.java b/src/main/java/com/newyetai/component/asyntasknotice/dto/AsyncTaskNoticeDTO.java new file mode 100644 index 0000000..6e3b368 --- /dev/null +++ b/src/main/java/com/newyetai/component/asyntasknotice/dto/AsyncTaskNoticeDTO.java @@ -0,0 +1,43 @@ +package com.newyetai.component.asyntasknotice.dto; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.component.action.dto.ActionDetailDTO; + +import com.newyetai.component.asyntasknotice.constant.AsyncTaskTypeEnum; +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2024-02-06 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@ApiModel(description = "异步任务通知") +public class AsyncTaskNoticeDTO extends BaseDTO { + + /** **/ + private static final long serialVersionUID = 1L; + /** @see AsyncTaskTypeEnum 关联类型:common_import等**/ + private String unionType; + /** 关联id**/ + private Long unionId; + /** 内容**/ + private String content; + /** 业务状态**/ + private String bizStatusStr; + /** 业务参数**/ + private String bizParamData; + /** 流程状态:1开启,2结束**/ + private Integer flowStatus; + /** 通知状态:1未读,2已读**/ + private Integer noticeStatus; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/asyntasknotice/dto/AsyncTaskNoticeFinishDTO.java b/src/main/java/com/newyetai/component/asyntasknotice/dto/AsyncTaskNoticeFinishDTO.java new file mode 100644 index 0000000..84be7f0 --- /dev/null +++ b/src/main/java/com/newyetai/component/asyntasknotice/dto/AsyncTaskNoticeFinishDTO.java @@ -0,0 +1,36 @@ +package com.newyetai.component.asyntasknotice.dto; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import com.newyetai.common.dto.BaseOperateDTO; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2024-02-06 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "异步任务通知结束") +public class AsyncTaskNoticeFinishDTO extends BaseOperateDTO{ + + /** **/ + private static final long serialVersionUID = 1L; + + /** 关联类型:common_import等**/ + @NotBlank(message = "关联类型不能为空") + private String unionType; + /** 关联id**/ + @NotNull(message = "关联id不能为空") + private Long unionId; + /** 业务状态**/ + private String bizStatusStr; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/asyntasknotice/dto/AsyncTaskNoticeQueryDTO.java b/src/main/java/com/newyetai/component/asyntasknotice/dto/AsyncTaskNoticeQueryDTO.java new file mode 100644 index 0000000..ba242f0 --- /dev/null +++ b/src/main/java/com/newyetai/component/asyntasknotice/dto/AsyncTaskNoticeQueryDTO.java @@ -0,0 +1,37 @@ +package com.newyetai.component.asyntasknotice.dto; + + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import io.swagger.annotations.ApiModel; + +import com.newyetai.common.dto.PageQueryDTO; + +/** + * @author sr on 2024-02-06 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "异步任务通知查询条件") +public class AsyncTaskNoticeQueryDTO extends PageQueryDTO{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("创建人") + private Long createBy; + + /** 关联类型:common_import等**/ + private String unionType; + /** 关联id**/ + private Long unionId; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/asyntasknotice/dto/AsyncTaskNoticeReadDTO.java b/src/main/java/com/newyetai/component/asyntasknotice/dto/AsyncTaskNoticeReadDTO.java new file mode 100644 index 0000000..1879b6b --- /dev/null +++ b/src/main/java/com/newyetai/component/asyntasknotice/dto/AsyncTaskNoticeReadDTO.java @@ -0,0 +1,32 @@ +package com.newyetai.component.asyntasknotice.dto; + +import com.newyetai.common.dto.BaseOperateDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2024-02-06 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "异步任务通知-读取") +public class AsyncTaskNoticeReadDTO extends BaseOperateDTO{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + /** 关联类型:common_import等**/ + private String unionType; + /** 关联id**/ + private Long unionId; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/asyntasknotice/entity/AsyncTaskNotice.java b/src/main/java/com/newyetai/component/asyntasknotice/entity/AsyncTaskNotice.java new file mode 100644 index 0000000..5c0d634 --- /dev/null +++ b/src/main/java/com/newyetai/component/asyntasknotice/entity/AsyncTaskNotice.java @@ -0,0 +1,43 @@ +package com.newyetai.component.asyntasknotice.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 异步任务通知 + * + * @author sr on 2024-02-06 + */ +@TableName("async_task_notice") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +public class AsyncTaskNotice extends BaseEntity { + + /** **/ + private static final long serialVersionUID = 1L; + + /** 关联类型:common_import等**/ + private String unionType; + /** 关联id**/ + private Long unionId; + /** 内容**/ + private String content; + /** 业务状态**/ + private String bizStatusStr; + /** 业务参数**/ + private String bizParamData; + /** 流程状态:1开启,2结束**/ + private Integer flowStatus; + /** 通知状态:1未读,2已读**/ + private Integer noticeStatus; + +} diff --git a/src/main/java/com/newyetai/component/asyntasknotice/mapper/AsyncTaskNoticeMapper.xml b/src/main/java/com/newyetai/component/asyntasknotice/mapper/AsyncTaskNoticeMapper.xml new file mode 100644 index 0000000..43da302 --- /dev/null +++ b/src/main/java/com/newyetai/component/asyntasknotice/mapper/AsyncTaskNoticeMapper.xml @@ -0,0 +1,57 @@ + + + + + + + update async_task_notice + set flow_status = 2,update_time = now(), update_by = #{param.operateUserId} + + ,biz_status_str = #{param.bizStatusStr} + + where + deleted = 0 + and union_type = #{param.unionType} + and union_id = #{param.unionId} + and flow_status = 1 + + + + update async_task_notice + set notice_status = 2,update_time = now(), update_by = #{param.operateUserId} + where + deleted = 0 + and create_by = #{param.operateUserId} + and notice_status = 1 + + and id = #{param.id} + + + and union_type = #{param.unionType} + + + and union_id = #{param.unionId} + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/asyntasknotice/mapstruct/AsyncTaskNoticeMapMapper.java b/src/main/java/com/newyetai/component/asyntasknotice/mapstruct/AsyncTaskNoticeMapMapper.java new file mode 100644 index 0000000..fc16280 --- /dev/null +++ b/src/main/java/com/newyetai/component/asyntasknotice/mapstruct/AsyncTaskNoticeMapMapper.java @@ -0,0 +1,36 @@ +package com.newyetai.component.asyntasknotice.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeCreateDTO; +import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeDTO; +import com.newyetai.component.asyntasknotice.entity.AsyncTaskNotice; + +/** + * @author sr on 2024-02-06 + */ +@Mapper +public interface AsyncTaskNoticeMapMapper { + + AsyncTaskNoticeMapMapper INSTANCE = + Mappers.getMapper(AsyncTaskNoticeMapMapper.class); + + /** + * dto to entity + * + * @param asyncTaskNoticeDto + * @return + * @author sr on 2024-02-06 + */ + AsyncTaskNotice toEntity( + AsyncTaskNoticeDTO asyncTaskNoticeDto); + + + /** + * @return + * @author sr on 2024-02-06 + */ + AsyncTaskNotice toEntity(AsyncTaskNoticeCreateDTO createDTO); + +} diff --git a/src/main/java/com/newyetai/component/asyntasknotice/service/AsyncTaskNoticeService.java b/src/main/java/com/newyetai/component/asyntasknotice/service/AsyncTaskNoticeService.java new file mode 100644 index 0000000..f8001fd --- /dev/null +++ b/src/main/java/com/newyetai/component/asyntasknotice/service/AsyncTaskNoticeService.java @@ -0,0 +1,87 @@ +package com.newyetai.component.asyntasknotice.service; + +import java.util.List; + +import javax.validation.Valid; + +import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeCreateDTO; +import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeDTO; +import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeFinishDTO; +import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeQueryDTO; +import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeReadDTO; + +/** + * 异步任务通知 + * + * @author sr on 2024-02-06 + */ +public interface AsyncTaskNoticeService { + + /** + * 创建 + * + * @param createDTO + * @return + * @author sr on 2024-02-06 + */ + Long create(@Valid AsyncTaskNoticeCreateDTO createDTO); + + /** + * 结束 + * @param finishDTO + * @author sr on 2024-02-06 + */ + void finish(@Valid AsyncTaskNoticeFinishDTO finishDTO); + + /** + * 读取 + * @param readDTO + * @return + * @author sr on 2024-02-06 + */ + Integer read(AsyncTaskNoticeReadDTO readDTO); + + + + /** + * 删除 + * + * @param id + * @author sr on 2024-02-06 + */ + void remove(Long id); + + + + /** + * 查询 + * + * @param asyncTaskNoticeQueryDTO + * @return + * @author sr on 2024-02-06 + */ + List list(AsyncTaskNoticeQueryDTO asyncTaskNoticeQueryDTO); + + /** + * 分页查询 + * + * @param asyncTaskNoticeQueryDTO + * @return + * @author sr on 2024-02-06 + */ + void page(AsyncTaskNoticeQueryDTO asyncTaskNoticeQueryDTO); + + /** + * 单个查询 + * + * @param asyncTaskNoticeQueryDTO + * @return + * @author sr on 2024-02-06 + */ + AsyncTaskNoticeDTO find(AsyncTaskNoticeQueryDTO asyncTaskNoticeQueryDTO); + + + + + +} diff --git a/src/main/java/com/newyetai/component/asyntasknotice/service/impl/AsyncTaskNoticeServiceImpl.java b/src/main/java/com/newyetai/component/asyntasknotice/service/impl/AsyncTaskNoticeServiceImpl.java new file mode 100644 index 0000000..0466b02 --- /dev/null +++ b/src/main/java/com/newyetai/component/asyntasknotice/service/impl/AsyncTaskNoticeServiceImpl.java @@ -0,0 +1,118 @@ +package com.newyetai.component.asyntasknotice.service.impl; + +import com.newyetai.component.notice.constant.NoticeFirstTypeEnum; +import com.newyetai.component.notice.dto.NoticeMsgDTO; +import com.newyetai.component.notice.service.AsyncNoticeHandler; +import com.newyetai.component.notice.util.NoticeUtils; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.ListUtil; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.component.asyntasknotice.constant.AsyncTaskFlowStatusEnum; +import com.newyetai.component.asyntasknotice.constant.AsyncTaskNoticeStatusEnum; +import com.newyetai.component.asyntasknotice.dao.AsyncTaskNoticeMapper; +import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeCreateDTO; +import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeDTO; +import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeFinishDTO; +import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeQueryDTO; +import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeReadDTO; +import com.newyetai.component.asyntasknotice.entity.AsyncTaskNotice; +import com.newyetai.component.asyntasknotice.mapstruct.AsyncTaskNoticeMapMapper; +import com.newyetai.component.asyntasknotice.service.AsyncTaskNoticeService; +import com.newyetai.component.asyntasknotice.util.AsyncTaskNoticeUtils; +import com.newyetai.frame.redis.aop.annotation.AutoUnLock; +import com.newyetai.frame.redis.dto.LockDTO; +import com.newyetai.frame.redis.redisson.RedissonUtils; +import com.newyetai.mq.util.MqSendUtils; + +/** + * @author sr on 2024-02-06 + */ +@Service +public class AsyncTaskNoticeServiceImpl implements AsyncTaskNoticeService { + + private static final String LOCK_NAME = "asynctasknotice"; + + @Autowired + private AsyncTaskNoticeMapper asyncTaskNoticeMapper; + + + public static LockDTO getLockDTO(String unionType, Long unionId) { + Assert.notBlank(unionType, "关联类型不能为空"); + Assert.notNull(unionId, "关联id不能为空"); + return LockDTO.builder().methodName(LOCK_NAME).tryLockWaitTime(0L) + .arg(unionType) + .arg(unionId.toString()) + .build(); + } + + @Override + @AutoUnLock + @Transactional + public Long create(AsyncTaskNoticeCreateDTO createDTO) { + String unionType = createDTO.getUnionType(); + Long unionId = createDTO.getUnionId(); + AsyncTaskNotice existNotice = AsyncTaskNotice.builder().unionId(unionId).unionId(unionId).build(); + boolean exist = asyncTaskNoticeMapper.existsEntity(existNotice); + Assert.isTrue(!exist, "已存在相同关联类型数据"); + LockDTO lockDTO = getLockDTO(unionType, unionId); + Assert.isTrue(RedissonUtils.tryLockAutomatically(lockDTO), "关联类型数据正在被操作"); + exist = asyncTaskNoticeMapper.existsEntity(existNotice); + Assert.isTrue(!exist, "已存在相同关联类型数据"); + AsyncTaskNotice notice = AsyncTaskNoticeMapMapper.INSTANCE.toEntity(createDTO); + notice.setFlowStatus(AsyncTaskFlowStatusEnum.START.getStatus()); + notice.setNoticeStatus(AsyncTaskNoticeStatusEnum.INIT.getStatus()); + asyncTaskNoticeMapper.saveEntity(notice); + return notice.getId(); + } + + @Override + @Transactional + public void finish(AsyncTaskNoticeFinishDTO finishDTO) { + AsyncTaskNoticeDTO noticeDTO = find(AsyncTaskNoticeQueryDTO.builder() + .unionType(finishDTO.getUnionType()).unionId(finishDTO.getUnionId()).build()); + Assert.notNull(noticeDTO, "未找到对应的异步任务"); + Assert.isTrue(AsyncTaskFlowStatusEnum.START.getStatus().equals(noticeDTO.getFlowStatus()), "异步任务已结束"); + noticeDTO.setFlowStatus(AsyncTaskFlowStatusEnum.END.getStatus()); + noticeDTO.setBizStatusStr(finishDTO.getBizStatusStr()); + asyncTaskNoticeMapper.updateEntitySelective(AsyncTaskNoticeMapMapper.INSTANCE.toEntity(noticeDTO)); + // 发通知 + NoticeUtils.sendAsyncNotice(NoticeMsgDTO.create(noticeDTO.getCreateBy(), NoticeFirstTypeEnum.ASYNC_TASK_NOTICE.getType(), noticeDTO)); + } + + @Override + @Transactional + public Integer read(AsyncTaskNoticeReadDTO readDTO) { + return asyncTaskNoticeMapper.read(readDTO); + } + + @Override + @Transactional + public void remove(Long id) { + asyncTaskNoticeMapper.deleteEntity(AsyncTaskNotice.builder().id(id).build(), + UserContextHolder.getLoginUserId()); + } + + @Override + public List list(AsyncTaskNoticeQueryDTO asyncTaskNoticeQueryDTO) { + asyncTaskNoticeQueryDTO.disablePage(); + return asyncTaskNoticeMapper.listAsyncTaskNoticeDTO(asyncTaskNoticeQueryDTO); + } + + @Override + public void page(AsyncTaskNoticeQueryDTO asyncTaskNoticeQueryDTO) { + asyncTaskNoticeMapper.listAsyncTaskNoticeDTO(asyncTaskNoticeQueryDTO); + } + + @Override + public AsyncTaskNoticeDTO find(AsyncTaskNoticeQueryDTO asyncTaskNoticeQueryDTO) { + List asyncTaskNoticeDTOs = this.list(asyncTaskNoticeQueryDTO); + return ListUtil.first(asyncTaskNoticeDTOs); + } + +} diff --git a/src/main/java/com/newyetai/component/asyntasknotice/util/AsyncTaskNoticeUtils.java b/src/main/java/com/newyetai/component/asyntasknotice/util/AsyncTaskNoticeUtils.java new file mode 100644 index 0000000..1febca5 --- /dev/null +++ b/src/main/java/com/newyetai/component/asyntasknotice/util/AsyncTaskNoticeUtils.java @@ -0,0 +1,44 @@ +package com.newyetai.component.asyntasknotice.util; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.util.EnvironmentUtils; +import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeCreateDTO; +import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeFinishDTO; +import com.newyetai.component.asyntasknotice.service.AsyncTaskNoticeService; + +import lombok.extern.slf4j.Slf4j; + +/** + * @author sr on 2024-02-06 + */ +@Component +@Slf4j +public class AsyncTaskNoticeUtils { + + private static AsyncTaskNoticeService asyncTaskNoticeService; + + @Autowired + public void setAsyncTaskNoticeService(AsyncTaskNoticeService asyncTaskNoticeService) { + AsyncTaskNoticeUtils.asyncTaskNoticeService = asyncTaskNoticeService; + } + + public static void create(AsyncTaskNoticeCreateDTO createDTO) { + try { + asyncTaskNoticeService.create(createDTO); + } catch (Exception e) { + log.info("异步任务通知创建失败:{}", e.getMessage()); + } + } + + public static void finish(AsyncTaskNoticeFinishDTO finishDTO) { + try { + asyncTaskNoticeService.finish(finishDTO); + } catch (Exception e) { + log.info("异步任务通知结束失败:{}", e.getMessage()); + } + + } +} diff --git a/src/main/java/com/newyetai/component/cardbin/dao/CardBinMapper.java b/src/main/java/com/newyetai/component/cardbin/dao/CardBinMapper.java new file mode 100644 index 0000000..e411cc3 --- /dev/null +++ b/src/main/java/com/newyetai/component/cardbin/dao/CardBinMapper.java @@ -0,0 +1,26 @@ +package com.newyetai.component.cardbin.dao; + +import java.util.List; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.newyetai.component.cardbin.entity.CardBin; + +/** + * @author sr on 2019-09-25 + */ +public interface CardBinMapper extends BaseMapper { + + /** + * 通过卡bin获取卡bin + * @param cardBin + * @return + */ + CardBin findByCardBin(String cardBin); + + /** + * 查询卡bin列表 + * @return + */ + List selectAllCardBinList(); + +} diff --git a/src/main/java/com/newyetai/component/cardbin/entity/BankCode.java b/src/main/java/com/newyetai/component/cardbin/entity/BankCode.java new file mode 100644 index 0000000..2584269 --- /dev/null +++ b/src/main/java/com/newyetai/component/cardbin/entity/BankCode.java @@ -0,0 +1,40 @@ +package com.newyetai.component.cardbin.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * + * + * @author sr on 2019-09-25 + */ +@TableName("xs_bank_code") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Builder +@Data +public class BankCode extends BaseEntity { + + /** + * 联行号 + **/ + private String bankCode; + + /** + * 银行名称 + **/ + private String bankName; + + /** + * 法人行号 + **/ + private String legalEntityCode; + +} diff --git a/src/main/java/com/newyetai/component/cardbin/entity/CardBin.java b/src/main/java/com/newyetai/component/cardbin/entity/CardBin.java new file mode 100644 index 0000000..2694ec6 --- /dev/null +++ b/src/main/java/com/newyetai/component/cardbin/entity/CardBin.java @@ -0,0 +1,60 @@ +package com.newyetai.component.cardbin.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * 卡bin表 + * + * @author sr on 2019-09-25 + */ +@TableName("xs_card_bin") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Builder +@Data +public class CardBin extends BaseEntity { + + /** + * 机构编号 + **/ + private String bankOrgCode; + /** + * 联网行编号 + **/ + private String bankNumber; + /** + * 机构名称 + **/ + private String bankOrgName; + /** + * 卡长度 + **/ + private Integer cardLength; + /** + * 卡BIN + **/ + private String cardBin; + /** + * 是否银联品牌卡 + **/ + private Boolean standardCard; + /** + * 卡种 + **/ + private String cardClassify; + + /** + * 总行行号(表里都没值,有点问题) + */ + private String bankNo; + + +} diff --git a/src/main/java/com/newyetai/component/cardbin/mapper/CardBinMapper.xml b/src/main/java/com/newyetai/component/cardbin/mapper/CardBinMapper.xml new file mode 100644 index 0000000..506c060 --- /dev/null +++ b/src/main/java/com/newyetai/component/cardbin/mapper/CardBinMapper.xml @@ -0,0 +1,26 @@ + + + + + + + + + diff --git a/src/main/java/com/newyetai/component/cardbin/service/CardBinService.java b/src/main/java/com/newyetai/component/cardbin/service/CardBinService.java new file mode 100644 index 0000000..4d7d317 --- /dev/null +++ b/src/main/java/com/newyetai/component/cardbin/service/CardBinService.java @@ -0,0 +1,53 @@ +package com.newyetai.component.cardbin.service; + +import com.newyetai.common.AlitaResult; +import com.newyetai.component.cardbin.entity.CardBin; + +import java.util.List; +import java.util.Set; + +/** + * @author sr on 2019-09-25 + */ +public interface CardBinService { + + /** + * 导入卡bin + * @author sr on 2019-09-25 + */ + void importCardBin(); + + /** + * 通过卡bin获取卡bin + * @param cardBin + * @return + */ + CardBin findByCardBin(String cardBin); + + /** + * + * @param bankNo + * @return + */ + AlitaResult isBankNo(String bankNo); + + /** + * 查询卡bin列表 + * + * @return + */ + List findAllCardBinList(); + + /** + * 校验银行卡 + * 如果返回null,代表没有可校验的资源 + * 否则,返回校验成功的银行卡号集合 + * + * @param bankNos 银行卡号集合 + * @return {@link Set}<{@link String}> + */ + Set checkBankNos(Set bankNos); + + String getBankNo(String bankNo); + +} diff --git a/src/main/java/com/newyetai/component/cardbin/service/impl/CardBinServiceImpl.java b/src/main/java/com/newyetai/component/cardbin/service/impl/CardBinServiceImpl.java new file mode 100644 index 0000000..2b0ce28 --- /dev/null +++ b/src/main/java/com/newyetai/component/cardbin/service/impl/CardBinServiceImpl.java @@ -0,0 +1,85 @@ +package com.newyetai.component.cardbin.service.impl; + +import com.newyetai.common.AlitaResult; +import com.newyetai.component.cardbin.dao.CardBinMapper; +import com.newyetai.component.cardbin.entity.CardBin; +import com.newyetai.component.cardbin.service.CardBinService; +import com.newyetai.frame.redis.util.RedissonValueUtils; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * @author sr on 2019-09-25 + */ +@Service +@Slf4j +public class CardBinServiceImpl implements CardBinService { + + @Resource + private CardBinMapper cardBinMapper; + + @Override + @Transactional(rollbackFor = Exception.class) + public void importCardBin() { + } + + @Override + public CardBin findByCardBin(String cardBin) { + if(StringUtils.isBlank(cardBin)){ + return null; + } + return cardBinMapper.findByCardBin(cardBin); + } + + @Override + public AlitaResult isBankNo(String bankNo) { + if (StringUtils.isBlank(bankNo)) { + return AlitaResult.error("银行卡号为空"); + } + CardBin cardBin = findByCardBin(bankNo); + return cardBin != null ? AlitaResult.success(cardBin.getBankOrgName()) + : AlitaResult.error("银行卡号格式错误"); + } + + @Override + public List findAllCardBinList() { + String key = "alita:cardbin:list"; + List cardBinList; + if (RedissonValueUtils.hasKey(key)) { + cardBinList = (List) RedissonValueUtils.get(key); + } else { + cardBinList = cardBinMapper.selectAllCardBinList(); + RedissonValueUtils.set(key, cardBinList); + } + return cardBinList; + } + + @Override + public Set checkBankNos(Set bankNos) { + List allCardBinList = findAllCardBinList(); + if (CollectionUtils.isEmpty(allCardBinList)) { + return null; + } + return bankNos.stream().filter(bankNo -> allCardBinList.parallelStream().anyMatch(cardBin -> + bankNo.startsWith(cardBin.getCardBin()) && bankNo.length() == cardBin.getCardLength())) + .collect(Collectors.toSet()); + } + + @Override + public String getBankNo(String bankNo) { + if (StringUtils.isBlank(bankNo)) { + return null; + } + CardBin cardBin = findByCardBin(bankNo); + return cardBin == null ? null : cardBin.getBankOrgName(); + } + +} diff --git a/src/main/java/com/newyetai/component/chat/constant/ChatConstants.java b/src/main/java/com/newyetai/component/chat/constant/ChatConstants.java new file mode 100644 index 0000000..443f72f --- /dev/null +++ b/src/main/java/com/newyetai/component/chat/constant/ChatConstants.java @@ -0,0 +1,8 @@ +package com.newyetai.component.chat.constant; + +/** + * @author sr on 2025-05-29 + */ +public interface ChatConstants { + +} diff --git a/src/main/java/com/newyetai/component/chat/constant/ChatMsgStatusEnum.java b/src/main/java/com/newyetai/component/chat/constant/ChatMsgStatusEnum.java new file mode 100644 index 0000000..8f7a83e --- /dev/null +++ b/src/main/java/com/newyetai/component/chat/constant/ChatMsgStatusEnum.java @@ -0,0 +1,27 @@ +package com.newyetai.component.chat.constant; + + + +public enum ChatMsgStatusEnum { + + /** 未读 **/ + INIT(1), + /** 已读 **/ + READ(2), + ; + + + + + private Integer status; + + ChatMsgStatusEnum(Integer status) { + this.status = status; + } + + public Integer getStatus() { + return status; + } + + +} diff --git a/src/main/java/com/newyetai/component/chat/constant/ChatMsgTypeEnum.java b/src/main/java/com/newyetai/component/chat/constant/ChatMsgTypeEnum.java new file mode 100644 index 0000000..8191c0b --- /dev/null +++ b/src/main/java/com/newyetai/component/chat/constant/ChatMsgTypeEnum.java @@ -0,0 +1,22 @@ +package com.newyetai.component.chat.constant; + +import com.google.common.collect.Maps; +import java.util.Map; + +public enum ChatMsgTypeEnum { + + /** 文字 */ + TEXT("text"), + ; + + private String type; + + ChatMsgTypeEnum(String type) { + this.type = type; + } + + public String getType() { + return type; + } + +} diff --git a/src/main/java/com/newyetai/component/chat/constant/ChatStatusEnum.java b/src/main/java/com/newyetai/component/chat/constant/ChatStatusEnum.java new file mode 100644 index 0000000..7e87b61 --- /dev/null +++ b/src/main/java/com/newyetai/component/chat/constant/ChatStatusEnum.java @@ -0,0 +1,25 @@ +package com.newyetai.component.chat.constant; + +import com.google.common.collect.Maps; +import java.util.Map; + +public enum ChatStatusEnum { + + /** 有效 **/ + ACTIVE(1), + /** 关闭 **/ + CLOSED(2), + ; + + private Integer status; + + ChatStatusEnum(Integer status) { + this.status = status; + } + + public Integer getStatus() { + return status; + } + + +} diff --git a/src/main/java/com/newyetai/component/chat/constant/ChatTypeEnum.java b/src/main/java/com/newyetai/component/chat/constant/ChatTypeEnum.java new file mode 100644 index 0000000..16b4090 --- /dev/null +++ b/src/main/java/com/newyetai/component/chat/constant/ChatTypeEnum.java @@ -0,0 +1,19 @@ +package com.newyetai.component.chat.constant; + +public enum ChatTypeEnum { + + /** 岗位 */ + POSITION("position"), + ; + + private String type; + + ChatTypeEnum(String type) { + this.type = type; + } + + public String getType() { + return type; + } + +} diff --git a/src/main/java/com/newyetai/component/chat/controller/ChatController.java b/src/main/java/com/newyetai/component/chat/controller/ChatController.java new file mode 100644 index 0000000..573a7e1 --- /dev/null +++ b/src/main/java/com/newyetai/component/chat/controller/ChatController.java @@ -0,0 +1,82 @@ +package com.newyetai.component.chat.controller; + +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.usercenter.user.constant.UserTypeEnum; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.PathVariable; + +import com.newyetai.common.validation.Update; +import com.newyetai.common.AlitaResult; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.component.chat.dto.ChatQueryDTO; +import com.newyetai.component.chat.service.ChatService; +import com.newyetai.component.chat.dto.ChatDTO; +import com.newyetai.component.chat.dto.ChatCreateDTO; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +/** + * @author sr on 2025-05-29 + */ +@RestController +@RequestMapping("chat") +@Api(tags = "聊天会话") +public class ChatController { + + @Autowired + private ChatService chatService; + + @PostMapping("/create") + @ApiOperation("创建") + public AlitaResult create( + @Validated @RequestBody ChatCreateDTO chatOperateDTO){ + return AlitaResult.success(chatService.create(chatOperateDTO)); + } + +/* @PutMapping("/modify") + @ApiOperation("修改") + public AlitaResult modify( + @Validated(Update.class) @RequestBody ChatCreateDTO chatOperateDTO){ + chatService.modify(chatOperateDTO); + return AlitaResult.success(true); + }*/ + + @DeleteMapping("/remove/{id}") + @ApiOperation("删除") + public AlitaResult remove(@PathVariable Long id){ + chatService.remove(id); + return AlitaResult.success(true); + } + + @GetMapping("/page") + @ApiOperation("分页查询") + public AlitaResult> page(ChatQueryDTO chatQueryDTO){ + chatService.page(chatQueryDTO); + return AlitaResult.success(chatQueryDTO.getPageResult()); + } + + @GetMapping("/page_curr") + @ApiOperation("分页查询") + public AlitaResult> pageCurr(ChatQueryDTO chatQueryDTO){ + Long orgId = UserContextHolder.getLoginOrgId(); + chatQueryDTO.setOrgId(orgId); + Long userId = UserContextHolder.getLoginUserId(); + if (UserTypeEnum.PERSON.getType().equals(UserContextHolder.getUserType())){ + chatQueryDTO.setPersonUserId(userId); + } else { + chatQueryDTO.setOrgUserId(userId); + } + chatService.page(chatQueryDTO); + return AlitaResult.success(chatQueryDTO.getPageResult()); + } + +} diff --git a/src/main/java/com/newyetai/component/chat/dao/ChatMapper.java b/src/main/java/com/newyetai/component/chat/dao/ChatMapper.java new file mode 100644 index 0000000..3ae312f --- /dev/null +++ b/src/main/java/com/newyetai/component/chat/dao/ChatMapper.java @@ -0,0 +1,28 @@ +package com.newyetai.component.chat.dao; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.newyetai.component.chat.dto.ChatDTO; +import com.newyetai.component.chat.dto.ChatQueryDTO; +import com.newyetai.component.chat.entity.Chat; +import com.newyetai.tkmybatis.mybatis.MyMapper; + +/** + * 聊天会话 + * + * @author sr on 2025-05-29 + */ +public interface ChatMapper extends MyMapper { + + /** + * 查询 + * + * @param chatQueryDTO + * @return + * @author sr on 2025-05-29 + */ + List listChatDTO(@Param("param") ChatQueryDTO chatQueryDTO); + +} diff --git a/src/main/java/com/newyetai/component/chat/dao/ChatMsgMapper.java b/src/main/java/com/newyetai/component/chat/dao/ChatMsgMapper.java new file mode 100644 index 0000000..649a9d6 --- /dev/null +++ b/src/main/java/com/newyetai/component/chat/dao/ChatMsgMapper.java @@ -0,0 +1,28 @@ +package com.newyetai.component.chat.dao; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.newyetai.component.chat.dto.ChatMsgDTO; +import com.newyetai.component.chat.dto.ChatMsgQueryDTO; +import com.newyetai.component.chat.entity.ChatMsg; +import com.newyetai.tkmybatis.mybatis.MyMapper; + +/** + * 聊天消息 + * + * @author sr on 2025-05-29 + */ +public interface ChatMsgMapper extends MyMapper { + + /** + * 查询 + * + * @param chatMsgQueryDTO + * @return + * @author sr on 2025-05-29 + */ + List listChatMsgDTO(@Param("param") ChatMsgQueryDTO chatMsgQueryDTO); + +} diff --git a/src/main/java/com/newyetai/component/chat/dto/ChatCreateDTO.java b/src/main/java/com/newyetai/component/chat/dto/ChatCreateDTO.java new file mode 100644 index 0000000..e390e95 --- /dev/null +++ b/src/main/java/com/newyetai/component/chat/dto/ChatCreateDTO.java @@ -0,0 +1,37 @@ +package com.newyetai.component.chat.dto; + +import com.newyetai.component.chat.constant.ChatTypeEnum; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Builder.Default; +import lombok.Data; +import lombok.NoArgsConstructor; +import io.swagger.annotations.ApiModel; +import javax.validation.constraints.NotNull; +import com.newyetai.common.validation.Update; + +import com.newyetai.common.dto.BaseOperateDTO; + +/** + * @author sr on 2025-05-29 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "聊天会话操作") +public class ChatCreateDTO extends BaseOperateDTO { + + /** **/ + private static final long serialVersionUID = 1L; + + @NotNull(message = "机构id不能为空") + private Long orgId; + @NotNull(message = "个人用户id不能为空") + private Long personUserId; + /** @see ChatTypeEnum 类型 */ + @Default + private String type = ChatTypeEnum.POSITION.getType(); + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/chat/dto/ChatDTO.java b/src/main/java/com/newyetai/component/chat/dto/ChatDTO.java new file mode 100644 index 0000000..907fbe1 --- /dev/null +++ b/src/main/java/com/newyetai/component/chat/dto/ChatDTO.java @@ -0,0 +1,44 @@ +package com.newyetai.component.chat.dto; + +import com.newyetai.common.dto.BaseDTO; + +import com.newyetai.component.chat.constant.ChatTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2025-05-29 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Builder +@Data +@ApiModel(description = "聊天会话") +public class ChatDTO extends BaseDTO { + + /** **/ + private static final long serialVersionUID = 1L; + + /** 机构id */ + private Long orgId; + /** 机构用户id */ + private Long orgUserId; + /** 个人用户id */ + private Long personUserId; + /** @see ChatTypeEnum 类型 */ + private Integer type; + /** 状态:1有效,2关闭 */ + private Integer status; + + /** 机构名称 */ + private String orgName; + /** 个人用户名称*/ + private String personUserName; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/chat/dto/ChatMsgCreateDTO.java b/src/main/java/com/newyetai/component/chat/dto/ChatMsgCreateDTO.java new file mode 100644 index 0000000..b05a2a3 --- /dev/null +++ b/src/main/java/com/newyetai/component/chat/dto/ChatMsgCreateDTO.java @@ -0,0 +1,45 @@ +package com.newyetai.component.chat.dto; + +import com.newyetai.component.chat.constant.ChatMsgTypeEnum; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotEmpty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Builder.Default; +import lombok.Data; +import lombok.NoArgsConstructor; +import io.swagger.annotations.ApiModel; +import javax.validation.constraints.NotNull; +import com.newyetai.common.validation.Update; + +import com.newyetai.common.dto.BaseOperateDTO; + +/** + * @author sr on 2025-05-29 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "聊天消息操作") +public class ChatMsgCreateDTO extends BaseOperateDTO{ + + /** **/ + private static final long serialVersionUID = 1L; + + /** 聊天id */ + private Long chatId; + /** 机构id */ + private Long orgId; + /** 个人用户id */ + private Long personUserId; + /** --- 聊天id 或 orgId+personUserId 两者选其一不为空 --- */ + + /** 消息类型:text等 */ + @Default + private String msgType = ChatMsgTypeEnum.TEXT.getType(); + /** 内容 */ + @NotEmpty(message = "内容不能为空") + private String content; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/chat/dto/ChatMsgDTO.java b/src/main/java/com/newyetai/component/chat/dto/ChatMsgDTO.java new file mode 100644 index 0000000..b512ecb --- /dev/null +++ b/src/main/java/com/newyetai/component/chat/dto/ChatMsgDTO.java @@ -0,0 +1,42 @@ +package com.newyetai.component.chat.dto; + +import com.newyetai.common.dto.BaseDTO; + +import com.newyetai.component.chat.constant.ChatMsgStatusEnum; +import com.newyetai.component.chat.constant.ChatMsgTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Builder.Default; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2025-05-29 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Builder +@Data +@ApiModel(description = "聊天消息") +public class ChatMsgDTO extends BaseDTO { + + /** **/ + private static final long serialVersionUID = 1L; + /** 聊天id */ + private Long chatId; + /** 发送用户id */ + private Long senderId; + /** 消息类型:text等 */ + @Default + private String msgType = ChatMsgTypeEnum.TEXT.getType(); + /** 内容 */ + private String content; + /** 消息状态:1未读,2已读 */ + @Default + private Integer msgStatus = ChatMsgStatusEnum.INIT.getStatus(); + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/chat/dto/ChatMsgQueryDTO.java b/src/main/java/com/newyetai/component/chat/dto/ChatMsgQueryDTO.java new file mode 100644 index 0000000..7137e04 --- /dev/null +++ b/src/main/java/com/newyetai/component/chat/dto/ChatMsgQueryDTO.java @@ -0,0 +1,28 @@ +package com.newyetai.component.chat.dto; + + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import io.swagger.annotations.ApiModel; + +import com.newyetai.common.dto.PageQueryDTO; + +/** + * @author sr on 2025-05-29 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "聊天消息查询条件") +public class ChatMsgQueryDTO extends PageQueryDTO{ + + /** **/ + private static final long serialVersionUID = 1L; + + private Long chatId; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/chat/dto/ChatQueryDTO.java b/src/main/java/com/newyetai/component/chat/dto/ChatQueryDTO.java new file mode 100644 index 0000000..595a5df --- /dev/null +++ b/src/main/java/com/newyetai/component/chat/dto/ChatQueryDTO.java @@ -0,0 +1,43 @@ +package com.newyetai.component.chat.dto; + + +import com.newyetai.component.chat.constant.ChatTypeEnum; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Builder.Default; +import lombok.Data; +import lombok.NoArgsConstructor; +import io.swagger.annotations.ApiModel; + +import com.newyetai.common.dto.PageQueryDTO; + +/** + * @author sr on 2025-05-29 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "聊天会话查询条件") +public class ChatQueryDTO extends PageQueryDTO{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + /** 机构id */ + private Long orgId; + /** 机构用户id */ + private Long orgUserId; + /** 个人用户id */ + private Long personUserId; + /** 状态:1有效,2关闭 */ + private Integer status; + /** @see ChatTypeEnum 类型 */ + @Default + private String type = ChatTypeEnum.POSITION.getType(); + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/chat/entity/Chat.java b/src/main/java/com/newyetai/component/chat/entity/Chat.java new file mode 100644 index 0000000..8c503d7 --- /dev/null +++ b/src/main/java/com/newyetai/component/chat/entity/Chat.java @@ -0,0 +1,41 @@ +package com.newyetai.component.chat.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import com.newyetai.component.chat.constant.ChatTypeEnum; +import lombok.AllArgsConstructor; +import lombok.experimental.SuperBuilder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * 聊天会话 + * + * @author sr on 2025-05-29 + */ +@TableName("xs_chat") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +public class Chat extends BaseEntity { + + /** **/ + private static final long serialVersionUID = 1L; + /** 机构id */ + private Long orgId; + /** 机构用户id */ + private Long orgUserId; + /** 个人用户id */ + private Long personUserId; + /** @see ChatTypeEnum 类型 */ + private String type; + /** 状态:1有效,2关闭 */ + private Integer status; + + + +} diff --git a/src/main/java/com/newyetai/component/chat/entity/ChatMsg.java b/src/main/java/com/newyetai/component/chat/entity/ChatMsg.java new file mode 100644 index 0000000..bf6158c --- /dev/null +++ b/src/main/java/com/newyetai/component/chat/entity/ChatMsg.java @@ -0,0 +1,44 @@ +package com.newyetai.component.chat.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.component.chat.constant.ChatMsgStatusEnum; +import com.newyetai.component.chat.constant.ChatMsgTypeEnum; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Builder.Default; +import lombok.experimental.SuperBuilder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * 聊天消息 + * + * @author sr on 2025-05-29 + */ +@TableName("xs_chat_msg") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +public class ChatMsg extends BaseEntity { + + /** **/ + private static final long serialVersionUID = 1L; + + /** 聊天id */ + private Long chatId; + /** 发送用户id */ + private Long senderId; + /** 消息类型:text等 */ + @Default + private String msgType = ChatMsgTypeEnum.TEXT.getType(); + /** 内容 */ + private String content; + /** 消息状态:1未读,2已读 */ + @Default + private Integer msgStatus = ChatMsgStatusEnum.INIT.getStatus(); + +} diff --git a/src/main/java/com/newyetai/component/chat/mapper/ChatMapper.xml b/src/main/java/com/newyetai/component/chat/mapper/ChatMapper.xml new file mode 100644 index 0000000..ffca195 --- /dev/null +++ b/src/main/java/com/newyetai/component/chat/mapper/ChatMapper.xml @@ -0,0 +1,30 @@ + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/chat/mapper/ChatMsgMapper.xml b/src/main/java/com/newyetai/component/chat/mapper/ChatMsgMapper.xml new file mode 100644 index 0000000..20b6044 --- /dev/null +++ b/src/main/java/com/newyetai/component/chat/mapper/ChatMsgMapper.xml @@ -0,0 +1,20 @@ + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/chat/mapstruct/ChatMapMapper.java b/src/main/java/com/newyetai/component/chat/mapstruct/ChatMapMapper.java new file mode 100644 index 0000000..23f780b --- /dev/null +++ b/src/main/java/com/newyetai/component/chat/mapstruct/ChatMapMapper.java @@ -0,0 +1,37 @@ +package com.newyetai.component.chat.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.newyetai.component.chat.dto.ChatDTO; +import com.newyetai.component.chat.entity.Chat; +import com.newyetai.component.chat.dto.ChatCreateDTO; + +/** + * @author sr on 2025-05-29 + */ +@Mapper +public interface ChatMapMapper { + + ChatMapMapper INSTANCE = + Mappers.getMapper(ChatMapMapper.class); + + /** + * dto to entity + * + * @param chatDto + * @return + * @author sr on 2025-05-29 + */ + Chat toEntity( + ChatDTO chatDto); + + + /** + * @param chatOperateDTO + * @return + * @author sr on 2025-05-29 + */ + Chat toEntity(ChatCreateDTO chatOperateDTO); + +} diff --git a/src/main/java/com/newyetai/component/chat/mapstruct/ChatMsgMapMapper.java b/src/main/java/com/newyetai/component/chat/mapstruct/ChatMsgMapMapper.java new file mode 100644 index 0000000..b654eaa --- /dev/null +++ b/src/main/java/com/newyetai/component/chat/mapstruct/ChatMsgMapMapper.java @@ -0,0 +1,39 @@ +package com.newyetai.component.chat.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.newyetai.component.chat.dto.ChatMsgDTO; +import com.newyetai.component.chat.entity.ChatMsg; +import com.newyetai.component.chat.dto.ChatMsgCreateDTO; + +/** + * @author sr on 2025-05-29 + */ +@Mapper +public interface ChatMsgMapMapper { + + ChatMsgMapMapper INSTANCE = + Mappers.getMapper(ChatMsgMapMapper.class); + + /** + * dto to entity + * + * @param chatMsgDto + * @return + * @author sr on 2025-05-29 + */ + ChatMsg toEntity( + ChatMsgDTO chatMsgDto); + + + /** + * @param chatMsgCreateDTO + * @return + * @author sr on 2025-05-29 + */ + ChatMsg toEntity(ChatMsgCreateDTO chatMsgCreateDTO); + + ChatMsgDTO toDto(ChatMsg chatMsg); + +} diff --git a/src/main/java/com/newyetai/component/chat/service/ChatMsgService.java b/src/main/java/com/newyetai/component/chat/service/ChatMsgService.java new file mode 100644 index 0000000..3f7f684 --- /dev/null +++ b/src/main/java/com/newyetai/component/chat/service/ChatMsgService.java @@ -0,0 +1,68 @@ +package com.newyetai.component.chat.service; + +import java.util.List; + +import com.newyetai.component.chat.dto.ChatMsgQueryDTO; +import com.newyetai.component.chat.dto.ChatMsgCreateDTO; +import com.newyetai.component.chat.dto.ChatMsgDTO; + +/** + * 聊天消息 + * + * @author sr on 2025-05-29 + */ +public interface ChatMsgService { + + /** + * 新增 + * + * @param chatMsgCreateDTO + * @return + * @author sr on 2025-05-29 + */ + Long create(ChatMsgCreateDTO chatMsgCreateDTO); + + /** + * 修改 + * + * @param chatMsgCreateDTO + * @author sr on 2025-05-29 + */ + void modify(ChatMsgCreateDTO chatMsgCreateDTO); + + /** + * 删除 + * + * @param id + * @author sr on 2025-05-29 + */ + void remove(Long id); + + /** + * 查询 + * + * @param chatMsgQueryDTO + * @return + * @author sr on 2025-05-29 + */ + List list(ChatMsgQueryDTO chatMsgQueryDTO); + + /** + * 分页查询 + * + * @param chatMsgQueryDTO + * @return + * @author sr on 2025-05-29 + */ + void page(ChatMsgQueryDTO chatMsgQueryDTO); + + /** + * 单个查询 + * + * @param chatMsgQueryDTO + * @return + * @author sr on 2025-05-29 + */ + ChatMsgDTO find(ChatMsgQueryDTO chatMsgQueryDTO); + +} diff --git a/src/main/java/com/newyetai/component/chat/service/ChatService.java b/src/main/java/com/newyetai/component/chat/service/ChatService.java new file mode 100644 index 0000000..cae2b79 --- /dev/null +++ b/src/main/java/com/newyetai/component/chat/service/ChatService.java @@ -0,0 +1,61 @@ +package com.newyetai.component.chat.service; + +import java.util.List; + +import com.newyetai.component.chat.dto.ChatQueryDTO; +import com.newyetai.component.chat.dto.ChatCreateDTO; +import com.newyetai.component.chat.dto.ChatDTO; + +/** + * 聊天会话 + * + * @author sr on 2025-05-29 + */ +public interface ChatService { + + /** + * 新增 + * + * @param chatCreateDTO + * @return + * @author sr on 2025-05-29 + */ + Long create(ChatCreateDTO chatCreateDTO); + + + /** + * 删除 + * + * @param id + * @author sr on 2025-05-29 + */ + void remove(Long id); + + /** + * 查询 + * + * @param chatQueryDTO + * @return + * @author sr on 2025-05-29 + */ + List list(ChatQueryDTO chatQueryDTO); + + /** + * 分页查询 + * + * @param chatQueryDTO + * @return + * @author sr on 2025-05-29 + */ + void page(ChatQueryDTO chatQueryDTO); + + /** + * 单个查询 + * + * @param chatQueryDTO + * @return + * @author sr on 2025-05-29 + */ + ChatDTO find(ChatQueryDTO chatQueryDTO); + +} diff --git a/src/main/java/com/newyetai/component/chat/service/impl/ChatMsgServiceImpl.java b/src/main/java/com/newyetai/component/chat/service/impl/ChatMsgServiceImpl.java new file mode 100644 index 0000000..c5220f4 --- /dev/null +++ b/src/main/java/com/newyetai/component/chat/service/impl/ChatMsgServiceImpl.java @@ -0,0 +1,108 @@ +package com.newyetai.component.chat.service.impl; + +import com.newyetai.component.chat.dto.ChatCreateDTO; +import com.newyetai.component.chat.dto.ChatDTO; +import com.newyetai.component.chat.dto.ChatQueryDTO; +import com.newyetai.component.chat.mapstruct.ChatMsgMapMapper; +import com.newyetai.component.chat.service.ChatService; +import com.newyetai.component.notice.constant.NoticeFirstTypeEnum; +import com.newyetai.component.notice.dto.NoticeMsgDTO; +import com.newyetai.component.notice.util.NoticeUtils; +import com.newyetai.usercenter.user.constant.UserTypeEnum; +import com.newyetai.usercenter.websocket.service.impl.WebsocketNoticeSendProvider; +import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.component.chat.dao.ChatMsgMapper; +import com.newyetai.component.chat.service.ChatMsgService; +import com.newyetai.component.chat.dto.ChatMsgQueryDTO; +import com.newyetai.component.chat.dto.ChatMsgDTO; +import com.newyetai.component.chat.dto.ChatMsgCreateDTO; +import com.newyetai.component.chat.entity.ChatMsg; + +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.common.util.ListUtil; + +/** + * @author sr on 2025-05-29 + */ +@Service +public class ChatMsgServiceImpl implements ChatMsgService { + + private static final Logger log = LoggerFactory.getLogger(ChatMsgServiceImpl.class); + @Autowired + private ChatMsgMapper chatMsgMapper; + + @Autowired + private ChatService chatService; + + @Override + @Transactional + public Long create(ChatMsgCreateDTO chatMsgCreateDTO) { + Long chatId = chatMsgCreateDTO.getChatId(); + Long senderId = UserContextHolder.getLoginUserId(); + Long personUserId = chatMsgCreateDTO.getPersonUserId(); + if (UserTypeEnum.PERSON.getType().equals(UserContextHolder.getUserType())){ + personUserId = senderId; + } + if (chatId == null) { + chatId = chatService.create(ChatCreateDTO.builder().orgId(chatMsgCreateDTO.getOrgId()) + .personUserId(personUserId).build()); + } + ChatMsg msg = ChatMsg.builder().chatId(chatId).senderId(senderId).content(chatMsgCreateDTO.getContent()).build(); + chatMsgMapper.saveEntity(msg); + // 发通知 + this.sendAsyncNotice(chatId, ChatMsgMapMapper.INSTANCE.toDto(msg)); + return msg.getId(); + } + + private void sendAsyncNotice(Long chatId, ChatMsgDTO msgDTO) { + try { + ChatDTO chatDTO = chatService.find(ChatQueryDTO.builder().id(chatId).build()); + Long receiverId = + msgDTO.getSenderId().equals(chatDTO.getPersonUserId()) ? chatDTO.getOrgUserId() + : chatDTO.getPersonUserId(); + NoticeUtils.sendAsyncNotice( + NoticeMsgDTO.create(receiverId, NoticeFirstTypeEnum.CHAT.getType(), msgDTO)); + } catch (Exception e) { + log.info("chat发送异步消息失败", e.getMessage()); + } + } + + + @Override + @Transactional + public void modify(ChatMsgCreateDTO chatMsgCreateDTO) { + // TODO Auto-generated method stub + + } + + @Override + @Transactional + public void remove(Long id) { + chatMsgMapper.deleteEntity(ChatMsg.builder().id(id).build(), + UserContextHolder.getLoginUserId()); + } + + @Override + public List list(ChatMsgQueryDTO chatMsgQueryDTO) { + chatMsgQueryDTO.disablePage(); + return chatMsgMapper.listChatMsgDTO(chatMsgQueryDTO); + } + + @Override + public void page(ChatMsgQueryDTO chatMsgQueryDTO) { + chatMsgMapper.listChatMsgDTO(chatMsgQueryDTO); + } + + @Override + public ChatMsgDTO find(ChatMsgQueryDTO chatMsgQueryDTO) { + List chatMsgDTOs = this.list(chatMsgQueryDTO); + return ListUtil.first(chatMsgDTOs); + } + +} diff --git a/src/main/java/com/newyetai/component/chat/service/impl/ChatServiceImpl.java b/src/main/java/com/newyetai/component/chat/service/impl/ChatServiceImpl.java new file mode 100644 index 0000000..a32d11e --- /dev/null +++ b/src/main/java/com/newyetai/component/chat/service/impl/ChatServiceImpl.java @@ -0,0 +1,99 @@ +package com.newyetai.component.chat.service.impl; + +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.common.validation.util.ValidateUtils; +import com.newyetai.component.chat.constant.ChatStatusEnum; +import com.newyetai.component.chat.mapstruct.ChatMapMapper; +import com.newyetai.component.dynamictable.entity.DynamicTable; +import com.newyetai.component.dynamictable.mapstruct.DynamicTableMapMapper; +import com.newyetai.frame.redis.dto.LockDTO; +import com.newyetai.frame.redis.redisson.RedissonUtils; +import com.newyetai.usercenter.user.dao.OrgUserMapper; +import com.newyetai.usercenter.user.dto.OrgUserDTO; +import com.newyetai.usercenter.user.dto.OrgUserQueryDTO; +import java.util.List; +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.component.chat.dao.ChatMapper; +import com.newyetai.component.chat.service.ChatService; +import com.newyetai.component.chat.dto.ChatQueryDTO; +import com.newyetai.component.chat.dto.ChatDTO; +import com.newyetai.component.chat.dto.ChatCreateDTO; +import com.newyetai.component.chat.entity.Chat; + +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.common.util.ListUtil; + +/** + * @author sr on 2025-05-29 + */ +@Service +public class ChatServiceImpl implements ChatService { + + @Autowired + private ChatMapper chatMapper; + + @Autowired + private OrgUserMapper orgUserMapper; + + public static LockDTO getLockDTO(Long orgId, Long personUserId) { + Assert.notNull(orgId, "机构id不能为空"); + Assert.notNull(personUserId, "个人用户id不能为空"); + return LockDTO.builder().methodName("chat").tryLockWaitTime(0L) + .arg(orgId.toString()) + .arg(personUserId.toString()) + .failMsg("该机构-个人聊天正在被操作") + .build(); + } + + @Override + @Transactional + public Long create(ChatCreateDTO createDTO) { + ValidateUtils.validateBiz(createDTO); + Long orgId = createDTO.getOrgId(); + Long personUserId = createDTO.getPersonUserId(); + ChatQueryDTO queryDTO = ChatQueryDTO.builder().orgId(orgId).personUserId(personUserId).status( + ChatStatusEnum.ACTIVE.getStatus()).build(); + + return RedissonUtils.lockAndSave(getLockDTO(orgId, personUserId), + () -> this.find(queryDTO), () -> { + List orgUserDTOs = orgUserMapper.listOrgUserDTO( + OrgUserQueryDTO.builder().orgId(orgId).administrator(Boolean.TRUE).build()); + Assert.isTrue(orgUserDTOs.size() == 1, orgId + ":机构管理员信息异常,请联系管理员"); + Chat chat = + ChatMapMapper.INSTANCE.toEntity(createDTO); + chat.setOrgUserId(orgUserDTOs.get(0).getUserId()); + chatMapper.saveEntity(chat); + return chat.getId(); + }); + } + + @Override + @Transactional + public void remove(Long id) { + chatMapper.deleteEntity(Chat.builder().id(id).build(), + UserContextHolder.getLoginUserId()); + } + + @Override + public List list(ChatQueryDTO chatQueryDTO) { + chatQueryDTO.disablePage(); + return chatMapper.listChatDTO(chatQueryDTO); + } + + @Override + public void page(ChatQueryDTO chatQueryDTO) { + chatMapper.listChatDTO(chatQueryDTO); + } + + @Override + public ChatDTO find(ChatQueryDTO chatQueryDTO) { + List chatDTOs = this.list(chatQueryDTO); + return ListUtil.first(chatDTOs); + } + +} diff --git a/src/main/java/com/newyetai/component/chat/util/ChatMsgUtils.java b/src/main/java/com/newyetai/component/chat/util/ChatMsgUtils.java new file mode 100644 index 0000000..a282f1c --- /dev/null +++ b/src/main/java/com/newyetai/component/chat/util/ChatMsgUtils.java @@ -0,0 +1,8 @@ +package com.newyetai.component.chat.util; + +/** + * @author sr on 2025-05-29 + */ +public class ChatMsgUtils { + +} diff --git a/src/main/java/com/newyetai/component/chat/util/ChatUtils.java b/src/main/java/com/newyetai/component/chat/util/ChatUtils.java new file mode 100644 index 0000000..2fa0145 --- /dev/null +++ b/src/main/java/com/newyetai/component/chat/util/ChatUtils.java @@ -0,0 +1,8 @@ +package com.newyetai.component.chat.util; + +/** + * @author sr on 2025-05-29 + */ +public class ChatUtils { + +} diff --git a/src/main/java/com/newyetai/component/commonimport/constant/ImportDetailStatusEnum.java b/src/main/java/com/newyetai/component/commonimport/constant/ImportDetailStatusEnum.java new file mode 100644 index 0000000..554ba19 --- /dev/null +++ b/src/main/java/com/newyetai/component/commonimport/constant/ImportDetailStatusEnum.java @@ -0,0 +1,29 @@ +package com.newyetai.component.commonimport.constant; + +/** + * 通用导入明细状态 + * @author sr on 2024-01-19 + */ +public enum ImportDetailStatusEnum { + /** 新建 **/ + INIT(1), + /** 校验成功 **/ + CHECK_SUCCESS(2), + /** 校验失败 **/ + CHECK_FAIL(3), + ; + + + + private Integer status; + + ImportDetailStatusEnum(Integer status) { + this.status = status; + } + + public Integer getStatus() { + return status; + } + + +} diff --git a/src/main/java/com/newyetai/component/commonimport/constant/ImportExecuteTypeEnum.java b/src/main/java/com/newyetai/component/commonimport/constant/ImportExecuteTypeEnum.java new file mode 100644 index 0000000..6584b47 --- /dev/null +++ b/src/main/java/com/newyetai/component/commonimport/constant/ImportExecuteTypeEnum.java @@ -0,0 +1,28 @@ +package com.newyetai.component.commonimport.constant; + +/** + * 指定执行类型 + * @author sr on 2024-01-23 + */ +public enum ImportExecuteTypeEnum { + /** 普通 **/ + NORMAL(1), + /** 指定外部id **/ + EXTRA_ID(2), + /** 明细表单 **/ + DETAIL_FORM(3), + ; + + + + + private Integer type; + + ImportExecuteTypeEnum(Integer type) { + this.type = type; + } + + public Integer getType() { + return type; + } +} diff --git a/src/main/java/com/newyetai/component/commonimport/constant/ImportStatusEnum.java b/src/main/java/com/newyetai/component/commonimport/constant/ImportStatusEnum.java new file mode 100644 index 0000000..bb747f5 --- /dev/null +++ b/src/main/java/com/newyetai/component/commonimport/constant/ImportStatusEnum.java @@ -0,0 +1,58 @@ +package com.newyetai.component.commonimport.constant; + +import java.util.Map; + +import com.google.common.collect.Maps; + +/** + * 通用导入状态 + * @author sr on 2024-01-19 + */ +public enum ImportStatusEnum { + + /** 新建 **/ + INIT(1, "新建"), + /** 解析失败 **/ + ANALY_FAIL(2, "解析失败"), + /** 校验中 **/ + CHECKING(3, "校验中"), + /** 校验失败 **/ + CHECK_FAIL(4, "校验失败"), + /** 校验完成 **/ + CHECKED(5, "校验完成"), + /** 执行导入完成 **/ + EXECUTE(6, "已完成"), + ; + + + private static Map importStatusMap ; + static { + ImportStatusEnum[] importStatusEnums = ImportStatusEnum.values(); + importStatusMap = Maps.newHashMapWithExpectedSize(importStatusEnums.length); + for(ImportStatusEnum e: importStatusEnums) { + importStatusMap.put(e.getStatus(), e); + } + } + + private Integer status; + private String name; + + ImportStatusEnum(Integer status, String name) { + this.status = status; + } + + public Integer getStatus() { + return status; + } + + public String getName() { + return name; + } + + public static ImportStatusEnum get(Integer status) { + return importStatusMap.get(status); + } + + + +} diff --git a/src/main/java/com/newyetai/component/commonimport/constant/ImportTypeEnum.java b/src/main/java/com/newyetai/component/commonimport/constant/ImportTypeEnum.java new file mode 100644 index 0000000..0dd6009 --- /dev/null +++ b/src/main/java/com/newyetai/component/commonimport/constant/ImportTypeEnum.java @@ -0,0 +1,50 @@ +package com.newyetai.component.commonimport.constant; + +import java.util.Map; + +import com.google.common.collect.Maps; + +/** + * 导入类型 + * @author sr on 2024-01-23 + */ +public enum ImportTypeEnum { + + TALENT("talent", "人才库导入"), + POSITION("position", "岗位导入"), + ADMIN_POSITION("admin_position", "admin岗位导入"), + ORG("org", "机构导入"), + ; + + private String type; + private String name; + + + private static Map importTypeMap ; + static { + ImportTypeEnum[] importTypeEnums = ImportTypeEnum.values(); + importTypeMap = Maps.newHashMapWithExpectedSize(importTypeEnums.length); + for(ImportTypeEnum e: importTypeEnums) { + importTypeMap.put(e.getType(), e); + } + } + + ImportTypeEnum(String type, String name) { + this.type = type; + this.name = name; + } + + public String getType() { + return type; + } + + public String getName() { + return name; + } + + public static ImportTypeEnum get(String type) { + return importTypeMap.get(type); + } + + +} diff --git a/src/main/java/com/newyetai/component/commonimport/controller/CommonImportController.java b/src/main/java/com/newyetai/component/commonimport/controller/CommonImportController.java new file mode 100644 index 0000000..17fe6ff --- /dev/null +++ b/src/main/java/com/newyetai/component/commonimport/controller/CommonImportController.java @@ -0,0 +1,109 @@ +package com.newyetai.component.commonimport.controller; + +import java.util.List; +import java.util.Map; + +import org.apache.poi.ss.formula.functions.T; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.component.commonimport.dto.ImportDetailPageDTO; +import com.newyetai.component.commonimport.dto.ImportMainCreateDTO; +import com.newyetai.component.commonimport.dto.ImportMainCreateFormDTO; +import com.newyetai.component.commonimport.dto.ImportMainDTO; +import com.newyetai.component.commonimport.dto.ImportMainQueryDTO; +import com.newyetai.component.commonimport.service.impl.CommonImportAdapter; +import com.newyetai.config.dto.ConfigDTO; +import com.newyetai.tkmybatis.pojo.Page; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +/** + * @author sr on 2024-01-19 + */ +@RestController +@RequestMapping("common_import") +@Api(tags = "通用导入") +public class CommonImportController { + + @Autowired(required = false) + private CommonImportAdapter commonImportAdapter; + + @GetMapping("/template/{type}") + @ApiOperation("模版") + public AlitaResult template(@PathVariable String type){ + Assert.notNull(commonImportAdapter, "无通用导入提供者"); + return AlitaResult.success(commonImportAdapter.template(type)); + } + + @GetMapping("/page") + @ApiOperation("分页查询") + public AlitaResult> page(ImportMainQueryDTO queryDTO){ + Assert.notNull(commonImportAdapter, "无通用导入提供者"); + commonImportAdapter.page(queryDTO); + return AlitaResult.success(queryDTO.getPageResult()); + } + + @GetMapping("/find") + @ApiOperation("单个查询") + public AlitaResult find(ImportMainQueryDTO queryDTO){ + Assert.notNull(commonImportAdapter, "无通用导入提供者"); + return AlitaResult.success(commonImportAdapter.find(queryDTO)); + } + + @PostMapping("/create") + @ApiOperation("创建") + public AlitaResult create( + @Validated @RequestBody ImportMainCreateDTO createDTO){ + Assert.notNull(commonImportAdapter, "无通用导入提供者"); + return AlitaResult.success(commonImportAdapter.create(createDTO)); + } + + @PostMapping("/create_async") + @ApiOperation("创建(异步)") + public AlitaResult createAsync( + @Validated @RequestBody ImportMainCreateDTO createDTO){ + Assert.notNull(commonImportAdapter, "无通用导入提供者"); + return AlitaResult.success(commonImportAdapter.createAsync(createDTO)); + } + + @PostMapping("/create_form") + @ApiOperation("创建(明细form)") + public AlitaResult createForm( + @Validated @RequestBody ImportMainCreateFormDTO createDTO){ + Assert.notNull(commonImportAdapter, "无通用导入提供者"); + return AlitaResult.success(commonImportAdapter.createForm(createDTO)); + } + + @PostMapping("/confirm/{type}") + @ApiOperation("执行导入") + public AlitaResult confirm(@PathVariable String type, + @RequestBody Map executeDto){ + Assert.notNull(commonImportAdapter, "无通用导入提供者"); + return AlitaResult.success(commonImportAdapter.confirmImport(type, executeDto)); + } + + @GetMapping("/pageDetail") + @ApiOperation("导入明细分页") + public AlitaResult> pageDetail(@Validated ImportDetailPageDTO importDetailPageDTO) { + Assert.notNull(commonImportAdapter, "无通用导入提供者"); + return AlitaResult.success(commonImportAdapter.pageDetail(importDetailPageDTO)); + } + + @GetMapping("/importDetailExport") + @ApiOperation("导入明细分页") + public void importDetailExport(@Validated ImportDetailPageDTO importDetailPageDTO) { + Assert.notNull(commonImportAdapter, "无通用导入提供者"); + commonImportAdapter.importDetailExport(importDetailPageDTO); + } +} diff --git a/src/main/java/com/newyetai/component/commonimport/dao/ImportMainMapper.java b/src/main/java/com/newyetai/component/commonimport/dao/ImportMainMapper.java new file mode 100644 index 0000000..d36d481 --- /dev/null +++ b/src/main/java/com/newyetai/component/commonimport/dao/ImportMainMapper.java @@ -0,0 +1,31 @@ +package com.newyetai.component.commonimport.dao; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.newyetai.component.commonimport.dto.ImportMainDTO; +import com.newyetai.component.commonimport.dto.ImportMainQueryDTO; +import com.newyetai.component.commonimport.dto.ImportMainUpdateDTO; +import com.newyetai.component.commonimport.entity.UcImportMain; +import com.newyetai.tkmybatis.mybatis.MyMapper; + +/** + * 通用导入 + * + * @author sr on 2024-01-19 + */ +public interface ImportMainMapper extends MyMapper { + + /** + * 查询 + * + * @param importMainQueryDTO + * @return + * @author sr on 2024-01-19 + */ + List listImportMainDTO(@Param("param") ImportMainQueryDTO importMainQueryDTO); + + int modify(@Param("param") ImportMainUpdateDTO updateDto); + +} diff --git a/src/main/java/com/newyetai/component/commonimport/dto/ImportDetailPageDTO.java b/src/main/java/com/newyetai/component/commonimport/dto/ImportDetailPageDTO.java new file mode 100644 index 0000000..b5454d4 --- /dev/null +++ b/src/main/java/com/newyetai/component/commonimport/dto/ImportDetailPageDTO.java @@ -0,0 +1,36 @@ +package com.newyetai.component.commonimport.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotNull; + +import lombok.Data; + +/** + * @description: + * @author: guixinman + * @create: 2024-01-30 14:04 + **/ +@Data +public class ImportDetailPageDTO implements Serializable { + + @NotNull(message = "参数异常") + private Long mainId; + + @NotNull(message = "参数异常") + private String type; + + /** + * 第几页 + **/ + private Integer pageNo = 1; + /** + * 页宽 + **/ + private Integer pageSize = 20; + + /** 导入状态:1新建,2校验成功,3校验失败 **/ + private Integer detailStatus; +} + + diff --git a/src/main/java/com/newyetai/component/commonimport/dto/ImportDetailSuperDTO.java b/src/main/java/com/newyetai/component/commonimport/dto/ImportDetailSuperDTO.java new file mode 100644 index 0000000..57bcace --- /dev/null +++ b/src/main/java/com/newyetai/component/commonimport/dto/ImportDetailSuperDTO.java @@ -0,0 +1,43 @@ +package com.newyetai.component.commonimport.dto; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.component.action.dto.ActionDetailDTO; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2024-01-19 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@ApiModel(description = "通用导入") +public class ImportDetailSuperDTO extends BaseDTO { + + /** **/ + private static final long serialVersionUID = 1L; + + /** 批次id **/ + private Long mainId; + /** 导入状态:1新建,2校验成功,3校验失败 **/ + private Integer detailStatus; + /** 失败原因 **/ + private String failReason; + /** 备注 **/ + private String remark; + /** 外部生成明细id **/ + private Long extraDetailId; + + + + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/commonimport/dto/ImportExecuteSuperDTO.java b/src/main/java/com/newyetai/component/commonimport/dto/ImportExecuteSuperDTO.java new file mode 100644 index 0000000..9932812 --- /dev/null +++ b/src/main/java/com/newyetai/component/commonimport/dto/ImportExecuteSuperDTO.java @@ -0,0 +1,40 @@ +package com.newyetai.component.commonimport.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotNull; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2024-01-19 + */ +@NoArgsConstructor +@AllArgsConstructor +@Builder +@Data +@ApiModel(description = "通用导入执行") +public class ImportExecuteSuperDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + /** 批次id **/ + @NotNull(message = "导入id不能为空") + private Long mainId; + + + /**(后台设置)执行类型:1.普通,2.指定外部id **/ + private Integer executeType; + /**(后台设置)外部生成id(可为空) **/ + private Long extraId; + + + + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/commonimport/dto/ImportMainCreateDTO.java b/src/main/java/com/newyetai/component/commonimport/dto/ImportMainCreateDTO.java new file mode 100644 index 0000000..cb47580 --- /dev/null +++ b/src/main/java/com/newyetai/component/commonimport/dto/ImportMainCreateDTO.java @@ -0,0 +1,45 @@ +package com.newyetai.component.commonimport.dto; + +import javax.validation.constraints.NotBlank; + +import com.newyetai.common.dto.BaseOperateDTO; +import com.newyetai.component.commonimport.constant.ImportExecuteTypeEnum; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.Builder.Default; + +/** + * @author sr on 2024-01-19 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "通用导入操作") +public class ImportMainCreateDTO extends BaseOperateDTO{ + + /** **/ + private static final long serialVersionUID = 1L; + /** 导入类型 **/ + @NotBlank(message = "导入类型不能为空") + private String type; + /** 文件CODE **/ + @NotBlank(message = "文件code不能为空") + private String fileCode; + /** 文件名称 **/ + @NotBlank(message = "文件名称不能为空") + private String fileName; + /** 备注 **/ + private String remark; + /** 执行类型:1.普通,2.指定外部id **/ + @Default + private Integer executeType = ImportExecuteTypeEnum.NORMAL.getType(); + /** 外部生成id **/ + private Long extraId; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/commonimport/dto/ImportMainCreateFormDTO.java b/src/main/java/com/newyetai/component/commonimport/dto/ImportMainCreateFormDTO.java new file mode 100644 index 0000000..39be333 --- /dev/null +++ b/src/main/java/com/newyetai/component/commonimport/dto/ImportMainCreateFormDTO.java @@ -0,0 +1,39 @@ +package com.newyetai.component.commonimport.dto; + +import java.util.List; +import java.util.Map; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import com.newyetai.common.dto.BaseOperateDTO; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2024-01-19 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "通用导入操作(form)") +public class ImportMainCreateFormDTO extends BaseOperateDTO{ + + /** **/ + private static final long serialVersionUID = 1L; + /** 导入类型 **/ + @NotBlank(message = "导入类型不能为空") + private String type; + /** 备注 **/ + private String remark; + @NotNull(message = "明细不能为空") + private List> details; + + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/commonimport/dto/ImportMainDTO.java b/src/main/java/com/newyetai/component/commonimport/dto/ImportMainDTO.java new file mode 100644 index 0000000..382c157 --- /dev/null +++ b/src/main/java/com/newyetai/component/commonimport/dto/ImportMainDTO.java @@ -0,0 +1,59 @@ +package com.newyetai.component.commonimport.dto; + +import java.util.Date; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.newyetai.common.dto.BaseDTO; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2024-01-19 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@ApiModel(description = "通用导入") +public class ImportMainDTO extends BaseDTO { + + /** **/ + private static final long serialVersionUID = 1L; + + /** 批次号 **/ + private String importNo; + /** 导入类型 **/ + private String type; + /** 导入状态:1新建,2解析失败,3校验中,4校验失败,5校验成功,6执行导入完成 **/ + private Integer importStatus; + /** 总数 **/ + private Integer totalNum; + /** 成功数 **/ + private Integer successNum; + /** 失败原因 **/ + private String failMsg; + /** 完成时间时间 **/ + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date finishTime; + /** 执行类型:1.普通,2.指定外部id,3.明细表单 **/ + private Integer executeType; + /** 外部生成id **/ + private Long extraId; + /** 文件CODE **/ + private String fileCode; + /** 文件名称 **/ + private String fileName; + /** 机构ID **/ + private Long orgId; + /** 备注 **/ + private String remark; + + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/commonimport/dto/ImportMainQueryDTO.java b/src/main/java/com/newyetai/component/commonimport/dto/ImportMainQueryDTO.java new file mode 100644 index 0000000..c174f3f --- /dev/null +++ b/src/main/java/com/newyetai/component/commonimport/dto/ImportMainQueryDTO.java @@ -0,0 +1,64 @@ +package com.newyetai.component.commonimport.dto; + + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import io.swagger.annotations.ApiModel; + +import java.util.Date; + +import org.springframework.format.annotation.DateTimeFormat; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.newyetai.common.dto.PageQueryDTO; + +/** + * @author sr on 2024-01-19 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "通用导入查询条件") +public class ImportMainQueryDTO extends PageQueryDTO{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + /** 批次号 **/ + private String importNo; + /** 导入类型 **/ + private String type; + /** 导入状态:1新建,2解析失败,3校验中,4校验失败,5校验成功,6执行导入完成 **/ + private Integer importStatus; + /** 文件名称 **/ + private String fileNameLike; + /** 外部生成id **/ + private Long extraId; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("完成时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date finishTimeStart; + @ApiModelProperty("完成时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date finishTimeEnd; + + private Long orgId; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/commonimport/dto/ImportMainUpdateDTO.java b/src/main/java/com/newyetai/component/commonimport/dto/ImportMainUpdateDTO.java new file mode 100644 index 0000000..da84a8e --- /dev/null +++ b/src/main/java/com/newyetai/component/commonimport/dto/ImportMainUpdateDTO.java @@ -0,0 +1,48 @@ +package com.newyetai.component.commonimport.dto; + +import java.util.Date; +import java.util.Set; + +import javax.validation.constraints.NotNull; + +import com.newyetai.common.dto.BaseOperateDTO; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2024-01-19 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "通用导入修改") +public class ImportMainUpdateDTO extends BaseOperateDTO{ + + /** **/ + private static final long serialVersionUID = 1L; + /** id **/ + @NotNull(message = "id不能为空") + private Long id; + /** 原状态 **/ + @NotNull(message = "原状态不能为空") + private Set oldStatusSet; + /** 新状态 **/ + @NotNull(message = "新状态不能为空") + private Integer newStatus; + /** 总数 **/ + private Integer totalNum; + /** 成功数 **/ + private Integer successNum; + /** 失败原因 **/ + private String failMsg; + /** 完成时间时间 **/ + private Date finishTime; + /** 外部生成id **/ + private Long extraId; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/commonimport/entity/UcImportMain.java b/src/main/java/com/newyetai/component/commonimport/entity/UcImportMain.java new file mode 100644 index 0000000..4bd3d0a --- /dev/null +++ b/src/main/java/com/newyetai/component/commonimport/entity/UcImportMain.java @@ -0,0 +1,57 @@ +package com.newyetai.component.commonimport.entity; + +import java.util.Date; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 通用导入 + * + * @author sr on 2024-01-19 + */ +@TableName("uc_import_main") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +public class UcImportMain extends BaseEntity { + + /** **/ + private static final long serialVersionUID = 1L; + + /** 批次号 **/ + private String importNo; + /** 导入类型 **/ + private String type; + /** 导入状态:1新建,2解析失败,3校验中,4校验失败,5校验成功,6执行导入完成 **/ + private Integer importStatus; + /** 总数 **/ + private Integer totalNum; + /** 成功数 **/ + private Integer successNum; + /** 失败原因 **/ + private String failMsg; + /** 完成时间时间 **/ + private Date finishTime; + /** 执行类型:1.普通,2.指定外部id,3.明细表单 **/ + private Integer executeType; + /** 外部生成id **/ + private Long extraId; + /** 文件CODE **/ + private String fileCode; + /** 文件名称 **/ + private String fileName; + /** 机构ID **/ + private Long orgId; + /** 备注 **/ + private String remark; + +} diff --git a/src/main/java/com/newyetai/component/commonimport/mapper/ImportMainMapper.xml b/src/main/java/com/newyetai/component/commonimport/mapper/ImportMainMapper.xml new file mode 100644 index 0000000..64d8f80 --- /dev/null +++ b/src/main/java/com/newyetai/component/commonimport/mapper/ImportMainMapper.xml @@ -0,0 +1,81 @@ + + + + + + + update uc_import_main + set + + import_status = #{param.newStatus}, + + + extra_id = #{param.extraId}, + + + total_num = #{param.totalNum}, + + + success_num = #{param.successNum}, + + + fail_msg = #{param.failMsg}, + + + finish_time = #{param.finishTime}, + + update_by = #{param.operateUserId}, + update_time = now() + where deleted = 0 + and id = #{param.id} + and import_status in + + #{oldStatus} + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/commonimport/mapstruct/ImportMainMapMapper.java b/src/main/java/com/newyetai/component/commonimport/mapstruct/ImportMainMapMapper.java new file mode 100644 index 0000000..966dacc --- /dev/null +++ b/src/main/java/com/newyetai/component/commonimport/mapstruct/ImportMainMapMapper.java @@ -0,0 +1,34 @@ +package com.newyetai.component.commonimport.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.newyetai.component.commonimport.dto.ImportMainCreateDTO; +import com.newyetai.component.commonimport.dto.ImportMainCreateFormDTO; +import com.newyetai.component.commonimport.dto.ImportMainDTO; +import com.newyetai.component.commonimport.entity.UcImportMain; + +/** + * @author sr on 2024-01-19 + */ +@Mapper +public interface ImportMainMapMapper { + + ImportMainMapMapper INSTANCE = + Mappers.getMapper(ImportMainMapMapper.class); + + /** + * dto to entity + * + * @param importMainDto + * @return + * @author sr on 2024-01-19 + */ + UcImportMain toEntity( + ImportMainDTO importMainDto); + + UcImportMain to(ImportMainCreateDTO createDto); + UcImportMain to(ImportMainCreateFormDTO createDto); + + +} diff --git a/src/main/java/com/newyetai/component/commonimport/service/ICommonImportProvider.java b/src/main/java/com/newyetai/component/commonimport/service/ICommonImportProvider.java new file mode 100644 index 0000000..f1ab162 --- /dev/null +++ b/src/main/java/com/newyetai/component/commonimport/service/ICommonImportProvider.java @@ -0,0 +1,64 @@ +package com.newyetai.component.commonimport.service; + +import java.util.List; + +import com.newyetai.component.commonimport.dto.ImportDetailPageDTO; +import com.newyetai.component.commonimport.dto.ImportDetailSuperDTO; +import com.newyetai.component.commonimport.dto.ImportExecuteSuperDTO; +import com.newyetai.component.commonimport.dto.ImportMainCreateDTO; +import com.newyetai.component.commonimport.dto.ImportMainCreateFormDTO; +import com.newyetai.tkmybatis.pojo.Page; + +public interface ICommonImportProvider { + + String getType(); + + /** + * 同步导入 + * @param createDto + * @return 导入批次头id + * @author sr on 2024-01-22 + */ + Long syncImport(ImportMainCreateDTO createDto); + + /** + * 异步导入 + * @param createDto + * @return 导入批次头id + * @author sr on 2024-01-22 + */ + Long ayncImport(ImportMainCreateDTO createDto); + + /** + * 确认导入 + * @param executeDto + * @return 外部id + * @author sr on 2024-01-23 + */ + Long confirmImport(IE executeDto); + + /** + * 同步导入(明细form) + * @param createDto + * @param detailCreateDtos + * @return + * @author sr on 2024-01-26 + */ + Long syncImportFrom(ImportMainCreateFormDTO createDto, List detailCreateDtos); + + /** + * @description: 通用明细查询 + * @return: + * @author: guixinman + * @param: + */ + Page pageDetail(ImportDetailPageDTO importDetailPageDTO); + + /** + * @description: 通用明细导出数据 + * @return: + * @author: guixinman + * @param: + */ + void importDetailExport(ImportDetailPageDTO importDetailPageDTO); +} diff --git a/src/main/java/com/newyetai/component/commonimport/service/IImportDetailForm.java b/src/main/java/com/newyetai/component/commonimport/service/IImportDetailForm.java new file mode 100644 index 0000000..dc72d1d --- /dev/null +++ b/src/main/java/com/newyetai/component/commonimport/service/IImportDetailForm.java @@ -0,0 +1,9 @@ +package com.newyetai.component.commonimport.service; + +/** + * 明细form + * @author sr on 2024-01-26 + */ +public interface IImportDetailForm { + +} diff --git a/src/main/java/com/newyetai/component/commonimport/service/ImportDetailSuperQueryDTO.java b/src/main/java/com/newyetai/component/commonimport/service/ImportDetailSuperQueryDTO.java new file mode 100644 index 0000000..1c3d100 --- /dev/null +++ b/src/main/java/com/newyetai/component/commonimport/service/ImportDetailSuperQueryDTO.java @@ -0,0 +1,11 @@ +package com.newyetai.component.commonimport.service; + +/** + * @description: 导入详情分页查询 + * @author: guixinman + * @create: 2024-01-30 13:27 + **/ + +public interface ImportDetailSuperQueryDTO { + +} diff --git a/src/main/java/com/newyetai/component/commonimport/service/ImportMainService.java b/src/main/java/com/newyetai/component/commonimport/service/ImportMainService.java new file mode 100644 index 0000000..ca6cadc --- /dev/null +++ b/src/main/java/com/newyetai/component/commonimport/service/ImportMainService.java @@ -0,0 +1,78 @@ +package com.newyetai.component.commonimport.service; + +import java.util.List; + +import com.newyetai.component.commonimport.dto.ImportMainCreateDTO; +import com.newyetai.component.commonimport.dto.ImportMainCreateFormDTO; +import com.newyetai.component.commonimport.dto.ImportMainDTO; +import com.newyetai.component.commonimport.dto.ImportMainQueryDTO; +import com.newyetai.component.commonimport.dto.ImportMainUpdateDTO; + +/** + * 通用导入 + * + * @author sr on 2024-01-19 + */ +public interface ImportMainService { + + /** + * 新增 + * + * @param importMainOperateDTO + * @return + * @author sr on 2024-01-19 + */ + Long create(ImportMainCreateDTO createDto); + + /** + * 修改 + * + * @param updateDto + * @author sr on 2024-01-19 + */ + void modify(ImportMainUpdateDTO updateDto); + + /** + * 删除 + * + * @param id + * @author sr on 2024-01-19 + */ + void remove(Long id); + + /** + * 查询 + * + * @param importMainQueryDTO + * @return + * @author sr on 2024-01-19 + */ + List list(ImportMainQueryDTO importMainQueryDTO); + + /** + * 分页查询 + * + * @param importMainQueryDTO + * @return + * @author sr on 2024-01-19 + */ + void page(ImportMainQueryDTO importMainQueryDTO); + + /** + * 单个查询 + * + * @param importMainQueryDTO + * @return + * @author sr on 2024-01-19 + */ + ImportMainDTO find(ImportMainQueryDTO importMainQueryDTO); + + /** + * 明细表单保存 + * @param createDto + * @return + * @author sr on 2024-01-26 + */ + Long createForm(ImportMainCreateFormDTO createDto); + +} diff --git a/src/main/java/com/newyetai/component/commonimport/service/impl/AbstractCommonImportProvider.java b/src/main/java/com/newyetai/component/commonimport/service/impl/AbstractCommonImportProvider.java new file mode 100644 index 0000000..d186ddf --- /dev/null +++ b/src/main/java/com/newyetai/component/commonimport/service/impl/AbstractCommonImportProvider.java @@ -0,0 +1,236 @@ +package com.newyetai.component.commonimport.service.impl; + +import java.util.Date; +import java.util.List; + +import com.google.common.collect.Sets; +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.EnvironmentUtils; +import com.newyetai.common.util.MockUtils; +import com.newyetai.common.validation.util.ValidateUtils; +import com.newyetai.component.asyntasknotice.constant.AsyncTaskTypeEnum; +import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeCreateDTO; +import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeFinishDTO; +import com.newyetai.component.asyntasknotice.util.AsyncTaskNoticeUtils; +import com.newyetai.component.commonimport.constant.ImportDetailStatusEnum; +import com.newyetai.component.commonimport.constant.ImportExecuteTypeEnum; +import com.newyetai.component.commonimport.constant.ImportStatusEnum; +import com.newyetai.component.commonimport.constant.ImportTypeEnum; +import com.newyetai.component.commonimport.dto.ImportDetailSuperDTO; +import com.newyetai.component.commonimport.dto.ImportExecuteSuperDTO; +import com.newyetai.component.commonimport.dto.ImportMainCreateDTO; +import com.newyetai.component.commonimport.dto.ImportMainCreateFormDTO; +import com.newyetai.component.commonimport.dto.ImportMainDTO; +import com.newyetai.component.commonimport.dto.ImportMainQueryDTO; +import com.newyetai.component.commonimport.dto.ImportMainUpdateDTO; +import com.newyetai.component.commonimport.service.ICommonImportProvider; +import com.newyetai.component.commonimport.service.IImportDetailForm; +import com.newyetai.component.commonimport.service.ImportMainService; +import com.newyetai.mq.consumer.handler.ITopicMqHandler; +import com.newyetai.mq.dto.TopicMqMessage; +import com.newyetai.mq.util.MqSendUtils; + +import org.springframework.aop.framework.AopContext; +import org.springframework.transaction.annotation.Transactional; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public abstract class AbstractCommonImportProvider + implements ICommonImportProvider, ITopicMqHandler { + + private ImportMainService imprImportMainService; + + public AbstractCommonImportProvider(ImportMainService imprImportMainService) { + this.imprImportMainService = imprImportMainService; + } + + @Override + public Long syncImport(ImportMainCreateDTO createDto) { + // 保存头 + Long mainId = imprImportMainService.create(createDto); + // 解析文件+明细 + analyAndCheck(mainId); + return mainId; + } + + /** + * 校验明细from + */ + protected void preCheckCreateForm(List detailCreateDtos) { + ValidateUtils.validateBiz(detailCreateDtos); + } + + @Override + public Long syncImportFrom(ImportMainCreateFormDTO createDto, List detailCreateDtos) { + preCheckCreateForm(detailCreateDtos); + // 保存头 + Long mainId = imprImportMainService.createForm(createDto); + checkAndSave(mainId, detailCreateDtos); + return mainId; + } + + /** + * 解析文件,校验明细 + */ + @Transactional(rollbackFor = Exception.class) + public void analyAndCheck(Long mainId) { + List detailCreateDtos = null; + try { + detailCreateDtos = analy(mainId); + Assert.notEmpty(detailCreateDtos, "文件明细不能为空"); + } catch (Exception e) { + analyFail(mainId, e.getMessage()); + return; + } + checkAndSave(mainId, detailCreateDtos); + } + /** + * 解析文件 + * @param mainId + * @return 文件明细dto + * @author sr on 2024-01-26 + */ + public abstract List analy(Long mainId); + /** + * 保存明细,校验明细 + * @param detailCreateDtos + * @author sr on 2024-01-26 + */ + public abstract void checkAndSave(Long mainId, List detailCreateDtos); + + /** + * 解析失败 + */ + protected void analyFail(Long mainId, String failMsg) { + ImportMainUpdateDTO updateDto = ImportMainUpdateDTO.builder().id(mainId) + .oldStatusSet(Sets.newHashSet(ImportStatusEnum.INIT.getStatus())) + .newStatus(ImportStatusEnum.ANALY_FAIL.getStatus()) + .failMsg(failMsg).build(); + imprImportMainService.modify(updateDto); + finishAsyncTask(mainId, ImportStatusEnum.ANALY_FAIL.getStatus()); + } + + /** + * 结束明细校验 + * @param mainId + * @param detailDtos 明细结果集 + * @author sr on 2024-01-26 + */ + protected void finishCheck(Long mainId, List detailDtos) { + Integer sucNum = 0; + Integer failNum = 0; + for(ID detailDto : detailDtos) { + if (ImportDetailStatusEnum.CHECK_SUCCESS.getStatus().equals(detailDto.getDetailStatus())) { + sucNum ++; + }else if (ImportDetailStatusEnum.CHECK_FAIL.getStatus().equals(detailDto.getDetailStatus())) { + failNum++; + } else { + throw new BusinessException("导入明细未全部校验结束"); + } + } + Integer totalNum = sucNum + failNum; + Integer importStatus = ImportStatusEnum.CHECKED.getStatus(); + if (sucNum == 0) { + importStatus = ImportStatusEnum.CHECK_FAIL.getStatus(); + } + ImportMainUpdateDTO updateDto = ImportMainUpdateDTO.builder().id(mainId) + .oldStatusSet(Sets.newHashSet(ImportStatusEnum.INIT.getStatus(), + ImportStatusEnum.CHECKING.getStatus())) + .newStatus(importStatus) + .totalNum(totalNum) + .successNum(sucNum).build(); + imprImportMainService.modify(updateDto); + finishAsyncTask(mainId, importStatus); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public Long confirmImport(IE executeDto) { + Long mainId = executeDto.getMainId(); + ImportMainDTO importMainDTO = imprImportMainService.find(ImportMainQueryDTO.builder().id(mainId).build()); + Assert.notNull(importMainDTO, "未找到指定导入批次"); + Assert.isTrue(ImportStatusEnum.CHECKED.getStatus().equals(importMainDTO.getImportStatus()), "校验完成状态才可确定导入"); + Integer executeType = importMainDTO.getExecuteType(); + executeDto.setExecuteType(executeType); + if (ImportExecuteTypeEnum.EXTRA_ID.getType().equals(executeType)) { + executeDto.setExtraId(importMainDTO.getExtraId()); + } else { + preCheckExecute(executeDto); + } + Long extraId = execute(executeDto); + finishExecute(executeDto.getMainId(), extraId); + return extraId; + } + + /** + * 执行dto参数校验 + * @author sr on 2024-01-26 + */ + protected void preCheckExecute(IE executeDto) { + ValidateUtils.validateBiz(executeDto); + } + + /** + * 执行(转正式业务数据) + * @param executeDto + * @return 正式数据头id + * @author sr on 2024-01-26 + */ + public abstract Long execute(IE executeDto); + + /** + * 完成执行 + * @author sr on 2024-01-26 + */ + protected void finishExecute(Long mainId, Long extraId) { + ImportMainUpdateDTO updateDto = ImportMainUpdateDTO.builder().id(mainId) + .oldStatusSet(Sets.newHashSet(ImportStatusEnum.CHECKED.getStatus())) + .newStatus(ImportStatusEnum.EXECUTE.getStatus()) + .extraId(extraId) + .finishTime(new Date()).build(); + imprImportMainService.modify(updateDto); + } + + @Override + public Long ayncImport(ImportMainCreateDTO createDto) { + // 保存头 + Long mainId = imprImportMainService.create(createDto); + MqSendUtils.send(TopicMqMessage.builder().routingKey(getRoutingKey()) + .data(mainId) + .build()); + AsyncTaskNoticeUtils.create(AsyncTaskNoticeCreateDTO.builder() + .unionType(AsyncTaskTypeEnum.COMMON_IMPORT.getType()) + .unionId(mainId) + .content(String.join(CommonConstants.HYPHEN, ImportTypeEnum.get(getType()).getName(), createDto.getFileName())) + .bizStatusStr(ImportStatusEnum.INIT.getName()).build()); + return mainId; + } + + @Override + public String getRoutingKey() { + return String.join(CommonConstants.UNDERLINE, + EnvironmentUtils.getApplicationName() + CommonConstants.POINT + "common_import", getType()); + } + + @Override + public void onMessage(TopicMqMessage message) { + try { + MockUtils.mockUser(message.getOperateUserId(), message.getOperateOrgId()); + AbstractCommonImportProvider abstractCommonImportProvider = (AbstractCommonImportProvider) AopContext.currentProxy(); + abstractCommonImportProvider.analyAndCheck(message.getData()); + } catch (Exception e) { + log.info("通用导入异步执行失败:", e); + } + } + + private static void finishAsyncTask(Long mainId, Integer importStatus) { + AsyncTaskNoticeUtils.finish(AsyncTaskNoticeFinishDTO.builder() + .unionType(AsyncTaskTypeEnum.COMMON_IMPORT.getType()).unionId(mainId) + .bizStatusStr(ImportStatusEnum.get(importStatus).getName()).build()); + } + + +} diff --git a/src/main/java/com/newyetai/component/commonimport/service/impl/CommonImportAdapter.java b/src/main/java/com/newyetai/component/commonimport/service/impl/CommonImportAdapter.java new file mode 100644 index 0000000..a6646ee --- /dev/null +++ b/src/main/java/com/newyetai/component/commonimport/service/impl/CommonImportAdapter.java @@ -0,0 +1,134 @@ +package com.newyetai.component.commonimport.service.impl; + +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.List; +import java.util.Map; + +import org.apache.poi.ss.formula.functions.T; +import org.springframework.aop.support.AopUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.stereotype.Service; + +import com.fasterxml.jackson.core.type.TypeReference; + +import com.google.common.collect.Maps; + +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.component.commonimport.dto.ImportDetailPageDTO; +import com.newyetai.component.commonimport.dto.ImportExecuteSuperDTO; +import com.newyetai.component.commonimport.dto.ImportMainCreateDTO; +import com.newyetai.component.commonimport.dto.ImportMainCreateFormDTO; +import com.newyetai.component.commonimport.dto.ImportMainDTO; +import com.newyetai.component.commonimport.dto.ImportMainQueryDTO; +import com.newyetai.component.commonimport.service.ICommonImportProvider; +import com.newyetai.component.commonimport.service.IImportDetailForm; +import com.newyetai.component.commonimport.service.ImportDetailSuperQueryDTO; +import com.newyetai.component.commonimport.service.ImportMainService; +import com.newyetai.config.dto.ConfigDTO; +import com.newyetai.config.service.ConfigService; +import com.newyetai.tkmybatis.pojo.Page; + +@Service +@ConditionalOnBean(AbstractCommonImportProvider.class) +public class CommonImportAdapter { + + private static Map providerMap = Maps.newHashMap(); + private static Map> executeTypeMap = Maps.newHashMap(); + private static Map> detailFormTypeMap = Maps.newHashMap(); + /** + * 通用导入模版前缀 + **/ + public static final String TEMPLATE_CODE_PREFIX = "common_import_template_"; + + public CommonImportAdapter(List providers) { + providers.forEach(provider -> { + String type = provider.getType(); + providerMap.put(type, provider); + ParameterizedType pt = (ParameterizedType) AopUtils.getTargetClass(provider).getGenericSuperclass(); + Type executeDtoType = pt.getActualTypeArguments()[0]; + TypeReference executeTypeReference = new TypeReference() { + @Override + public Type getType() { + return executeDtoType; + } + }; + Type detailFormType = pt.getActualTypeArguments()[2]; + TypeReference detailFormTypeReference = new TypeReference() { + @Override + public Type getType() { + return detailFormType; + } + }; + + executeTypeMap.put(type, executeTypeReference); + detailFormTypeMap.put(type, detailFormTypeReference); + }); + } + + @Autowired + private ConfigService configService; + @Autowired + private ImportMainService importMainService; + + private ICommonImportProvider getProvider(String type) { + ICommonImportProvider provider = providerMap.get(type); + Assert.notNull(provider, "通用导入类型有误:" + type); + return provider; + } + + public ConfigDTO template(String type) { + getProvider(type); + String configCode = TEMPLATE_CODE_PREFIX + type; + return configService.queryConfigByCode(CommonConstants.PLATFORM_ORG_ID, configCode); + } + + public void page(ImportMainQueryDTO queryDTO) { + importMainService.page(queryDTO); + } + + public ImportMainDTO find(ImportMainQueryDTO queryDTO) { + return importMainService.find(queryDTO); + } + + public Long create(ImportMainCreateDTO createDto) { + ICommonImportProvider provider = getProvider(createDto.getType()); + return provider.syncImport(createDto); + } + + public Long createAsync(ImportMainCreateDTO createDto) { + ICommonImportProvider provider = getProvider(createDto.getType()); + return provider.ayncImport(createDto); + } + + public Long createForm(ImportMainCreateFormDTO createDto) { + String type = createDto.getType(); + ICommonImportProvider provider = getProvider(type); + String detailJson = JsonUtils.toJsonString(JsonUtils.buildObjectMapper(), createDto.getDetails()); + List details = JsonUtils.toList(detailJson, (Class) detailFormTypeMap.get(type).getType()); + return provider.syncImportFrom(createDto, details); + } + + public Long confirmImport(String type, Map executeDtoMap) { + ICommonImportProvider provider = getProvider(type); + String executeJson = JsonUtils.toJsonString(JsonUtils.buildObjectMapper(), executeDtoMap); + ImportExecuteSuperDTO executeDto = JsonUtils.toObject(executeJson, executeTypeMap.get(type)); + return provider.confirmImport(executeDto); + } + + public Page pageDetail(ImportDetailPageDTO importDetailPageDTO) { + String type = importDetailPageDTO.getType(); + ICommonImportProvider provider = getProvider(type); + return provider.pageDetail(importDetailPageDTO); + } + + public void importDetailExport(ImportDetailPageDTO importDetailPageDTO) { + String type = importDetailPageDTO.getType(); + ICommonImportProvider provider = getProvider(type); + provider.importDetailExport(importDetailPageDTO); + } + +} diff --git a/src/main/java/com/newyetai/component/commonimport/service/impl/ImportMainServiceImpl.java b/src/main/java/com/newyetai/component/commonimport/service/impl/ImportMainServiceImpl.java new file mode 100644 index 0000000..2f3d339 --- /dev/null +++ b/src/main/java/com/newyetai/component/commonimport/service/impl/ImportMainServiceImpl.java @@ -0,0 +1,100 @@ +package com.newyetai.component.commonimport.service.impl; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.codegenerator.util.CodeUtils; +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.ListUtil; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.component.commonimport.constant.ImportExecuteTypeEnum; +import com.newyetai.component.commonimport.constant.ImportStatusEnum; +import com.newyetai.component.commonimport.dao.ImportMainMapper; +import com.newyetai.component.commonimport.dto.ImportMainCreateDTO; +import com.newyetai.component.commonimport.dto.ImportMainCreateFormDTO; +import com.newyetai.component.commonimport.dto.ImportMainDTO; +import com.newyetai.component.commonimport.dto.ImportMainQueryDTO; +import com.newyetai.component.commonimport.dto.ImportMainUpdateDTO; +import com.newyetai.component.commonimport.entity.UcImportMain; +import com.newyetai.component.commonimport.mapstruct.ImportMainMapMapper; +import com.newyetai.component.commonimport.service.ImportMainService; +import com.newyetai.component.constants.CodeTypeEnum; + +/** + * @author sr on 2024-01-19 + */ +@Service +public class ImportMainServiceImpl implements ImportMainService { + + @Autowired + private ImportMainMapper importMainMapper; + + @Override + @Transactional + public Long create(ImportMainCreateDTO createDto) { + Long extraId = createDto.getExtraId(); + UcImportMain ucImportMain = ImportMainMapMapper.INSTANCE.to(createDto); + init(ucImportMain); + if (extraId != null) { + ucImportMain.setExecuteType(ImportExecuteTypeEnum.EXTRA_ID.getType()); + } + importMainMapper.saveEntity(ucImportMain); + return ucImportMain.getId(); + } + + private void init(UcImportMain ucImportMain) { + ucImportMain.setImportNo(CodeUtils.getCode(CodeTypeEnum.COMMON_IMPORT)); + ucImportMain.setImportStatus(ImportStatusEnum.INIT.getStatus()); + ucImportMain.setOrgId(UserContextHolder.getExistLoginOrgId()); + } + + @Override + @Transactional + public Long createForm(ImportMainCreateFormDTO createDto) { + UcImportMain ucImportMain = ImportMainMapMapper.INSTANCE.to(createDto); + ucImportMain.setExecuteType(ImportExecuteTypeEnum.DETAIL_FORM.getType()); + ucImportMain.setFileName("快速发放"); + init(ucImportMain); + importMainMapper.saveEntity(ucImportMain); + return ucImportMain.getId(); + } + + @Override + @Transactional + public void modify(ImportMainUpdateDTO updateDto) { + int num = importMainMapper.modify(updateDto); + Assert.isTrue(num > 0, "修改导入批次失败"); + } + + @Override + @Transactional + public void remove(Long id) { + importMainMapper.deleteEntity(UcImportMain.builder().id(id).build(), + UserContextHolder.getLoginUserId()); + } + + @Override + public List list(ImportMainQueryDTO importMainQueryDTO) { + importMainQueryDTO.disablePage(); + return importMainMapper.listImportMainDTO(importMainQueryDTO); + } + + @Override + public void page(ImportMainQueryDTO importMainQueryDTO) { + if (!CommonConstants.PLATFORM_ORG_ID.equals(UserContextHolder.getExistLoginOrgId())) { + importMainQueryDTO.setOrgId(UserContextHolder.getExistLoginOrgId()); + } + importMainMapper.listImportMainDTO(importMainQueryDTO); + } + + @Override + public ImportMainDTO find(ImportMainQueryDTO importMainQueryDTO) { + List importMainDTOs = this.list(importMainQueryDTO); + return ListUtil.first(importMainDTOs); + } + +} diff --git a/src/main/java/com/newyetai/component/constants/CodeTypeEnum.java b/src/main/java/com/newyetai/component/constants/CodeTypeEnum.java new file mode 100644 index 0000000..7bc1584 --- /dev/null +++ b/src/main/java/com/newyetai/component/constants/CodeTypeEnum.java @@ -0,0 +1,29 @@ +package com.newyetai.component.constants; + +import com.newyetai.codegenerator.pojo.CodeParam; + +/** + * @author sr on 2020-08-04 + */ +public enum CodeTypeEnum { + + /** + * FileClass(备用) + **/ + FILE_CLASS(CodeParam.builder().type("FC").build()), + + /** 通用导入 **/ + COMMON_IMPORT(CodeParam.builder().type("CI").build()); + + private CodeParam codeParam; + + CodeTypeEnum(CodeParam codeParam) { + this.codeParam = codeParam; + } + + public CodeParam getCodeParam() { + return this.codeParam; + } + + +} diff --git a/src/main/java/com/newyetai/component/dict/controller/DictController.java b/src/main/java/com/newyetai/component/dict/controller/DictController.java new file mode 100644 index 0000000..ffe56cd --- /dev/null +++ b/src/main/java/com/newyetai/component/dict/controller/DictController.java @@ -0,0 +1,105 @@ +package com.newyetai.component.dict.controller; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.component.dict.dto.DictDTO; +import com.newyetai.component.dict.dto.DictDetailQueryDTO; +import com.newyetai.component.dict.dto.DictQueryDTO; +import com.newyetai.component.dict.dto.DropdownDictDetailDTO; +import com.newyetai.component.dict.service.DictCacheService; +import com.newyetai.component.dict.service.DictDetailService; +import com.newyetai.component.dict.service.DictService; +import com.newyetai.tkmybatis.pojo.Page; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.Collection; + +/** + * + * @author Rey(leijiaping@newyetai.com) + * + */ +@Api(tags = "字典表") +@RestController +@RequestMapping({"/dict"}) +public class DictController { + + @Autowired + private DictService dictService; + + @Autowired + private DictDetailService dictDetailService; + + @Autowired + private DictCacheService dictCacheService; + + /** + * 新增 + * + * @param dict + */ + @ApiOperation("新增字典") + @PostMapping("create") + public AlitaResult createDict(@RequestBody DictDTO dict) { + dictService.createDict(dict, UserContextHolder.getLoginUserId()); + return AlitaResult.success(dict); + } + + /** + * 修改 + * + * @param dict + */ + @ApiOperation("修改字典") + @PostMapping("modify") + public AlitaResult modifyDict(@RequestBody DictDTO dict) { + dictService.modifyDict(dict, UserContextHolder.getLoginUserId()); + return AlitaResult.success(dict); + } + + /** + * 删除 + * + * @param dict + */ + @ApiOperation("删除字典") + @PostMapping("remove") + public AlitaResult removeDict(@RequestBody DictDTO dict) { + dictService.removeDict(dict, UserContextHolder.getLoginUserId()); + return AlitaResult.success(dict); + } + + /** + * 查询 + * + * @param dict + */ + @ApiOperation("后边页面列出字典-带分页") + @GetMapping("page") + public AlitaResult> page(DictQueryDTO dict) { + dictService.page(dict); + return AlitaResult.success(dict.getPageResult()); + } + + /** + * 查询 + * + * @param dictDetailDTO + */ + @ApiOperation("列出字典") + @GetMapping("lookup") + public AlitaResult> find(DictDetailQueryDTO dictDetailDTO) { + return AlitaResult.success(dictDetailService.getDropdownDictDetails(dictDetailDTO)); + } + + @ApiOperation("刷新字典-dictCode") + @GetMapping("flush/{dictCode}") + public AlitaResult flushByDictCode(@PathVariable String dictCode){ + dictCacheService.removeTreeDictDetailByCode(dictCode); + return AlitaResult.success(Boolean.TRUE); + } + +} diff --git a/src/main/java/com/newyetai/component/dict/dao/DictDetailMapper.java b/src/main/java/com/newyetai/component/dict/dao/DictDetailMapper.java new file mode 100644 index 0000000..3089cb2 --- /dev/null +++ b/src/main/java/com/newyetai/component/dict/dao/DictDetailMapper.java @@ -0,0 +1,45 @@ +package com.newyetai.component.dict.dao; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.newyetai.component.dict.dto.DictDetailDTO; +import com.newyetai.component.dict.dto.DictDetailQueryDTO; +import com.newyetai.component.dict.dto.DropdownDictDetailDTO; +import com.newyetai.component.dict.entity.DictDetail; +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.tkmybatis.pojo.Page; + +/** + * @author Rey(leijiaping@newyetai.com) + */ +public interface DictDetailMapper extends MyMapper { + + /** + * 查询 + * + * @param page 不为空分页 + * @param dictDetail + * @return + */ + List list(Page page, @Param("param") DictDetailQueryDTO dictDetailQueryDTO); + + /** + * 查询 + * + * @param dictDetailDTO + * @return + */ + List getDropdownDictDetails(@Param("param") DictDetailQueryDTO dictDetailQueryDTO); + + /** + * 获取字典编码 + * + * @param dictDetailQueryDTO + * @return + * @author sr on 2020-07-30 + */ + List getDictCode(@Param("param") DictDetailQueryDTO dictDetailQueryDTO); + +} diff --git a/src/main/java/com/newyetai/component/dict/dao/DictMapper.java b/src/main/java/com/newyetai/component/dict/dao/DictMapper.java new file mode 100644 index 0000000..17f0a3f --- /dev/null +++ b/src/main/java/com/newyetai/component/dict/dao/DictMapper.java @@ -0,0 +1,24 @@ +package com.newyetai.component.dict.dao; + +import com.newyetai.component.dict.dto.DictDTO; +import com.newyetai.component.dict.dto.DictQueryDTO; +import com.newyetai.component.dict.entity.Dict; +import com.newyetai.tkmybatis.mybatis.MyMapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @author Rey(leijiaping@newyetai.com) + */ +public interface DictMapper extends MyMapper { + + /** + * 分页查询 + * + * @param dict + * @return + */ + List list(@Param("param") DictQueryDTO dict); + +} diff --git a/src/main/java/com/newyetai/component/dict/dto/DictDTO.java b/src/main/java/com/newyetai/component/dict/dto/DictDTO.java new file mode 100644 index 0000000..6b3dec1 --- /dev/null +++ b/src/main/java/com/newyetai/component/dict/dto/DictDTO.java @@ -0,0 +1,38 @@ +package com.newyetai.component.dict.dto; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.component.action.dto.ActionDetailDTO; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2020-07-30 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@SuperBuilder +public class DictDTO extends BaseDTO implements Serializable { + + /** **/ + private static final long serialVersionUID = -8242172908364818906L; + + @ApiModelProperty("字典编码") + private String dictCode; + + @ApiModelProperty("字典名称") + private String dictName; + + @ApiModelProperty("数据字典详情列表") + private List dictDetailList; + +} diff --git a/src/main/java/com/newyetai/component/dict/dto/DictDetailDTO.java b/src/main/java/com/newyetai/component/dict/dto/DictDetailDTO.java new file mode 100644 index 0000000..a2d715a --- /dev/null +++ b/src/main/java/com/newyetai/component/dict/dto/DictDetailDTO.java @@ -0,0 +1,56 @@ +package com.newyetai.component.dict.dto; + +import com.google.common.collect.Lists; +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.common.util.TreeNode; +import com.newyetai.component.action.dto.ActionDetailDTO; + +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.SuperBuilder; + +import java.util.Date; +import java.util.List; + +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Data +@SuperBuilder +public class DictDetailDTO extends BaseDTO implements TreeNode { + + /** + * + **/ + private static final long serialVersionUID = -1396551692759999448L; + + @ApiModelProperty("字典ID") + private Long dictId; + + @ApiModelProperty("字典编码") + private String dictCode; + + @ApiModelProperty("字典明细编码") + private String dictDetailCode; + + @ApiModelProperty("字典明细名称") + private String dictDetailName; + + @ApiModelProperty("顺序") + private Integer dictOrder; + + @ApiModelProperty("父子项的ID") + private Long parentId; + + @ApiModelProperty("父子项的Name") + private String parentName; + + private List children = Lists.newArrayList(); + + + @Override + public void addChildren(DictDetailDTO node) { + this.children.add(node); + } + +} diff --git a/src/main/java/com/newyetai/component/dict/dto/DictDetailQueryDTO.java b/src/main/java/com/newyetai/component/dict/dto/DictDetailQueryDTO.java new file mode 100644 index 0000000..979d622 --- /dev/null +++ b/src/main/java/com/newyetai/component/dict/dto/DictDetailQueryDTO.java @@ -0,0 +1,59 @@ +package com.newyetai.component.dict.dto; + +import com.newyetai.common.dto.PageQueryDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * + * @author Rey(leijiaping@newyetai.com) + * + */ +@NoArgsConstructor +@AllArgsConstructor +@Builder +@Data +@ApiModel("字典详情") +public class DictDetailQueryDTO extends PageQueryDTO { + + /** + * + */ + private static final long serialVersionUID = 2138839246462138493L; + + @ApiModelProperty("字典类型") + private String type; + + @ApiModelProperty("字典类型-多个字典类型(查询)") + private String[] types; + + @ApiModelProperty("字典id") + private Long dictId; + + @ApiModelProperty("字典名称") + private String dictName; + + @ApiModelProperty("字典编码") + private String dictCode; + + @ApiModelProperty("字典明细id") + private Long dictDetailId; + + @ApiModelProperty("字典明细名称") + private String dictDetailName; + + @ApiModelProperty("字典明细编码") + private String dictDetailCode; + + @ApiModelProperty("父id") + private Long parentId; + + @ApiModelProperty("查询值,同时筛选 dictCode,dictName") + private String queryCode; + + +} diff --git a/src/main/java/com/newyetai/component/dict/dto/DictQueryDTO.java b/src/main/java/com/newyetai/component/dict/dto/DictQueryDTO.java new file mode 100644 index 0000000..7c90253 --- /dev/null +++ b/src/main/java/com/newyetai/component/dict/dto/DictQueryDTO.java @@ -0,0 +1,34 @@ +package com.newyetai.component.dict.dto; + +import com.newyetai.common.dto.PageQueryDTO; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2020-07-30 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class DictQueryDTO extends PageQueryDTO { + + /** **/ + private static final long serialVersionUID = -8242172908364818906L; + + @ApiModelProperty("字典id") + private Long dictId; + + @ApiModelProperty("字典编码") + private String dictCode; + + @ApiModelProperty("字典名称") + private String dictName; + + @ApiModelProperty("查询值,同时筛选 dictCode,dictName") + private String queryCode; + +} diff --git a/src/main/java/com/newyetai/component/dict/dto/DropdownDictDetailDTO.java b/src/main/java/com/newyetai/component/dict/dto/DropdownDictDetailDTO.java new file mode 100644 index 0000000..3067cb6 --- /dev/null +++ b/src/main/java/com/newyetai/component/dict/dto/DropdownDictDetailDTO.java @@ -0,0 +1,38 @@ +package com.newyetai.component.dict.dto; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@Builder +@Data +@ApiModel("下拉字典详情") +public class DropdownDictDetailDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = -6549004852720101531L; + + @ApiModelProperty("明细id") + private Long detailId; + + @ApiModelProperty("字典类型") + private String type; + + @ApiModelProperty("字典编码") + private String dictDetailCode; + + @ApiModelProperty("字典名称") + private String dictDetailName; + + @ApiModelProperty("顺序") + private Integer dictOrder; + + +} diff --git a/src/main/java/com/newyetai/component/dict/entity/Dict.java b/src/main/java/com/newyetai/component/dict/entity/Dict.java new file mode 100644 index 0000000..1d05049 --- /dev/null +++ b/src/main/java/com/newyetai/component/dict/entity/Dict.java @@ -0,0 +1,46 @@ +package com.newyetai.component.dict.entity; + +import java.util.Date; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author Rey(leijiaping @ newyetai.com) + */ +@TableName("xs_dict") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Data +public class Dict extends BaseEntity { + + /** **/ + private static final long serialVersionUID = 1802939371884168684L; + + /** + * 字典编码 + */ + private String dictCode; + + /** + * 字典名称 + */ + private String dictName; + + @Builder + public Dict(Long id, Boolean deleted, Long createBy, Date createTime, Long updateBy, + Date updateTime, Long proxyBy, String dictCode, String dictName) { + super(id, deleted, createBy, createTime, updateBy, updateTime, proxyBy); + this.dictCode = dictCode; + this.dictName = dictName; + } + + +} diff --git a/src/main/java/com/newyetai/component/dict/entity/DictDetail.java b/src/main/java/com/newyetai/component/dict/entity/DictDetail.java new file mode 100644 index 0000000..68f8d8c --- /dev/null +++ b/src/main/java/com/newyetai/component/dict/entity/DictDetail.java @@ -0,0 +1,65 @@ +package com.newyetai.component.dict.entity; + +import java.util.Date; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author Rey(leijiaping @ newyetai.com) + */ +@TableName("xs_dict_detail") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Builder +@Data +public class DictDetail extends BaseEntity { + + /** **/ + private static final long serialVersionUID = -1396551692759999448L; + + /** + * 字典ID + */ + private Long dictId; + + /** + * 字典明细编码 + */ + private String dictDetailCode; + + /** + * 字典明细名称 + */ + private String dictDetailName; + + /** + * 顺序 + */ + private Integer dictOrder; + + /** + * 父子项的ID + */ + private Long parentId; + + @Builder + public DictDetail(Long id, Boolean deleted, Long createBy, Date createTime, + Long updateBy, Date updateTime, Long proxyBy, Long dictId, + String dictDetailCode, String dictDetailName, Integer dictOrder, Long parentId) { + super(id, deleted, createBy, createTime, updateBy, updateTime, proxyBy); + this.dictId = dictId; + this.dictDetailCode = dictDetailCode; + this.dictDetailName = dictDetailName; + this.dictOrder = dictOrder; + this.parentId = parentId; + } + +} diff --git a/src/main/java/com/newyetai/component/dict/mapper/DictDetailMapper.xml b/src/main/java/com/newyetai/component/dict/mapper/DictDetailMapper.xml new file mode 100644 index 0000000..98a4321 --- /dev/null +++ b/src/main/java/com/newyetai/component/dict/mapper/DictDetailMapper.xml @@ -0,0 +1,77 @@ + + + + + + from + xs_dict dict + inner join xs_dict_detail detail on dict.id = detail.dict_id + where + dict.deleted = 0 and detail.deleted = 0 + + + AND dict.dict_name like #{dictNameLike} + + + AND dict.dict_code = #{param.dictCode} + + + AND detail.dict_id = #{param.dictId} + + + AND detail.id = #{param.dictDetailId} + + + + AND detail.dict_detail_name like #{dictDetailNameLike} + + + AND detail.dict_detail_code = #{param.dictDetailCode} + + + AND detail.parent_id = #{param.parentId} + + + AND dict.dict_code = #{param.type} + + + AND dict.dict_code in + + #{code} + + + + + AND (detail.dict_detail_name like #{queryCodeLike} OR detail.dict_detail_code like #{queryCodeLike}) + + + + + + + + + + + diff --git a/src/main/java/com/newyetai/component/dict/mapper/DictMapper.xml b/src/main/java/com/newyetai/component/dict/mapper/DictMapper.xml new file mode 100644 index 0000000..e66f20d --- /dev/null +++ b/src/main/java/com/newyetai/component/dict/mapper/DictMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + diff --git a/src/main/java/com/newyetai/component/dict/mapstruct/DictDetailMapMapper.java b/src/main/java/com/newyetai/component/dict/mapstruct/DictDetailMapMapper.java new file mode 100644 index 0000000..61a6f65 --- /dev/null +++ b/src/main/java/com/newyetai/component/dict/mapstruct/DictDetailMapMapper.java @@ -0,0 +1,24 @@ +package com.newyetai.component.dict.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.newyetai.component.dict.dto.DictDetailDTO; +import com.newyetai.component.dict.entity.DictDetail; + +/** + * @author sr on 2020-07-30 + */ +@Mapper +public interface DictDetailMapMapper { + + DictDetailMapMapper INSTANCE = Mappers.getMapper(DictDetailMapMapper.class); + + /** + * @param dictDetailDTO + * @return + * @author sr on 2020-07-30 + */ + DictDetail toEntity(DictDetailDTO dictDetailDTO); + +} diff --git a/src/main/java/com/newyetai/component/dict/mapstruct/DictMapMapper.java b/src/main/java/com/newyetai/component/dict/mapstruct/DictMapMapper.java new file mode 100644 index 0000000..f13c634 --- /dev/null +++ b/src/main/java/com/newyetai/component/dict/mapstruct/DictMapMapper.java @@ -0,0 +1,39 @@ +package com.newyetai.component.dict.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.newyetai.component.dict.dto.DictDTO; +import com.newyetai.component.dict.dto.DictQueryDTO; +import com.newyetai.component.dict.entity.Dict; + +/** + * @author sr on 2020-07-30 + */ +@Mapper +public interface DictMapMapper { + + DictMapMapper INSTANCE = Mappers.getMapper(DictMapMapper.class); + + /** + * @param dictDetailDTO + * @return + * @author sr on 2020-07-30 + */ + Dict toEntity(DictDTO dictDTO); + + /** + * @param dictQueryDTO + * @return + * @author sr on 2020-07-30 + */ + Dict toEntity(DictQueryDTO dictQueryDTO); + + /** + * @param dict + * @return + * @author sr on 2020-07-30 + */ + DictDTO toDto(Dict dict); + +} diff --git a/src/main/java/com/newyetai/component/dict/service/DictCacheService.java b/src/main/java/com/newyetai/component/dict/service/DictCacheService.java new file mode 100644 index 0000000..8b67686 --- /dev/null +++ b/src/main/java/com/newyetai/component/dict/service/DictCacheService.java @@ -0,0 +1,47 @@ +package com.newyetai.component.dict.service; + +import java.util.List; + +import com.newyetai.component.dict.dto.DictDetailDTO; + +/** + * 字典缓存 + * + * @author sr on 2020-04-03 + */ +public interface DictCacheService { + + /** + * 获取dictCode的树形数据字典缓存 + * + * @param dictCode + * @return + * @author sr on 2020-04-03 + */ + List getTreeDictDetailByCode(String dictCode); + + /** + * 更新dictCode的树形数据字典缓存 + * + * @param dictCode + * @return + * @author sr on 2020-04-03 + */ + List putTreeDictDetailByCode(String dictCode); + + /** + * 清除dictCode的树形数据字典缓存 + * + * @param dictCode + * @author sr on 2020-04-03 + */ + void removeTreeDictDetailByCode(String dictCode); + + /** + * 清除树形数据字典缓存 + * + * @author sr on 2020-04-03 + */ + void removeTreeDictDetail(); + +} diff --git a/src/main/java/com/newyetai/component/dict/service/DictDetailService.java b/src/main/java/com/newyetai/component/dict/service/DictDetailService.java new file mode 100644 index 0000000..12b6fab --- /dev/null +++ b/src/main/java/com/newyetai/component/dict/service/DictDetailService.java @@ -0,0 +1,107 @@ +package com.newyetai.component.dict.service; + +import com.newyetai.component.dict.dto.DictDetailDTO; +import com.newyetai.component.dict.dto.DictDetailQueryDTO; +import com.newyetai.component.dict.dto.DropdownDictDetailDTO; +import com.newyetai.tkmybatis.pojo.Page; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * + * @author Rey(leijiaping@newyetai.com) + * + */ +public interface DictDetailService { + + /** + * 新增 + * + * @param dictDetail + * @param operateUserId + */ + void createDictDetail(DictDetailDTO dictDetail, Long operateUserId); + + /** + * 修改 + * + * @param dictDetail + */ + void modifyDictDetail(DictDetailDTO dictDetail, Long operateUserId); + + /** + * 删除 + * + * @param dictDetail + */ + void removeDictDetail(DictDetailDTO dictDetail, Long operateUserId); + + /** + * 查询 + * + * @param page + * @param dictDetail + */ + void page(Page page, DictDetailQueryDTO dictDetail); + + /** + * 查询 + * + * @param dictDetailDTO + */ + Collection getDropdownDictDetails(DictDetailQueryDTO dictDetailDTO); + + /** + * 查询 + * + * @param dictDetail + */ + List list(DictDetailQueryDTO dictDetail); + + /** + * 获取map + * @param parentType + * @return + */ + Map getDictDetailsMap(String parentType); + + /** + * 获取map + * @param parentCode + * @param operateUserId + * @return + */ + Map getDictDetailMap(String parentCode, Long operateUserId); + + /** + * 获取字典详情 + * @param dictId + * @param code + * @param parentId + * @return + */ + DictDetailDTO findDetail(Long dictId, String code, Long parentId); + + /** + * 刷新字典缓存 + * + * @param dictDetail + * @author sr on 2020-07-30 + */ + void refreshDictCache(DictDetailQueryDTO dictDetailQueryDTO); + + /** + * 根据给定的type类型,返回Map + * 以 auth_status 为例子,返回的Map key->value 为 + * authStatus1->未认证 + * authStatus2->认证中 + * authStatus3->认证成功 + * authStatus4->认证失败 + * + * @param types + * @return + */ + Map getMapByTypes(List types); +} diff --git a/src/main/java/com/newyetai/component/dict/service/DictService.java b/src/main/java/com/newyetai/component/dict/service/DictService.java new file mode 100644 index 0000000..637e00a --- /dev/null +++ b/src/main/java/com/newyetai/component/dict/service/DictService.java @@ -0,0 +1,46 @@ +package com.newyetai.component.dict.service; + +import com.newyetai.component.dict.dto.DictDTO; +import com.newyetai.component.dict.dto.DictQueryDTO; + +/** + * + * @author Rey(leijiaping@newyetai.com) + * + */ +public interface DictService{ + + /** + * 新增 + * + * @param dict + * @return + */ + DictDTO createDict(DictDTO dict, Long operateUserId); + + /** + * 修改 + * + * @param dict + * @return + */ + DictDTO modifyDict(DictDTO dict, Long operateUserId); + + /** + * 删除 + * + * @param dict + */ + void removeDict(DictDTO dict, Long operateUserId); + + /** + * 查询 + * + * @param dict + */ + void page(DictQueryDTO dict); + + DictDTO find(DictQueryDTO dict); + + DictDTO findOrInsert(DictQueryDTO dict, Long operateUserId); +} diff --git a/src/main/java/com/newyetai/component/dict/service/impl/DictCacheServiceImpl.java b/src/main/java/com/newyetai/component/dict/service/impl/DictCacheServiceImpl.java new file mode 100644 index 0000000..699d7f0 --- /dev/null +++ b/src/main/java/com/newyetai/component/dict/service/impl/DictCacheServiceImpl.java @@ -0,0 +1,55 @@ +package com.newyetai.component.dict.service.impl; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.CachePut; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +import com.newyetai.common.constant.CacheConstants; +import com.newyetai.common.util.TreeHelper; +import com.newyetai.component.dict.dao.DictDetailMapper; +import com.newyetai.component.dict.dto.DictDetailDTO; +import com.newyetai.component.dict.dto.DictDetailQueryDTO; +import com.newyetai.component.dict.service.DictCacheService; + +/** + * @author sr on 2020-04-03 + */ +@Service +public class DictCacheServiceImpl implements DictCacheService { + + @Autowired + private DictDetailMapper dictDetailMapper; + + @Override + @Cacheable(key = "#dictCode", value = CacheConstants.CACHE_NAME_DICT) + public List getTreeDictDetailByCode(String dictCode) { + DictDetailQueryDTO queryDTO = DictDetailQueryDTO.builder().dictCode(dictCode).build(); + queryDTO.disablePage(); + List details = + dictDetailMapper.list(null, queryDTO); + return TreeHelper.buildTree(null, details); + } + + @Override + @CachePut(key = "#dictCode", value = CacheConstants.CACHE_NAME_DICT) + public List putTreeDictDetailByCode(String dictCode) { + return this.getTreeDictDetailByCode(dictCode); + } + + @Override + @CacheEvict(key = "#dictCode", value = CacheConstants.CACHE_NAME_DICT) + public void removeTreeDictDetailByCode(String dictCode) { + // do nothing... + } + + @Override + @CacheEvict(allEntries = true, value = CacheConstants.CACHE_NAME_DICT) + public void removeTreeDictDetail() { + // do nothing... + } + +} diff --git a/src/main/java/com/newyetai/component/dict/service/impl/DictDetailServiceImpl.java b/src/main/java/com/newyetai/component/dict/service/impl/DictDetailServiceImpl.java new file mode 100644 index 0000000..6d8caa6 --- /dev/null +++ b/src/main/java/com/newyetai/component/dict/service/impl/DictDetailServiceImpl.java @@ -0,0 +1,150 @@ +package com.newyetai.component.dict.service.impl; + +import com.google.common.base.CaseFormat; +import com.google.common.collect.Maps; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.component.dict.dao.DictDetailMapper; +import com.newyetai.component.dict.dto.*; +import com.newyetai.component.dict.mapstruct.DictDetailMapMapper; +import com.newyetai.component.dict.service.DictCacheService; +import com.newyetai.component.dict.service.DictDetailService; +import com.newyetai.component.dict.service.DictService; +import com.newyetai.tkmybatis.pojo.Page; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * + * @author Rey(leijiaping@newyetai.com) + * + */ +@Service +public class DictDetailServiceImpl implements DictDetailService { + + @Resource + private DictDetailMapper dictDetailMapper; + + @Autowired + private DictService dictService; + + @Autowired + private DictCacheService dictCacheService; + + @Override + public Map getMapByTypes(List types) { + if (CollectionUtils.isEmpty(types)) { + return Maps.newHashMap(); + } + Map dictCodeMap = types.stream().collect(Collectors.toMap(dictCode -> dictCode, dictCode -> CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, dictCode))); + + List dictDetails = dictDetailMapper + .getDropdownDictDetails(DictDetailQueryDTO.builder().types(types.toArray(new String[0])).build()); + + return dictDetails.stream().collect(Collectors.toMap(item -> + dictCodeMap.get(item.getType()) + item.getDictDetailCode() + , DropdownDictDetailDTO::getDictDetailName)); + } + + @Override + public void createDictDetail(DictDetailDTO dictDetail, Long operateUserId) { + dictDetailMapper.saveEntity(DictDetailMapMapper.INSTANCE.toEntity(dictDetail), operateUserId); + refreshDictCache(dictDetail.getDictId()); + } + + @Override + public void modifyDictDetail(DictDetailDTO dictDetail, Long operateUserId) { + dictDetailMapper.updateEntitySelective(DictDetailMapMapper.INSTANCE.toEntity(dictDetail), operateUserId); + refreshDictCache(dictDetail.getDictId()); + } + + @Override + public void removeDictDetail(DictDetailDTO dictDetail, Long operateUserId) { + dictDetailMapper.deleteEntity(DictDetailMapMapper.INSTANCE.toEntity(dictDetail), operateUserId); + refreshDictCache(dictDetail.getDictId()); + } + + /** + * 刷新缓存 + * + * @param dictDetail 字典详情 + * @author sr on 2020-07-30 + */ + private void refreshDictCache(Long dictId) { + Assert.notNull(dictId, "字典id不能为空"); + this.refreshDictCache(DictDetailQueryDTO.builder().dictId(dictId).build()); + } + + @Override + public void page(Page page, DictDetailQueryDTO dictDetail) { + dictDetailMapper.list(page, dictDetail); + } + + @Override + public Collection getDropdownDictDetails(DictDetailQueryDTO dictDetailDTO) { + boolean dtoIsNull = dictDetailDTO == null || (StringUtils.isBlank(dictDetailDTO.getType()) + && ArrayUtils.isEmpty(dictDetailDTO.getTypes())); + if (dtoIsNull) { + return null; + } + return dictDetailMapper.getDropdownDictDetails(dictDetailDTO); + } + + @Override + public List list(DictDetailQueryDTO dictDetail) { + return dictDetailMapper.list(null, dictDetail); + } + + @Override + public Map getDictDetailsMap(String parentType) { + DictDetailQueryDTO queryDTO = new DictDetailQueryDTO(); + queryDTO.setType(parentType); + Collection details = getDropdownDictDetails(queryDTO); + if (details == null || details.size() == 0) { + return null; + } + Map dictMap = Maps.newHashMapWithExpectedSize(details.size()); + for (DropdownDictDetailDTO dto : details) { + dictMap.put(dto.getDictDetailName(), dto); + } + return dictMap; + } + + @Override + public Map getDictDetailMap(String parentCode, Long operateUserId) { + DictDTO dict = dictService.findOrInsert(DictQueryDTO.builder().dictCode(parentCode).build(), operateUserId); + List details = list(DictDetailQueryDTO.builder().dictId(dict.getId()).build()); + if (details == null || details.size() == 0) { + return Maps.newHashMap(); + } + Map dictMap = Maps.newHashMapWithExpectedSize(details.size()); + for (DictDetailDTO detail : details) { + dictMap.put(detail.getDictDetailCode(), detail.getDictDetailName()); + } + return dictMap; + } + + @Override + public DictDetailDTO findDetail(Long dictId, String code, Long parentId) { + List list = list(DictDetailQueryDTO.builder().dictId(dictId).dictDetailCode(code).parentId(parentId).build()); + if(CollectionUtils.isEmpty(list)){ + return null; + } + return list.get(0); + } + + @Override + public void refreshDictCache(DictDetailQueryDTO dictDetailQueryDTO) { + dictDetailQueryDTO.setNeedPage(Boolean.FALSE); + List dictCodes = dictDetailMapper.getDictCode(dictDetailQueryDTO); + dictCodes.forEach(dictCode -> dictCacheService.putTreeDictDetailByCode(dictCode)); + } +} diff --git a/src/main/java/com/newyetai/component/dict/service/impl/DictServiceImpl.java b/src/main/java/com/newyetai/component/dict/service/impl/DictServiceImpl.java new file mode 100644 index 0000000..454e320 --- /dev/null +++ b/src/main/java/com/newyetai/component/dict/service/impl/DictServiceImpl.java @@ -0,0 +1,96 @@ +package com.newyetai.component.dict.service.impl; + +import com.newyetai.common.constant.ExceptionMsgs; +import com.newyetai.common.exception.util.ExceptionUtils; +import com.newyetai.component.dict.dao.DictMapper; +import com.newyetai.component.dict.dto.DictDTO; +import com.newyetai.component.dict.dto.DictQueryDTO; +import com.newyetai.component.dict.entity.Dict; +import com.newyetai.component.dict.mapstruct.DictMapMapper; +import com.newyetai.component.dict.service.DictCacheService; +import com.newyetai.component.dict.service.DictService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author Rey(leijiaping @ newyetai.com) + */ +@Service +public class DictServiceImpl implements DictService { + + @Autowired + private DictMapper dictMapper; + + @Autowired + private DictCacheService dictCacheService; + + + @Override + public DictDTO createDict(DictDTO dict, Long operateUserId) { + String dictCode = dict.getDictCode(); + ExceptionUtils.throwBusinessException( + dictMapper.existsEntity(Dict.builder().dictCode(dictCode).build()), + ExceptionMsgs.ENTITY_HAS_EXISTS); + Dict dictEntity=DictMapMapper.INSTANCE.toEntity(dict); + dictMapper.saveEntity(dictEntity, operateUserId); + dictCacheService.putTreeDictDetailByCode(dictCode); + dict.setId(dictEntity.getId()); + return dict; + } + + @Override + public DictDTO modifyDict(DictDTO dict, Long operateUserId) { + String dictCode = dict.getDictCode(); + Long dictId = dict.getId(); + ExceptionUtils.throwBusinessException( + dictMapper.existsEntity(Dict.builder().id(dictId).dictCode(dictCode).build()), + ExceptionMsgs.ENTITY_HAS_EXISTS); + dictMapper.updateEntitySelective(DictMapMapper.INSTANCE.toEntity(dict), operateUserId); + refreshDictCache(dictId, dictCode); + return dict; + } + + private void refreshDictCache(Long dictId, String newDictCode) { + String dictCode = dictMapper.getById(dictId).getDictCode(); + if (newDictCode != null && !dictCode.equals(newDictCode)) { + dictCacheService.putTreeDictDetailByCode(newDictCode); + } + dictCacheService.putTreeDictDetailByCode(dictCode); + } + + @Override + public void removeDict(DictDTO dict, Long operateUserId) { + dictMapper.deleteEntity(DictMapMapper.INSTANCE.toEntity(dict), operateUserId); + refreshDictCache(dict.getId(), null); + } + + @Override + public void page(DictQueryDTO dict) { + dictMapper.list(dict); + } + + @Override + public DictDTO find(DictQueryDTO dict) { + List dictDtos = dictMapper.list(dict); + return dictDtos.isEmpty() ? null : dictDtos.get(0); + } + + @Override + public DictDTO findOrInsert(DictQueryDTO dictQueryDTO, Long operateUserId) { + DictDTO result = find(dictQueryDTO); + if (result == null) { + synchronized (this) { + result = find(dictQueryDTO); + if (result == null) { + Dict dict = DictMapMapper.INSTANCE.toEntity(dictQueryDTO); + dictMapper.saveEntity(dict, operateUserId); + result = DictMapMapper.INSTANCE.toDto(dict); + } + } + } + return result; + } + +} diff --git a/src/main/java/com/newyetai/component/dict/util/DictUtils.java b/src/main/java/com/newyetai/component/dict/util/DictUtils.java new file mode 100644 index 0000000..10a70d8 --- /dev/null +++ b/src/main/java/com/newyetai/component/dict/util/DictUtils.java @@ -0,0 +1,64 @@ +package com.newyetai.component.dict.util; + +import java.util.List; +import java.util.Map;import java.util.stream.Collector; +import java.util.stream.Collectors; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.newyetai.component.dict.dto.DictDetailDTO; +import com.newyetai.component.dict.entity.Dict; +import com.newyetai.component.dict.service.DictCacheService; + +/** + * 字典工具类 + * @author sr on 2019-12-09 + */ +@Component +public class DictUtils { + + private static DictCacheService dictCacheService; + + @Autowired + public void setDictCacheService(DictCacheService dictCacheService) { + this.dictCacheService = dictCacheService; + } + /** + * 校验对应字典编码是否存在 + * @param id + * @param dictCode + * @return + * @author sr on 2019-12-09 + */ + public static Dict toCheckDuplicateCode(Dict dict) { + return Dict.builder().id(dict.getId()).dictCode(dict.getDictCode()).build(); + } + + public static List getCacheTree(String dictCode){ + return dictCacheService.getTreeDictDetailByCode(dictCode); + } + + /** + * 获取数据字典明细map(detailCode:detailName) + * @param dictCode + * @return + * @author sr on 2022-02-21 + */ + public static Map getCodeNameMap(String dictCode) { + return dictCacheService.getTreeDictDetailByCode(dictCode).stream().collect( + Collectors.toMap(DictDetailDTO::getDictDetailCode, DictDetailDTO::getDictDetailName)); + } + + /** + * 获取数据字典明细map(detailName:detailCode) + * @param dictCode + * @return + * @author sr on 2022-06-30 + */ + public static Map getNameCodeMap(String dictCode) { + return dictCacheService.getTreeDictDetailByCode(dictCode).stream().collect( + Collectors.toMap(DictDetailDTO::getDictDetailName, DictDetailDTO::getDictDetailCode)); + } + +} diff --git a/src/main/java/com/newyetai/component/dropdown/constant/DropdownConstants.java b/src/main/java/com/newyetai/component/dropdown/constant/DropdownConstants.java new file mode 100644 index 0000000..97096ac --- /dev/null +++ b/src/main/java/com/newyetai/component/dropdown/constant/DropdownConstants.java @@ -0,0 +1,23 @@ +package com.newyetai.component.dropdown.constant; + +/** + * 通用配置常量类 + * @author sr on 2019-10-22 + */ +public class DropdownConstants { + + /** 字典 **/ + public static final String PROVIDER_TYPE_DICT = "dict"; + /** 编码配置 **/ + public static final String PROVIDER_TYPE_CODE_SETTING = "code_setting"; + + + /** 参数名:编码 **/ + public static final String PARAM_CODE = "code"; + /** 参数名:编码配置类型 **/ + public static final String PARAM_CODE_TYPE = "codeType"; + /** 参数名:编码串 **/ + public static final String PARAM_CODES = "codes"; + + +} diff --git a/src/main/java/com/newyetai/component/dropdown/controller/DropdownController.java b/src/main/java/com/newyetai/component/dropdown/controller/DropdownController.java new file mode 100644 index 0000000..8f2212d --- /dev/null +++ b/src/main/java/com/newyetai/component/dropdown/controller/DropdownController.java @@ -0,0 +1,63 @@ +package com.newyetai.component.dropdown.controller; + +import java.util.List; +import java.util.Map; + +import org.apache.commons.collections.MapUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.component.dropdown.dto.DropdownDTO; +import com.newyetai.component.dropdown.service.impl.DropdownServiceImpl; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +/** + * @author sr on 2019-10-22 + */ +@Api(tags = "下拉框") +@RestController +@RequestMapping("/anon/dropdown") +@ConditionalOnProperty(name = CommonConstants.USELOCAL_KEY, havingValue = "true", matchIfMissing = true) +public class DropdownController { + + @Autowired + private DropdownServiceImpl dropdownService; + + @GetMapping("/list") + @ApiOperation("获取数据字典列表") + public AlitaResult> list(DropdownDTO dropdownDTO, + @RequestHeader(value = "OEM", defaultValue = "1") String org) { + String type = dropdownDTO.getType(); + if (type == null || "dict".equals(type)) { + Map map = dropdownDTO.getParamMap(); + String codes = MapUtils.getString(map, "dictCode", ""); + map.put("dictCode", codes.replace("oem_config", "oem_config_" + org)); + dropdownDTO.setParams(JsonUtils.toJsonString(map)); + } + return AlitaResult.success(dropdownService.list(dropdownDTO, UserContextHolder.getLoginUser())); + } + + @GetMapping("/map") + @ApiOperation("获取多个数据字典map") + public AlitaResult> map(DropdownDTO dropdownDTO, + @RequestHeader(value = "OEM", defaultValue = "1") String org) { + String type = dropdownDTO.getType(); + if (type == null || "dict".equals(type)) { + Map map = dropdownDTO.getParamMap(); + String codes = MapUtils.getString(map, "codes", ""); + map.put("codes", codes.replace("oem_config", "oem_config_" + org)); + dropdownDTO.setParams(JsonUtils.toJsonString(map)); + } + return AlitaResult.success(dropdownService.map(dropdownDTO, UserContextHolder.getLoginUser())); + } +} diff --git a/src/main/java/com/newyetai/component/dropdown/dto/DropdownDTO.java b/src/main/java/com/newyetai/component/dropdown/dto/DropdownDTO.java new file mode 100644 index 0000000..a63ac2e --- /dev/null +++ b/src/main/java/com/newyetai/component/dropdown/dto/DropdownDTO.java @@ -0,0 +1,45 @@ +package com.newyetai.component.dropdown.dto; + +import java.io.Serializable; +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; + +import com.google.common.collect.Maps; +import com.newyetai.common.util.JsonUtils; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 下拉框对象 + * + * @author sr on 2019-11-05 + */ +@ApiModel("下拉框对象") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class DropdownDTO implements Serializable { + + /** **/ + private static final long serialVersionUID = -8053031023722973608L; + + /** @link DropdownConstants **/ + @ApiModelProperty("类型") + private String type; + + @ApiModelProperty("参数") + private String params; + + public Map getParamMap() { + return StringUtils.isBlank(params) ? Maps.newHashMap() : JsonUtils.toMap(params); + } + + +} diff --git a/src/main/java/com/newyetai/component/dropdown/service/DropdownProvider.java b/src/main/java/com/newyetai/component/dropdown/service/DropdownProvider.java new file mode 100644 index 0000000..481395c --- /dev/null +++ b/src/main/java/com/newyetai/component/dropdown/service/DropdownProvider.java @@ -0,0 +1,39 @@ +package com.newyetai.component.dropdown.service; + +import java.util.List; +import java.util.Map; + +import com.newyetai.usercenter.dto.IUserDetail; + +/** + * 下拉框提供者 + * @author sr on 2019-10-22 + */ +public interface DropdownProvider { + + /** + * 下拉框类型 + * @return + * @author sr on 2019-11-05 + */ + String getType(); + + /** + * 根据参数获取下拉框对象列表(list) + * @param params + * @param userDto + * @return + * @author sr on 2019-11-05 + */ + List list(Map params, IUserDetail userDto); + + /** + * 根据参数获取多组下拉对象列表(map) + * @param params + * @param userDto + * @return + * @author sr on 2019-11-05 + */ + Map map(Map params, IUserDetail userDto); + +} diff --git a/src/main/java/com/newyetai/component/dropdown/service/DropdownService.java b/src/main/java/com/newyetai/component/dropdown/service/DropdownService.java new file mode 100644 index 0000000..9c30609 --- /dev/null +++ b/src/main/java/com/newyetai/component/dropdown/service/DropdownService.java @@ -0,0 +1,32 @@ +package com.newyetai.component.dropdown.service; + +import java.util.List; +import java.util.Map; + +import com.newyetai.component.dropdown.dto.DropdownDTO; +import com.newyetai.usercenter.dto.IUserDetail; + +/** + * 下拉框service + * @author sr on 2019-10-22 + */ +public interface DropdownService { + + /** + * 获取单个下拉框列表 + * @param dropdownDTO + * @param userDto 可为空 + * @return + * @author sr on 2019-11-05 + */ + List list(DropdownDTO dropdownDTO, IUserDetail userDto); + + /** + * 获取多组下拉框 + * @param dropdownDTO + * @param userDto 可为空 + * @return + * @author sr on 2019-11-05 + */ + Map map(DropdownDTO dropdownDTO, IUserDetail userDto); +} diff --git a/src/main/java/com/newyetai/component/dropdown/service/impl/CodeSettingDropdownProvider.java b/src/main/java/com/newyetai/component/dropdown/service/impl/CodeSettingDropdownProvider.java new file mode 100644 index 0000000..a7fcd2a --- /dev/null +++ b/src/main/java/com/newyetai/component/dropdown/service/impl/CodeSettingDropdownProvider.java @@ -0,0 +1,46 @@ +package com.newyetai.component.dropdown.service.impl; + +import java.util.List; +import java.util.Map; + +import org.apache.commons.collections.MapUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.newyetai.codesetting.service.CodeSettingService; +import com.newyetai.common.exception.NoneLoginException; +import com.newyetai.common.exception.util.ExceptionUtils; +import com.newyetai.component.dropdown.constant.DropdownConstants; +import com.newyetai.component.dropdown.service.DropdownProvider; +import com.newyetai.usercenter.dto.IUserDetail; + +/** + * 编码配置下拉框 + * + * @author sr on 2019-11-05 + */ +@Service +public class CodeSettingDropdownProvider implements DropdownProvider { + + @Autowired + private CodeSettingService codeSettingService; + + @Override + public Map map(Map params, IUserDetail userDto) { + return null; + } + + @Override + public String getType() { + return DropdownConstants.PROVIDER_TYPE_CODE_SETTING; + } + + @Override + public List list(Map params, IUserDetail userDto) { + String codeSettingType = MapUtils.getString(params, DropdownConstants.PARAM_CODE_TYPE); + ExceptionUtils.throwBusinessException(userDto == null, NoneLoginException.ERROR_MSG); + String orgType = userDto.getOrgType(); + return codeSettingService.queryCode(codeSettingType, orgType); + } + +} diff --git a/src/main/java/com/newyetai/component/dropdown/service/impl/DictDropdownProvider.java b/src/main/java/com/newyetai/component/dropdown/service/impl/DictDropdownProvider.java new file mode 100644 index 0000000..1b5a1cf --- /dev/null +++ b/src/main/java/com/newyetai/component/dropdown/service/impl/DictDropdownProvider.java @@ -0,0 +1,63 @@ +package com.newyetai.component.dropdown.service.impl; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.google.common.collect.Maps; +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.component.dict.dao.DictDetailMapper; +import com.newyetai.component.dict.dto.DictDetailDTO; +import com.newyetai.component.dict.dto.DictDetailQueryDTO; +import com.newyetai.component.dict.entity.DictDetail; +import com.newyetai.component.dict.service.DictCacheService; +import com.newyetai.component.dropdown.constant.DropdownConstants; +import com.newyetai.component.dropdown.service.DropdownProvider; +import com.newyetai.usercenter.dto.IUserDetail; + +/** + * 数据字典下拉框 + * + * @author sr on 2019-11-05 + */ +@Service +public class DictDropdownProvider implements DropdownProvider { + + @Autowired + private DictDetailMapper dictDetailMapper; + + @Autowired + private DictCacheService dictCacheService; + + @Override + public Map> map(Map params, IUserDetail userDto) { + String codeString = MapUtils.getString(params, DropdownConstants.PARAM_CODES); + if (StringUtils.isBlank(codeString)) { + return Collections.emptyMap(); + } + String[] codes = codeString.split(CommonConstants.COMMA); + Map> resultMap = Maps.newHashMapWithExpectedSize(codes.length); + for (String code : codes) { + List details = dictCacheService.getTreeDictDetailByCode(code); + resultMap.put(code, details); + } + return resultMap; + } + + @Override + public String getType() { + return DropdownConstants.PROVIDER_TYPE_DICT; + } + + @Override + public List list(Map params, IUserDetail userDto) { + return dictDetailMapper.list(null, JsonUtils.objToClassObj(params, DictDetailQueryDTO.class)); + } + +} diff --git a/src/main/java/com/newyetai/component/dropdown/service/impl/DropdownServiceImpl.java b/src/main/java/com/newyetai/component/dropdown/service/impl/DropdownServiceImpl.java new file mode 100644 index 0000000..28050e0 --- /dev/null +++ b/src/main/java/com/newyetai/component/dropdown/service/impl/DropdownServiceImpl.java @@ -0,0 +1,47 @@ +package com.newyetai.component.dropdown.service.impl; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.newyetai.component.dropdown.constant.DropdownConstants; +import com.newyetai.component.dropdown.dto.DropdownDTO; +import com.newyetai.component.dropdown.service.DropdownProvider; +import com.newyetai.component.dropdown.service.DropdownService; +import com.newyetai.usercenter.dto.IUserDetail; + +/** + * 下拉框 + * + * @author sr on 2019-10-22 + */ +@Service +public class DropdownServiceImpl implements DropdownService { + + private Map providerMap; + + @Autowired + private void providers(List dropdownProviders) { + providerMap = dropdownProviders.stream() + .collect(Collectors.toMap(DropdownProvider::getType, provider -> provider)); + } + + private DropdownProvider getProvider(String type) { + DropdownProvider provider = providerMap.get(type); + return provider == null ? providerMap.get(DropdownConstants.PROVIDER_TYPE_DICT) : provider; + } + + @Override + public List list(DropdownDTO dropdownDTO, IUserDetail userDto) { + return getProvider(dropdownDTO.getType()).list(dropdownDTO.getParamMap(), userDto); + } + + @Override + public Map map(DropdownDTO dropdownDTO, IUserDetail userDto) { + return getProvider(dropdownDTO.getType()).map(dropdownDTO.getParamMap(), userDto); + } + +} diff --git a/src/main/java/com/newyetai/component/dynamictable/constant/DynamicTableConstants.java b/src/main/java/com/newyetai/component/dynamictable/constant/DynamicTableConstants.java new file mode 100644 index 0000000..c51cf24 --- /dev/null +++ b/src/main/java/com/newyetai/component/dynamictable/constant/DynamicTableConstants.java @@ -0,0 +1,8 @@ +package com.newyetai.component.dynamictable.constant; + +/** + * @author sr on 2024-04-09 + */ +public interface DynamicTableConstants { + +} diff --git a/src/main/java/com/newyetai/component/dynamictable/controller/DynamicTableController.java b/src/main/java/com/newyetai/component/dynamictable/controller/DynamicTableController.java new file mode 100644 index 0000000..d56f37d --- /dev/null +++ b/src/main/java/com/newyetai/component/dynamictable/controller/DynamicTableController.java @@ -0,0 +1,65 @@ +package com.newyetai.component.dynamictable.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.component.dynamictable.dto.DynamicTableCreateDTO; +import com.newyetai.component.dynamictable.dto.DynamicTableDTO; +import com.newyetai.component.dynamictable.dto.DynamicTableModifyDTO; +import com.newyetai.component.dynamictable.dto.DynamicTableQueryDTO; +import com.newyetai.component.dynamictable.service.DynamicTableService; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +/** + * @author sr on 2024-04-09 + */ +@RestController +@RequestMapping("dynamic_table") +@Api(tags = "动态表格") +public class DynamicTableController { + + @Autowired + private DynamicTableService dynamicTableService; + + @PostMapping("/create") + @ApiOperation("创建") + public AlitaResult create( + @Validated @RequestBody DynamicTableCreateDTO dynamicTableCreateDTO){ + dynamicTableCreateDTO.setUserId(UserContextHolder.getExistLoginUserId()); + return AlitaResult.success(dynamicTableService.create(dynamicTableCreateDTO)); + } + + @PostMapping("/modify") + @ApiOperation("修改") + public AlitaResult modify( + @Validated @RequestBody DynamicTableModifyDTO dynamicTableModifyDTO){ + dynamicTableModifyDTO.setUserId(UserContextHolder.getExistLoginUserId()); + dynamicTableService.modify(dynamicTableModifyDTO); + return AlitaResult.success(true); + } + + @DeleteMapping("/remove/{tableType}") + @ApiOperation("删除") + public AlitaResult remove(@PathVariable String tableType){ + dynamicTableService.remove(tableType); + return AlitaResult.success(true); + } + + @GetMapping("/find") + @ApiOperation("查询") + public AlitaResult find(DynamicTableQueryDTO dynamicTableQueryDTO){ + return AlitaResult.success(dynamicTableService.find(dynamicTableQueryDTO)); + } + +} diff --git a/src/main/java/com/newyetai/component/dynamictable/dao/DynamicTableMapper.java b/src/main/java/com/newyetai/component/dynamictable/dao/DynamicTableMapper.java new file mode 100644 index 0000000..1a7e22d --- /dev/null +++ b/src/main/java/com/newyetai/component/dynamictable/dao/DynamicTableMapper.java @@ -0,0 +1,28 @@ +package com.newyetai.component.dynamictable.dao; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.newyetai.component.dynamictable.dto.DynamicTableDTO; +import com.newyetai.component.dynamictable.dto.DynamicTableQueryDTO; +import com.newyetai.component.dynamictable.entity.DynamicTable; +import com.newyetai.tkmybatis.mybatis.MyMapper; + +/** + * 动态表格 + * + * @author sr on 2024-04-09 + */ +public interface DynamicTableMapper extends MyMapper { + + /** + * 查询 + * + * @param dynamicTableQueryDTO + * @return + * @author sr on 2024-04-09 + */ + List listDynamicTableDTO(@Param("param") DynamicTableQueryDTO dynamicTableQueryDTO); + +} diff --git a/src/main/java/com/newyetai/component/dynamictable/dto/DynamicTableColumnDTO.java b/src/main/java/com/newyetai/component/dynamictable/dto/DynamicTableColumnDTO.java new file mode 100644 index 0000000..d5b3556 --- /dev/null +++ b/src/main/java/com/newyetai/component/dynamictable/dto/DynamicTableColumnDTO.java @@ -0,0 +1,38 @@ +package com.newyetai.component.dynamictable.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotBlank; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 动态表格列 + * @author sr on 2024-04-09 + */ +@NoArgsConstructor +@AllArgsConstructor +@Data +@Builder +public class DynamicTableColumnDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = -218789958565751460L; + /** 列名 **/ + @NotBlank(message = "列名不能为空") + private String title; + /** 列标识 **/ + @NotBlank(message = "列标识不能为空") + private String dataIndex; + /** 固定类型 **/ + private String fixed; + /** 宽度 **/ + private Integer width; + /** 排序 **/ + private Integer order; + + +} diff --git a/src/main/java/com/newyetai/component/dynamictable/dto/DynamicTableCreateDTO.java b/src/main/java/com/newyetai/component/dynamictable/dto/DynamicTableCreateDTO.java new file mode 100644 index 0000000..69c42f7 --- /dev/null +++ b/src/main/java/com/newyetai/component/dynamictable/dto/DynamicTableCreateDTO.java @@ -0,0 +1,42 @@ +package com.newyetai.component.dynamictable.dto; + +import java.util.List; + +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import com.newyetai.common.dto.BaseOperateDTO; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2024-04-09 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Builder +@Data +@ApiModel(description = "动态表格") +public class DynamicTableCreateDTO extends BaseOperateDTO { + + /** **/ + private static final long serialVersionUID = 1L; + + /** 表格类型 **/ + @NotBlank(message = "表格类型不能为空") + private String tableType; + /** 用户id **/ + private Long userId; + /** 表格列配置数据 **/ + @NotNull(message = "表格配置不能为空") + @Valid + private List columnDTOs; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/dynamictable/dto/DynamicTableDTO.java b/src/main/java/com/newyetai/component/dynamictable/dto/DynamicTableDTO.java new file mode 100644 index 0000000..205b70c --- /dev/null +++ b/src/main/java/com/newyetai/component/dynamictable/dto/DynamicTableDTO.java @@ -0,0 +1,53 @@ +package com.newyetai.component.dynamictable.dto; + +import java.util.List; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.ListUtils; +import org.apache.commons.lang3.StringUtils; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.google.common.collect.Lists; +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.common.util.JsonUtils; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.Builder.Default; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2024-04-09 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@ApiModel(description = "动态表格") +public class DynamicTableDTO extends BaseDTO { + + /** **/ + private static final long serialVersionUID = 1L; + + /** 类型 **/ + private String tableType; + /** 用户id **/ + private Long userId; + /** 表格列数据json **/ + @JsonIgnore + private String columnData; + @Default + private List columnDTOs = ListUtils.EMPTY_LIST; + + public void setColumnData(String columnData) { + this.columnData = columnData; + if (StringUtils.isNotBlank(columnData)) { + columnDTOs = JsonUtils.toList(columnData, DynamicTableColumnDTO.class); + } + } + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/dynamictable/dto/DynamicTableModifyDTO.java b/src/main/java/com/newyetai/component/dynamictable/dto/DynamicTableModifyDTO.java new file mode 100644 index 0000000..a940426 --- /dev/null +++ b/src/main/java/com/newyetai/component/dynamictable/dto/DynamicTableModifyDTO.java @@ -0,0 +1,43 @@ +package com.newyetai.component.dynamictable.dto; + +import java.util.List; + +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import com.newyetai.common.dto.BaseOperateDTO; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2024-04-09 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Builder +@Data +@ApiModel(description = "动态表格") +public class DynamicTableModifyDTO extends BaseOperateDTO { + + /** **/ + private static final long serialVersionUID = 1L; + + /** 表格类型 **/ + @NotBlank(message = "表格类型不能为空") + private String tableType; + /** 用户id **/ + private Long userId; + /** 表格列配置数据 **/ + @NotNull(message = "表格配置不能为空") + @Valid + private List columnDTOs; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/dynamictable/dto/DynamicTableQueryDTO.java b/src/main/java/com/newyetai/component/dynamictable/dto/DynamicTableQueryDTO.java new file mode 100644 index 0000000..e20bc67 --- /dev/null +++ b/src/main/java/com/newyetai/component/dynamictable/dto/DynamicTableQueryDTO.java @@ -0,0 +1,33 @@ +package com.newyetai.component.dynamictable.dto; + + +import com.newyetai.common.dto.PageQueryDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2024-04-09 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "动态表格查询条件") +public class DynamicTableQueryDTO extends PageQueryDTO{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + /** 表格类型 **/ + private String tableType; + /** 用户id **/ + private Long userId; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/dynamictable/entity/DynamicTable.java b/src/main/java/com/newyetai/component/dynamictable/entity/DynamicTable.java new file mode 100644 index 0000000..00164cb --- /dev/null +++ b/src/main/java/com/newyetai/component/dynamictable/entity/DynamicTable.java @@ -0,0 +1,36 @@ +package com.newyetai.component.dynamictable.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 动态表格 + * + * @author sr on 2024-04-09 + */ +@TableName("uc_dynamic_table") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +public class DynamicTable extends BaseEntity { + + /** **/ + private static final long serialVersionUID = 1L; + + /** 类型 **/ + private String tableType; + /** 用户id **/ + private Long userId; + /** 表格列数据json **/ + private String columnData; + + +} diff --git a/src/main/java/com/newyetai/component/dynamictable/mapper/DynamicTableMapper.xml b/src/main/java/com/newyetai/component/dynamictable/mapper/DynamicTableMapper.xml new file mode 100644 index 0000000..8adf150 --- /dev/null +++ b/src/main/java/com/newyetai/component/dynamictable/mapper/DynamicTableMapper.xml @@ -0,0 +1,22 @@ + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/dynamictable/mapstruct/DynamicTableMapMapper.java b/src/main/java/com/newyetai/component/dynamictable/mapstruct/DynamicTableMapMapper.java new file mode 100644 index 0000000..b61c0d5 --- /dev/null +++ b/src/main/java/com/newyetai/component/dynamictable/mapstruct/DynamicTableMapMapper.java @@ -0,0 +1,39 @@ +package com.newyetai.component.dynamictable.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.newyetai.component.dynamictable.dto.DynamicTableCreateDTO; +import com.newyetai.component.dynamictable.dto.DynamicTableDTO; +import com.newyetai.component.dynamictable.dto.DynamicTableModifyDTO; +import com.newyetai.component.dynamictable.entity.DynamicTable; + +/** + * @author sr on 2024-04-09 + */ +@Mapper +public interface DynamicTableMapMapper { + + DynamicTableMapMapper INSTANCE = + Mappers.getMapper(DynamicTableMapMapper.class); + + /** + * dto to entity + * + * @param dynamicTableDto + * @return + * @author sr on 2024-04-09 + */ + DynamicTable toEntity( + DynamicTableDTO dynamicTableDto); + + + /** + * @param dynamicTableCreateDTO + * @return + * @author sr on 2024-04-09 + */ + DynamicTable toEntity(DynamicTableCreateDTO dynamicTableCreateDTO); + DynamicTable toEntity(DynamicTableModifyDTO dynamicTableModifyDTO); + +} diff --git a/src/main/java/com/newyetai/component/dynamictable/service/DynamicTableService.java b/src/main/java/com/newyetai/component/dynamictable/service/DynamicTableService.java new file mode 100644 index 0000000..128736a --- /dev/null +++ b/src/main/java/com/newyetai/component/dynamictable/service/DynamicTableService.java @@ -0,0 +1,69 @@ +package com.newyetai.component.dynamictable.service; + +import java.util.List; + +import com.newyetai.component.dynamictable.dto.DynamicTableCreateDTO; +import com.newyetai.component.dynamictable.dto.DynamicTableDTO; +import com.newyetai.component.dynamictable.dto.DynamicTableModifyDTO; +import com.newyetai.component.dynamictable.dto.DynamicTableQueryDTO; + +/** + * 动态表格 + * + * @author sr on 2024-04-09 + */ +public interface DynamicTableService { + + /** + * 新增 + * + * @param dynamicTableCreateDTO + * @return + * @author sr on 2024-04-09 + */ + Long create(DynamicTableCreateDTO dynamicTableCreateDTO); + + /** + * 修改 + * + * @param dynamicTableOperateDTO + * @author sr on 2024-04-09 + */ + void modify(DynamicTableModifyDTO dynamicTableModifyDTO); + + /** + * 删除 + * + * @param tableType + * @author sr on 2024-04-09 + */ + void remove(String tableType); + + /** + * 查询 + * + * @param dynamicTableQueryDTO + * @return + * @author sr on 2024-04-09 + */ + List list(DynamicTableQueryDTO dynamicTableQueryDTO); + + /** + * 分页查询 + * + * @param dynamicTableQueryDTO + * @return + * @author sr on 2024-04-09 + */ + void page(DynamicTableQueryDTO dynamicTableQueryDTO); + + /** + * 单个查询 + * + * @param dynamicTableQueryDTO + * @return + * @author sr on 2024-04-09 + */ + DynamicTableDTO find(DynamicTableQueryDTO dynamicTableQueryDTO); + +} diff --git a/src/main/java/com/newyetai/component/dynamictable/service/impl/DynamicTableServiceImpl.java b/src/main/java/com/newyetai/component/dynamictable/service/impl/DynamicTableServiceImpl.java new file mode 100644 index 0000000..3ef562c --- /dev/null +++ b/src/main/java/com/newyetai/component/dynamictable/service/impl/DynamicTableServiceImpl.java @@ -0,0 +1,136 @@ +package com.newyetai.component.dynamictable.service.impl; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.common.util.ListUtil; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.component.dynamictable.dao.DynamicTableMapper; +import com.newyetai.component.dynamictable.dto.DynamicTableColumnDTO; +import com.newyetai.component.dynamictable.dto.DynamicTableCreateDTO; +import com.newyetai.component.dynamictable.dto.DynamicTableDTO; +import com.newyetai.component.dynamictable.dto.DynamicTableModifyDTO; +import com.newyetai.component.dynamictable.dto.DynamicTableQueryDTO; +import com.newyetai.component.dynamictable.entity.DynamicTable; +import com.newyetai.component.dynamictable.mapstruct.DynamicTableMapMapper; +import com.newyetai.component.dynamictable.service.DynamicTableService; +import com.newyetai.frame.redis.dto.LockDTO; +import com.newyetai.frame.redis.redisson.RedissonUtils; + +/** + * @author sr on 2024-04-09 + */ +@Service +public class DynamicTableServiceImpl implements DynamicTableService { + + @Autowired + private DynamicTableMapper dynamicTableMapper; + + public static LockDTO getLockDTO(Long userId, String tableType) { + Assert.notNull(userId, "用户id不能为空"); + Assert.notNull(tableType, "表格类型不能为空"); + return LockDTO.builder().methodName("dynamictable").tryLockWaitTime(0L) + .arg(userId.toString()) + .arg(tableType) + .failMsg("该用户表格配置正在被操作") + .build(); + } + + @Override + // @AutoUnLock + @Transactional + public Long create(DynamicTableCreateDTO dynamicTableCreateDTO) { + Long userId = dynamicTableCreateDTO.getUserId(); + String tableType = dynamicTableCreateDTO.getTableType(); + DynamicTableQueryDTO dynamicTableQueryDTO = DynamicTableQueryDTO.builder().userId(userId) + .tableType(tableType).build(); + // 校验 + List columnDTOs = dynamicTableCreateDTO.getColumnDTOs(); + checkColumn(columnDTOs); + + return RedissonUtils.lockAndSave(getLockDTO(userId, tableType), + () -> this.find(dynamicTableQueryDTO), () -> { + DynamicTable dynamicTable = + DynamicTableMapMapper.INSTANCE.toEntity(dynamicTableCreateDTO); + dynamicTable.setColumnData(JsonUtils.toDefaultJsonString(columnDTOs)); + dynamicTableMapper.saveEntity(dynamicTable); + return dynamicTable.getId(); + }); + + // Long userId = dynamicTableCreateDTO.getUserId(); + // String tableType = dynamicTableCreateDTO.getTableType(); + // DynamicTableQueryDTO dynamicTableQueryDTO = DynamicTableQueryDTO.builder().userId(userId) + // .tableType(tableType).build(); + // + // DynamicTableDTO dynamicTableDTO = this.find(dynamicTableQueryDTO); + // if (dynamicTableDTO != null) { + // return dynamicTableDTO.getId(); + // } + // LockDTO lockDTO = getPhoneLockDTO(userId, tableType); + // Assert.isTrue(RedissonUtils.tryLockAutomatically(lockDTO), lockDTO.getFailMsg()); + // dynamicTableQueryDTO = this.find(dynamicTableQueryDTO); + // if (dynamicTableDTO != null) { + // return dynamicTableDTO.getId(); + // } + // DynamicTable dynamicTable = DynamicTableMapMapper.INSTANCE.toEntity(dynamicTableCreateDTO); + // dynamicTableMapper.saveEntity(dynamicTable); + // return dynamicTable.getId(); + } + + private void checkColumn(List columnDTOs) { + Assert.isTrue(!columnDTOs.isEmpty(), "表格配置不能为空"); + } + + @Override + @Transactional + public void modify(DynamicTableModifyDTO dynamicTableModifyDTO) { + Long userId = dynamicTableModifyDTO.getUserId(); + String tableType = dynamicTableModifyDTO.getTableType(); + DynamicTableQueryDTO dynamicTableQueryDTO = DynamicTableQueryDTO.builder().userId(userId) + .tableType(tableType).build(); + // 校验 + List columnDTOs = dynamicTableModifyDTO.getColumnDTOs(); + checkColumn(columnDTOs); + + DynamicTableDTO dynamicTableDTO = this.find(dynamicTableQueryDTO); + Assert.notNull(dynamicTableDTO, "该用户表格配置不存在"); + DynamicTable dynamicTable = + DynamicTableMapMapper.INSTANCE.toEntity(dynamicTableModifyDTO); + dynamicTable + .setColumnData(JsonUtils.toDefaultJsonString(dynamicTableModifyDTO.getColumnDTOs())); + dynamicTableMapper.updateEntitySelective(dynamicTable); + } + + @Override + @Transactional + public void remove(String tableType) { + DynamicTableDTO dynamicTableDTO = + this.find(DynamicTableQueryDTO.builder().userId(UserContextHolder.getExistLoginUserId()) + .tableType(tableType).build()); + Assert.notNull(dynamicTableDTO, "该用户表格配置不存在"); + dynamicTableMapper.deleteEntity(DynamicTable.builder().id(dynamicTableDTO.getId()).build()); + } + + @Override + public List list(DynamicTableQueryDTO dynamicTableQueryDTO) { + dynamicTableQueryDTO.disablePage(); + return dynamicTableMapper.listDynamicTableDTO(dynamicTableQueryDTO); + } + + @Override + public void page(DynamicTableQueryDTO dynamicTableQueryDTO) { + dynamicTableMapper.listDynamicTableDTO(dynamicTableQueryDTO); + } + + @Override + public DynamicTableDTO find(DynamicTableQueryDTO dynamicTableQueryDTO) { + List dynamicTableDTOs = this.list(dynamicTableQueryDTO); + return ListUtil.first(dynamicTableDTOs); + } + +} diff --git a/src/main/java/com/newyetai/component/dynamictable/util/DynamicTableUtils.java b/src/main/java/com/newyetai/component/dynamictable/util/DynamicTableUtils.java new file mode 100644 index 0000000..67176ed --- /dev/null +++ b/src/main/java/com/newyetai/component/dynamictable/util/DynamicTableUtils.java @@ -0,0 +1,8 @@ +package com.newyetai.component.dynamictable.util; + +/** + * @author sr on 2024-04-09 + */ +public class DynamicTableUtils { + +} diff --git a/src/main/java/com/newyetai/component/exceptionrecord/dao/ExceptionRecordMapper.java b/src/main/java/com/newyetai/component/exceptionrecord/dao/ExceptionRecordMapper.java new file mode 100644 index 0000000..7f3591f --- /dev/null +++ b/src/main/java/com/newyetai/component/exceptionrecord/dao/ExceptionRecordMapper.java @@ -0,0 +1,11 @@ +package com.newyetai.component.exceptionrecord.dao; + + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.newyetai.component.exceptionrecord.entity.ExceptionRecord; + + +public interface ExceptionRecordMapper extends BaseMapper { + + int getExceptionRecordCount(); +} diff --git a/src/main/java/com/newyetai/component/exceptionrecord/emuns/ExceptionRecordSysEnum.java b/src/main/java/com/newyetai/component/exceptionrecord/emuns/ExceptionRecordSysEnum.java new file mode 100644 index 0000000..f9b8f81 --- /dev/null +++ b/src/main/java/com/newyetai/component/exceptionrecord/emuns/ExceptionRecordSysEnum.java @@ -0,0 +1,26 @@ +package com.newyetai.component.exceptionrecord.emuns; + +import com.baomidou.mybatisplus.annotation.EnumValue; + +/** + * 接口记录系统枚举 + */ +public enum ExceptionRecordSysEnum { + + HYG("1", "慧用工"), + XINPAI("2", "薪派"); + + @EnumValue + private final String source; + + private final String desc; + + ExceptionRecordSysEnum(String source, String desc) { + this.source = source; + this.desc = desc; + } + + public String getSource() { + return source; + } +} diff --git a/src/main/java/com/newyetai/component/exceptionrecord/entity/ExceptionRecord.java b/src/main/java/com/newyetai/component/exceptionrecord/entity/ExceptionRecord.java new file mode 100644 index 0000000..09ec13f --- /dev/null +++ b/src/main/java/com/newyetai/component/exceptionrecord/entity/ExceptionRecord.java @@ -0,0 +1,43 @@ +package com.newyetai.component.exceptionrecord.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; +import com.newyetai.component.exceptionrecord.emuns.ExceptionRecordSysEnum; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * 异常接口调用记录 + * @author fzp on 2021年7月8日15:21:53 + */ +@EqualsAndHashCode(callSuper = true) +@TableName("xs_exception_record") +@NoArgsConstructor +@AllArgsConstructor +@Data +@Builder +public class ExceptionRecord extends BaseEntity { + + private static final long serialVersionUID = 1449782318298222341L; + /** + * 入参json + */ + private String paramJson; + /** + * 响应json + */ + private String resultJson; + /** + * 调用接口地址 + */ + private String url; + /** + * 系统 1 慧用工、2、3、4待定 + */ + private ExceptionRecordSysEnum sys; + +} diff --git a/src/main/java/com/newyetai/component/exceptionrecord/mapper/ExceptionRecordMapper.xml b/src/main/java/com/newyetai/component/exceptionrecord/mapper/ExceptionRecordMapper.xml new file mode 100644 index 0000000..2239539 --- /dev/null +++ b/src/main/java/com/newyetai/component/exceptionrecord/mapper/ExceptionRecordMapper.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/src/main/java/com/newyetai/component/exceptionrecord/service/ExceptionRecordService.java b/src/main/java/com/newyetai/component/exceptionrecord/service/ExceptionRecordService.java new file mode 100644 index 0000000..c8f3863 --- /dev/null +++ b/src/main/java/com/newyetai/component/exceptionrecord/service/ExceptionRecordService.java @@ -0,0 +1,12 @@ +package com.newyetai.component.exceptionrecord.service; + + +import com.baomidou.mybatisplus.extension.service.IService; +import com.newyetai.component.exceptionrecord.entity.ExceptionRecord; + +/** + * @author sr on 2020-05-26 + */ +public interface ExceptionRecordService extends IService { + +} diff --git a/src/main/java/com/newyetai/component/exceptionrecord/service/impl/ExceptionRecordServiceImpl.java b/src/main/java/com/newyetai/component/exceptionrecord/service/impl/ExceptionRecordServiceImpl.java new file mode 100644 index 0000000..e4969c5 --- /dev/null +++ b/src/main/java/com/newyetai/component/exceptionrecord/service/impl/ExceptionRecordServiceImpl.java @@ -0,0 +1,18 @@ +package com.newyetai.component.exceptionrecord.service.impl; + + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.newyetai.component.exceptionrecord.dao.ExceptionRecordMapper; +import com.newyetai.component.exceptionrecord.entity.ExceptionRecord; +import com.newyetai.component.exceptionrecord.service.ExceptionRecordService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * @author fzp on 2021年7月8日15:16:46 + */ +@Slf4j +@Service +public class ExceptionRecordServiceImpl extends ServiceImpl implements ExceptionRecordService { + +} diff --git a/src/main/java/com/newyetai/component/file/config/FileProperties.java b/src/main/java/com/newyetai/component/file/config/FileProperties.java new file mode 100644 index 0000000..45df275 --- /dev/null +++ b/src/main/java/com/newyetai/component/file/config/FileProperties.java @@ -0,0 +1,35 @@ +package com.newyetai.component.file.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import lombok.Data; +import lombok.NoArgsConstructor; + +@ConfigurationProperties(prefix = "file") +@Component +@Data +public class FileProperties { + + /** 文件上传路径 **/ + private String uploadDir; + + private final Storage storage = new Storage(); + + @Data + @NoArgsConstructor + public static class Storage{ + private String type; + private final AliStorage ali = new AliStorage(); + } + + @Data + @NoArgsConstructor + public static class AliStorage{ + private String endpoint; + private String accessKeyId; + private String accessKeySecret; + private String bucketName; + } + +} diff --git a/src/main/java/com/newyetai/component/file/constant/FileClassCodeEnum.java b/src/main/java/com/newyetai/component/file/constant/FileClassCodeEnum.java new file mode 100644 index 0000000..474a9c3 --- /dev/null +++ b/src/main/java/com/newyetai/component/file/constant/FileClassCodeEnum.java @@ -0,0 +1,31 @@ +package com.newyetai.component.file.constant; + +/** + * 附件类型标识 + * @author sr on 2022-09-29 + */ +public enum FileClassCodeEnum { + + EXCEL("100", ".xls.xlsx"), + WORD("200", ".doc.docx"), + IMG("300", ".jpg.jpeg.gif.png.bmp"), + PDF("400", ".pdf"), + ; + + private String code; + private String suffix; + + FileClassCodeEnum (String code, String suffix) { + this.code = code; + this.suffix = suffix; + } + + public String getCode() { + return this.code; + } + + public String getSuffix() { + return this.suffix; + } + +} diff --git a/src/main/java/com/newyetai/component/file/constant/FileConstants.java b/src/main/java/com/newyetai/component/file/constant/FileConstants.java new file mode 100644 index 0000000..6e7c2c0 --- /dev/null +++ b/src/main/java/com/newyetai/component/file/constant/FileConstants.java @@ -0,0 +1,36 @@ +package com.newyetai.component.file.constant; + +import java.math.BigDecimal; + +/** + * + * @author Rey(leijiaping@newyetai.com) + * + */ +public class FileConstants { + + /** 默认压缩比例 **/ + public static final BigDecimal DEFAULT_QUALITY = new BigDecimal("0.6"); + + + public enum Unit{ + //单位 + B("B", 1L), K("K", 1024L), M("B", 1048576L), G("G", 1073741824L), T("T", 1099511627776L); + private Unit(String name, long value){ + this.name = name; + this.value = value; + } + private String name; + + private Long value; + + public String getName() { + return name; + } + + public Long getValue() { + return value; + } + } + +} diff --git a/src/main/java/com/newyetai/component/file/constant/FileStorageEnum.java b/src/main/java/com/newyetai/component/file/constant/FileStorageEnum.java new file mode 100644 index 0000000..c666d6a --- /dev/null +++ b/src/main/java/com/newyetai/component/file/constant/FileStorageEnum.java @@ -0,0 +1,20 @@ +package com.newyetai.component.file.constant; + +public enum FileStorageEnum { + + LOCAL(FileStorageEnum.LOCAL_NAME),ALI(FileStorageEnum.ALI_NAME); + + public static final String LOCAL_NAME = "local"; + public static final String ALI_NAME = "ali"; + + private String type; + + FileStorageEnum(String type){ + this.type = type; + } + + public String getType() { + return this.type; + } + +} diff --git a/src/main/java/com/newyetai/component/file/controller/AnonFileController.java b/src/main/java/com/newyetai/component/file/controller/AnonFileController.java new file mode 100644 index 0000000..72caadb --- /dev/null +++ b/src/main/java/com/newyetai/component/file/controller/AnonFileController.java @@ -0,0 +1,51 @@ +package com.newyetai.component.file.controller; + +import com.newyetai.common.AlitaResult; +import com.newyetai.component.file.dto.FileUploadDTO; +import com.newyetai.component.file.entity.FileRecord; +import com.newyetai.component.file.service.FileService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.math.BigDecimal; + +/** + * @author sr on 2019-12-11 + */ +@RestController +@RequestMapping("/anon") +@Api(tags = "匿名文件操作") +public class AnonFileController { + + @Autowired + private FileService fileService; + + @ApiOperation("根据code下载文件") + @GetMapping("/file/download/{fileCode}") + public void download(@PathVariable String fileCode, HttpServletRequest request, + HttpServletResponse response) throws IOException { + fileService.download(fileCode, request, response, Boolean.FALSE); + } + + @ApiOperation("根据code预览文件") + @GetMapping("/file/display/{fileCode}") + public void display(@PathVariable String fileCode, HttpServletRequest request, + HttpServletResponse response) throws IOException { + fileService.download(fileCode, request, response, Boolean.TRUE); + } + + @ApiOperation("附件上传") + @PostMapping(value = "/file/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + public AlitaResult upload(@Validated FileUploadDTO fileUploadDTO) { + return AlitaResult.success(fileService.upload(fileUploadDTO)); + } + +} diff --git a/src/main/java/com/newyetai/component/file/controller/FileClassController.java b/src/main/java/com/newyetai/component/file/controller/FileClassController.java new file mode 100644 index 0000000..aa4be13 --- /dev/null +++ b/src/main/java/com/newyetai/component/file/controller/FileClassController.java @@ -0,0 +1,88 @@ +package com.newyetai.component.file.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; +import com.newyetai.component.file.dto.FileClassDTO; +import com.newyetai.component.file.service.FileClassService; +import com.newyetai.tkmybatis.pojo.Page; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +/** + * @author Rey(leijiaping @ newyetai.com) + */ +@Api(tags = "文件配置操作") +@RestController +@RequestMapping({"/file_class"}) +public class FileClassController { + + @Autowired + private FileClassService fileClassService; + + /** + * 新增 + * + * @param fileClass + */ + @ApiOperation("新增文件配置") + @PostMapping("save") + public AlitaResult saveFile(@Validated(Create.class) @RequestBody FileClassDTO fileClassDto) { + fileClassService.save(fileClassDto); + return AlitaResult.success(fileClassDto); + } + + /** + * 修改 + * + * @param fileClass + */ + @ApiOperation("修改文件配置") + @PostMapping("update") + public AlitaResult updateFile(@Validated(Update.class) @RequestBody FileClassDTO fileClassDto) { + fileClassService.upadte(fileClassDto); + return AlitaResult.success(fileClassDto); + } + + /** + * 删除 + * + * @param fileClassId + */ + @ApiOperation("删除文件配置") + @PostMapping("delete") + public AlitaResult deleteFile(@RequestBody Long fileClassId) { + fileClassService.delete(fileClassId); + return AlitaResult.success(true); + } + + /** + * 查询 + * + * @param page + * @param fileClass + */ + @ApiOperation("分页查询文件配置") + @GetMapping("list") + public AlitaResult> query(Page page, FileClassDTO fileClassDto) { + fileClassService.query(page, fileClassDto); + return AlitaResult.success(page); + } + + @ApiOperation("根据编码获取文件配置") + @GetMapping("find_by_code/{code}") + public AlitaResult findByCode(@PathVariable String code){ + return AlitaResult.success(fileClassService.findByCode(code)); + } + +} diff --git a/src/main/java/com/newyetai/component/file/controller/FileRecordController.java b/src/main/java/com/newyetai/component/file/controller/FileRecordController.java new file mode 100644 index 0000000..e1df687 --- /dev/null +++ b/src/main/java/com/newyetai/component/file/controller/FileRecordController.java @@ -0,0 +1,104 @@ +package com.newyetai.component.file.controller; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.component.file.entity.FileRecord; +import com.newyetai.component.file.service.FileRecordService; +import com.newyetai.component.file.service.FileService; +import com.newyetai.component.file.util.FileUtils; +import com.newyetai.tkmybatis.pojo.Page; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * @author Rey(leijiaping @ newyetai.com) + */ +@Api(tags = "文件记录操作") +@RestController +@RequestMapping({"/file"}) +public class FileRecordController { + + @Autowired + private FileRecordService fileRecordService; + + @Autowired + private FileService fileService; + + /** + * 新增 + * + * @param fileRecord + */ + @ApiOperation("新增文件记录") + @PostMapping("save") + public AlitaResult saveFile(@RequestBody FileRecord fileRecord) { + fileRecordService.saveFileRecord(fileRecord); + return AlitaResult.success(fileRecord); + } + + /** + * 修改 + * + * @param fileRecord + */ + @ApiOperation("修改文件记录") + @PostMapping("update") + public AlitaResult updateFile(@RequestBody FileRecord fileRecord) { + fileRecordService.updateFileRecord(fileRecord); + return AlitaResult.success(fileRecord); + } + + /** + * 删除 + * + * @param fileRecord + */ + @ApiOperation("删除文件记录") + @PostMapping("delete") + public AlitaResult deleteFile(@RequestBody FileRecord fileRecord) { + fileRecordService.deleteFileRecord(fileRecord); + return AlitaResult.success(fileRecord); + } + + /** + * 查询 + * + * @param page + * @param fileRecord + */ + @ApiOperation("分页查询文件记录") + @GetMapping("list") + public AlitaResult> query(Page page, FileRecord fileRecord) { + fileRecordService.query(page, fileRecord); + return AlitaResult.success(page); + } + + @ApiOperation("查询单个文件") + @GetMapping("find") + public AlitaResult find(FileRecord fileRecord) { + return AlitaResult.success(fileRecordService.find(fileRecord)); + } + + + /** + * 附件下载 + */ + @ApiOperation("下载文件记录") + @PostMapping("download") + public void download(@RequestBody FileRecord fileRecord, HttpServletRequest request, HttpServletResponse response) { + fileRecord.setOrgId(UserContextHolder.getLoginOrgId()); + FileRecord temp = fileRecordService.find(fileRecord); + try { + fileService.download(temp, request, response, Boolean.FALSE); + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/main/java/com/newyetai/component/file/dao/FileClassMapper.java b/src/main/java/com/newyetai/component/file/dao/FileClassMapper.java new file mode 100644 index 0000000..fc7fa5e --- /dev/null +++ b/src/main/java/com/newyetai/component/file/dao/FileClassMapper.java @@ -0,0 +1,27 @@ +package com.newyetai.component.file.dao; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.newyetai.component.file.dto.FileClassDTO; +import com.newyetai.component.file.entity.FileClass; +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.tkmybatis.pojo.Page; + +/** + * 文件类型 + * + * @author on 2019-11-05 + */ +public interface FileClassMapper extends MyMapper { + + /** + * 分页查询 + * + * @param page + * @param fileClass + * @return + */ + List query(Page page, @Param("param") FileClassDTO fileClassDto); +} diff --git a/src/main/java/com/newyetai/component/file/dao/FileRecordMapper.java b/src/main/java/com/newyetai/component/file/dao/FileRecordMapper.java new file mode 100644 index 0000000..cf7ae7d --- /dev/null +++ b/src/main/java/com/newyetai/component/file/dao/FileRecordMapper.java @@ -0,0 +1,33 @@ +package com.newyetai.component.file.dao; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.newyetai.component.file.entity.FileRecord; +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.tkmybatis.pojo.Page; + +/** + * @author Rey(leijiaping @ newyetai.com) + */ +public interface FileRecordMapper extends MyMapper { + + /** + * 分页查询 + * + * @param page + * @param file + * @return + */ + List query(Page page, @Param("param") FileRecord file); + + FileRecord find(@Param("param")FileRecord fileRecord); + + /** + * 根据fileCode获取导入文件路径 + * @param fileRecord + * @return + */ + String findFilePathByCode(@Param("param")FileRecord fileRecord); +} diff --git a/src/main/java/com/newyetai/component/file/dto/FileClassDTO.java b/src/main/java/com/newyetai/component/file/dto/FileClassDTO.java new file mode 100644 index 0000000..f8c9097 --- /dev/null +++ b/src/main/java/com/newyetai/component/file/dto/FileClassDTO.java @@ -0,0 +1,45 @@ +package com.newyetai.component.file.dto; + +import javax.validation.constraints.NotEmpty; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.common.validation.Create; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2019-12-10 + */ +@ApiModel("文件配置") +@Data +@EqualsAndHashCode(callSuper = false) +@NoArgsConstructor +@SuperBuilder +public class FileClassDTO extends BaseDTO { + + /** **/ + private static final long serialVersionUID = -4289393281290178026L; + + @NotEmpty(message = "文件编码为空", groups = {Create.class}) + @ApiModelProperty("文件编码") + private String classCode; + + @ApiModelProperty("文件描述") + @NotEmpty(message = "文件描述为空", groups = {Create.class}) + private String className; + + @ApiModelProperty("文件最大大小(kb)") + private Integer fileMaxSize; + + @ApiModelProperty("支持的文件后缀") + private String fileSuffix; + + @ApiModelProperty("机构id") + private Long orgId; + +} diff --git a/src/main/java/com/newyetai/component/file/dto/FileUploadDTO.java b/src/main/java/com/newyetai/component/file/dto/FileUploadDTO.java new file mode 100644 index 0000000..642553d --- /dev/null +++ b/src/main/java/com/newyetai/component/file/dto/FileUploadDTO.java @@ -0,0 +1,74 @@ +package com.newyetai.component.file.dto; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Serializable; +import java.math.BigDecimal; + +import javax.validation.constraints.NotNull; + +import org.springframework.http.MediaType; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.util.FileCopyUtils; +import org.springframework.web.multipart.MultipartFile; + +import com.newyetai.common.annotation.Mask; +import com.newyetai.common.exception.BusinessException; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel("附件上传") +@Slf4j +public class FileUploadDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 8811233334943715159L; + + @NotNull(message = "文件不能为空") + @ApiModelProperty("文件") + @Mask + private MultipartFile file; + @ApiModelProperty("文件名,如果未传,则通过file获取") + private String filename; + @ApiModelProperty("压缩比例(0-1) 一位小数 超出范围不进行压缩") + private BigDecimal quality; + @ApiModelProperty("文件类型编码") + private String fileClassCode; + @ApiModelProperty("是否临时文件") + private boolean temp; + @ApiModelProperty("文件上传大小限制") + private Long fileSizeLimit; + + public FileUploadDTO setIs(InputStream is) { + try { + return this.setByte(FileCopyUtils.copyToByteArray(is)); + } catch (IOException e) { + throw new BusinessException("文件流转byte失败"); + } + } + + public FileUploadDTO setByte(byte[] bytes) { + MockMultipartFile mockMultipartFile; + String fileName = this.getFilename(); + try { + mockMultipartFile = new MockMultipartFile(fileName, fileName, + MediaType.APPLICATION_OCTET_STREAM.toString(), bytes); + this.setFile(mockMultipartFile); + return this; + } catch (Exception e) { + log.info("构建mockMultipartFile失败", e); + throw new BusinessException("文件存储失败"); + } + } + +} diff --git a/src/main/java/com/newyetai/component/file/entity/FileClass.java b/src/main/java/com/newyetai/component/file/entity/FileClass.java new file mode 100644 index 0000000..b959414 --- /dev/null +++ b/src/main/java/com/newyetai/component/file/entity/FileClass.java @@ -0,0 +1,47 @@ +package com.newyetai.component.file.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.OrgBaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author Rey(leijiaping @ newyetai.com) + */ +@TableName("xs_file_class") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Data +@SuperBuilder +public class FileClass extends OrgBaseEntity { + + /** **/ + private static final long serialVersionUID = -6032690348770194026L; + + /** + * 文件编码 + */ + private String classCode; + + /** + * 文件描述 + */ + private String className; + + /** + * 文件最大大小(kb) + */ + private Integer fileMaxSize; + + /** + * 支持的文件后缀 + */ + private String fileSuffix; + + +} diff --git a/src/main/java/com/newyetai/component/file/entity/FileRecord.java b/src/main/java/com/newyetai/component/file/entity/FileRecord.java new file mode 100644 index 0000000..67c902b --- /dev/null +++ b/src/main/java/com/newyetai/component/file/entity/FileRecord.java @@ -0,0 +1,74 @@ +package com.newyetai.component.file.entity; + +import org.springframework.data.annotation.Transient; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author Rey(leijiaping @ newyetai.com) + */ +@TableName("xs_file_record") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Builder +@Data +public class FileRecord extends BaseEntity { + + /** **/ + private static final long serialVersionUID = -4977814778074210092L; + + /** + * 文件编码 + */ + private String fileCode; + + /** + * 文件路径 + */ + private String filePath; + + /** + * 文件名 + */ + private String fileName; + + /** + * 文件大小(kb) + */ + private Long fileSize; + + /** + * 文件md5 + */ + private String md5Code; + + /** + * 文件后缀 + */ + private String fileSuffix; + + /** + * 所属机构 + */ + private Long orgId; + + /** 储存器类型 **/ + private String storageType; + + /** + * 外部文件url + */ + @Transient + private String externalFileUrl; + + @Transient + private String importType; +} diff --git a/src/main/java/com/newyetai/component/file/mapper/FileClassMapper.xml b/src/main/java/com/newyetai/component/file/mapper/FileClassMapper.xml new file mode 100644 index 0000000..08e6bba --- /dev/null +++ b/src/main/java/com/newyetai/component/file/mapper/FileClassMapper.xml @@ -0,0 +1,51 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/file/mapper/FileRecordMapper.xml b/src/main/java/com/newyetai/component/file/mapper/FileRecordMapper.xml new file mode 100644 index 0000000..a5c5cf7 --- /dev/null +++ b/src/main/java/com/newyetai/component/file/mapper/FileRecordMapper.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/component/file/service/FileClassMapMapper.java b/src/main/java/com/newyetai/component/file/service/FileClassMapMapper.java new file mode 100644 index 0000000..fdcbcdc --- /dev/null +++ b/src/main/java/com/newyetai/component/file/service/FileClassMapMapper.java @@ -0,0 +1,34 @@ +package com.newyetai.component.file.service; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.newyetai.component.file.dto.FileClassDTO; +import com.newyetai.component.file.entity.FileClass; + +/** + * 文件配置entity/dto转换 + * @author sr on 2019-12-10 + */ +@Mapper +public interface FileClassMapMapper { + + FileClassMapMapper INSTANCE = Mappers.getMapper(FileClassMapMapper.class); + + /** + * entity to dto + * @param fileClass + * @return + * @author sr on 2019-12-10 + */ + FileClassDTO entityToDto(FileClass fileClass); + + /** + * dto to entity + * @param fileClassDto + * @return + * @author sr on 2019-12-10 + */ + FileClass dtoToEntity(FileClassDTO fileClassDto); + +} diff --git a/src/main/java/com/newyetai/component/file/service/FileClassService.java b/src/main/java/com/newyetai/component/file/service/FileClassService.java new file mode 100644 index 0000000..dd72bc2 --- /dev/null +++ b/src/main/java/com/newyetai/component/file/service/FileClassService.java @@ -0,0 +1,45 @@ +package com.newyetai.component.file.service; + +import com.newyetai.component.file.dto.FileClassDTO; +import com.newyetai.tkmybatis.pojo.Page; + +/** + * 文件类型 + * + * @author on 2019-11-05 + */ +public interface FileClassService { + + /** + * 保存 + * @param fileClassDto + */ + void save(FileClassDTO fileClassDto); + + /** + * 更新 + * @param fileClassDto + */ + void upadte(FileClassDTO fileClassDto); + + /** + * 删除 + * @param id + */ + void delete(Long id); + + /** + * 分页查询 + * @param page + * @param fileClassDto + */ + + void query(Page page, FileClassDTO fileClassDto); + + /** + * 根据code获取 + * @param code + * @return + */ + FileClassDTO findByCode(String code); +} diff --git a/src/main/java/com/newyetai/component/file/service/FileRecordService.java b/src/main/java/com/newyetai/component/file/service/FileRecordService.java new file mode 100644 index 0000000..adbb07f --- /dev/null +++ b/src/main/java/com/newyetai/component/file/service/FileRecordService.java @@ -0,0 +1,54 @@ +package com.newyetai.component.file.service; + +import java.io.InputStream; + +import com.newyetai.component.file.entity.FileRecord; +import com.newyetai.tkmybatis.pojo.Page; + +/** + * @author Rey(leijiaping @ newyetai.com) + */ +public interface FileRecordService { + + /** + * 新增 + * + * @param file + */ + void saveFileRecord(FileRecord file); + + /** + * 修改 + * + * @param file + */ + void updateFileRecord(FileRecord file); + + /** + * 删除 + * + * @param file + */ + void deleteFileRecord(FileRecord file); + + /** + * 查询 + * + * @param page + * @param file + */ + void query(Page page, FileRecord file); + + /** + * @param fileRecord + * @return + */ + @Deprecated + InputStream getFile(FileRecord fileRecord); + + InputStream getFile(String fileCode); + + FileRecord find(FileRecord fileRecord); + + String findFilePathByCode(FileRecord fileRecord); +} diff --git a/src/main/java/com/newyetai/component/file/service/FileService.java b/src/main/java/com/newyetai/component/file/service/FileService.java new file mode 100644 index 0000000..b01d6e6 --- /dev/null +++ b/src/main/java/com/newyetai/component/file/service/FileService.java @@ -0,0 +1,116 @@ +package com.newyetai.component.file.service; + +import com.newyetai.component.file.dto.FileUploadDTO; +import com.newyetai.component.file.entity.FileRecord; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.InputStream; +import java.math.BigDecimal; + +/** + * 文件 + * + * @author sr on 2019-10-24 + */ +public interface FileService { + + + /** + * 根据远程地址上传(非临时文件) + * + * @param url url + * @param fileName 文件名称 + * @param contentType 内容类型 + * @param fileSizeLimit 文件大小限制 + * @return {@link FileRecord} + */ + FileRecord upload(String url, String fileName, String contentType, long fileSizeLimit); + + /** + * 上传(非临时文件) + * + * @param file + * @return + * @author sr on 2019-10-24 + */ + FileRecord upload(MultipartFile file); + + /** + * 上传 + * + * @param fileUploadDTO + * @return {@link FileRecord} + */ + FileRecord upload(FileUploadDTO fileUploadDTO); + + /** + * 下载 + * + * @param fileCode + * @param request + * @param response + * @author sr on 2019-10-24 + */ + void download(String fileCode, HttpServletRequest request, HttpServletResponse response, + Boolean display) throws IOException; + + void download(FileRecord fileRecord, HttpServletRequest request, HttpServletResponse response, + Boolean display) throws IOException; + + /** + * 检查文件(非临时文件) + * @param file + * @param code + */ + void checkFile(MultipartFile file, String code); + + /** + * 根据url保存文件到服务器(非临时文件) + * @param externalFileUrl + * @param fileName + * @return + */ + FileRecord uploadFileByURL(String externalFileUrl, String fileName); + + /** + * (非临时文件) + * @param fileName + * @param bytes + * @return + * @author sr on 2021-12-20 + */ + FileRecord upload(String fileName, byte[] bytes); + + /** + * (临时文件) + * @param fileName + * @param bytes + * @return + * @author sr on 2023-12-07 + */ + FileRecord uploadTemp(String fileName, byte[] bytes); + + /** + * (非临时文件) + * @param fileName + * @param is + * @return + * @author sr on 2023-12-07 + */ + FileRecord upload(String fileName, InputStream is); + + /** + * (临时文件) + * @param fileName + * @param is + * @return + * @author sr on 2023-12-07 + */ + FileRecord uploadTemp(String fileName, InputStream is); + + InputStream getFile(String fileCode); + +} diff --git a/src/main/java/com/newyetai/component/file/service/IFileStorage.java b/src/main/java/com/newyetai/component/file/service/IFileStorage.java new file mode 100644 index 0000000..3b9c6d8 --- /dev/null +++ b/src/main/java/com/newyetai/component/file/service/IFileStorage.java @@ -0,0 +1,33 @@ +package com.newyetai.component.file.service; + +import java.io.InputStream; +import java.io.OutputStream; + +public interface IFileStorage { + + String getType(); + + /** + * 上传 + * @param is + * @param filePath + * @author sr on 2022-03-01 + */ + void upload(InputStream is, String filePath); + + /** + * 下载 + * @param filePath + * @param os + * @author sr on 2022-03-01 + */ + void download(String filePath, OutputStream os); + + /** + * @param filePath + * @return + * @author sr on 2022-03-08 + */ + InputStream download(String filePath); + +} diff --git a/src/main/java/com/newyetai/component/file/service/impl/FileClassServiceImpl.java b/src/main/java/com/newyetai/component/file/service/impl/FileClassServiceImpl.java new file mode 100644 index 0000000..9d043b4 --- /dev/null +++ b/src/main/java/com/newyetai/component/file/service/impl/FileClassServiceImpl.java @@ -0,0 +1,74 @@ +package com.newyetai.component.file.service.impl; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.codegenerator.util.CodeUtils; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.BaseDtoUtils; +import com.newyetai.common.util.ListUtil; +import com.newyetai.component.constants.CodeTypeEnum; +import com.newyetai.component.file.dao.FileClassMapper; +import com.newyetai.component.file.dto.FileClassDTO; +import com.newyetai.component.file.entity.FileClass; +import com.newyetai.component.file.service.FileClassMapMapper; +import com.newyetai.component.file.service.FileClassService; +import com.newyetai.tkmybatis.pojo.Page; + +/** + * 文件类型 + * + * @author on 2019-11-05 + */ +@Service +public class FileClassServiceImpl implements FileClassService { + + @Autowired + private FileClassMapper fileClassMapper; + + + @Override + @Transactional(rollbackFor = RuntimeException.class) + public void save(FileClassDTO fileClassDto) { + fileClassDto.setClassCode(CodeUtils.getCode(CodeTypeEnum.FILE_CLASS)); + FileClass fileClass = FileClassMapMapper.INSTANCE.dtoToEntity(fileClassDto); + fileClassMapper.saveEntity(fileClass); + BaseDtoUtils.createCopy(fileClass, fileClassDto); + } + + @Override + @Transactional(rollbackFor = RuntimeException.class) + public void upadte(FileClassDTO fileClassDto) { + FileClass fileClass = FileClassMapMapper.INSTANCE.dtoToEntity(fileClassDto); + fileClassMapper.updateEntity(fileClass); + BaseDtoUtils.updateCopy(fileClass, fileClassDto); + } + + @Override + @Transactional(rollbackFor = RuntimeException.class) + public void delete(Long id) { + FileClass fileClass = new FileClass(); + fileClass.setId(id); + fileClassMapper.deleteEntity(fileClass); + } + + + @Override + @Transactional(rollbackFor = RuntimeException.class) + public void query(Page page, FileClassDTO fileClassDto) { + fileClassMapper.query(page, fileClassDto); + } + + @Override + @Transactional(rollbackFor = RuntimeException.class) + public FileClassDTO findByCode(String code) { + List fileClassDTOs = fileClassMapper.query(null, + FileClassDTO.builder().classCode(code).deleted(Boolean.FALSE).build()); + Assert.isTrue(!fileClassDTOs.isEmpty(), "未找到指定编码的文件配置"); + return ListUtil.first(fileClassDTOs); + } + +} diff --git a/src/main/java/com/newyetai/component/file/service/impl/FileRecordServiceImpl.java b/src/main/java/com/newyetai/component/file/service/impl/FileRecordServiceImpl.java new file mode 100644 index 0000000..43c6fa5 --- /dev/null +++ b/src/main/java/com/newyetai/component/file/service/impl/FileRecordServiceImpl.java @@ -0,0 +1,94 @@ +package com.newyetai.component.file.service.impl; + +import java.io.InputStream; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.newyetai.common.exception.util.Assert; +import com.newyetai.component.file.dao.FileRecordMapper; +import com.newyetai.component.file.entity.FileRecord; +import com.newyetai.component.file.service.FileRecordService; +import com.newyetai.component.file.util.FileStorageUtils; +import com.newyetai.tkmybatis.pojo.Page; + +/** + * @author Rey(leijiaping @ newyetai.com) + */ +@Service +public class FileRecordServiceImpl implements FileRecordService { + + @Autowired + private FileRecordMapper fileRecordMapper; + + /** + * 新增 + * + * @param fileRecord + */ + @Override + public void saveFileRecord(FileRecord fileRecord) { + fileRecordMapper.saveEntity(fileRecord); + } + + /** + * 修改 + * + * @param fileRecord + */ + @Override + public void updateFileRecord(FileRecord fileRecord) { + fileRecordMapper.updateEntity(fileRecord); + } + + /** + * 删除 + * + * @param fileRecord + */ + @Override + public void deleteFileRecord(FileRecord fileRecord) { + fileRecordMapper.deleteEntity(fileRecord); + } + + /** + * 查询 + * + * @param page + * @param fileRecord + */ + @Override + public void query(Page page, FileRecord fileRecord) { +// System.out.println("=================" + fileClassService.query(Maps.newHashMap())); + fileRecordMapper.query(page, fileRecord); + } + + + /** + * @param fileRecord + * @return + */ + @Override + public InputStream getFile(FileRecord fileRecord) { + // TODO 校验当前账号是否有权限操作文件 + return FileStorageUtils.get().download(fileRecord.getFilePath()); + } + + @Override + public InputStream getFile(String fileCode) { + FileRecord fileRecord = fileRecordMapper.find(FileRecord.builder().fileCode(fileCode).build()); + Assert.notNull(fileRecord, "文件不存在"); + return FileStorageUtils.get().download(fileRecord.getFilePath()); + } + + @Override + public FileRecord find(FileRecord fileRecord) { + return fileRecordMapper.find(fileRecord); + } + + @Override + public String findFilePathByCode(FileRecord fileRecord) { + return fileRecordMapper.findFilePathByCode(fileRecord); + } + +} diff --git a/src/main/java/com/newyetai/component/file/service/impl/FileServiceImpl.java b/src/main/java/com/newyetai/component/file/service/impl/FileServiceImpl.java new file mode 100644 index 0000000..9c1bb4a --- /dev/null +++ b/src/main/java/com/newyetai/component/file/service/impl/FileServiceImpl.java @@ -0,0 +1,399 @@ +package com.newyetai.component.file.service.impl; + +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.math.BigDecimal; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.util.Objects; +import java.util.Optional; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.tomcat.util.http.fileupload.ByteArrayOutputStream; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.MimeTypeUtils; +import org.springframework.web.multipart.MultipartFile; + +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.exception.util.ExceptionUtils; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.component.file.config.FileProperties; +import com.newyetai.component.file.constant.FileClassCodeEnum; +import com.newyetai.component.file.constant.FileConstants; +import com.newyetai.component.file.dto.FileClassDTO; +import com.newyetai.component.file.dto.FileUploadDTO; +import com.newyetai.component.file.entity.FileRecord; +import com.newyetai.component.file.service.FileClassService; +import com.newyetai.component.file.service.FileRecordService; +import com.newyetai.component.file.service.FileService; +import com.newyetai.component.file.service.IFileStorage; +import com.newyetai.component.file.util.FileUtils; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.img.Img; +import cn.hutool.core.img.ImgUtil; +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpUtil; +import lombok.extern.slf4j.Slf4j; + +/** + * 文件 + * + * @author sr on 2019-10-24 + */ +@Slf4j +@Service +public class FileServiceImpl implements FileService { + + @Autowired + private FileProperties fileProperties; + + @Autowired + private FileRecordService fileRecordService; + + @Autowired + private FileClassService fileClassService; + + @Autowired + private IFileStorage fileStorage; + + @Override + public void download(String fileCode, HttpServletRequest request, + HttpServletResponse response, Boolean display) throws IOException { + if (fileCode.contains(".")) { + fileCode = StrUtil.subBefore(fileCode, ".", true); + } + FileRecord fileRecord = fileRecordService.find(FileRecord.builder().fileCode(fileCode).build()); + this.download(fileRecord, request, response, display); + } + + @Override + public void download(FileRecord fileRecord, HttpServletRequest request, + HttpServletResponse response, Boolean display) throws IOException { + ExceptionUtils.throwBusinessException(fileRecord == null, "未找到对应文件"); + HttpSession session = request.getSession(); + + String filename = fileRecord.getFileName(); + if (Objects.nonNull(request) && StringUtils.isNotBlank(request.getParameter("filename"))) { + filename = URLDecoder.decode(request.getParameter("filename"),"utf-8"); + } + response.setContentType(session.getServletContext().getMimeType(filename)); + String encodFilename = URLEncoder.encode(filename, "utf-8"); + response.setHeader("code", "200"); + response.setHeader("Cache-Control", "max-age=31556926"); + if (!Boolean.TRUE.equals(display)) { + response.setHeader("Content-Disposition", + String.format("attachment; filename=\"%1$s\"; filename*=utf-8''%1$s", encodFilename)); + } + try (OutputStream outputStream = response.getOutputStream()) { + fileStorage.download(fileRecord.getFilePath(), outputStream); + } + } + + + + @Override + public void checkFile(MultipartFile file, String code) { + Assert.notBlank(code, "未指定文件配置"); + FileClassDTO fileClass = fileClassService.findByCode(code); + if (fileClass == null) { + throw new BusinessException("未设置文件配置,无法上传"); + } + if (!FileUtils.checkFileSize(file.getSize(), fileClass.getFileMaxSize(), + FileConstants.Unit.K)) { + throw new BusinessException( + "上传文件过大,最大不得超过" + fileClass.getFileMaxSize() + FileConstants.Unit.K.getName()); + } + String fileName = file.getOriginalFilename(); + if (StringUtils.isBlank(fileName)) { + throw new BusinessException(("文件名不能为空")); + } + String suffix = FileUtils.getSuffix(fileName); + if (!fileClass.getFileSuffix().contains(suffix)) { + throw new BusinessException("只能上传拓展名为" + fileClass.getFileSuffix() + "的文件"); + } + } + + @Override + public FileRecord upload(String url, String fileName, String contentType, long fileSizeLimit) { + Assert.isTrue(StringUtils.isNotEmpty(url) && StringUtils.startsWithAny(url, "http", "https"), + "上传地址有误"); + Assert.isTrue(StringUtils.isNotEmpty(contentType), "文件类型不能为空"); + byte[] bytes = HttpUtil.createGet(url).execute().bodyBytes(); + ByteArrayInputStream inputStream = IoUtil.toStream(bytes); + //文件类型校验 + String contentTypeAct = ""; + try { + contentTypeAct = HttpURLConnection.guessContentTypeFromStream(inputStream); + } catch (IOException e) { + e.printStackTrace(); + } + if (StringUtils.isEmpty(contentTypeAct) || !checkContentType(contentTypeAct, contentType)) { + log.info("上传文件格式校验失败,contentType:[{}],contentTypeAct:[{}]", contentType, contentTypeAct); + ExceptionUtils.throwBusinessException("文件格式错误"); + } + if (fileSizeLimit > 0) { + long fileSizeAct = inputStream.available(); + if (fileSizeAct > fileSizeLimit) { + log.info("上传文件大小校验失败,fileSizeLimit:[{}],fileSizeAct:[{}]", fileSizeLimit, fileSizeAct); + ExceptionUtils.throwBusinessException("文件超过限制"); + } + } + String fileNameAct = fileName + "." + contentType; + return upload(fileNameAct, bytes); + } + + /** + * 检查内容类型 + * + * @param contentTypeAct 内容类型的行为 + * @param contentType 内容类型 + * @return boolean + */ + private boolean checkContentType(String contentTypeAct, String contentType) { + if (StringUtils.isEmpty(contentType) || StringUtils.isEmpty(contentTypeAct)) { + return false; + } + String[] split = StringUtils.split(contentType, ","); + for (String s : split) { + if (contentTypeAct.contains(s)) { + return true; + } + } + return false; + } + + @Override + public FileRecord upload(MultipartFile file) { + return upload(FileUploadDTO.builder().file(file).build()); + } + + @Override + public FileRecord upload(FileUploadDTO fileUploadDTO) { + MultipartFile file = fileUploadDTO.getFile(); + //校验上传文件 + checkMultipartFile(file, fileUploadDTO.getFileClassCode()); + //构建FileRecord + FileRecord fileRecord = buildFileRecord(fileUploadDTO); + //复制属性返回 + FileRecord resultFile; + BeanUtils.copyProperties(fileRecord, + (resultFile = FileRecord.builder().build()), + "filePath"); + return resultFile; + } + + /** + * 构建FileRecord + * + * @param file 文件 + * @return {@link FileRecord} + */ + private FileRecord buildFileRecord(FileUploadDTO fileUploadDTO) { + MultipartFile file = fileUploadDTO.getFile(); + String filename = fileUploadDTO.getFilename(); + BigDecimal quality = fileUploadDTO.getQuality(); + boolean temp = fileUploadDTO.isTemp(); + // 文件code + String fileCode = IdUtil.fastSimpleUUID(); + // 文件名称 + String fileName = StrUtil.isEmpty(filename) ? file.getOriginalFilename() : filename; + // 文件后缀 + String fileSuffix = FilenameUtils.getExtension(fileName); + // 目标文件路径 + String targetPath; + if (!temp) { + targetPath = String.join(String.valueOf(File.separatorChar), + fileProperties.getUploadDir(), + Optional.ofNullable(UserContextHolder.getLoginOrgId()).map(Object::toString) + .orElse("null"), + fileCode); + } else { + targetPath = String.join(String.valueOf(File.separatorChar), + fileProperties.getUploadDir(), + "temp", + DateUtil.today(), + fileCode); + } + + String md5Code; + Long fileSize = file.getSize(); + FileRecord fileRecord = null; + try (InputStream is = file.getInputStream()) { + //验证通过则进行图片压缩处理ø + if (Boolean.TRUE.equals(checkNeedCompression(quality, fileSuffix))) { + log.info("file compress,before:{}, quality:{}", fileSize, quality); + try (ByteArrayOutputStream os = new ByteArrayOutputStream()) { + Img.from(is).setQuality(quality.doubleValue()).write(os); + byte[] osByte = os.toByteArray(); + try (ByteArrayInputStream comIs = new ByteArrayInputStream(osByte)) { + fileSize = Long.valueOf(osByte.length); + // 判断文件大小限制 + Assert.isTrue(fileUploadDTO.getFileSizeLimit() == null + || fileSize < fileUploadDTO.getFileSizeLimit(), "上传文件超过限制"); + md5Code = DigestUtils.md5Hex(osByte).toUpperCase(); + fileRecord = fileRecordService.find(FileRecord.builder().md5Code(md5Code).build()); + if (fileRecord != null) { + return fileRecord; + } + fileStorage.upload(comIs, targetPath); + } catch (IOException ie) { + log.info("获取图片压缩输入流失败", ie); + throw new BusinessException("获取图片压缩输入流失败"); + } + } catch (IOException ie) { + log.info("图片文件压缩失败,请稍后重试", ie); + throw new BusinessException("图片文件压缩失败,请稍后重试"); + } + } else { + // 判断文件大小限制 + Assert.isTrue(fileUploadDTO.getFileSizeLimit() == null + || fileSize < fileUploadDTO.getFileSizeLimit(), "上传文件超过限制"); + md5Code = DigestUtils.md5Hex(file.getBytes()).toUpperCase(); + fileRecord = fileRecordService.find(FileRecord.builder().md5Code(md5Code).build()); + if (fileRecord != null) { + return fileRecord; + } + fileStorage.upload(is, targetPath); + } + + } catch (IOException e) { + log.error("文件上传io异常", e); + throw new BusinessException("文件上传异常"); + } + // 构建FileRecord + fileRecord = FileRecord.builder() + .orgId(UserContextHolder.getLoginOrgId()) + .fileName(fileName) + .fileSize(fileSize) + .fileCode(fileCode) + .filePath(targetPath) + .fileSuffix(fileSuffix) + .md5Code(md5Code) + .storageType(fileStorage.getType()).build(); + fileRecordService.saveFileRecord(fileRecord); + return fileRecord; + } + + public static ByteArrayInputStream getCompressIs(InputStream is, BigDecimal quality) { + try (ByteArrayOutputStream os = new ByteArrayOutputStream()) { + Img.from(is).setQuality(quality.doubleValue()) + .write(os); + return new ByteArrayInputStream(os.toByteArray()); + } catch (IOException ie) { + log.info("图片文件压缩失败,请稍后重试", ie); + throw new BusinessException("图片文件压缩失败,请稍后重试"); + } + } + + /** + * 验证本次上传的文件是否能进行压缩处理 + * quality 在 0~1之间 + * fileSuffix 文件结尾是图片格式 + * + * @param quality 质量 + * @param fileSuffix 文件后缀 + * @return {@link Boolean} + */ + private Boolean checkNeedCompression(BigDecimal quality, String fileSuffix) { + return Objects.nonNull(quality) && + (BigDecimal.ZERO.compareTo(quality) < 0 && BigDecimal.ONE.compareTo(quality) > 0) && + StringUtils.equalsAnyIgnoreCase(fileSuffix, ImgUtil.IMAGE_TYPE_JPG, + ImgUtil.IMAGE_TYPE_BMP, ImgUtil.IMAGE_TYPE_GIF, ImgUtil.IMAGE_TYPE_JPEG, + ImgUtil.IMAGE_TYPE_PSD); + } + + + /** + * 检查上传文件 + * + * @param file 文件 + */ + private void checkMultipartFile(MultipartFile file, String fileClassCode) { + Assert.isTrue(Objects.nonNull(file) && !file.isEmpty(), "文件为空"); + if (StringUtils.isNotBlank(fileClassCode)) { + this.checkFile(file, fileClassCode); + } + + } + + + @Override + public FileRecord uploadFileByURL(String externalFileUrl, String fileName) { + // 搞不懂取名,取个链接下载,里面其实限制是图片/pdf下载,其他类型慎用!!! + if (StringUtils.isBlank(externalFileUrl)) { + return null; + } + try { + URL url = new URL(externalFileUrl); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + String fileSuffix = MimeTypeUtils.parseMimeType(connection.getContentType()).getSubtype().toLowerCase(); + String fileClassCode = null; + if (FileClassCodeEnum.IMG.getSuffix().contains(fileSuffix)) { + fileClassCode = FileClassCodeEnum.IMG.getCode(); + } else if(FileClassCodeEnum.PDF.getSuffix().contains(fileSuffix)){ + fileClassCode = FileClassCodeEnum.PDF.getCode(); + }else { + log.info("文件格式不是图片/pdf类型,url: {}, 当前文件格式:{}", externalFileUrl, fileSuffix); + throw new BusinessException("文件格式不是图片/pdf类型"); + } + try (BufferedInputStream is = new BufferedInputStream(connection.getInputStream())) { + FileUploadDTO fileUploadDTO = FileUploadDTO.builder().filename(fileName + "." + fileSuffix) + .fileClassCode(fileClassCode).build(); + return upload(fileUploadDTO.setIs(is)); + } finally { + connection.disconnect(); + } + } catch (Exception e) { + log.info("根据url下载照片失败!url:{}, fileName: {}", externalFileUrl, fileName, e); + return null; + } + } + + @Override + public FileRecord upload(String fileName, byte[] bytes) { + FileUploadDTO fileUploadDTO = FileUploadDTO.builder().filename(fileName).build(); + return upload(fileUploadDTO.setByte(bytes)); + } + + @Override + public FileRecord uploadTemp(String fileName, byte[] bytes) { + FileUploadDTO fileUploadDTO = FileUploadDTO.builder().filename(fileName).temp(true).build(); + return upload(fileUploadDTO.setByte(bytes)); + } + + @Override + public FileRecord upload(String fileName, InputStream is) { + FileUploadDTO fileUploadDTO = FileUploadDTO.builder().filename(fileName).build(); + return upload(fileUploadDTO.setIs(is)); + } + + @Override + public FileRecord uploadTemp(String fileName, InputStream is) { + FileUploadDTO fileUploadDTO = FileUploadDTO.builder().filename(fileName).temp(true).build(); + return upload(fileUploadDTO.setIs(is)); + } + + @Override + public InputStream getFile(String fileCode) { + return fileRecordService.getFile(fileCode); + } + +} diff --git a/src/main/java/com/newyetai/component/file/service/storage/LocalFileStorage.java b/src/main/java/com/newyetai/component/file/service/storage/LocalFileStorage.java new file mode 100644 index 0000000..090f83b --- /dev/null +++ b/src/main/java/com/newyetai/component/file/service/storage/LocalFileStorage.java @@ -0,0 +1,58 @@ +package com.newyetai.component.file.service.storage; + +import com.newyetai.common.exception.BusinessException; +import com.newyetai.component.file.constant.FileStorageEnum; +import com.newyetai.component.file.service.IFileStorage; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; + +import java.io.*; +import java.nio.file.Files; + +@Slf4j +public class LocalFileStorage implements IFileStorage { + + @Override + public void upload(InputStream is, String filePath) { + File file = new File(filePath); + try { + FileUtils.forceMkdirParent(file); + } catch (IOException e) { + log.info("上传存储异常", e); + throw new BusinessException("上传存储异常 " + e.getMessage()); + } + try (OutputStream os = Files.newOutputStream(file.toPath())) { + IOUtils.copy(is, os); + } catch (IOException e) { + log.info("上传存储异常", e); + throw new BusinessException("上传存储异常 " + e.getMessage()); + } + } + + @Override + public void download(String filePath, OutputStream os) { + try (InputStream inputStream = download(filePath)) { + IOUtils.copy(inputStream, os); + } catch (IOException e) { + log.info("下载异常", e); + throw new BusinessException("下载异常" + e.getMessage()); + } + } + + @Override + public String getType() { + return FileStorageEnum.LOCAL_NAME; + } + + @Override + public InputStream download(String filePath) { + try { + return new FileInputStream(filePath); + } catch (FileNotFoundException e) { + log.info("下载异常", e); + throw new BusinessException("下载异常" + e.getMessage()); + } + } + +} diff --git a/src/main/java/com/newyetai/component/file/util/FileStorageUtils.java b/src/main/java/com/newyetai/component/file/util/FileStorageUtils.java new file mode 100644 index 0000000..066d674 --- /dev/null +++ b/src/main/java/com/newyetai/component/file/util/FileStorageUtils.java @@ -0,0 +1,22 @@ +package com.newyetai.component.file.util; + +import com.newyetai.common.exception.util.Assert; +import com.newyetai.component.file.service.IFileStorage; + +/** + * @author sr on 2022-03-08 + */ +public class FileStorageUtils { + + public static IFileStorage fileStorage; + + public FileStorageUtils(IFileStorage fileStorage) { + Assert.isNull(FileStorageUtils.fileStorage, "文件存储器已存在..."); + FileStorageUtils.fileStorage = fileStorage; + } + + public static IFileStorage get() { + return fileStorage; + } + +} diff --git a/src/main/java/com/newyetai/component/file/util/FileUtils.java b/src/main/java/com/newyetai/component/file/util/FileUtils.java new file mode 100644 index 0000000..25eff80 --- /dev/null +++ b/src/main/java/com/newyetai/component/file/util/FileUtils.java @@ -0,0 +1,253 @@ +package com.newyetai.component.file.util; + +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.util.Base64; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import javax.imageio.ImageIO; + +import org.springframework.util.FileCopyUtils; + +import com.newyetai.common.exception.BusinessException; +import com.newyetai.component.file.constant.FileConstants; + +import cn.hutool.core.img.Img; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.IORuntimeException; +import lombok.extern.slf4j.Slf4j; +import ws.schild.jave.Encoder; +import ws.schild.jave.EncoderException; +import ws.schild.jave.MultimediaObject; +import ws.schild.jave.encode.AudioAttributes; +import ws.schild.jave.encode.EncodingAttributes; + +/** + * 文件工具类 + * + * @author on 2019-12-10 + */ +@Slf4j +public class FileUtils { + + public static final double IMG_QUALITY = 0.6d; + + private FileUtils() {} + + + /** + * 得到字节大小字符串 + * + * @param size 大小 + * @return {@link String} + */ + public static String getByteSizePretty(long size) { + //如果字节数少于1024,则直接以B为单位,否则先除于1024,后3位因太少无意义 + if (size < 1024) { + return String.valueOf(size) + "B"; + } else { + size = size / 1024; + } + //如果原字节数除于1024之后,少于1024,则可以直接以KB作为单位 + //因为还没有到达要使用另一个单位的时候 + //接下去以此类推 + if (size < 1024) { + return String.valueOf(size) + "KB"; + } else { + size = size / 1024; + } + if (size < 1024) { + //因为如果以MB为单位的话,要保留最后1位小数, + //因此,把此数乘以100之后再取余 + size = size * 100; + return String.valueOf((size / 100)) + "." + + String.valueOf((size % 100)) + "MB"; + } else { + //否则如果要以GB为单位的,先除于1024再作同样的处理 + size = size * 100 / 1024; + return String.valueOf((size / 100)) + "." + + String.valueOf((size % 100)) + "GB"; + } + } + + /** + * 判断文件大小 + * + * @param len 文件长度 + * @param size 限制大小 + * @param unit 限制单位(B,K,M,G) + * @return + */ + public static boolean checkFileSize(Long len, int size, FileConstants.Unit unit) { + Long fileSize = len / unit.getValue(); + if (fileSize > size) { + return false; + } + return true; + } + + /** + * Java文件操作 获取文件扩展名 + */ + public static String getSuffix(String filename) { + if ((filename != null) && (filename.length() > 0)) { + int dot = filename.lastIndexOf('.'); + if ((dot > -1) && (dot < (filename.length() - 1))) { + return filename.substring(dot + 1); + } + } + return filename; + } + + /** + * Java文件操作 获取不带扩展名的文件名 + */ + public static String getFileNameNoSuffix(String filename) { + if ((filename != null) && (filename.length() > 0)) { + int dot = filename.lastIndexOf('.'); + if ((dot > -1) && (dot < (filename.length()))) { + return filename.substring(0, dot); + } + } + return filename; + } + + /** + * 解压图片压缩包(带压缩功能) + * 默认utf-8解压,异常(zip流没问题,nextElement会非法参数malformed异常)后用gbk解压;原因:mac的压缩包得用utf-8解压、Windows的压缩包用gbk + * @param fileRecordPath + * @param targetPath + * @return !!!记得删解压后的文件 + * @author sr on 2022-01-25 + */ + public static List unzipImg(String fileRecordPath, String targetPath) { + try (ZipInputStream zipFile = + new ZipInputStream(FileStorageUtils.get().download(fileRecordPath))) { + return unzipImg(zipFile, targetPath, IMG_QUALITY); + } catch (Exception e) { + try (ZipInputStream zipFile = new ZipInputStream( + FileStorageUtils.get().download(fileRecordPath), Charset.forName("gbk"))) { + return unzipImg(zipFile, targetPath, IMG_QUALITY); + } catch (IOException e2) { + throw new BusinessException("zip编码异常", e2); + } + } + } + + public static List unzipImg(ZipInputStream zis, String targetPath, double quality) { + try { + ZipEntry zipEntry; + File outItemFile; + while ((zipEntry = zis.getNextEntry()) != null) { + if (zipEntry.isDirectory()) { + continue; + } + // 写出文件 + try { + InputStream in = zis; + if (quality >= 1) { + outItemFile = mkParentdirs(targetPath, zipEntry.getName()); + FileUtil.writeFromStream(in, outItemFile); + continue; + } + BufferedImage bi = ImageIO.read(in); + if (bi == null) { + // 图片为空 + continue; + } + outItemFile = mkParentdirs(targetPath, zipEntry.getName()); + Img.from(bi).setQuality(quality) + .write(outItemFile); + + } catch (IOException e) { + throw new IORuntimeException(e); + } + } + return FileUtil.loopFiles(targetPath); + } catch (Exception e) { + throw new BusinessException("解压异常", e); + } + } + + + public static File mkParentdirs(String targetPath, String namePath) { + File file = FileUtil.file(targetPath, namePath); + File parentFile = file.getParentFile(); + if (parentFile != null && !parentFile.exists()) { + parentFile.mkdirs(); + } + return file; + } + + /** + * 获取base64字符串 + * @param filePath + * @return + * @author sr on 2022-10-09 + */ + public static String encodeBase64(String filePath) { + try (InputStream is = FileStorageUtils.get().download(filePath)) { + byte[] buffer = FileCopyUtils.copyToByteArray(is); + byte[] data = Base64.getEncoder().encode(buffer); + return new String(data); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * @param base64 + * @return + * @author sr on 2022-10-09 + */ + public static byte[] decodeBase64(String base64) { + String[] split = base64.split(","); + if (split.length == 2) { + base64 = split[1]; + } + return Base64.getDecoder().decode(base64); + } + + /** + * WebmToMp3 + * @param webmFilePath + * @param mp3FilePath + * @author sr on 2025-01-10 + */ + public static InputStream convertWebmToMp3(File source) { + + AudioAttributes audio = new AudioAttributes(); + audio.setCodec("libmp3lame"); + // 设置音频编码格式为L16(这里假设目标是这个格式) + // audio.setCodec("pcm_s16le"); + // 设置采样率为16000Hz + audio.setSamplingRate(16000); + + EncodingAttributes attrs = new EncodingAttributes(); + attrs.setOutputFormat("mp3"); + attrs.setAudioAttributes(audio); + + try { + File tmpDir = new File("tmp/mebmtomp3"); + tmpDir.mkdirs(); + Encoder encoder = new Encoder(); + File target = File.createTempFile("/mp3", null, tmpDir); + encoder.encode(new MultimediaObject(source), target, attrs); + InputStream is = new FileInputStream(target); + target.delete(); + return is; + } catch (Exception e) { + log.info("使用JAVE库转换失败!", e); + throw new BusinessException("mp3转换失败"); + } + } + + +} diff --git a/src/main/java/com/newyetai/component/file/util/PDFBuilder.java b/src/main/java/com/newyetai/component/file/util/PDFBuilder.java new file mode 100644 index 0000000..af09ea4 --- /dev/null +++ b/src/main/java/com/newyetai/component/file/util/PDFBuilder.java @@ -0,0 +1,465 @@ +package com.newyetai.component.file.util; + +import com.itextpdf.text.BaseColor; +import com.itextpdf.text.Document; +import com.itextpdf.text.DocumentException; +import com.itextpdf.text.Element; +import com.itextpdf.text.Font; +import com.itextpdf.text.PageSize; +import com.itextpdf.text.Paragraph; +import com.itextpdf.text.Phrase; +import com.itextpdf.text.Rectangle; +import com.itextpdf.text.pdf.BaseFont; +import com.itextpdf.text.pdf.PdfPCell; +import com.itextpdf.text.pdf.PdfPTable; +import com.itextpdf.text.pdf.PdfWriter; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.OutputStream; +import java.lang.reflect.Field; + +public class PDFBuilder { + // 表头背景色 + private BaseColor headerBgColor = BaseColor.GRAY; + // 表头文字色 + private BaseColor headerFontColor = BaseColor.WHITE; + // 表格文字色 + private BaseColor cellFontColor = BaseColor.BLACK; + // 表格背景色 + private BaseColor cellBgColor = BaseColor.WHITE; + // 表格内距 + private float padding = 0f; + // 表格离标题的距离 + private float spacing = 50f; + // 表格的宽度, 默认自适应 + private float tableWidth = 0f; + // pdf大小 + private Rectangle pageSize = PageSize.A4; + // 段落文字大小 + private int paragraphFontSize = 20; + // 表格文字大小 + private int cellFontSize = 14; + // 表头文字大小 + private int headerFontSize = 16; + // 自动分页,默认自适应 + private int limit = 0; + // 标题 + private String title; + + private Document document; + private boolean isHorizontal = true; + // private LinkedList data = new LinkedList<>(); + private Object[] data; + private Class clazz = null; + private BaseFont baseFont; + private Font bodyFont; + private Font headerFont; + private float[] ratio; + + + public void setRatio(float[] ratio) { + this.ratio = ratio; + } + + public void setHeaderBgColor(BaseColor headerBgColor) { + this.headerBgColor = headerBgColor; + } + + public void setHeaderFontColor(BaseColor headerFontColor) { + this.headerFontColor = headerFontColor; + } + + public void setCellFontColor(BaseColor cellFontColor) { + this.cellFontColor = cellFontColor; + } + + public void setCellBgColor(BaseColor cellBgColor) { + this.cellBgColor = cellBgColor; + } + + public void setPadding(float padding) { + this.padding = padding; + } + + public void setSpacing(float spacing) { + this.spacing = spacing; + } + + public void setTableWidth(float tableWidth) { + this.tableWidth = tableWidth; + } + + public void setPageSize(Rectangle pageSize) { + this.pageSize = pageSize; + } + + public void setParagraphFontSize(int paragraphFontSize) { + this.paragraphFontSize = paragraphFontSize; + } + + public void setCellFontSize(int cellFontSize) { + this.cellFontSize = cellFontSize; + } + + public void setHeaderFontSize(int headerFontSize) { + this.headerFontSize = headerFontSize; + } + + public void setTitle(String title) { + this.title = title; + } + + /* ----- */ + private PDFBuilder() { + try { + baseFont = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED); + } catch (Exception exception) { + exception.printStackTrace(); + } + } + + public void setData(Object[] data){ + if(data == null || data.length == 0) { + System.err.println("set data null"); + return; + }else if(limit > 0){ + int page = (int) Math.ceil((double) data.length / limit); + document.setPageCount(page); + } + this.data = data; + } + + public void setHead(Class clazz){ + this.clazz = clazz; + } + + public void horizontal(boolean horizontal) { + isHorizontal = horizontal; + } + + public static PDFBuilder builder(){ + return new PDFBuilder(); + } + + public void build(){ + document.close(); + } + + public void autoPage(int limit){ + this.limit = limit; + } + + private void addHeadCell(PdfPTable table, Phrase phrase){ + PdfPCell cell = new PdfPCell(phrase); + cell.setPadding(padding); + cell.setBackgroundColor(headerBgColor); + cell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER); + cell.setUseAscender(true); + cell.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE); + table.addCell(cell); + } + + private void addHeadCell(PdfPTable table, PdfPCell cell,int index){ + if(index % 2 == 0) + cell.setBackgroundColor(BaseColor.WHITE); + cell.setUseAscender(true); + cell.setBorder(0); + cell.setPadding(padding); + cell.setBackgroundColor(headerBgColor); + table.addCell(cell); + } + + private void addHeadCell2(PdfPTable table, Phrase phrase,int index){ + PdfPCell cell = new PdfPCell(phrase); + cell.setPadding(padding); + cell.setBackgroundColor(headerBgColor); + cell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER); + cell.setUseAscender(true); + cell.setBorder(0); + if(index % 2 == 0) + cell.setBackgroundColor(BaseColor.WHITE); + cell.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE); + table.addCell(cell); + } + + private void addBodyCell(PdfPTable table,Phrase phrase, int index){ + PdfPCell cell = new PdfPCell(phrase); + cell.setPadding(padding); + cell.setBackgroundColor(cellBgColor); + cell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER); + cell.setUseAscender(true); + cell.setBorder(0); + if(index % 2 == 0) + cell.setBackgroundColor(BaseColor.WHITE); + cell.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE); + table.addCell(cell); + } + + private void addBodyCell(PdfPTable table,PdfPCell cell){ + cell.setPadding(padding); + cell.setBackgroundColor(cellBgColor); + cell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER); + cell.setUseAscender(true); + cell.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE); + table.addCell(cell); + } + + private void addParagraph(Document document, Phrase phrase) throws DocumentException { + Paragraph paragraph=new Paragraph(); + paragraph.add(phrase); + paragraph.setAlignment(Element.ALIGN_CENTER); + document.add(paragraph); + } + + public PDFBuilder addDocument(File file){ + try { + FileOutputStream out = new FileOutputStream(file); + return addDocument(out); + } catch (Exception e) { + System.err.println("create document error"); + e.printStackTrace(); + } + return null; + } + + public PDFBuilder addDocument(OutputStream outputStream){ + try{ + document = new Document(pageSize); + PdfWriter.getInstance(document, outputStream); + document.open(); + return this; + }catch (Exception e) { + System.err.println("create document error"); + e.printStackTrace(); + } + return null; + } + + private void nextLine(PdfPTable table){ + table.completeRow(); + } + + public void nextPage(){ + document.newPage(); + } + + private PdfPTable addCellNumber(int cellNumber){ + return new PdfPTable(cellNumber); + } + + private void attach(PdfPTable table, String[] strArr) { + try{ + table.getDefaultCell().setBorder(0); + Font font = new Font(baseFont, cellFontSize, Font.NORMAL, BaseColor.BLACK); + + for (String s : strArr) { + PdfPCell pdfPCell = new PdfPCell(new Phrase(s, font)); + pdfPCell.setBorder(0); + pdfPCell.setPadding(5f); + addBodyCell(table,pdfPCell); + } + nextLine(table); + } catch (Exception e) { + e.printStackTrace(); + } + + } + + private void clear(){ + this.data = null; + this.clazz = null; + this.padding = 0f; + this.spacing = 50f; + this.tableWidth = 0f; + this.pageSize = PageSize.A4; + this.paragraphFontSize = 20; + this.cellFontSize = 14; + this.headerFontSize = 16; + this.limit = 0; + this.title = null; + this.headerBgColor = BaseColor.GRAY; + this.headerFontColor = BaseColor.WHITE; + this.cellFontColor = BaseColor.BLACK; + this.cellBgColor = BaseColor.WHITE; + this.horizontal(Boolean.TRUE); + this.ratio = null; + } + + public void addTable(){ + addTable(null); + } + + public void addTable(String[] content){ + try{ + if (clazz == null) { + System.err.println("class not be defined"); + return; + } + Font paragraphFont = new Font(baseFont, paragraphFontSize, Font.BOLD); + addParagraph(document, new Phrase(title, paragraphFont)); + + headerFont = new Font(baseFont, headerFontSize, Font.NORMAL, headerFontColor); + bodyFont = new Font(baseFont, cellFontSize, Font.NORMAL,cellFontColor); + + Field[] declaredFields = clazz.getDeclaredFields(); + PdfPTable table; + if (isHorizontal) { + table = renderByHorizontal(declaredFields,content); + } else { + table = renderByVertical(declaredFields,content); + } +// table.setSpacingAfter(spacing); + document.add(table); + }catch (Exception exception){ + System.err.println("add table error"); + exception.printStackTrace(); + }finally { + clear(); + } + } + + private int calcTableCol(Field[] declaredFields) { + for (Field declaredField : declaredFields) { + declaredField.setAccessible(true); + PDFProperty annotation = declaredField.getAnnotation(PDFProperty.class); + if(null != annotation && null != annotation.value()){ + return 1; + } + } + return 0; + } + + private PdfPTable renderByHorizontal(Field[] declaredFields, String[] content) { + int col = calcTableCol(declaredFields); + PdfPTable table; + if(ratio == null || ratio.length != declaredFields.length){ + table = addCellNumber(declaredFields.length); + }else{ + table = new PdfPTable(ratio); + } + + table.getDefaultCell().setBorder(0); + table.getDefaultCell().setBorder(0); + table.setSpacingBefore(spacing); + if(content != null && content.length > 0){ + attach(table,content); + } + if(tableWidth > 0){ + table.setLockedWidth(true); + table.setTotalWidth(tableWidth); + } + try{ + for (Field declaredField : declaredFields) { + PDFProperty annotation = declaredField.getAnnotation(PDFProperty.class); + if(col > 0){ + if(null != annotation){ + addHeadCell(table,new Phrase(annotation.value(),headerFont)); + }else{ + addHeadCell(table,new Phrase("",headerFont)); + } + } + } + nextLine(table); + int counter = 0; + for (int i = 0; i < data.length; i++) { + for (Field field : declaredFields) { + field.setAccessible(true); + if(null == data[i] || null == field.get(data[i])){ + addBodyCell(table, new Phrase(""),i); + }else{ + addBodyCell(table, new Phrase(field.get(data[i]).toString(), bodyFont),i); + } + } + counter++; + if(limit > 0 && counter == limit){ + table.completeRow(); + document.add(table); + document.newPage(); + if(ratio == null || ratio.length != declaredFields.length){ + table = addCellNumber(declaredFields.length); + }else{ + table = new PdfPTable(ratio); + } + if(limit > 0 && tableWidth > 0){ + table.setLockedWidth(true); + table.setTotalWidth(tableWidth); + } + counter = 0; + } + } + + } catch (Exception e) { + System.err.println("render pdf page error"); + e.printStackTrace(); + } + return table; + } + + private PdfPTable renderByVertical(Field[] declaredFields, String[] content) { + + int col = calcTableCol(declaredFields); + PdfPTable table; + if(ratio == null || ratio.length != data.length + col){ + table = addCellNumber(data.length + col); + }else{ + table = new PdfPTable(ratio); + } + table.setSpacingBefore(spacing); + if(content != null && content.length > 0){ + attach(table,content); + } + if(tableWidth > 0){ + table.setLockedWidth(true); + table.setTotalWidth(tableWidth); + } + try{ + int counter = 0; + for (int i = 0; i < declaredFields.length; i++) { + Field declaredField = declaredFields[i]; + PDFProperty annotation = declaredField.getAnnotation(PDFProperty.class); + if(col > 0){ + if(null != annotation){ + PdfPCell pdfPCell = new PdfPCell(new Phrase(annotation.value(), headerFont)); + pdfPCell.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE); + pdfPCell.setHorizontalAlignment(PdfPCell.ALIGN_LEFT); + addHeadCell(table,pdfPCell,i); + }else{ + addHeadCell2(table, new Phrase("",headerFont),i); + } + } + + for (Object meta : data) { + declaredField.setAccessible(true); + if(null == data || null == declaredField.get(meta)){ + addBodyCell(table, new Phrase(""),i); + }else{ + addBodyCell(table, new Phrase(declaredField.get(meta).toString(), bodyFont),i); + } + } + counter++; + nextLine(table); + if(limit > 0 && counter == limit){ + nextLine(table); + document.add(table); + document.newPage(); + if(ratio == null || ratio.length != data.length + col){ + table = addCellNumber(data.length + col); + }else{ + table = new PdfPTable(ratio); + } + if(tableWidth > 0){ + table.setLockedWidth(true); + table.setTotalWidth(tableWidth); + } + counter = 0; + } + } + }catch (Exception exception){ + System.err.println("render pdf page error"); + exception.printStackTrace(); + } + return table; + } + +} diff --git a/src/main/java/com/newyetai/component/file/util/PDFProperty.java b/src/main/java/com/newyetai/component/file/util/PDFProperty.java new file mode 100644 index 0000000..09c1971 --- /dev/null +++ b/src/main/java/com/newyetai/component/file/util/PDFProperty.java @@ -0,0 +1,13 @@ +package com.newyetai.component.file.util; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface PDFProperty { + + String value() default ""; +} diff --git a/src/main/java/com/newyetai/component/file/util/Pdf2ImageUtil.java b/src/main/java/com/newyetai/component/file/util/Pdf2ImageUtil.java new file mode 100644 index 0000000..1a5a2ad --- /dev/null +++ b/src/main/java/com/newyetai/component/file/util/Pdf2ImageUtil.java @@ -0,0 +1,191 @@ +package com.newyetai.component.file.util; + +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.net.URLConnection; +import java.util.List; +import java.util.function.Supplier; + +import javax.imageio.ImageIO; + +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.rendering.PDFRenderer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.google.common.collect.Lists; +import com.newyetai.component.file.entity.FileRecord; +import com.newyetai.component.file.service.FileService; + +import cn.hutool.core.util.StrUtil; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Component +public class Pdf2ImageUtil { + + private static final int DEFAULT_DPI = 99; + + private static final List SEPARATORS = Lists.newArrayList("/", "\\"); + + private static final long MAX_BYTE_NUM = 10 * 1024 * 1024; +// private static final int MAX_BYTE_NUM = 10; + + private Pdf2ImageUtil() { + } + + private static FileService fileService; + + @Autowired + public void setFileService(FileService fileService) { + this.fileService = fileService; + } + + /** + * 远程PDF链接转长图 + * + * @param pdfRemoteUrl 远程PDF链接 + * @param imgFilePath 目标图片文件路径 /usr/local/contract.png + * @return + */ + public static FileRecord pdf2Image(String pdfRemoteUrl, String imgFilePath) { + return pdf2Image("1", pdfRemoteUrl, imgFilePath); + } + + /** + * 远程PDF链接转长图 + * + * @param pdfType 1:远程 2:文件系统 + * @param pdfRemoteUrl 远程PDF链接 + * @return + */ + public static FileRecord pdf2Image(String pdfType, String pdfRemoteUrl, String imgFileName) { + log.info("PDF链接转图片,pdfRemoteUrl:[{}],imgFilePath:[{}]", pdfRemoteUrl, imgFileName); + if (StrUtil.equals(pdfType, "2")) { + return filePdf2Image(pdfRemoteUrl, imgFileName, DEFAULT_DPI); + } + return remotePdf2Image(pdfRemoteUrl, imgFileName, DEFAULT_DPI); + } + + /** + * PDF文件转PNG图片 + * + * @param filePdfPath PDF文件路径 + * @param imgFileName 图片文件名称 + * @param dpi 清晰度 + * @return + */ + public static FileRecord filePdf2Image(String filePdfPath, String imgFileName, int dpi) { + log.info("文件PDF链接转图片,filePdfPath:[{}],imgFileFolder:[{}],imgFileName:[{}],dpi:[{}]", filePdfPath, imgFileName, dpi); + return pdf2Image(imgFileName, dpi, () -> { + try { + return PDDocument.load(FileStorageUtils.get().download(filePdfPath)); + } catch (Exception e) { + log.error("获取文件资源错误, filePdfPath: [{}]", filePdfPath, e); + e.printStackTrace(); + return null; + } + }); + } + + /** + * 远程PDF链接转长图 + * + * @param pdfRemoteUrl 远程PDF链接 + * @param imgFileName 图片文件名 contract.png + * @param dpi 图片精度 + * @return + */ + public static FileRecord remotePdf2Image(String pdfRemoteUrl, String imgFileName, int dpi) { + log.info("远程PDF链接转图片,pdfRemoteUrl:[{}],imgFileFolder:[{}],imgFileName:[{}],dpi:[{}]", pdfRemoteUrl, imgFileName, dpi); + return pdf2Image(imgFileName, dpi, () -> { + URL url = null; + try { + url = new URL(pdfRemoteUrl); + URLConnection urlConnection = url.openConnection(); + int contentLength = urlConnection.getContentLength(); + if (contentLength > MAX_BYTE_NUM) { + log.info("PDF文件过大,文件大小:[{}]", FileUtils.getByteSizePretty(contentLength)); + return null; + } + } catch (IOException e) { + e.printStackTrace(); + return null; + } + + try (InputStream is = url.openStream()) { + return PDDocument.load(is); + } catch (Exception e) { + log.error("获取远程资源错误, pdfRemoteUrl: [{}]", pdfRemoteUrl, e); + e.printStackTrace(); + return null; + } + }); + } + + + /** + * PDF转图片内部处理逻辑 + * + * @param imgFileName 图片名称带后缀 + * @param dpi 图片清晰度 + * @param supplier + * @param + * @return + */ + private static FileRecord pdf2Image(String imgFileName, int dpi, Supplier supplier) { + String fileFormat = ""; + if (StrUtil.isNotEmpty(imgFileName)) { + List split = StrUtil.split(imgFileName, "."); + if (split.size() == 2) { + fileFormat = split.get(1); + } + + } + if (StrUtil.isEmpty(fileFormat)) { + return null; + } + + try (PDDocument pdDocument = supplier.get()) { + if (pdDocument == null) { + return null; + } + //定义PDF转换器 + PDFRenderer renderer = new PDFRenderer(pdDocument); + /* dpi越大转换后越清晰,相对转换速度越慢 */ + int numberOfPages = pdDocument.getNumberOfPages(); + int width = 0; + int height = 0; + BufferedImage bi = null; + for (int i = 0; i < numberOfPages; i++) { + BufferedImage image = renderer.renderImageWithDPI(i, dpi); + if (bi == null) { + width = image.getWidth(); + height = image.getHeight(); + bi = new BufferedImage(width, height * numberOfPages, BufferedImage.TYPE_4BYTE_ABGR); + } + //复制图片像素点,将多个图片合并成一个长图 + int nowHeight = i * height; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + bi.setRGB(x, nowHeight + y, image.getRGB(x, y)); + } + } + } + + try (ByteArrayOutputStream out = new ByteArrayOutputStream(2 << 12)){ + ImageIO.write(bi, fileFormat, out); + return fileService.upload(imgFileName, out.toByteArray()); + } catch (Exception e) { + return null; + } + } catch (Exception e) { + log.error("PDF链接转PNG图片失败,", e); + } + return null; + } + +} diff --git a/src/main/java/com/newyetai/component/file/util/PdfUtils.java b/src/main/java/com/newyetai/component/file/util/PdfUtils.java new file mode 100644 index 0000000..3b76444 --- /dev/null +++ b/src/main/java/com/newyetai/component/file/util/PdfUtils.java @@ -0,0 +1,121 @@ +package com.newyetai.component.file.util; + +import java.awt.geom.Rectangle2D; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.PDPage; + +import com.newyetai.common.exception.BusinessException; +import com.spire.pdf.FileFormat; +import com.spire.pdf.PdfDocument; +import com.spire.pdf.PdfPageBase; +import com.spire.pdf.annotations.PdfRubberStampAnnotation; +import com.spire.pdf.annotations.appearance.PdfAppearance; +import com.spire.pdf.graphics.PdfImage; +import com.spire.pdf.graphics.PdfTemplate; +import com.spire.pdf.widget.PdfPageCollection; + +import lombok.extern.slf4j.Slf4j; + + +@Slf4j +public class PdfUtils { + + /** + * pdf盖章(每页) + * @param pdfIn pdf + * @param stampIn 章 + * @param pdfOut + * @author sr on 2023-11-16 + */ + public static void pdfStampPerPage(InputStream pdfIn, InputStream stampIn, OutputStream pdfOut) { + PdfDocument doc = new PdfDocument(); + doc.loadFromStream(pdfIn); + //添加空白文档 + doc.getPages().add(); + PdfPageCollection pages = doc.getPages(); + if (pages.getCount() == 0) { + return; + } + PdfRubberStampAnnotation stamp = getStamp(doc.getPages().get(0), stampIn); + for (int i = 0; i < pages.getCount(); i++) { + PdfPageBase page = doc.getPages().get(i); + //添加图章到PDF + page.getAnnotationsWidget().add(stamp); + } + //保存文档 + try (ByteArrayOutputStream pdfStampOut = new ByteArrayOutputStream()) { + doc.saveToStream(pdfStampOut, FileFormat.PDF); + //删除空白文档 + removeLast(pdfStampOut.toByteArray(), pdfOut); + } catch (IOException e) { + log.info("pdf添加印章失败:", e); + throw new BusinessException("pdf添加印章失败:" + e.getMessage()); + } + } + + + + /** + * 删除pdf最后一页 + * @param pdfStampBytes + * @param pdfOut + * @author sr on 2023-11-16 + */ + public static void removeLast(byte[] pdfStampBytes, OutputStream pdfOut) { + try { + // 加载PDF文档 + PDDocument document = PDDocument.load(pdfStampBytes); + int pageNumberToRemove = document.getPages().getCount() - 1; + // 获取要删除的页 + PDPage pageToRemove = document.getPage(pageNumberToRemove); + // 删除页 + document.removePage(pageToRemove); + // 保存修改后的PDF + document.save(pdfOut); + // 关闭文档 + document.close(); + } catch (IOException e) { + log.info("pdf删除最后页失败:", e); + throw new BusinessException("pdf删除最后页失败:" + e.getMessage()); + } + } + + + private static PdfRubberStampAnnotation getStamp(PdfPageBase page, InputStream stampIn) { + //加载印章图片 + PdfImage image = PdfImage.fromStream(stampIn); + //获取印章图片的宽度和高度 + int width = image.getWidth(); + int height = image.getHeight(); + + //创建PdfTemplate对象 + PdfTemplate template = new PdfTemplate(width, height); + //将图片绘制到模板 要在pdf上调整好大小 + template.getGraphics().drawImage(image, 20, 0, 100, 100); + + //创建PdfRubebrStampAnnotation对象,指定大小和位置 + Rectangle2D rect = new Rectangle2D.Float((float) (page.getActualSize().getWidth() - width - 0), + (float) (page.getActualSize().getHeight() - height + 50), width, height); + + PdfRubberStampAnnotation stamp = new PdfRubberStampAnnotation(rect); + + //创建PdfAppearance对象 + PdfAppearance pdfAppearance = new PdfAppearance(stamp); + //将模板应用为PdfAppearance的一般状态 + pdfAppearance.setNormal(template); + //将PdfAppearance 应用为图章的样式 + stamp.setAppearance(pdfAppearance); + return stamp; + } + +} diff --git a/src/main/java/com/newyetai/component/notice/constant/NoticeFirstTypeEnum.java b/src/main/java/com/newyetai/component/notice/constant/NoticeFirstTypeEnum.java new file mode 100644 index 0000000..62b1765 --- /dev/null +++ b/src/main/java/com/newyetai/component/notice/constant/NoticeFirstTypeEnum.java @@ -0,0 +1,24 @@ +package com.newyetai.component.notice.constant; + +/** + * 通知大类 + */ +public enum NoticeFirstTypeEnum { + + /** 异步任务 */ + ASYNC_TASK_NOTICE("async_task_notice"), + /** 聊天 */ + CHAT("chat"), + ; + + private String type; + + NoticeFirstTypeEnum(String type) { + this.type = type; + } + + public String getType() { + return type; + } + +} diff --git a/src/main/java/com/newyetai/component/notice/dto/NoticeMsgDTO.java b/src/main/java/com/newyetai/component/notice/dto/NoticeMsgDTO.java new file mode 100644 index 0000000..a082b16 --- /dev/null +++ b/src/main/java/com/newyetai/component/notice/dto/NoticeMsgDTO.java @@ -0,0 +1,26 @@ +package com.newyetai.component.notice.dto; + +import com.newyetai.component.notice.constant.NoticeFirstTypeEnum; +import java.io.Serializable; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class NoticeMsgDTO implements Serializable { + + private Long receiverId; + /** @see NoticeFirstTypeEnum 类型 **/ + private String type; + /** 消息对象 */ + private T data; + + public static NoticeMsgDTO create(Long receiverId, String type, T data) { + return new NoticeMsgDTO(receiverId, type, data); + } + +} diff --git a/src/main/java/com/newyetai/component/notice/service/AsyncNoticeHandler.java b/src/main/java/com/newyetai/component/notice/service/AsyncNoticeHandler.java new file mode 100644 index 0000000..b3c4a41 --- /dev/null +++ b/src/main/java/com/newyetai/component/notice/service/AsyncNoticeHandler.java @@ -0,0 +1,42 @@ +package com.newyetai.component.notice.service; + +import com.newyetai.component.notice.dto.NoticeMsgDTO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.stereotype.Service; + +import com.newyetai.component.asyntasknotice.util.AsyncTaskNoticeUtils; +import com.newyetai.mq.consumer.handler.ITopicMqHandler; +import com.newyetai.mq.dto.TopicMqMessage; + +@Service +@ConditionalOnBean(INoticeSendProvider.class) +public class AsyncNoticeHandler implements ITopicMqHandler{ + + @Autowired(required = false) + private INoticeSendProvider noticeSendProvider; + + public static final String ROUTING_KEY = "async_notice"; + + @Override + public String getRoutingKey() { + return ROUTING_KEY; + } + + @Override + public void onMessage(TopicMqMessage message) { + try { + if (noticeSendProvider != null) { + noticeSendProvider.send(message.getData()); + } + } catch (Exception e) { + } + } + + @Override + public boolean isBroadcast() { + return true; + } + + +} diff --git a/src/main/java/com/newyetai/component/notice/service/INoticeSendProvider.java b/src/main/java/com/newyetai/component/notice/service/INoticeSendProvider.java new file mode 100644 index 0000000..c5ecb09 --- /dev/null +++ b/src/main/java/com/newyetai/component/notice/service/INoticeSendProvider.java @@ -0,0 +1,13 @@ +package com.newyetai.component.notice.service; + +import com.newyetai.component.notice.dto.NoticeMsgDTO; + +/** + * 异步任务发送 + * @author sr on 2024-03-06 + */ +public interface INoticeSendProvider { + + void send(NoticeMsgDTO msg); + +} diff --git a/src/main/java/com/newyetai/component/notice/util/NoticeUtils.java b/src/main/java/com/newyetai/component/notice/util/NoticeUtils.java new file mode 100644 index 0000000..25aa789 --- /dev/null +++ b/src/main/java/com/newyetai/component/notice/util/NoticeUtils.java @@ -0,0 +1,17 @@ +package com.newyetai.component.notice.util; + +import com.newyetai.component.notice.dto.NoticeMsgDTO; +import com.newyetai.component.notice.service.AsyncNoticeHandler; +import com.newyetai.mq.util.MqSendUtils; + +public class NoticeUtils { + + /** + * 发送异步通知 + * @param msg + */ + public static void sendAsyncNotice(NoticeMsgDTO msg){ + MqSendUtils.send(AsyncNoticeHandler.ROUTING_KEY, msg); + } + +} diff --git a/src/main/java/com/newyetai/config/constant/ConfigConstants.java b/src/main/java/com/newyetai/config/constant/ConfigConstants.java new file mode 100644 index 0000000..8497c12 --- /dev/null +++ b/src/main/java/com/newyetai/config/constant/ConfigConstants.java @@ -0,0 +1,28 @@ +package com.newyetai.config.constant; + +/** + * 配置常量类 + * @author sr on 2019-10-20 + */ +public class ConfigConstants { + + /** + * -----校验信息----- + **/ + public static final String CONFIG_ID_NULL = "配置id不能为空"; + public static final String CONFIG_CODE_EMPTY = "配置编码不能为空"; + /** -----校验信息----- **/ + + + /** + * -----异常信息----- + **/ + public static final String CONFIG_CODE_EXIST = "配置编码已存在"; + public static final String CONFIG_NOT_EXIST = "未找到对应配置"; + /** -----异常信息----- **/ + + /** + * 业务数据忽略机构配置 + */ + public static final String CONFIG_IGNORE_ORG_INFO = "ignore_org_info"; +} diff --git a/src/main/java/com/newyetai/config/controller/ConfigController.java b/src/main/java/com/newyetai/config/controller/ConfigController.java new file mode 100644 index 0000000..26592ae --- /dev/null +++ b/src/main/java/com/newyetai/config/controller/ConfigController.java @@ -0,0 +1,96 @@ +package com.newyetai.config.controller; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.common.validation.Create; +import com.newyetai.config.dao.ConfigMapper; +import com.newyetai.config.dto.*; +import com.newyetai.config.service.ConfigService; +import com.newyetai.tkmybatis.pojo.Page; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.List; + +/** + * 配置操作 + * + * @author on 2019-11-05 + */ +@RestController +@RequestMapping("config") +@Api(tags = "配置操作") +public class ConfigController { + + @Autowired + private ConfigService configService; + + @Resource + private ConfigMapper configMapper; + + @PostMapping + @ApiOperation("配置表-创建") + public AlitaResult create(@RequestBody ConfigOperatorDTO operatorDTO) { + return AlitaResult.success(configService.create(operatorDTO)); + } + + @PutMapping + @ApiOperation("配置表-修改") + public AlitaResult modify(@RequestBody ConfigOperatorDTO operatorDTO) { + return AlitaResult.success(configService.modify(operatorDTO)); + } + + @DeleteMapping("{id}") + @ApiOperation("配置表-删除") + public AlitaResult delete(@PathVariable("id") Long id) { + return AlitaResult.success(configService.delete(id)); + } + + @GetMapping("{id}") + @ApiOperation("配置表-查询单个") + public AlitaResult findById(@PathVariable("id") Long id) { + return AlitaResult.success(configService.findById(id)); + } + + @GetMapping("list") + @ApiOperation("配置表-列表查询") + public AlitaResult> list(ConfigQueryDTO queryDTO) { + return AlitaResult.success(configService.list(queryDTO)); + } + + @GetMapping("page") + @ApiOperation("配置表-分页查询") + public AlitaResult> page(ConfigPageQueryDTO queryDTO) { + configService.page(queryDTO); + return AlitaResult.success(queryDTO.getPageResult()); + } + + @GetMapping("org_list/{configCode}") + @ApiOperation("可分配的机构列表") + public AlitaResult> orgListCanSelect(@PathVariable("configCode") String configCode) { + return AlitaResult.success(configMapper.orgList(configCode)); + } + + + + @ApiOperation("根据编码获取配置") + @GetMapping("/code/{configCode}") + public AlitaResult getTemplate(@PathVariable("configCode") String configCode) { + return AlitaResult + .success(configService.queryConfigByCode(UserContextHolder.getExistLoginOrgId(), configCode)); + } + + @ApiOperation("根据编码获取配置") + @GetMapping("/org_code/{configCode}") + public AlitaResult getOrgConfig(@PathVariable("configCode") String configCode) { + return AlitaResult + .success(configService.queryOrgConfigByCode(UserContextHolder.getExistLoginOrgId(), configCode)); + } + +} diff --git a/src/main/java/com/newyetai/config/convert/ConfigConvert.java b/src/main/java/com/newyetai/config/convert/ConfigConvert.java new file mode 100644 index 0000000..c7c6321 --- /dev/null +++ b/src/main/java/com/newyetai/config/convert/ConfigConvert.java @@ -0,0 +1,25 @@ +package com.newyetai.config.convert; + +import com.newyetai.config.dto.ConfigDTO; +import com.newyetai.config.dto.ConfigOperatorDTO; +import com.newyetai.config.entity.Config; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * 配置表 + * + * @author chenyun chenyun.home@outlook.com + * @since 1.0.0 2023-01-04 + */ +@Mapper +public interface ConfigConvert { + ConfigConvert INSTANCE = Mappers.getMapper(ConfigConvert.class); + + Config convert(ConfigDTO dto); + + ConfigDTO convert(Config entity); + + Config convert(ConfigOperatorDTO dto); + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/config/dao/ConfigMapper.java b/src/main/java/com/newyetai/config/dao/ConfigMapper.java new file mode 100644 index 0000000..e2d272a --- /dev/null +++ b/src/main/java/com/newyetai/config/dao/ConfigMapper.java @@ -0,0 +1,94 @@ +package com.newyetai.config.dao; + +import com.newyetai.config.dto.ConfigDTO; +import com.newyetai.config.dto.ConfigPageQueryDTO; +import com.newyetai.config.dto.ConfigQueryDTO; +import com.newyetai.config.dto.OrgInfoDTO; +import com.newyetai.config.entity.Config; +import com.newyetai.tkmybatis.mybatis.MyMapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; +import java.util.Set; + +/** + * 配置mapper + * + * @author sr on 2019-10-20 + */ +public interface ConfigMapper extends MyMapper { + + /** + * 排除已经被分配的配置机构,剩余的机构 + * + * @param configCode 配置代码 + * @return {@link List}<{@link OrgInfoDTO}> + */ + List orgList(@Param("configCode") String configCode); + + List page(@Param("param") ConfigPageQueryDTO queryDTO); + + List list(@Param("param") ConfigQueryDTO queryDTO); + + /** + * 查询配置 + * + * @param config + * @return + * @author sr on 2019-11-05 + */ + List find(@Param("param") Config config); + + /** + * + * @param configCode + * @param orgIds + * @return + */ + List listByCodeAndOrgIds(@Param("configCode") String configCode, @Param("orgIds") Set orgIds); + + /** + * 校验配置编码是否存在 + * @param orgId + * @param configCode + * @param configId 为空则判断所有(新增),不为空代表判断除该id之外的(修改) + * @return + * @author sr on 2019-10-20 + */ + int existConfigCode(@Param("orgId") Long orgId, @Param("configCode") String configCode, @Param("configId") Long configId); + + /** + * 根据编码获取配置 + * @param platformOrgId + * @param orgId + * @param configCode + * @return + * @author sr on 2019-10-23 + */ + ConfigDTO queryConfigByCode(@Param("platformOrgId") Long platformOrgId, + @Param("orgId") Long orgId, @Param("configCode") String configCode); + + /** + * 根据编码获取机构配置 + * @param orgId + * @param configCode + * @return + * @author sr on 2019-10-23 + */ + ConfigDTO queryOrgConfigByCode(@Param("orgId") Long orgId, @Param("configCode") String configCode); + + /** + * 新增并校验是否重复(org_id,config_code),重复则不新增 + * + * @param config + */ + int saveAndCheckExist(@Param("param") Config config, @Param("userId") Long userId); + + /** + * 批量删除 + * + * @param configCode 配置代码 + * @param userId 用户id + */ + void batchDelete(@Param("configCode") String configCode, @Param("userId") Long userId); +} diff --git a/src/main/java/com/newyetai/config/dto/ConfigDTO.java b/src/main/java/com/newyetai/config/dto/ConfigDTO.java new file mode 100644 index 0000000..2c8a2a5 --- /dev/null +++ b/src/main/java/com/newyetai/config/dto/ConfigDTO.java @@ -0,0 +1,52 @@ +package com.newyetai.config.dto; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; +import com.newyetai.config.constant.ConfigConstants; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +/** + * 配置 + * + * @author on 2019-11-05 + */ +@ApiModel("配置") +@Data +@EqualsAndHashCode(callSuper = true) +public class ConfigDTO extends BaseDTO implements Serializable { + + /** + * + **/ + private static final long serialVersionUID = -7378966546274876887L; + + @ApiModelProperty("配置id") + @NotNull(message = ConfigConstants.CONFIG_ID_NULL, groups = {Update.class}) + private Long id; + + @ApiModelProperty("机构名称") + private String orgName; + + private Long orgId; + + @ApiModelProperty("编码") + @NotBlank(message = ConfigConstants.CONFIG_CODE_EMPTY, groups = {Create.class, Update.class}) + private String configCode; + + @ApiModelProperty("配置值") + private String configValue; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("是否启用") + private Boolean enable; +} diff --git a/src/main/java/com/newyetai/config/dto/ConfigOperatorDTO.java b/src/main/java/com/newyetai/config/dto/ConfigOperatorDTO.java new file mode 100644 index 0000000..b11fac1 --- /dev/null +++ b/src/main/java/com/newyetai/config/dto/ConfigOperatorDTO.java @@ -0,0 +1,45 @@ +package com.newyetai.config.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 chenyun chenyun.home@outlook.com +* @since 1.0.0 2023-01-04 +*/ +@ApiModel("配置表") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ConfigOperatorDTO implements Serializable { + + private static final long serialVersionUID = -6593867699038600971L; + + private Long id; + + @ApiModelProperty("编码") + private String configCode; + + @ApiModelProperty("配置值") + private String configValue; + + @ApiModelProperty("机构") + private Long orgId; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("是否启用") + private Boolean enable; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/config/dto/ConfigPageQueryDTO.java b/src/main/java/com/newyetai/config/dto/ConfigPageQueryDTO.java new file mode 100644 index 0000000..cf94b3d --- /dev/null +++ b/src/main/java/com/newyetai/config/dto/ConfigPageQueryDTO.java @@ -0,0 +1,77 @@ +package com.newyetai.config.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.newyetai.common.annotation.trimAndUpper.TrimAndUpper; +import com.newyetai.common.dto.PageQueryDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +/** + * 配置表 + * + * @author chenyun chenyun.home@outlook.com + * @since 1.0.0 2023-01-04 + */ + +@ApiModel("配置表") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class ConfigPageQueryDTO extends PageQueryDTO { + + private static final long serialVersionUID = -2457835934025456625L; + + @ApiModelProperty("主键ID") + private Long id; + + @ApiModelProperty("机构名称 (模糊匹配)") + @TrimAndUpper(TrimAndUpper.ExecuteType.TRIM) + private String orgNameLike; + + @ApiModelProperty("编码") + private String configCode; + + @ApiModelProperty("编码(模糊匹配)") + @TrimAndUpper(TrimAndUpper.ExecuteType.TRIM) + private String configCodeLike; + + @ApiModelProperty("配置值") + private String configValue; + + @ApiModelProperty("机构") + private Long orgId; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("是否启用") + private Boolean enable; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("修改时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeStart; + + @ApiModelProperty("修改时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeEnd; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/config/dto/ConfigQueryDTO.java b/src/main/java/com/newyetai/config/dto/ConfigQueryDTO.java new file mode 100644 index 0000000..8fc9330 --- /dev/null +++ b/src/main/java/com/newyetai/config/dto/ConfigQueryDTO.java @@ -0,0 +1,76 @@ +package com.newyetai.config.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.format.annotation.DateTimeFormat; + +import java.io.Serializable; +import java.util.Date; +import java.util.Set; + +/** + * 配置表 + * + * @author chenyun chenyun.home@outlook.com + * @since 1.0.0 2023-01-04 + */ +@ApiModel("配置表") +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ConfigQueryDTO implements Serializable { + + private static final long serialVersionUID = 2141446474852301916L; + + @ApiModelProperty("主键ID") + private Long id; + + @ApiModelProperty("编码") + private String configCode; + + @ApiModelProperty("编码(模糊匹配)") + private String configCodeLike; + + @ApiModelProperty("配置值") + private String configValue; + + @ApiModelProperty("机构") + private Long orgId; + + @ApiModelProperty("机构集合") + private Set orgIds; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("是否启用") + private Boolean enable; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("修改时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeStart; + + @ApiModelProperty("修改时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeEnd; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/config/dto/OrgInfoDTO.java b/src/main/java/com/newyetai/config/dto/OrgInfoDTO.java new file mode 100644 index 0000000..807eeda --- /dev/null +++ b/src/main/java/com/newyetai/config/dto/OrgInfoDTO.java @@ -0,0 +1,26 @@ +package com.newyetai.config.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class OrgInfoDTO implements Serializable { + private static final long serialVersionUID = 4030022865543182548L; + + /** + * id + */ + private Long id; + + /** + * 机构名字 + */ + private String orgName; +} diff --git a/src/main/java/com/newyetai/config/entity/Config.java b/src/main/java/com/newyetai/config/entity/Config.java new file mode 100644 index 0000000..33afa04 --- /dev/null +++ b/src/main/java/com/newyetai/config/entity/Config.java @@ -0,0 +1,64 @@ +package com.newyetai.config.entity; + + +import java.util.Date; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * 配置 + * + * @author on 2019-11-05 + */ +@TableName(value = "xs_config") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Data +public class Config extends BaseEntity { + + /** **/ + private static final long serialVersionUID = -4915635782620683517L; + /** + * 编码 + */ + private String configCode; + /** + * 配置值 + */ + private String configValue; + /** + * 机构 + */ + private Long orgId; + /** + * 备注 + */ + private String remark; + /** + * 是否启用 + */ + private Boolean enable; + + @Builder + public Config(Long id, Boolean deleted, Long createBy, Date createTime, Long updateBy, + Date updateTime, Long proxyBy, String configCode, String configValue, Long orgId, + String remark, Boolean enable) { + super(id, deleted, createBy, createTime, updateBy, updateTime, proxyBy); + this.configCode = configCode; + this.configValue = configValue; + this.orgId = orgId; + this.remark = remark; + this.enable = enable; + } + + + +} diff --git a/src/main/java/com/newyetai/config/mapper/ConfigMapper.xml b/src/main/java/com/newyetai/config/mapper/ConfigMapper.xml new file mode 100644 index 0000000..5ecdb49 --- /dev/null +++ b/src/main/java/com/newyetai/config/mapper/ConfigMapper.xml @@ -0,0 +1,222 @@ + + + + + UPDATE xs_config + SET deleted = TRUE, + update_time = NOW(), + update_by = #{userId} + WHERE deleted = 0 + AND config_code = #{configCode} + + + + + + + + FROM + xs_config t + WHERE t.deleted = 0 + + AND t.id = #{param.id} + + + AND t.config_code = #{param.configCode} + + + AND t.config_value = #{param.configValue} + + + + and config_code like #{configCodeLike} + + + AND t.org_id = #{param.orgId} + + + AND t.remark = #{param.remark} + + + AND t.enable = #{param.enable} + + + AND t.create_time >= #{param.createTimeStart} + + + AND t.create_time <= #{param.createTimeEnd} + + + AND t.update_time >= #{param.updateTimeStart} + + + AND t.update_time <= #{param.updateTimeEnd} + + ORDER BY t.id DESC + + + + + + + + + + + + + + + INSERT INTO xs_config (config_code, + config_value, + org_id, + remark, + enable, + deleted, + create_time, + create_by) + SELECT #{param.configCode}, + #{param.configValue}, + #{param.orgId}, + #{param.remark}, + #{param.enable}, + 0 AS deleted, + NOW() AS create_time, + #{userId} AS create_by + FROM DUAL + WHERE NOT EXISTS(SELECT 1 + FROM xs_config + WHERE org_id = #{param.orgId} + and config_code = #{param.configCode} + and deleted = 0) + + diff --git a/src/main/java/com/newyetai/config/service/ConfigService.java b/src/main/java/com/newyetai/config/service/ConfigService.java new file mode 100644 index 0000000..4fabfb9 --- /dev/null +++ b/src/main/java/com/newyetai/config/service/ConfigService.java @@ -0,0 +1,132 @@ +package com.newyetai.config.service; + +import com.newyetai.config.dto.ConfigDTO; +import com.newyetai.config.dto.ConfigOperatorDTO; +import com.newyetai.config.dto.ConfigPageQueryDTO; +import com.newyetai.config.dto.ConfigQueryDTO; +import com.newyetai.config.entity.Config; + +import javax.validation.Valid; +import java.util.List; +import java.util.Set; + +/** + * 配置 + * + * @author sr on 2019-10-20 + */ +public interface ConfigService { + + + /** + * 配置表 - 创建 + * + * @param operatorDto 操作dto + * @return {@link com.newyetai.config.dto.ConfigDTO} + */ + ConfigDTO create(@Valid ConfigOperatorDTO operatorDto); + + /** + * 配置表 - 修改 + * + * @param operatorDto 操作dto + * @return {@link com.newyetai.config.dto.ConfigDTO} + */ + ConfigDTO modify(@Valid ConfigOperatorDTO operatorDto); + + /** + * 配置表 - 删除 + * + * @param id id + * @return {@link com.newyetai.config.dto.ConfigDTO} + */ + ConfigDTO delete(Long id); + + /** + * 配置表 - 根据ID查询单个 + * + * @param id id + * @return {@link com.newyetai.config.dto.ConfigDTO} + */ + ConfigDTO findById(Long id); + + /** + * 配置表 - 列表查询 + * + * @param queryDTO 列表查询dto + * @return {@link List}<{@link com.newyetai.config.dto.ConfigDTO}> + */ + List list(ConfigQueryDTO queryDTO); + + /** + * 配置表 - 分页查询 + * + * @param queryDTO 分页查询dto + * @return {@link com.newyetai.config.dto.ConfigDTO} + */ + List page(ConfigPageQueryDTO queryDTO); + + /** + * 查询配置 + * + * @param config + * @return + * @author sr on 2019-11-05 + */ + List find(Config config); + + /** + * 根据code和机构id集合查询配置 + * @param code + * @param orgIds + * @return + */ + List findByCodeAndOrgIds(String code, Set orgIds); + + /** + * 获取配置值 + * @param code + * @param orgId + * @param enable + * @return + */ + String getConfigValue(String code, Long orgId, boolean enable); + + + /** + * 根据code查询配置 + * @param orgId + * @param configCode + * @return + * @author sr on 2019-10-23 + */ + ConfigDTO queryConfigByCode(Long orgId, String configCode); + + /** + * 根据code查询配置 + * @param orgId + * @param configCode + * @return + * @author sr on 2019-10-23 + */ + ConfigDTO queryOrgConfigByCode(Long orgId, String configCode); + + /** + * 获取配置 + * @param code + * @param orgId + * @param enable + * @return + */ + Config getConfig(String code, Long orgId, boolean enable); + + /** + * 获取配置的dto + * @param code + * @param orgId + * @param enable + * @return + */ + ConfigDTO getConfigDto(String code, Long orgId, boolean enable); + +} diff --git a/src/main/java/com/newyetai/config/service/impl/ConfigServiceImpl.java b/src/main/java/com/newyetai/config/service/impl/ConfigServiceImpl.java new file mode 100644 index 0000000..f98e82d --- /dev/null +++ b/src/main/java/com/newyetai/config/service/impl/ConfigServiceImpl.java @@ -0,0 +1,157 @@ +package com.newyetai.config.service.impl; + + +import java.util.List; +import java.util.Objects; +import java.util.Set; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.exception.util.ExceptionUtils; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.config.constant.ConfigConstants; +import com.newyetai.config.convert.ConfigConvert; +import com.newyetai.config.dao.ConfigMapper; +import com.newyetai.config.dto.ConfigDTO; +import com.newyetai.config.dto.ConfigOperatorDTO; +import com.newyetai.config.dto.ConfigPageQueryDTO; +import com.newyetai.config.dto.ConfigQueryDTO; +import com.newyetai.config.entity.Config; +import com.newyetai.config.service.ConfigService; + +/** + * 配置 + * + * @author sr on 2019-10-20 + */ +@Service +public class ConfigServiceImpl implements ConfigService { + + @Autowired + private ConfigMapper configMapper; + + + @Override + public ConfigDTO create(ConfigOperatorDTO operatorDto) { + Config config = ConfigConvert.INSTANCE.convert(operatorDto); + configMapper.saveEntity(config); + + return ConfigConvert.INSTANCE.convert(config); + } + + @Override + public ConfigDTO modify(ConfigOperatorDTO operatorDto) { + ConfigDTO configDto = this.findById(operatorDto.getId()); + if (Objects.isNull(configDto)) { + return null; + } + Config config = ConfigConvert.INSTANCE.convert(operatorDto); + configMapper.updateEntity(config); + return this.findById(operatorDto.getId()); + } + + @Override + public ConfigDTO delete(Long id) { + ConfigDTO configDto = this.findById(id); + if (Objects.isNull(configDto)) { + return null; + } + Config config = Config.builder().build(); + config.setId(id); + configMapper.deleteEntity(config, UserContextHolder.getLoginUserId()); + return configDto; + } + + @Override + public ConfigDTO findById(Long id) { + Config config = configMapper.getById(id); + if (Objects.isNull(config)) { + return null; + } + return ConfigConvert.INSTANCE.convert(config); + } + + @Override + public List list(ConfigQueryDTO queryDTO) { + return configMapper.list(queryDTO); + } + + @Override + public List page(ConfigPageQueryDTO queryDTO) { + return configMapper.page(queryDTO); + } + + + @Override + public List find(Config config) { + return configMapper.find(config); + } + + @Override + public List findByCodeAndOrgIds(String code, Set orgIds) { + return configMapper.listByCodeAndOrgIds(code, orgIds); + } + + @Override + public String getConfigValue(String code, Long orgId, boolean enable) { + List configs = find(Config.builder().configCode(code).orgId(orgId).enable(enable).deleted(false).build()); + if(CollectionUtils.isEmpty(configs)) { + return null; + } + return configs.get(0).getConfigValue(); + } + + /** + * 校验配置编码是否存在 + * @param + * @param + */ + private void checkTemplateCode(Long orgId, String configCode, Long configId) { + int num = configMapper.existConfigCode(orgId, configCode, configId); + ExceptionUtils.throwBusinessException(num > 0, ConfigConstants.CONFIG_CODE_EXIST); + } + + + @Override + @Transactional(rollbackFor = RuntimeException.class) + public ConfigDTO queryConfigByCode(Long orgId, String configCode) { + return configMapper.queryConfigByCode(CommonConstants.PLATFORM_ORG_ID, orgId, configCode); + } + + @Override + public ConfigDTO queryOrgConfigByCode(Long orgId, String configCode) { + return configMapper.queryOrgConfigByCode(orgId, configCode); + } + + @Override + public Config getConfig(String code, Long orgId, boolean enable) { + Config query = Config.builder().configCode(code).orgId(orgId).enable(enable).build(); + List configs = find(query); + if(CollectionUtils.isEmpty(configs) && ObjectUtils.notEqual(CommonConstants.PLATFORM_ORG_ID, orgId)) { + query.setOrgId(CommonConstants.PLATFORM_ORG_ID); + configs = find(query); + } + if(CollectionUtils.isEmpty(configs)){ + return null; + } + return configs.get(0); + } + + @Override + public ConfigDTO getConfigDto(String code, Long orgId, boolean enable) { + Config config = getConfig(code, orgId, enable); + if(config == null){ + return null; + } + ConfigDTO dto = new ConfigDTO(); + BeanUtils.copyProperties(config, dto); + return dto; + } + +} diff --git a/src/main/java/com/newyetai/config/util/ConfigUtils.java b/src/main/java/com/newyetai/config/util/ConfigUtils.java new file mode 100644 index 0000000..a13d154 --- /dev/null +++ b/src/main/java/com/newyetai/config/util/ConfigUtils.java @@ -0,0 +1,40 @@ +package com.newyetai.config.util; + +import com.newyetai.config.dto.ConfigDTO; +import com.newyetai.config.entity.Config; + +/** + * 配置工具类 + * + * @author sr on 2019-10-20 + */ +public class ConfigUtils { + + /** + * dto转entity, 新增 + * + * @param + * @param orgId + * @return + */ + public static Config toCreate(ConfigDTO configDTO, Long orgId) { + Config config = Config.builder().configCode(configDTO.getConfigCode()) + .configValue(configDTO.getConfigValue()).remark(configDTO.getRemark()) + .enable(!Boolean.FALSE.equals(configDTO.getEnable())).orgId(orgId).build(); + return config; + } + + /** + * dto转entity,修改,有id;orgId不变(置空) + * + * @param + * @return + */ + public static Config toUpdate(ConfigDTO configDTO) { + Config config = Config.builder().id(configDTO.getId()).configCode(configDTO.getConfigCode()) + .configValue(configDTO.getConfigValue()).remark(configDTO.getRemark()) + .enable(!Boolean.FALSE.equals(configDTO.getEnable())).build(); + return config; + } + +} diff --git a/src/main/java/com/newyetai/frame/redis/aop/annotation/AutoUnLock.java b/src/main/java/com/newyetai/frame/redis/aop/annotation/AutoUnLock.java new file mode 100644 index 0000000..1bb4820 --- /dev/null +++ b/src/main/java/com/newyetai/frame/redis/aop/annotation/AutoUnLock.java @@ -0,0 +1,17 @@ +package com.newyetai.frame.redis.aop.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 自动解锁 + */ +@Target({ElementType.TYPE, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface AutoUnLock { + +} diff --git a/src/main/java/com/newyetai/frame/redis/aop/annotation/RedissonLock.java b/src/main/java/com/newyetai/frame/redis/aop/annotation/RedissonLock.java new file mode 100644 index 0000000..f71315f --- /dev/null +++ b/src/main/java/com/newyetai/frame/redis/aop/annotation/RedissonLock.java @@ -0,0 +1,60 @@ +package com.newyetai.frame.redis.aop.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.concurrent.TimeUnit; + +/** + * @author dylanyuan + */ +@Target({ElementType.TYPE, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +@Repeatable(RedissonLocks.class) +public @interface RedissonLock { + + /** + * 前缀 + * @return + */ + String prefix() default ""; + + /** + * 指定参数名 只支持字符串和字符串数组 + * @return + */ + String paramName(); + + /** + * 超时时间 默认-1:即为1天失效 + * 不允许不添加失效时间 + * @return + */ + long expires() default -1L; + + /** + * 时间单位,默认为秒 + * @return + */ + TimeUnit timeUnit() default TimeUnit.SECONDS; + + /** + * 尝试加锁等待时时间 默认0, + * -1则不进行trylock + * @return + */ + long tryLockWaitTime() default 0; + + /** + * 允许param值为空则跳过加锁 + * @return + */ + boolean skipIfNull() default false; + +} diff --git a/src/main/java/com/newyetai/frame/redis/aop/annotation/RedissonLocks.java b/src/main/java/com/newyetai/frame/redis/aop/annotation/RedissonLocks.java new file mode 100644 index 0000000..da78209 --- /dev/null +++ b/src/main/java/com/newyetai/frame/redis/aop/annotation/RedissonLocks.java @@ -0,0 +1,21 @@ +package com.newyetai.frame.redis.aop.annotation; + + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author dylanyuan + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE, ElementType.METHOD}) +@Documented +@Inherited +public @interface RedissonLocks { + + RedissonLock[] value(); +} diff --git a/src/main/java/com/newyetai/frame/redis/aop/annotation/RedissonMultiLock.java b/src/main/java/com/newyetai/frame/redis/aop/annotation/RedissonMultiLock.java new file mode 100644 index 0000000..c875445 --- /dev/null +++ b/src/main/java/com/newyetai/frame/redis/aop/annotation/RedissonMultiLock.java @@ -0,0 +1,66 @@ +package com.newyetai.frame.redis.aop.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.concurrent.TimeUnit; + +/** + * @author dylanyuan + */ +@Target({ElementType.TYPE, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +public @interface RedissonMultiLock { + + /** + * 前缀 + * @return + */ + String prefix() default ""; + + /** + * 指定参数名 只支持字符串和字符串数组 + * @return + */ + String paramName(); + + /** + * 超时时间 默认-1:即为1天失效 + * 不允许不添加失效时间 + * @return + */ + long expires() default -1L; + + /** + * 时间单位 默认为秒 + * @return + */ + TimeUnit timeUnit() default TimeUnit.SECONDS; + + /** + * 尝试加锁等待时时间 默认-1则不进行trylock + * @return + */ + long tryLockWaitTime() default -1; + + /** + * 是否允许部分成功 + * true, 入参必须存在Set failSet, 失败的会从加入失败队列,原始数据不移除 + * false, 不允许部分成功,所有的lock,必须全部成功 + * 默认是false + * @return + */ + boolean allowPartSuccess() default false; + + + /** + * 允许param值为空则跳过加锁 + * @return + */ + boolean skipIfNull() default false; +} diff --git a/src/main/java/com/newyetai/frame/redis/aop/aspect/RedissonLockAop.java b/src/main/java/com/newyetai/frame/redis/aop/aspect/RedissonLockAop.java new file mode 100644 index 0000000..981714f --- /dev/null +++ b/src/main/java/com/newyetai/frame/redis/aop/aspect/RedissonLockAop.java @@ -0,0 +1,44 @@ +package com.newyetai.frame.redis.aop.aspect; + +import com.newyetai.frame.redis.aop.annotation.RedissonLock; +import com.newyetai.frame.redis.util.IAopUtils; +import com.newyetai.frame.redis.util.LockUtils; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.redisson.api.RLock; +import org.springframework.stereotype.Component; + +/** + * @author dylanyuan + */ +@Aspect +@Component +@Slf4j +public class RedissonLockAop { + + @Pointcut("@annotation(com.newyetai.frame.redis.aop.annotation.RedissonLock)") + public void annotationPointCut() { + } + + @Around("annotationPointCut()") + public Object around(ProceedingJoinPoint joinPoint) throws Throwable { + log.info("redisson lock {}方法 加锁开始:{}", joinPoint.getSignature().getName(), + joinPoint.toString()); + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); + RedissonLock redissonLock = signature.getMethod().getAnnotation(RedissonLock.class); + RLock lock = null; + try { + lock = IAopUtils.lock(joinPoint, redissonLock); + return joinPoint.proceed(); + } finally { + LockUtils.unlock(lock); + log.info("redisson lock {}方法 加锁结束:{}", joinPoint.getSignature().getName(), joinPoint.toString()); + } + } + + +} diff --git a/src/main/java/com/newyetai/frame/redis/aop/aspect/RedissonLocksAop.java b/src/main/java/com/newyetai/frame/redis/aop/aspect/RedissonLocksAop.java new file mode 100644 index 0000000..d89ee04 --- /dev/null +++ b/src/main/java/com/newyetai/frame/redis/aop/aspect/RedissonLocksAop.java @@ -0,0 +1,52 @@ +package com.newyetai.frame.redis.aop.aspect; + +import com.newyetai.frame.redis.aop.annotation.RedissonLock; +import com.newyetai.frame.redis.aop.annotation.RedissonLocks; +import com.newyetai.frame.redis.util.IAopUtils; +import com.newyetai.frame.redis.util.LockUtils; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.redisson.api.RLock; +import org.springframework.stereotype.Component; + +/** + * @author dylanyuan + */ +@Aspect +@Component +@Slf4j +public class RedissonLocksAop { + + @Pointcut("@annotation(com.newyetai.frame.redis.aop.annotation.RedissonLocks)") + public void annotationPointCut() { + } + + @Around("annotationPointCut()") + public Object around(ProceedingJoinPoint joinPoint) throws Throwable { + log.info("redisson locks {}方法 加锁开始:{}", joinPoint.getSignature().getName(), joinPoint.toString()); + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); + RedissonLocks redissonLocks = signature.getMethod().getAnnotation(RedissonLocks.class); + RedissonLock[] redissonLockArray = redissonLocks.value(); + RLock[] locks = new RLock[redissonLockArray.length]; + try { + for (int i = 0; i < redissonLockArray.length; i++) { + locks[i] = IAopUtils.lock(joinPoint, redissonLockArray[i]); + } + return joinPoint.proceed(); + }finally { + for (RLock lock : locks) { + try { + LockUtils.unlock(lock); + }catch (Exception e){ + log.error("redisson locks 锁【{}】解锁失败", lock.getName(), e); + } + } + log.info("redisson locks {}方法 加锁结束:{}", joinPoint.getSignature().getName(), + joinPoint.toString()); + } + } +} diff --git a/src/main/java/com/newyetai/frame/redis/aop/aspect/RedissonMultiLockAop.java b/src/main/java/com/newyetai/frame/redis/aop/aspect/RedissonMultiLockAop.java new file mode 100644 index 0000000..395265f --- /dev/null +++ b/src/main/java/com/newyetai/frame/redis/aop/aspect/RedissonMultiLockAop.java @@ -0,0 +1,166 @@ +package com.newyetai.frame.redis.aop.aspect; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.lang3.StringUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.redisson.api.RLock; +import org.springframework.stereotype.Component; + +import com.newyetai.common.util.JsonUtils; +import com.newyetai.frame.redis.aop.annotation.RedissonMultiLock; +import com.newyetai.frame.redis.exception.RedisLockErrorParamException; +import com.newyetai.frame.redis.exception.RedisLockFailException; +import com.newyetai.frame.redis.redisson.RedissonUtils; +import com.newyetai.frame.redis.util.IAopUtils; +import com.newyetai.frame.redis.util.LockUtils; + +import lombok.extern.slf4j.Slf4j; + +/** + * @author dylanyuan + */ +@Aspect +@Component +@Slf4j +public class RedissonMultiLockAop { + + public static final String FAIL_SET = "failSet"; + + @Pointcut("@annotation(com.newyetai.frame.redis.aop.annotation.RedissonMultiLock)") + public void annotationPointCut() {} + + @Around("annotationPointCut()") + public Object around(ProceedingJoinPoint joinPoint) throws Throwable { + String methodName = joinPoint.getSignature().getName(); + log.info("redisson batchlock {}方法 加锁开始:{}", methodName, joinPoint.toString()); + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); + RedissonMultiLock redisMultiLock = signature.getMethod().getAnnotation(RedissonMultiLock.class); + String paramName = redisMultiLock.paramName(); + if (StringUtils.isBlank(paramName)) { + throw new RedisLockErrorParamException( + "redisson batchlock 方法 " + methodName + " paramName不能为空"); + } + Object paramValue = IAopUtils.getParamValue(joinPoint, paramName); + if (paramValue == null) { + boolean skipIfNull = redisMultiLock.skipIfNull(); + if (skipIfNull) { + return joinPoint.proceed(); + } + throw new RedisLockErrorParamException( + "redisson batchlock 方法 " + methodName + " paramName[" + paramName + "]所对应的参数内容不能为空"); + } + IAopUtils.checkParamType(IAopUtils.getMethod(joinPoint), paramName, paramValue, true); + boolean allowPartSuccess = redisMultiLock.allowPartSuccess(); + Collection failSet = null; + if (allowPartSuccess) { + try { + Object temp = IAopUtils.getParamValue(joinPoint, FAIL_SET); + if (temp == null) { + throw new RedisLockErrorParamException("redisson batchlock 方法 " + methodName + + " 使用部分成功加锁时必须存在失败集合参数[Collection failSet]"); + } + failSet = (Collection) temp; + } catch (Exception e) { + throw new RedisLockErrorParamException( + "redisson batchlock 方法 " + methodName + " 使用部分成功加锁时必须存在失败集合参数[Set failSet]"); + } + } else { + failSet = new ArrayList<>(); + } + long expires = redisMultiLock.expires(); + TimeUnit timeUnit = redisMultiLock.timeUnit(); + if (expires == -1) { + expires = 1; + timeUnit = TimeUnit.DAYS; + } + long tryLockWaitTime = redisMultiLock.tryLockWaitTime(); + Map key2ParamMap = new HashMap<>(); + if (paramValue instanceof String[]) { + String[] values = (String[]) paramValue; + for (String value : values) { + key2ParamMap.put(redisMultiLock.prefix() + value, value); + } + } else if (paramValue instanceof Iterable) { + Iterable iterable = (Iterable) paramValue; + Iterator iterator = iterable.iterator(); + while (iterator.hasNext()) { + String value = iterator.next(); + key2ParamMap.put(redisMultiLock.prefix() + value, value); + } + } + return partSuccessBatchLock(joinPoint, expires, timeUnit, tryLockWaitTime, key2ParamMap, + paramValue, failSet, allowPartSuccess); + } + + private Object partSuccessBatchLock(ProceedingJoinPoint joinPoint, long expires, + TimeUnit timeUnit, long tryLockWaitTime, Map key2ParamMap, Object paramValue, + Collection failSet, boolean allowPartSuccess) throws Throwable { + Map map = new HashMap<>(key2ParamMap.size()); + for (String key : key2ParamMap.keySet()) { + map.put(key, RedissonUtils.getLock(key)); + } + try { + for (Entry entry : map.entrySet()) { + LockUtils.lock(expires, timeUnit, tryLockWaitTime, entry.getValue()); + if (!entry.getValue().isLocked()) { + String value = key2ParamMap.get(entry.getKey()); + log.error("方法[{}]所对应的参数[{}]正在运行中,请不要重复操作!", joinPoint.getSignature().getName(), value); + failSet.add(value); + } + } + if (allowPartSuccess) { + if (map.size() == failSet.size()) { + throw new RedisLockFailException( + "方法[" + joinPoint.getSignature().getName() + "]所对应的参数[" + + JsonUtils.toJsonString(key2ParamMap.values()) + + "]正在运行中,请不要重复操作!"); + } else if (failSet.size() > 0) { + if (paramValue instanceof String[]) { + String[] values = (String[]) paramValue; + for (int i = 0; i < values.length; i++) { + if (failSet.contains(values[i])) { + values[i] = null; + } + } + } else if (paramValue instanceof Iterable) { + Iterable iterable = (Iterable) paramValue; + Iterator iterator = iterable.iterator(); + while (iterator.hasNext()) { + if (failSet.contains(iterator.next())) { + iterator.remove(); + } + } + } + } + } else { + if (failSet.size() > 0) { + throw new RedisLockFailException("方法[" + joinPoint.getSignature().getName() + "]所对应的参数[" + + JsonUtils.toJsonString(key2ParamMap.values()) + "]正在运行中,请不要重复操作!"); + } + } + return joinPoint.proceed(); + } finally { + for (RLock lock : map.values()) { + try { + LockUtils.unlock(lock); + } catch (Exception e) { + log.error("redisson batchlock 锁【{}】解锁失败", lock.getName(), e); + } + } + log.info("redisson batchlock {}方法 加锁结束:{}", joinPoint.getSignature().getName(), + joinPoint.toString()); + } + } + +} diff --git a/src/main/java/com/newyetai/frame/redis/aop/aspect/UnLockAutomaticallyAop.java b/src/main/java/com/newyetai/frame/redis/aop/aspect/UnLockAutomaticallyAop.java new file mode 100644 index 0000000..d23a9fe --- /dev/null +++ b/src/main/java/com/newyetai/frame/redis/aop/aspect/UnLockAutomaticallyAop.java @@ -0,0 +1,33 @@ +package com.newyetai.frame.redis.aop.aspect; + +import com.newyetai.frame.redis.redisson.RedissonUtils; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +/** + * 自动解锁 + */ +@Aspect +@Component +@Order(1) +@Slf4j +public class UnLockAutomaticallyAop { + + @Pointcut("@annotation(com.newyetai.frame.redis.aop.annotation.AutoUnLock)") + public void annotationPointCut() { + } + + @Around("annotationPointCut()") + public Object around(ProceedingJoinPoint joinPoint) throws Throwable { + try { + return joinPoint.proceed(); + } finally { + RedissonUtils.unLockAutomatically(); + } + } +} diff --git a/src/main/java/com/newyetai/frame/redis/config/RedisCacheConfig.java b/src/main/java/com/newyetai/frame/redis/config/RedisCacheConfig.java new file mode 100644 index 0000000..9c269c5 --- /dev/null +++ b/src/main/java/com/newyetai/frame/redis/config/RedisCacheConfig.java @@ -0,0 +1,110 @@ +package com.newyetai.frame.redis.config; + +import java.util.LinkedHashSet; +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.cache.CacheManagerCustomizer; +import org.springframework.boot.autoconfigure.cache.CacheManagerCustomizers; +import org.springframework.boot.autoconfigure.cache.CacheProperties; +import org.springframework.boot.autoconfigure.cache.CacheProperties.Redis; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.core.io.ResourceLoader; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.cache.RedisCacheManager.RedisCacheManagerBuilder; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializationContext.SerializationPair; + +/** + * 参考 org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration + * org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration + * + * @author sr on 2020-07-16 + */ +@Configuration +@AutoConfigureAfter({RedisAutoConfiguration.class}) +@ConditionalOnClass(RedisConnectionFactory.class) +//@ConditionalOnBean(RedisConnectionFactory.class) +@ConditionalOnMissingBean(RedisCacheManager.class) +@EnableConfigurationProperties({CacheProperties.class}) +public class RedisCacheConfig { + + private final CacheProperties cacheProperties; + + /** CacheAutoConfiguration中定义,自动注入 **/ + @Autowired + private CacheManagerCustomizers customizerInvoker; + + private final org.springframework.data.redis.cache.RedisCacheConfiguration redisCacheConfiguration; + + RedisCacheConfig(CacheProperties cacheProperties, + ObjectProvider redisCacheConfiguration) { + this.cacheProperties = cacheProperties; + this.redisCacheConfiguration = redisCacheConfiguration.getIfAvailable(); + } + + @Bean + @ConditionalOnMissingBean + public CacheManagerCustomizers cacheManagerCustomizers( + ObjectProvider> customizers) { + return new CacheManagerCustomizers(customizers.orderedStream().collect(Collectors.toList())); + } + + /** + * redis缓存,默认缓存 + * + * @param redisConnectionFactory + * @param resourceLoader + * @return + * @author sr on 2020-07-16 + */ + @Bean + @Primary + public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory, + ResourceLoader resourceLoader) { + RedisCacheManagerBuilder builder = RedisCacheManager.builder(redisConnectionFactory) + .cacheDefaults(determineConfiguration(resourceLoader.getClassLoader())); + List cacheNames = this.cacheProperties.getCacheNames(); + if (!cacheNames.isEmpty()) { + builder.initialCacheNames(new LinkedHashSet<>(cacheNames)); + } + return this.customizerInvoker.customize(builder.build()); + } + + private org.springframework.data.redis.cache.RedisCacheConfiguration determineConfiguration( + ClassLoader classLoader) { + if (this.redisCacheConfiguration != null) { + return this.redisCacheConfiguration; + } + Redis redisProperties = this.cacheProperties.getRedis(); + org.springframework.data.redis.cache.RedisCacheConfiguration config = + org.springframework.data.redis.cache.RedisCacheConfiguration + .defaultCacheConfig(); + config = config.serializeValuesWith( + SerializationPair.fromSerializer(new JdkSerializationRedisSerializer(classLoader))); + if (redisProperties.getTimeToLive() != null) { + config = config.entryTtl(redisProperties.getTimeToLive()); + } + if (redisProperties.getKeyPrefix() != null) { + config = config.prefixKeysWith(redisProperties.getKeyPrefix()); + } + if (!redisProperties.isCacheNullValues()) { + config = config.disableCachingNullValues(); + } + if (!redisProperties.isUseKeyPrefix()) { + config = config.disableKeyPrefix(); + } + return config; + } + +} diff --git a/src/main/java/com/newyetai/frame/redis/config/RedisConfig.java b/src/main/java/com/newyetai/frame/redis/config/RedisConfig.java new file mode 100644 index 0000000..6d90ff0 --- /dev/null +++ b/src/main/java/com/newyetai/frame/redis/config/RedisConfig.java @@ -0,0 +1,54 @@ +package com.newyetai.frame.redis.config; + +import org.redisson.api.RedissonClient; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.newyetai.frame.redis.redisson.RedissonUtils; + +import lombok.extern.slf4j.Slf4j; + +/** + * @author Jerry.li + * @description Redis配置类 + * @date 2020/4/16 + */ +@Slf4j +@Configuration +public class RedisConfig { + + @SuppressWarnings({"rawtypes", "unchecked"}) + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + log.info("--------RedisConfig redisTemplate 初始化----->>"); + RedisTemplate redisTemplate = new RedisTemplate<>(); + redisTemplate.setConnectionFactory(factory); + + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = + new Jackson2JsonRedisSerializer(Object.class); + jackson2JsonRedisSerializer.setObjectMapper(objectMapper); + + redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); + redisTemplate.setKeySerializer(jackson2JsonRedisSerializer); + redisTemplate.setHashKeySerializer(new StringRedisSerializer()); + redisTemplate.afterPropertiesSet(); + return redisTemplate; + } + + @Bean + public RedissonUtils redissonUtils(RedissonClient redissonClient) { + return new RedissonUtils(redissonClient); + } + +} diff --git a/src/main/java/com/newyetai/frame/redis/dto/LockDTO.java b/src/main/java/com/newyetai/frame/redis/dto/LockDTO.java new file mode 100644 index 0000000..b388e55 --- /dev/null +++ b/src/main/java/com/newyetai/frame/redis/dto/LockDTO.java @@ -0,0 +1,136 @@ +package com.newyetai.frame.redis.dto; + +import com.newyetai.common.util.EnvironmentUtils; +import lombok.*; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; + +import java.io.Serializable; +import java.util.List; +import java.util.concurrent.TimeUnit; + +/** + * @author chenyun + * @description 锁的key对象 + * @date 2020/9/11 13:44 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class LockDTO implements Serializable { + + private static final long serialVersionUID = 5125024940029525121L; + + private static final String SPLIT; + + private static final Long DEFAULT_TIME; + + static { + SPLIT = ":"; + DEFAULT_TIME = 60L; + } + + /** + * 系统编码 + */ + private Integer systemCode; + + + /** + * 锁执行的业务方法名 + */ + private String methodName; + + /** + * 锁对象其他参数 + */ + @Singular + private List args; + + /** + * 锁的key + */ + private String lockKey; + + /** + * 时间单位 + */ + private TimeUnit unit; + + /** + * 尝试获取锁的时间,超过这个时间表示获取锁失败 + */ + private Long tryLockWaitTime; + + /** + * 锁对象存活时间,超过这个时间,锁自动释放 + */ + private Long lockTimeout; + + private String failMsg; + + + public TimeUnit getUnit() { + if (this.unit == null) { + this.unit = TimeUnit.SECONDS; + } + return this.unit; + } + + public Long getTryLockWaitTime() { + if (this.tryLockWaitTime == null) { + this.tryLockWaitTime = DEFAULT_TIME; + } + return this.tryLockWaitTime; + } + + public Long getLockTimeout() { + if (this.lockTimeout == null) { + this.lockTimeout = DEFAULT_TIME; + } + return this.lockTimeout; + } + + public String getLockKey() { + return StringUtils.isEmpty(lockKey) ? lockKey = invoke() : lockKey; + } + + public Integer getSystem() { + if (systemCode == null) { + this.systemCode = EnvironmentUtils.getSystemCode(); + } + return this.systemCode; + } + + /** + * 组装lockKey + * + * @return + */ + private String invoke() { + StringBuilder sb = new StringBuilder(); + if (getSystem() != null) { + sb.append(getSystem()).append(SPLIT); + } + if (StringUtils.isNotEmpty(getMethodName())) { + sb.append(getMethodName()).append(SPLIT); + } + List args = getArgs(); + if (CollectionUtils.isNotEmpty(args)) { + int size = args.size(); + for (int i = 0; i < size; i++) { + String arg = args.get(i); + if (StringUtils.isEmpty(arg)) { + continue; + } + sb.append(arg); + + if (i < size - 1) { + sb.append(SPLIT); + } + } + } + return sb.toString(); + } +} diff --git a/src/main/java/com/newyetai/frame/redis/exception/RedisLockErrorParamException.java b/src/main/java/com/newyetai/frame/redis/exception/RedisLockErrorParamException.java new file mode 100644 index 0000000..3356530 --- /dev/null +++ b/src/main/java/com/newyetai/frame/redis/exception/RedisLockErrorParamException.java @@ -0,0 +1,24 @@ +package com.newyetai.frame.redis.exception; + +/** + * redis锁错误参数异常 + * @author dylanyuan + */ +public class RedisLockErrorParamException extends RedisLockException { + + private static final long serialVersionUID = -2632401028683380018L; + + public RedisLockErrorParamException() {} + + public RedisLockErrorParamException(String message) { + super(message); + } + + public RedisLockErrorParamException(String message, Throwable cause) { + super(message, cause); + } + + public RedisLockErrorParamException(Throwable cause) { + super(cause); + } +} diff --git a/src/main/java/com/newyetai/frame/redis/exception/RedisLockException.java b/src/main/java/com/newyetai/frame/redis/exception/RedisLockException.java new file mode 100644 index 0000000..b956e60 --- /dev/null +++ b/src/main/java/com/newyetai/frame/redis/exception/RedisLockException.java @@ -0,0 +1,27 @@ +package com.newyetai.frame.redis.exception; + + +import com.newyetai.common.exception.AlitaException; + +/** + * redis锁专用异常父类 + * @author dylanyuan + */ +public class RedisLockException extends AlitaException { + + private static final long serialVersionUID = -6487400012014351701L; + + public RedisLockException() {} + + public RedisLockException(String message) { + super(message); + } + + public RedisLockException(String message, Throwable cause) { + super(message, cause); + } + + public RedisLockException(Throwable cause) { + super(cause); + } +} diff --git a/src/main/java/com/newyetai/frame/redis/exception/RedisLockFailException.java b/src/main/java/com/newyetai/frame/redis/exception/RedisLockFailException.java new file mode 100644 index 0000000..ca93d77 --- /dev/null +++ b/src/main/java/com/newyetai/frame/redis/exception/RedisLockFailException.java @@ -0,0 +1,24 @@ +package com.newyetai.frame.redis.exception; + +/** + * 加锁失败异常 + * @author dylanyuan + */ +public class RedisLockFailException extends RedisLockException { + + private static final long serialVersionUID = 8204346409836254547L; + + public RedisLockFailException() {} + + public RedisLockFailException(String message) { + super(message); + } + + public RedisLockFailException(String message, Throwable cause) { + super(message, cause); + } + + public RedisLockFailException(Throwable cause) { + super(cause); + } +} diff --git a/src/main/java/com/newyetai/frame/redis/property/RedissonProperties.java b/src/main/java/com/newyetai/frame/redis/property/RedissonProperties.java new file mode 100644 index 0000000..c13bf3f --- /dev/null +++ b/src/main/java/com/newyetai/frame/redis/property/RedissonProperties.java @@ -0,0 +1,18 @@ +package com.newyetai.frame.redis.property; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * @Author dylanyuan + * @Date 2020/12/10 11:37 上午 + * @Version 1.0 + */ +@ConfigurationProperties( + prefix = "alita.redisson" +) +@Data +public class RedissonProperties { + + private int pingConnectionInterval = 0; +} diff --git a/src/main/java/com/newyetai/frame/redis/redisson/RedissonConfig.java b/src/main/java/com/newyetai/frame/redis/redisson/RedissonConfig.java new file mode 100644 index 0000000..3ea4113 --- /dev/null +++ b/src/main/java/com/newyetai/frame/redis/redisson/RedissonConfig.java @@ -0,0 +1,158 @@ +//package com.newyetai.frame.redis.redisson; +// +//import com.newyetai.frame.redis.property.RedissonProperties; +//import java.lang.reflect.Method; +//import java.util.ArrayList; +//import java.util.Arrays; +//import java.util.List; +// +//import org.apache.commons.lang3.StringUtils; +//import org.redisson.Redisson; +//import org.redisson.api.RedissonClient; +//import org.redisson.config.Config; +//import org.redisson.spring.data.connection.RedissonConnectionFactory; +////import org.redisson.spring.data.connection.RedissonConnectionFactory; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.boot.autoconfigure.AutoConfigureAfter; +//import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +//import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +//import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; +//import org.springframework.boot.autoconfigure.data.redis.RedisProperties; +//import org.springframework.boot.autoconfigure.data.redis.RedisProperties.Sentinel; +//import org.springframework.boot.context.properties.EnableConfigurationProperties; +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +//import org.springframework.context.annotation.Import; +//import org.springframework.data.redis.connection.RedisConnectionFactory; +//import org.springframework.data.redis.core.RedisOperations; +//import org.springframework.data.redis.core.RedisTemplate; +//import org.springframework.data.redis.core.StringRedisTemplate; +//import org.springframework.util.ReflectionUtils; +// +///** +// * 参考redisson-spring-boot-starter的RedissonAutoConfiguration,沿用redis配置,移除自定义配置文件解析配置 +// * +// * @author sr on 2020-05-26 +// */ +//@Configuration +//@ConditionalOnClass({Redisson.class, RedisOperations.class}) +//@AutoConfigureAfter({RedisAutoConfiguration.class}) +//@EnableConfigurationProperties({RedisProperties.class, RedissonProperties.class}) +//@Import({RedisAutoConfiguration.class}) +//public class RedissonConfig { +// +// @Autowired +// private RedisProperties redisProperties; +// +// @Autowired +// private RedissonProperties redissonProperties; +// +// @Bean +// @ConditionalOnMissingBean(name = "redisTemplate") +// public RedisTemplate redisTemplate( +// RedisConnectionFactory redisConnectionFactory) { +// RedisTemplate template = new RedisTemplate(); +// template.setConnectionFactory(redisConnectionFactory); +// return template; +// } +// +// @Bean +// @ConditionalOnMissingBean(StringRedisTemplate.class) +// public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) { +// StringRedisTemplate template = new StringRedisTemplate(); +// template.setConnectionFactory(redisConnectionFactory); +// return template; +// } +// +// @Bean +// @ConditionalOnMissingBean(RedisConnectionFactory.class) +// public RedissonConnectionFactory redissonConnectionFactory(RedissonClient redisson) { +// return new RedissonConnectionFactory(redisson); +// } +// +// @SuppressWarnings("unchecked") +// @Bean(destroyMethod = "shutdown") +// @ConditionalOnMissingBean(RedissonClient.class) +// public RedissonClient redisson() { +// Config config = null; +// Method clusterMethod = ReflectionUtils.findMethod(RedisProperties.class, "getCluster"); +// Method timeoutMethod = ReflectionUtils.findMethod(RedisProperties.class, "getTimeout"); +// Object timeoutValue = ReflectionUtils.invokeMethod(timeoutMethod, redisProperties); +// int timeout; +// if (null == timeoutValue) { +// timeout = 0; +// } else if (!(timeoutValue instanceof Integer)) { +// Method millisMethod = ReflectionUtils.findMethod(timeoutValue.getClass(), "toMillis"); +// timeout = ((Long) ReflectionUtils.invokeMethod(millisMethod, timeoutValue)).intValue(); +// } else { +// timeout = (Integer) timeoutValue; +// } +// +// // 修复不设置密码,传入空字符串,置为空 +// String password = redisProperties.getPassword(); +// password = StringUtils.isBlank(password) ? null : password; +// if (redisProperties.getSentinel() != null) { +// Method nodesMethod = ReflectionUtils.findMethod(Sentinel.class, "getNodes"); +// Object nodesValue = ReflectionUtils.invokeMethod(nodesMethod, redisProperties.getSentinel()); +// +// String[] nodes; +// if (nodesValue instanceof String) { +// nodes = convert(Arrays.asList(((String) nodesValue).split(","))); +// } else { +// nodes = convert((List) nodesValue); +// } +// +// config = new Config(); +// config.useSentinelServers() +// .setPingConnectionInterval(redissonProperties.getPingConnectionInterval()) +// .setMasterName(redisProperties.getSentinel().getMaster()) +// .addSentinelAddress(nodes).setDatabase(redisProperties.getDatabase()) +// .setConnectTimeout(timeout).setPassword(password); +// } else if (clusterMethod != null +// && ReflectionUtils.invokeMethod(clusterMethod, redisProperties) != null) { +// Object clusterObject = ReflectionUtils.invokeMethod(clusterMethod, redisProperties); +// Method nodesMethod = ReflectionUtils.findMethod(clusterObject.getClass(), "getNodes"); +// List nodesObject = (List) ReflectionUtils.invokeMethod(nodesMethod, clusterObject); +// +// String[] nodes = convert(nodesObject); +// +// config = new Config(); +// config.useClusterServers() +// .setPingConnectionInterval(redissonProperties.getPingConnectionInterval()) +// .addNodeAddress(nodes).setConnectTimeout(timeout) +// .setPassword(password); +// } else { +// config = new Config(); +// String prefix = "redis://"; +// Method method = ReflectionUtils.findMethod(RedisProperties.class, "isSsl"); +// if (method != null && (Boolean) ReflectionUtils.invokeMethod(method, redisProperties)) { +// prefix = "rediss://"; +// } +// +// config.useSingleServer() +// .setPingConnectionInterval(redissonProperties.getPingConnectionInterval()) +// .setAddress(prefix + redisProperties.getHost() + ":" + redisProperties.getPort()) +// .setConnectTimeout(timeout).setDatabase(redisProperties.getDatabase()) +// .setPassword(password); +// } +// return Redisson.create(config); +// } +// +// private String[] convert(List nodesObject) { +// List nodes = new ArrayList(nodesObject.size()); +// for (String node : nodesObject) { +// if (!node.startsWith("redis://") && !node.startsWith("rediss://")) { +// nodes.add("redis://" + node); +// } else { +// nodes.add(node); +// } +// } +// return nodes.toArray(new String[nodes.size()]); +// } +// +// @Bean +// public RedissonUtils redissonUtils() { +// return new RedissonUtils(redisson()); +// } +// +//} diff --git a/src/main/java/com/newyetai/frame/redis/redisson/RedissonUtils.java b/src/main/java/com/newyetai/frame/redis/redisson/RedissonUtils.java new file mode 100644 index 0000000..79c2e72 --- /dev/null +++ b/src/main/java/com/newyetai/frame/redis/redisson/RedissonUtils.java @@ -0,0 +1,381 @@ +package com.newyetai.frame.redis.redisson; + +import com.google.common.collect.Lists; +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.common.dto.IBaseDTO; +import com.newyetai.common.exception.ExistException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.function.TransactionAfterCommit; +import com.newyetai.frame.redis.dto.LockDTO; +import lombok.extern.slf4j.Slf4j; + +import org.apache.commons.lang3.StringUtils; +import org.redisson.RedissonMultiLock; +import org.redisson.api.RLock; +import org.redisson.api.RedissonClient; + +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.Stack; +import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +/** + * 使用@Autowired注入工具类 + * + * @author sr on 2020-05-26 + */ +@Slf4j +public class RedissonUtils { + + private static RedissonClient client; + + /** + * 锁对象缓存实现 ,同一个线程可能持有多把锁 + */ + private static final ThreadLocal> LOCK_DTO_THREAD_LOCAL = new ThreadLocal<>(); + + public RedissonUtils(RedissonClient redissonClient) { + RedissonUtils.client = redissonClient; + } + + public static RedissonClient getClient() { + return client; + } + + /** + * 获取锁对象 + * @param lockKey + * @return + */ + public static RLock getLock(String lockKey) { + return client.getLock(lockKey); + } + + /** + * 获取连所对象 + * @param lockKeys + * @return + */ + public static RLock getMultiLock(String... lockKeys) { + RLock[] locks = new RLock[lockKeys.length]; + for (int i = 0; i < lockKeys.length; i++) { + locks[i] = client.getLock(lockKeys[i]); + } + return client.getMultiLock(locks); + } + + /** + * 获取连所对象 + * @param lockKeys + * @return + */ + public static RLock getMultiLock(List lockKeys) { + RLock[] locks = new RLock[lockKeys.size()]; + for (int i = 0; i < lockKeys.size(); i++) { + locks[i] = client.getLock(lockKeys.get(i)); + } + return client.getMultiLock(locks); + } + + + /** + * 获取锁(自旋等待锁) + * + * @param lockDTO + * @return + * @author sr on 2020-05-26 + */ + public static RLock lock(LockDTO lockDTO) { + RLock lock = client.getLock(lockDTO.getLockKey()); + lock.lock(); + return lock; + } + + /** + * 获取锁(自旋等待锁) + * + * @param lockKey + * @return + * @author sr on 2020-05-26 + */ + public static RLock lock(String lockKey) { + RLock lock = client.getLock(lockKey); + lock.lock(); + return lock; + } + + /** + * 获取超时锁(自旋等待锁) + * + * @param lockKey + * @param timeout 加锁后自动释放时间(秒) + * @return + * @author sr on 2020-05-26 + */ + public static RLock lock(String lockKey, long timeout) { + return lock(lockKey, TimeUnit.SECONDS, timeout); + } + + /** + * 超时锁 + * + * @param lockKey + * @param unit 时间单位 + * @param timeout 加锁后自动释放时间 + * @return + * @author sr on 2020-05-26 + */ + public static RLock lock(String lockKey, TimeUnit unit, long timeout) { + log.info("lockKey:{}" + lockKey); + RLock lock = client.getLock(lockKey); + lock.lock(timeout, unit); + return lock; + } + + /** + * 尝试获取锁(时间-秒) + * + * @param lockDTO + * @return + */ + public static boolean tryLock(LockDTO lockDTO) { + return tryLock(lockDTO.getLockKey(), lockDTO.getUnit(), lockDTO.getTryLockWaitTime(), lockDTO.getLockTimeout()); + } + + /** + * 将锁对象缓存入ThreadLocal中 + * 尝试获取锁(时间-秒) + * + * @param lockDTO 锁对象 + * @return true: 加锁成功 false: 加锁失败 + */ + public static boolean tryLockAutomatically(LockDTO lockDTO) { + Stack stack = LOCK_DTO_THREAD_LOCAL.get(); + if (Objects.isNull(stack)) { + LOCK_DTO_THREAD_LOCAL.set(stack = new Stack<>()); + } + stack.push(lockDTO); + return tryLock(lockDTO); + } + + /** + * 自动解锁 + * + * @return true: 解锁成功 false: 解锁失败 + */ + public static boolean unLockAutomatically() { + Stack stack = LOCK_DTO_THREAD_LOCAL.get(); + if (Objects.nonNull(stack) && !stack.isEmpty()) { + return unlock(stack.pop()); + } + return false; + } + + /** + * 尝试获取锁(时间-秒) + * + * @param lockKey + * @param waitTime 最多等待时间,未拿到锁返回false + * @param timeout 上锁后自动释放锁时间 + * @return + * @author sr on 2020-08-28 + */ + public static boolean tryLock(String lockKey, long waitTime, long timeout) { + return tryLock(lockKey, TimeUnit.SECONDS, waitTime, timeout); + } + + /** + * 尝试获取锁 + * + * @param lockKey + * @param unit 时间单位 + * @param waitTime 最多等待时间,未拿到锁返回false + * @param timeout 上锁后自动释放锁时间 + * @return + * @author sr on 2020-05-26 + */ + public static boolean tryLock(String lockKey, TimeUnit unit, long waitTime, long timeout) { + RLock lock = client.getLock(lockKey); + try { + return lock.tryLock(waitTime, timeout, unit); + } catch (InterruptedException e) { + return false; + } + } + + /** + * 释放锁 + * + * @param lockKey + * @author sr on 2020-05-26 + */ + public static boolean unlock(String lockKey) { + try { + RLock lock = client.getLock(lockKey); + return unlock(lock); + } catch (Exception e) { + log.error("unlock key:{}, error:{}", lockKey, e.getMessage()); + return false; + } + } + + /** + * 释放锁 + * + * @param lockDTO + * @return + */ + public static boolean unlock(LockDTO lockDTO) { + RLock lock = client.getLock(lockDTO.getLockKey()); + if (lock.isLocked() && lock.isHeldByCurrentThread()) { + return unlock(lockDTO.getLockKey()); + } + return true; + } + + /** + * 释放锁 + * + * @param lock + * @author sr on 2020-05-26 + */ + public static boolean unlock(RLock lock) { + try { + if (!lock.isLocked()) { + return true; + } + lock.unlock(); + } catch (Exception e) { + log.error("unlock key:{}, error msg:{}", lock.getName(), e.getMessage()); + return false; + } + return true; + } + + /** + * 联锁 + * + * @param lockKeys + * @return + * @author sr on 2020-05-28 + */ + public static RLock multiLock(Set lockKeys) { + RLock[] locks = (RLock[]) lockKeys.stream().map(lockKey -> client.getLock(lockKey)).toArray(); + RedissonMultiLock multiLock = new RedissonMultiLock(locks); + multiLock.lock(); + return multiLock; + } + + /** + * 尝试获取联锁 + * + * @param lockKeys + * @param unit 时间单位 + * @param waitTime 最多等待时间,未拿到锁返回false + * @param timeout 上锁后自动释放锁时间 + * @return + * @author sr on 2020-05-28 + */ + public static boolean tryMultiLock(Set lockKeys, TimeUnit unit, long waitTime, long timeout) { + RLock[] locks = new RLock[lockKeys.size()]; + locks = lockKeys.stream().map(lockKey -> client.getLock(lockKey)).collect(Collectors.toList()).toArray(locks); + RedissonMultiLock multiLock = new RedissonMultiLock(locks); + try { + return multiLock.tryLock(waitTime, timeout, unit); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return false; + } + + /** + * 尝试获取联锁 + * + * @param lockKeys 锁的钥匙 + * @param unit 单位 + * @param waitTime 等待时间 + * @param timeout 超时 + * @return {@link RLock} + */ + public static RLock tryMultiLockAndReturn(Set lockKeys, TimeUnit unit, long waitTime, long timeout) { + RLock multiLock = getMultiLock(Lists.newArrayList(lockKeys)); + try { + if (multiLock.tryLock(waitTime, timeout, unit)){ + return multiLock; + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + return null; + } + + + /** + * 校验上锁保存(有事务幂等) + * @param + * @param lockDTO + * @param existSupplier + * @param saveSupplier + * @return + * @author sr on 2024-04-18 + */ + public static Long lockAndSave(LockDTO lockDTO, Supplier existSupplier, + Supplier saveSupplier) { + return lockAndSave(lockDTO, existSupplier, saveSupplier, true, null); + } + + + public static Long lockAndSave(LockDTO lockDTO, Supplier existSupplier, + Supplier saveSupplier, String existMsg) { + return lockAndSave(lockDTO, existSupplier, saveSupplier, true, existMsg); + } + + /** + * 校验上锁保存 + * @param + * @param lockDTO 锁 + * @param existSupplier 查询存在的dto + * @param saveSupplier 保存 + * @param hasTransaction 当前是否有事务 + * @param existMsg 存在抛的异常消息,空则不抛异常返回id + * @return + * @author sr on 2024-04-18 + */ + public static Long lockAndSave(LockDTO lockDTO, Supplier existSupplier, + Supplier saveSupplier, boolean hasTransaction, String existMsg) throws ExistException{ + IBaseDTO baseDTO = existSupplier.get(); + if (baseDTO != null) { + if (StringUtils.isBlank(existMsg)) { + return baseDTO.getId(); + } else { + throw new ExistException(existMsg); + } + } + try { + Assert.isTrue(RedissonUtils.tryLock(lockDTO), lockDTO.getFailMsg()); + baseDTO = existSupplier.get(); + if (baseDTO != null) { + if (StringUtils.isBlank(existMsg)) { + return baseDTO.getId(); + } else { + throw new ExistException(existMsg); + } + } + return saveSupplier.get(); + } finally { + if (hasTransaction) { + TransactionAfterCommit.doSomeThingAfterCompletion(()->{ + RedissonUtils.unlock(lockDTO); + }); + } else { + RedissonUtils.unlock(lockDTO); + } + } + } + +} + + diff --git a/src/main/java/com/newyetai/frame/redis/util/IAopUtils.java b/src/main/java/com/newyetai/frame/redis/util/IAopUtils.java new file mode 100644 index 0000000..354bfdd --- /dev/null +++ b/src/main/java/com/newyetai/frame/redis/util/IAopUtils.java @@ -0,0 +1,148 @@ +package com.newyetai.frame.redis.util; + +import com.newyetai.frame.redis.aop.annotation.RedissonLock; +import com.newyetai.frame.redis.exception.RedisLockErrorParamException; +import com.newyetai.frame.redis.exception.RedisLockFailException; +import com.newyetai.frame.redis.redisson.RedissonUtils; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.concurrent.TimeUnit; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.Signature; +import org.aspectj.lang.reflect.MethodSignature; +import org.redisson.api.RLock; + +/** + * @author Created by dylan_yuan + */ +@Slf4j +public class IAopUtils { + + public static Method getMethod(JoinPoint joinPoint) throws Exception { + String methodName = joinPoint.getSignature().getName(); + // 获取目标对象 + Class classTarget = joinPoint.getTarget().getClass(); + // 获取目标对象类型 + Class[] parameterTypes = ((MethodSignature) joinPoint.getSignature()).getParameterTypes(); + // 获取目标对象方法 + return classTarget.getMethod(methodName, parameterTypes); + } + + public static Type getType(Method method, String paramName) { + Type[] types = method.getGenericParameterTypes(); + if(types == null || types.length == 0){ + return null; + } + for (Type type : types) { + if (paramName.equals(type.getTypeName())) { + return type; + } + } + return null; + } + + public static Object getParamValue(ProceedingJoinPoint joinPoint, String paramName) { + if (joinPoint == null || StringUtils.isBlank(paramName)) { + return null; + } + Object[] args = joinPoint.getArgs(); + Signature signature = joinPoint.getSignature(); + MethodSignature methodSignature = (MethodSignature) signature; + String[] names = methodSignature.getParameterNames(); + if (names == null || names.length == 0) { + return null; + } + for (int i = 0; i < names.length; i++) { + if (names[i].equals(paramName)) { + return args[i]; + } + } + return null; + } + + public static Object getParamValue(ProceedingJoinPoint joinPoint, int index) { + if (joinPoint == null || index < 0) { + return null; + } + Object[] args = joinPoint.getArgs(); + Signature signature = joinPoint.getSignature(); + MethodSignature methodSignature = (MethodSignature) signature; + String[] names = methodSignature.getParameterNames(); + if (names == null || names.length == 0 || names.length < index) { + return null; + } + return args[index]; + } + + + public static void checkParamType(Method method, String paramName, Object paramValue, boolean isArray){ + String prefix = "redis" + (isArray?"batch":"") + "lock"; + String suffix = "字符串" + (isArray?"数组或集合":""); + boolean classTypeMatching; + if(isArray){ + Type type = getType(method, paramName); + classTypeMatching = paramValue instanceof String[] || (paramValue instanceof Iterable && checkGenericTypeIsString(type)); + }else{ + classTypeMatching = paramValue instanceof String; + } + if(!classTypeMatching) { + throw new RedisLockErrorParamException(prefix + + " paramName[" + paramName + "]所对应的参数类型必须为" + suffix); + } + } + + private static boolean checkGenericTypeIsString(Type type){ + if(type == null){ + return false; + } + try { + ParameterizedType pt = (ParameterizedType)type; + Type[] tempTypes = pt.getActualTypeArguments(); + if(tempTypes == null || tempTypes.length != 1){ + return false; + } + Type temp = tempTypes[0]; + if("java.lang.String".equals(temp.getTypeName())) { + return true; + } + }catch (Exception e){ + log.error("获取方法入参数类型失败,{}", type.getTypeName()); + } + return false; + } + + public static RLock lock(ProceedingJoinPoint joinPoint, RedissonLock redissonLock) + throws Exception { + String paramName = redissonLock.paramName(); + if (StringUtils.isBlank(paramName)) { + throw new RedisLockErrorParamException("redisson lock paramName不能为空"); + } + Object paramValue = IAopUtils.getParamValue(joinPoint, paramName); + if (paramValue == null) { + boolean skipIfNull = redissonLock.skipIfNull(); + if(skipIfNull){ + return null; + } + throw new RedisLockErrorParamException("redisson lock paramName[" + paramName + "]所对应的参数内容不能为空"); + } + IAopUtils.checkParamType(IAopUtils.getMethod(joinPoint), paramName, paramValue, false); + long expires = redissonLock.expires(); + TimeUnit timeUnit = redissonLock.timeUnit(); + if(expires == -1){ + expires = 1; + timeUnit = TimeUnit.DAYS; + } + long tryLockWaitTime = redissonLock.tryLockWaitTime(); + String key = redissonLock.prefix() + paramValue; + RLock lock = RedissonUtils.getLock(key); + LockUtils.lock(expires, timeUnit, tryLockWaitTime, lock); + if(!lock.isLocked()) { + throw new RedisLockFailException("方法["+joinPoint.getSignature().getName()+"]所对应的参数["+key+"]正在运行中,请不要重复操作!"); + } + return lock; + } +} diff --git a/src/main/java/com/newyetai/frame/redis/util/LockUtils.java b/src/main/java/com/newyetai/frame/redis/util/LockUtils.java new file mode 100644 index 0000000..e7c79b5 --- /dev/null +++ b/src/main/java/com/newyetai/frame/redis/util/LockUtils.java @@ -0,0 +1,84 @@ +package com.newyetai.frame.redis.util; + +import com.newyetai.common.exception.util.Assert; +import com.newyetai.frame.redis.redisson.RedissonUtils; +import java.util.concurrent.TimeUnit; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.redisson.RedissonMultiLock; +import org.redisson.api.RLock; + +/** + * @author dylanyuan + */ +@Slf4j +public class LockUtils { + + + public static void unlock(RLock lock) { + if (lock == null){ + return; + } + if(lock instanceof RedissonMultiLock){ + lock.unlock(); + return; + } + if(lock.isLocked() && lock.isHeldByCurrentThread()){ + lock.unlock(); + return; + } + } + + public static void lock(long expires, TimeUnit timeUnit, RLock lock) { + lock(expires, timeUnit, -1, lock); + } + + public static void lock(long expires, TimeUnit timeUnit, long tryLockWaitTime, RLock lock) { + Assert.isTrue(lock != null, "锁不能为空"); + if(tryLockWaitTime == -1){ + lock.lock(expires, timeUnit); + }else { + try { + lock.tryLock(tryLockWaitTime, expires, timeUnit); + } catch (InterruptedException e) { + //如果出现异常的话,当前线程立刻解锁 + unlock(lock); + log.error("[{}] try lock 失败", lock.getName(), e); + } + } + } + + public static boolean trylock(long expires, TimeUnit timeUnit, long tryLockWaitTime, RLock lock) { + Assert.isTrue(lock != null, "锁不能为空"); + Assert.isTrue(tryLockWaitTime >=0, "等待时间必须大于-1"); + try { + return lock.tryLock(tryLockWaitTime, expires, timeUnit); + } catch (InterruptedException e) { + //如果出现异常的话,当前线程立刻解锁 + unlock(lock); + log.error("[{}] try lock 失败", lock.getName(), e); + } + return false; + } + + public static RLock simpleLock(long expires, TimeUnit timeUnit, String key) { + return simpleLock(expires, timeUnit, -1, key); + } + + public static RLock simpleLock(long expires, TimeUnit timeUnit, long tryLockWaitTime, String key) { + Assert.isTrue(StringUtils.isNotBlank(key), "锁值不能为空"); + RLock lock = RedissonUtils.getLock(key); + if(tryLockWaitTime == -1){ + lock.lock(expires, timeUnit); + }else { + try { + lock.tryLock(tryLockWaitTime, expires, timeUnit); + } catch (InterruptedException e) { + //如果出现异常的话,当前线程立刻解锁 + unlock(lock); + log.error("[{}] try lock 失败", lock.getName(), e); + } + } + return lock; + } +} diff --git a/src/main/java/com/newyetai/frame/redis/util/RedisUtils.java b/src/main/java/com/newyetai/frame/redis/util/RedisUtils.java new file mode 100644 index 0000000..ced4886 --- /dev/null +++ b/src/main/java/com/newyetai/frame/redis/util/RedisUtils.java @@ -0,0 +1,324 @@ +package com.newyetai.frame.redis.util; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import javax.annotation.PostConstruct; + +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; + +import com.google.common.base.Objects; + +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; + +/** + * + * @author Jerry.li + * @description Redis工具类 + * @date 2020/4/16 + * + * 使用案例 + * @Autowired private RedisUtils redisUtils; redisUtils.getExpire(key); + */ +@Slf4j +@Component +public class RedisUtils{ + + + @Autowired + private RedisTemplate redisTemplateClient; + + private static RedisTemplate redisTemplate; + + @PostConstruct + private void init() { + redisTemplate = redisTemplateClient; + } + + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param expireTime 过期时间(秒) + * @return + */ + public static void expire(@NonNull String key, long expireTime) { + if (expireTime > 0 && hasKey(key)) { + redisTemplate.expire(key, expireTime, TimeUnit.SECONDS); + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public static Long getExpire(@NonNull String key) { + if (!hasKey(key)) { + return null; + } + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public static boolean hasKey(@NonNull String key) { + Boolean hasKey = redisTemplate.hasKey(key); + if (Objects.equal(hasKey, null)) { + return false; + } + return hasKey; + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + public static void remove(@NonNull String key) { + try { + if (hasKey(key)) { + redisTemplate.delete(key); + } + } catch (Exception e) { + log.info("redis remove key:{}, error:{}", key, e.getMessage()); + } + + } + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public static Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 永久普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public static void add(@NonNull String key, Object value) { + redisTemplate.opsForValue().set(key, value); + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public static void add(@NonNull String key, Object value, long time) { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + add(key, value); + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + public static void removeList(@NonNull String key, Object value) { + try { + if (hasKey(key)) { + redisTemplate.opsForList().remove(key,0,value); + } + } catch (Exception e) { + log.info("redis remove key:{} value:{}, error:{}", key, value, e.getMessage()); + } + + } + + /** + * 将list放入缓存(向后追加方式) + * @param key + * @param value + */ + public static void listAddAll(@NonNull String key, Object... value) { + redisTemplate.opsForList().rightPushAll(key,value); + } + + /** + * 将list放入缓存(向后追加方式) + * + * @param key 键 + * @param value 值 + */ + public static void listAdd(@NonNull String key, Object value) { + redisTemplate.opsForList().rightPush(key, value); + } + + /** + * 将list放入缓存(向后追加方式) + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + */ + public static void listAdd(@NonNull String key, Object value, long time) { + listAdd(key, value); + if (time > 0) { + expire(key, time); + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @return List + */ + public static List listGet(@NonNull String key) { + return redisTemplate.opsForList().range(key, 0, -1); + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return List + */ + public static List listGet(@NonNull String key, long start, long end) { + return redisTemplate.opsForList().range(key, start, end); + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public static Long getListSize(@NonNull String key) { + return redisTemplate.opsForList().size(key); + } + + /** + * HashMap + * + * @param key 键 + * @param map 对应多个键值 + */ + public static void mapAdd(@NonNull String key, Map map) { + redisTemplate.opsForHash().putAll(key, map); + } + + /** + * HashMap 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + */ + public static void mapAdd(@NonNull String key, Map map, long time) { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key redis键 + * @param hashKey 项 + * @param value 值 + */ + public static void mapAdd(@NonNull String key, @NonNull String hashKey, Object value) { + redisTemplate.opsForHash().put(key, hashKey, value); + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param hashKey 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + */ + public static void mapAdd(String key, String hashKey, Object value, long time) { + redisTemplate.opsForHash().put(key, hashKey, value); + if (time > 0) { + expire(key, time); + } + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param hashKey map key 不能为null + */ + public static boolean mapHasValue(@NonNull String key, @NonNull String hashKey) { + return redisTemplate.opsForHash().hasKey(key, hashKey); + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param hashKey 项 不能为null + * @return 值 + */ + public static Object mapGet(@NonNull String key, @NonNull String hashKey) { + return redisTemplate.opsForHash().get(key, hashKey); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public static Map mapGet(@NonNull String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * 自增并设置过期时间 + * @param key + * @param expireTime + * @return + * @author sr on 2020-08-03 + */ + public static long increment(@NonNull String key, long expireTime) { + long data = redisTemplate.opsForValue().increment(key); + if (data == 1L) { + redisTemplate.expire(key, expireTime, TimeUnit.SECONDS); + } + return data; + } + + /** + * 自减 + * @param key + * @return + * @author sr on 2021-06-16 + */ + public static long decrement(@NonNull String key) { + return redisTemplate.opsForValue().decrement(key); + } + +} diff --git a/src/main/java/com/newyetai/frame/redis/util/RedissonHashUtils.java b/src/main/java/com/newyetai/frame/redis/util/RedissonHashUtils.java new file mode 100644 index 0000000..fd571f8 --- /dev/null +++ b/src/main/java/com/newyetai/frame/redis/util/RedissonHashUtils.java @@ -0,0 +1,44 @@ +package com.newyetai.frame.redis.util; + +import com.newyetai.frame.redis.redisson.RedissonUtils; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import org.apache.commons.lang3.ObjectUtils; +import org.redisson.api.RMap; + +/** + * @Author dylanyuan + * @Date 2020/11/27 下午6:29 + * @Version 1.0 + */ +public class RedissonHashUtils { + + public static void clear(String hashKey){ + RedissonUtils.getClient().getMap(hashKey).clear(); + } + + public static void set(String hashKey, String key, Object value){ + RMap rMap = RedissonUtils.getClient().getMap(hashKey); + rMap.put(key, value); + } + + public static void set(String hashKey, String key, Object value, Long expires, TimeUnit timeUnit){ + RMap rMap = RedissonUtils.getClient().getMap(hashKey); + rMap.expire(expires, timeUnit); + rMap.put(key, value); + } + + public static Map get(String hashKey){ + return RedissonUtils.getClient().getMap(hashKey); + } + + public static Object get(String hashKey, String key){ + RMap rMap = RedissonUtils.getClient().getMap(hashKey); + return rMap.get(key); + } + + public static String getString(String hashKey, String key){ + RMap rMap = RedissonUtils.getClient().getMap(hashKey); + return ObjectUtils.identityToString(rMap.get(key)); + } +} diff --git a/src/main/java/com/newyetai/frame/redis/util/RedissonSetUtils.java b/src/main/java/com/newyetai/frame/redis/util/RedissonSetUtils.java new file mode 100644 index 0000000..4d30b82 --- /dev/null +++ b/src/main/java/com/newyetai/frame/redis/util/RedissonSetUtils.java @@ -0,0 +1,33 @@ +package com.newyetai.frame.redis.util; + +import com.newyetai.frame.redis.redisson.RedissonUtils; +import java.util.concurrent.TimeUnit; +import org.redisson.api.RSet; + +/** + * @Author dylanyuan + * @Date 2020/11/27 下午6:29 + * @Version 1.0 + */ +public class RedissonSetUtils { + + public static void set(String setKey, Object value){ + RSet rSet = RedissonUtils.getClient().getSet(setKey); + rSet.add(value); + } + + public static void set(String setKey, Object value, Long expires, TimeUnit timeUnit){ + RSet rSet = RedissonUtils.getClient().getSet(setKey); + rSet.expire(expires, timeUnit); + rSet.add(value); + } + + public static void clear(String setKey){ + RedissonUtils.getClient().getSet(setKey).clear(); + } + + public static RSet get(String setKey){ + RSet rSet = RedissonUtils.getClient().getSet(setKey); + return rSet; + } +} diff --git a/src/main/java/com/newyetai/frame/redis/util/RedissonValueUtils.java b/src/main/java/com/newyetai/frame/redis/util/RedissonValueUtils.java new file mode 100644 index 0000000..f1b3bd9 --- /dev/null +++ b/src/main/java/com/newyetai/frame/redis/util/RedissonValueUtils.java @@ -0,0 +1,39 @@ +package com.newyetai.frame.redis.util; + +import com.newyetai.frame.redis.redisson.RedissonUtils; +import java.util.concurrent.TimeUnit; +import org.apache.commons.lang3.ObjectUtils; +import org.redisson.api.RBucket; + +/**nng + * @Author dylanyuan + * @Date 2020/11/27 下午6:29 + * @Version 1.0 + */ +public class RedissonValueUtils { + + public static void set(String key, Object value){ + RBucket rBucket = RedissonUtils.getClient().getBucket(key); + rBucket.set(value); + } + + public static void set(String key, Object value, Long expires, TimeUnit timeUnit){ + RBucket rBucket = RedissonUtils.getClient().getBucket(key); + rBucket.set(value, expires, timeUnit); + } + + public static boolean hasKey(String key){ + RBucket rBucket = RedissonUtils.getClient().getBucket(key); + return rBucket.isExists(); + } + + public static Object get(String key){ + RBucket rBucket = RedissonUtils.getClient().getBucket(key); + return rBucket.get(); + } + + public static String getString(String key){ + RBucket rBucket = RedissonUtils.getClient().getBucket(key); + return ObjectUtils.identityToString(rBucket.get()); + } +} diff --git a/src/main/java/com/newyetai/mq/config/ExchangeManager.java b/src/main/java/com/newyetai/mq/config/ExchangeManager.java new file mode 100644 index 0000000..f8231c9 --- /dev/null +++ b/src/main/java/com/newyetai/mq/config/ExchangeManager.java @@ -0,0 +1,55 @@ +package com.newyetai.mq.config; + +import org.springframework.amqp.core.CustomExchange; +import org.springframework.amqp.core.Exchange; +import org.springframework.amqp.core.TopicExchange; +import org.springframework.beans.factory.annotation.Autowired; + +import com.newyetai.common.exception.util.Assert; +import com.newyetai.mq.constant.ExchangeTypeEnum; +import com.newyetai.mq.exception.MqException; + +public class ExchangeManager { + + @Autowired + private TopicExchange topicExchange; + +// @Autowired +// private CustomExchange delayedCustomExchange; + + public TopicExchange getTopicExchange() { + return topicExchange; + } + +// public CustomExchange getDelayedCustomExchange() { +// return delayedCustomExchange; +// } + + /** + * 获取交换器名称 + * + * @return + * @author sr on 2020-07-27 + */ + public String getTopicExchangeName() { + return topicExchange.getName(); + } + + public Exchange getExchangeByType(String exchangeType) { + Assert.notNull(exchangeType, "交换机不能为空"); + ExchangeTypeEnum exchangeTypeEnum = ExchangeTypeEnum.valueOf(exchangeType); + switch (exchangeTypeEnum) { + case TOPIC: + return topicExchange; +// case DELAYED: +// return delayedCustomExchange; + default: + throw new MqException("未找到对应交换机"); + } + } + + public String getExchangeNameByType(String exchangeType) { + return getExchangeByType(exchangeType).getName(); + } + +} diff --git a/src/main/java/com/newyetai/mq/config/QueueManager.java b/src/main/java/com/newyetai/mq/config/QueueManager.java new file mode 100644 index 0000000..f43c788 --- /dev/null +++ b/src/main/java/com/newyetai/mq/config/QueueManager.java @@ -0,0 +1,65 @@ +package com.newyetai.mq.config; + +import org.springframework.amqp.core.*; +import org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * 消息管理(queue/binding) + * + * @author sr on 2020-07-22 + */ +public class QueueManager { + + @Autowired + private AmqpAdmin amqpAdmin; + + @Autowired + private ExchangeManager exchangeManager; + + @Autowired + private AbstractMessageListenerContainer messageListenerContainer; + + /** + * 添加队列 + * + * @param queueName + * @return + * @author sr on 2020-07-27 + */ + public Queue addQueue(String queueName) { + Queue queue = new Queue(queueName); + if (amqpAdmin.getQueueProperties(queueName) == null) { + amqpAdmin.declareQueue(queue); + } + return queue; + } + + /** + * 绑定队列和路由键 + * + * @param queueName + * @param routingKey + * @author sr on 2020-07-27 + */ + public void addQueueAndRoutingKey(String queueName, String routingKey) { + Queue queue = this.addQueue(queueName); + Binding binding = BindingBuilder.bind(queue).to(exchangeManager.getTopicExchange()).with(routingKey); + amqpAdmin.declareBinding(binding); + messageListenerContainer.addQueues(queue); + } + + /** + * 绑定队列和路由键 + * + * @param queueName + * @param routingKey + * @author sr on 2020-07-27 + */ + public void addQueueAndRoutingKey(Exchange exchange, String queueName, String routingKey) { + Queue queue = this.addQueue(queueName); + amqpAdmin.declareBinding(BindingBuilder.bind(queue).to(exchange).with(routingKey).noargs()); + messageListenerContainer.addQueues(queue); + } + +} diff --git a/src/main/java/com/newyetai/mq/config/RabbitCustomProperties.java b/src/main/java/com/newyetai/mq/config/RabbitCustomProperties.java new file mode 100644 index 0000000..5a3ea35 --- /dev/null +++ b/src/main/java/com/newyetai/mq/config/RabbitCustomProperties.java @@ -0,0 +1,37 @@ +package com.newyetai.mq.config; + +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * 定制配置 + * + * @author sr on 2020-07-22 + */ +@ConfigurationProperties(prefix = "rabbitmq.custom") +@Data +@NoArgsConstructor +public class RabbitCustomProperties { + + /** + * 通配符交换器名称 + **/ + private String topicExchangeName; + + /** + * 延时队里名称 + */ + private String delayedExchangeName; + + /** + * 指定消费者ip + **/ + private String consumerAppId; + + /** + * 广播id-同系统内需要广播时配置 + **/ + private String broadcastId; + +} diff --git a/src/main/java/com/newyetai/mq/config/RabbitMqConfiguration.java b/src/main/java/com/newyetai/mq/config/RabbitMqConfiguration.java new file mode 100644 index 0000000..0439c46 --- /dev/null +++ b/src/main/java/com/newyetai/mq/config/RabbitMqConfiguration.java @@ -0,0 +1,197 @@ +package com.newyetai.mq.config; + +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.amqp.core.CustomExchange; +import org.springframework.amqp.core.TopicExchange; +import org.springframework.amqp.rabbit.config.AbstractRabbitListenerContainerFactory; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer; +import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter; +import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import com.google.common.collect.Maps; +import com.newyetai.common.CommonConfiguration; +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.util.EnvironmentUtils; +import com.newyetai.mq.consumer.ConsumerDeliverer; +import com.newyetai.mq.consumer.InitHandler; +import com.newyetai.mq.consumer.handler.IMqHandler; +import com.newyetai.mq.producer.sender.DefaultMqSender; +import com.newyetai.mq.producer.sender.IMqSender; +import com.newyetai.mq.util.MqSendUtils; + +/** + * @author sr on 2020-07-22 + */ +@Configuration +@EnableConfigurationProperties(RabbitCustomProperties.class) +@AutoConfigureAfter(CommonConfiguration.class) +public class RabbitMqConfiguration { + + public static final String DEFAULT_EXCHANGE_NAME = "alita_exchange"; + + /** + * 默认延时队列交换机名称 + */ + public static final String DEFAULT_DELAYED_EXCHANGE_NAME = "alita_delayed_exchange"; + + @Autowired + private RabbitCustomProperties rabbitCustomProperties; + + private String getExchangeName() { + String exchangeName = rabbitCustomProperties.getTopicExchangeName(); + if (StringUtils.isBlank(exchangeName)) { + exchangeName = DEFAULT_EXCHANGE_NAME; + } + return String.join(CommonConstants.UNDERLINE, exchangeName, + EnvironmentUtils.getProfile()); + } + + private String getDelayedExchangeName() { + String delayedExchangeName = rabbitCustomProperties.getDelayedExchangeName(); + if (StringUtils.isEmpty(delayedExchangeName)) { + delayedExchangeName = DEFAULT_DELAYED_EXCHANGE_NAME; + } + return String.join(CommonConstants.UNDERLINE, delayedExchangeName, + EnvironmentUtils.getProfile()); + } + + + /** + * 交换器 + * + * @return + * @author sr on 2020-07-22 + */ + @Bean + TopicExchange topicExchange(EnvironmentUtils environmentUtils) { + return new TopicExchange(getExchangeName()); + } + + /*@Bean + public CustomExchange delayedCustomExchange(EnvironmentUtils environmentUtils) { + Map args = Maps.newHashMap(); + //延时交换机一定要设置x-delayed-type属性 + args.put("x-delayed-type", "direct"); + //第二个参数type需要设置成x-delayed-message + return new CustomExchange(getDelayedExchangeName(), "x-delayed-message", true, false, args); + }*/ + + /** + * 消息监听容器 + * + * @param containerFactory + * @param messageListenerAdapter + * @return + * @author sr on 2020-07-22 + */ + @Bean + T messageListenerContainer( + AbstractRabbitListenerContainerFactory containerFactory, + MessageListenerAdapter messageListenerAdapter) { + AbstractMessageListenerContainer container = + containerFactory.createListenerContainer(); + container.setMessageListener(messageListenerAdapter); + return (T) container; + } + + /** + * 消息监听适配器 + * + * @param consumerDeliverer + * @return + * @author sr on 2020-07-22 + */ + @Bean + MessageListenerAdapter messageListenerAdapter(ConsumerDeliverer consumerDeliverer) { + MessageListenerAdapter messageListenerAdapter = new MessageListenerAdapter(consumerDeliverer); + // 暂不做消息转换, 交给consumerDeliverer处理 + messageListenerAdapter.setMessageConverter(null); + return messageListenerAdapter; + } + + /** + * 初始化消息处理器,注册队列,绑定路由 + * + * @param messageManager + * @param handlers + * @return + * @author sr on 2020-07-24 + */ + @Bean + InitHandler initHandler() { + return new InitHandler(); + } + + /** + * 消息转换器 + * + * @return + * @author sr on 2020-07-24 + */ + @Bean + Jackson2JsonMessageConverter jackson2JsonMessageConverter() { + return new Jackson2JsonMessageConverter("com.newyetai"); + } + + /** + * 队列管理 + * + * @return + * @author sr on 2020-07-24 + */ + @Bean + QueueManager queueManager() { + return new QueueManager(); + } + + /** + * 交换机管理 + * @return + * @author sr on 2021-01-06 + */ + @Bean + ExchangeManager exchangeManager() { + return new ExchangeManager(); + } + + /** + * 消息消费分发 + * + * @param handlers + * @param handlers + * @return + * @author sr on 2020-07-24 + */ + @Bean + ConsumerDeliverer consumerDeliverer(List> handlers) { + ConsumerDeliverer consumerDeliverer = new ConsumerDeliverer(handlers); + consumerDeliverer.setMessageConvert(jackson2JsonMessageConverter()); + return consumerDeliverer; + } + + /** + * 消息发送者 + * + * @param rabbitTemplate + * @param messageManager + * @return + * @author sr on 2020-07-24 + */ + @Bean + IMqSender mqSender(RabbitTemplate rabbitTemplate, QueueManager messageManager, + RabbitCustomProperties rabbitCustomProperties) { + DefaultMqSender defaultMqSender = new DefaultMqSender(); + MqSendUtils mqSendUtils = new MqSendUtils(defaultMqSender); + return defaultMqSender; + } + +} diff --git a/src/main/java/com/newyetai/mq/constant/ExchangeTypeEnum.java b/src/main/java/com/newyetai/mq/constant/ExchangeTypeEnum.java new file mode 100644 index 0000000..3f48541 --- /dev/null +++ b/src/main/java/com/newyetai/mq/constant/ExchangeTypeEnum.java @@ -0,0 +1,15 @@ +package com.newyetai.mq.constant; + +/** + * 交换机 + * @author sr on 2021-01-06 + */ +public enum ExchangeTypeEnum { + + /** (通用)主题交换机 **/ + TOPIC, + /** 延迟交换机 **/ + DELAYED; + + +} diff --git a/src/main/java/com/newyetai/mq/constant/MqConstant.java b/src/main/java/com/newyetai/mq/constant/MqConstant.java new file mode 100644 index 0000000..7ec449a --- /dev/null +++ b/src/main/java/com/newyetai/mq/constant/MqConstant.java @@ -0,0 +1,12 @@ +package com.newyetai.mq.constant; + +/** + * mq常数 + * + * @author Carlye + * @date 2021/01/14 + */ +public interface MqConstant { + + String NACOS_DISCOVERY_IP = "spring.cloud.nacos.discovery.ip"; +} diff --git a/src/main/java/com/newyetai/mq/consumer/ConsumerDeliverer.java b/src/main/java/com/newyetai/mq/consumer/ConsumerDeliverer.java new file mode 100644 index 0000000..d6ed9ba --- /dev/null +++ b/src/main/java/com/newyetai/mq/consumer/ConsumerDeliverer.java @@ -0,0 +1,137 @@ +package com.newyetai.mq.consumer; + +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.amqp.core.Message; +import org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener; +import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; +import org.springframework.amqp.support.converter.MessageConversionException; +import org.springframework.aop.support.AopUtils; +import org.springframework.core.ParameterizedTypeReference; + +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import com.newyetai.common.constant.ProjectProfileEnum; +import com.newyetai.common.util.EnvironmentUtils; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.common.util.ParameterizedTypeImpl; +import com.newyetai.mq.constant.MqConstant; +import com.newyetai.mq.consumer.handler.IMqHandler; +import com.newyetai.mq.dto.IMqMessage; +import com.rabbitmq.client.Channel; + +import lombok.extern.slf4j.Slf4j; + +/** + * 消息分发 + * + * @author sr on 2020-07-22 + */ +@Slf4j +public class ConsumerDeliverer implements ChannelAwareMessageListener { + + private Jackson2JsonMessageConverter jackson2JsonMessageConverter = + new Jackson2JsonMessageConverter(); + + public static final Map> MQ_HANDLER_MAP = Maps.newHashMap(); + + /** + * key-routingKey,value-ParameterizedTypeReference + **/ + @SuppressWarnings("rawtypes") + private Map messqgeTypeMap = Maps.newConcurrentMap(); + + public ConsumerDeliverer(List> handlers) { + handlers.forEach(handler -> MQ_HANDLER_MAP.put(handler.getRoutingKey(), handler)); + } + + public void setMessageConvert(Jackson2JsonMessageConverter jackson2JsonMessageConverter) { + this.jackson2JsonMessageConverter = jackson2JsonMessageConverter; + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + @Override + public void onMessage(Message message, Channel channel) throws Exception { + String routingKey = message.getMessageProperties().getReceivedRoutingKey(); + String appId = StringUtils.defaultString(message.getMessageProperties().getAppId(), ""); + Set appIp = Sets.newHashSet(appId.split(",")); + //TODO 重复失败消费三次,进死信 + + IMqHandler handler = MQ_HANDLER_MAP.get(routingKey); + if (handler == null) { + log.info(routingKey + "未找到对应routingKey消费者..."); + return; + } + + // 非广播消息&指定消费者ip消费&只能开发环境 + if (!handler.isBroadcast() + && ProjectProfileEnum.DEV.getValue().equals(EnvironmentUtils.getProfile()) + && StringUtils.isNotBlank(appId)) { + // String ip = InetAddress.getLocalHost().getHostAddress(); + String ip = EnvironmentUtils.getProperty(MqConstant.NACOS_DISCOVERY_IP); + log.info("Mq消息消费指定appId:{},当前ip:{}", appId, ip); + if (!appIp.contains(ip)) { + log.info("Mq消息消费异常,appId:[{}],ip:[{}],message:[{}]", appId, ip, JsonUtils.toJsonString(message)); + //放回queue使用其他消费者消费 + channel.basicRecover(true); + return; + } + } + + Object obj = null; + try { + obj = jackson2JsonMessageConverter.fromMessage(message, + getParameterizedTypeReference(routingKey, handler)); + handler.onMessage((IMqMessage) obj); + return; + } catch (MessageConversionException e) { + // 转换失败异常处理 + log.info("mqMessage convert error:{}", e); + } catch (Exception e) { + // TODO 消息消费异常处理 + log.info("mqMessage deal obj:{}", obj, e); + //throw new MqException("message consume error:" + e.getMessage()); + } + } + + /** + * 获取消息范型对象 + * + * @param routingKey + * @param handler + * @return + * @author sr on 2020-09-02 + */ + @SuppressWarnings("rawtypes") + private ParameterizedTypeReference getParameterizedTypeReference(String routingKey, + IMqHandler handler) { + ParameterizedTypeReference type = messqgeTypeMap.get(routingKey); + if (type != null) { + return type; + } + // 有可能是代理对象 + for(Method method :AopUtils.getTargetClass(handler).getMethods()) { + // 有可能是同名方法,非桥接 + if ("onMessage".equals(method.getName()) && !method.isBridge()) { + try { + Type argType = method.getGenericParameterTypes()[0]; + ParameterizedType parameterizedType = (ParameterizedType) (argType); + type = ParameterizedTypeReference.forType(new ParameterizedTypeImpl( + new Type[] {parameterizedType.getActualTypeArguments()[0]}, null, parameterizedType.getRawType())); + messqgeTypeMap.put(routingKey, type); + break; + } catch (Exception e) { + log.error(e.getMessage()); + } + } + } + return type; + } + +} diff --git a/src/main/java/com/newyetai/mq/consumer/InitHandler.java b/src/main/java/com/newyetai/mq/consumer/InitHandler.java new file mode 100644 index 0000000..d810d93 --- /dev/null +++ b/src/main/java/com/newyetai/mq/consumer/InitHandler.java @@ -0,0 +1,56 @@ +package com.newyetai.mq.consumer; + +import com.google.common.collect.Lists; +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.util.EnvironmentUtils; +import com.newyetai.mq.config.ExchangeManager; +import com.newyetai.mq.config.QueueManager; +import com.newyetai.mq.config.RabbitCustomProperties; +import com.newyetai.mq.constant.MqConstant; +import com.newyetai.mq.consumer.handler.IMqHandler; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; + +/** + * 初始化消息消费处理类,初始queue/binding + * + * @author sr on 2020-07-24 + */ +public class InitHandler implements InitializingBean { + + @Autowired(required = false) + private List> handlers = Lists.newArrayList(); + + @Autowired + private QueueManager queueManager; + + @Autowired + private ExchangeManager exchangeManager; + + @Autowired + private RabbitCustomProperties rabbitCustomProperties; + + @Override + public void afterPropertiesSet() throws Exception { + String applicationName = EnvironmentUtils.getApplicationName(); + handlers.forEach(handler -> { + String routingKey = handler.getRoutingKey(); + String queueName = handler.getQueueName(); + // 初始化binding + if (queueName == null) { + queueName = String.join(CommonConstants.UNDERLINE, applicationName, + EnvironmentUtils.getProfile(), routingKey); + if (handler.isBroadcast()) { +// queueName = String.join(CommonConstants.UNDERLINE, queueName,rabbitCustomProperties.getBroadcastId()); + String nacosDiscoveryIp = EnvironmentUtils.getProperty(MqConstant.NACOS_DISCOVERY_IP); + queueName = String.join(CommonConstants.UNDERLINE, queueName, nacosDiscoveryIp); + } + } + queueManager.addQueueAndRoutingKey( + exchangeManager.getExchangeByType(handler.getExchangeType()), queueName, routingKey); + }); + } + +} diff --git a/src/main/java/com/newyetai/mq/consumer/handler/IDelayedMqHandler.java b/src/main/java/com/newyetai/mq/consumer/handler/IDelayedMqHandler.java new file mode 100644 index 0000000..291a84d --- /dev/null +++ b/src/main/java/com/newyetai/mq/consumer/handler/IDelayedMqHandler.java @@ -0,0 +1,22 @@ +//package com.newyetai.mq.consumer.handler; +// +//import com.newyetai.mq.constant.ExchangeTypeEnum; +//import com.newyetai.mq.dto.DelayedMqMessage; +// +///** +// * 消费者处理类(延时交换机) +// * +// * @author sr on 2021-01-06 +// * @param +// */ +//public interface IDelayedMqHandler extends IMqHandler>{ +// +// default String getExchangeType() { +// return ExchangeTypeEnum.DELAYED.name(); +// } +// +// default Class getMessageTypeClazz() { +// return DelayedMqMessage.class; +// } +// +//} diff --git a/src/main/java/com/newyetai/mq/consumer/handler/IMqHandler.java b/src/main/java/com/newyetai/mq/consumer/handler/IMqHandler.java new file mode 100644 index 0000000..0a0a5c3 --- /dev/null +++ b/src/main/java/com/newyetai/mq/consumer/handler/IMqHandler.java @@ -0,0 +1,67 @@ +package com.newyetai.mq.consumer.handler; + +import com.newyetai.mq.constant.ExchangeTypeEnum; +import com.newyetai.mq.dto.IMqMessage; + +/** + * 消费者处理类 + * + * @author sr on 2021-01-06 + * @param + */ +public interface IMqHandler> { + + /** + * 为空,默认:系统名_routingKey;每个routingkey有专属queue + * + * @return + * @author sr on 2020-07-24 + */ + default String getQueueName() { + return null; + } + + /** + * 是否同项目广播,默认否 + * @return + * @author sr on 2020-08-04 + */ + default boolean isBroadcast() { + return false; + } + + /** + * routingKey 路由键 + * + * @return + * @author sr on 2020-07-24 + */ + String getRoutingKey(); + + /** + * 消费消息 + * + * @param message + * @return 如果抛异常,则代表消费失败,会重新入队 + * @author sr on 2020-07-24 + */ + void onMessage(M message); + + /** + * 获取mq消息对象class + * + * @return + * @author sr on 2021-01-06 + */ + Class getMessageTypeClazz(); + + + /** + * 交换机 + * + * @return {@link ExchangeTypeEnum}.name() + * @author sr on 2021-01-06 + */ + String getExchangeType(); + +} diff --git a/src/main/java/com/newyetai/mq/consumer/handler/ITopicMqHandler.java b/src/main/java/com/newyetai/mq/consumer/handler/ITopicMqHandler.java new file mode 100644 index 0000000..b6ebe85 --- /dev/null +++ b/src/main/java/com/newyetai/mq/consumer/handler/ITopicMqHandler.java @@ -0,0 +1,28 @@ +package com.newyetai.mq.consumer.handler; + +import com.newyetai.mq.constant.ExchangeTypeEnum; +import com.newyetai.mq.dto.TopicMqMessage; + +/** + * 消费者处理类(通用交换机) + * + * @author sr on 2020-07-22 + * @param + */ +public interface ITopicMqHandler extends IMqHandler>{ + + default Class getMessageTypeClazz() { + return TopicMqMessage.class; + } + + /** + * 交换机 + * + * @return {@link ExchangeTypeEnum}.name() + * @author sr on 2021-01-06 + */ + default String getExchangeType() { + return ExchangeTypeEnum.TOPIC.name(); + } + +} diff --git a/src/main/java/com/newyetai/mq/dto/AbstractMqMessage.java b/src/main/java/com/newyetai/mq/dto/AbstractMqMessage.java new file mode 100644 index 0000000..c5d166e --- /dev/null +++ b/src/main/java/com/newyetai/mq/dto/AbstractMqMessage.java @@ -0,0 +1,38 @@ +package com.newyetai.mq.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public abstract class AbstractMqMessage implements IMqMessage{ + + /** + * 消息id,可为空(uuid生成) + **/ + private String messageId; + + /** + * 路由键,不能为空 + **/ + private String routingKey; + + /** + * 消息对象 + **/ + private T data; + + /** 操作机构ID(发送方有登录信息时有值) **/ + private Long operateOrgId; + + /** 操作用户ID(发送方有登录信息时有值) **/ + private Long operateUserId; + + /** 用户类型 **/ + private Integer operateUserType; + +} diff --git a/src/main/java/com/newyetai/mq/dto/DelayedMqMessage.java b/src/main/java/com/newyetai/mq/dto/DelayedMqMessage.java new file mode 100644 index 0000000..deac3ed --- /dev/null +++ b/src/main/java/com/newyetai/mq/dto/DelayedMqMessage.java @@ -0,0 +1,42 @@ +package com.newyetai.mq.dto; + +import java.util.Optional; +import java.util.concurrent.TimeUnit; + +import com.newyetai.mq.constant.ExchangeTypeEnum; + +import lombok.AllArgsConstructor; +import lombok.Builder.Default; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.SuperBuilder; + +@Data +@ToString(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class DelayedMqMessage extends AbstractMqMessage{ + + /** 交换机,可为空(DELAYED) **/ + @Default + private String exchangeType = ExchangeTypeEnum.DELAYED.name(); + +// /** +// * 延时发送时间,不能为空 +// */ +// private Long delayedTime; +// +// /** +// * 时间类型,可为空 +// */ +// @Default +// private TimeUnit timeUnit = TimeUnit.SECONDS; +// +// +// public TimeUnit getTimeUnit() { +// return Optional.ofNullable(timeUnit).orElse(TimeUnit.SECONDS); +// } + +} diff --git a/src/main/java/com/newyetai/mq/dto/IMqMessage.java b/src/main/java/com/newyetai/mq/dto/IMqMessage.java new file mode 100644 index 0000000..b045daa --- /dev/null +++ b/src/main/java/com/newyetai/mq/dto/IMqMessage.java @@ -0,0 +1,35 @@ +package com.newyetai.mq.dto; + +import com.newyetai.mq.constant.ExchangeTypeEnum; + +/** + * 消息 + * + * @author sr on 2021-01-06 + * @param + */ +public interface IMqMessage { + + /** + * 交换机类型 + * @return {@link ExchangeTypeEnum} + * @author sr on 2021-01-06 + */ + String getExchangeType(); + + /** + * routingKey 路由键 + * + * @return + * @author sr on 2021-01-06 + */ + String getRoutingKey(); + + /** + * 消息体 + * @return + * @author sr on 2021-01-06 + */ + T getData(); + +} diff --git a/src/main/java/com/newyetai/mq/dto/TopicMqMessage.java b/src/main/java/com/newyetai/mq/dto/TopicMqMessage.java new file mode 100644 index 0000000..9171767 --- /dev/null +++ b/src/main/java/com/newyetai/mq/dto/TopicMqMessage.java @@ -0,0 +1,27 @@ +package com.newyetai.mq.dto; + +import com.newyetai.mq.constant.ExchangeTypeEnum; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Builder.Default; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2020-07-24 + */ +@Data +@ToString(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class TopicMqMessage extends AbstractMqMessage{ + + /** 交换机 **/ + @Default + private String exchangeType = ExchangeTypeEnum.TOPIC.name(); + +} diff --git a/src/main/java/com/newyetai/mq/exception/MqException.java b/src/main/java/com/newyetai/mq/exception/MqException.java new file mode 100644 index 0000000..3c2502f --- /dev/null +++ b/src/main/java/com/newyetai/mq/exception/MqException.java @@ -0,0 +1,29 @@ +package com.newyetai.mq.exception; + +import com.newyetai.common.exception.BusinessException; + +/** + * 异常 + * + * @author sr on 2020-07-24 + */ +public class MqException extends BusinessException { + + /** **/ + private static final long serialVersionUID = -7022341715833999512L; + + public MqException() {} + + public MqException(String message) { + super(message); + } + + public MqException(String message, Throwable cause) { + super(message, cause); + } + + public MqException(Throwable cause) { + super(cause); + } + +} diff --git a/src/main/java/com/newyetai/mq/producer/sender/DefaultMqSender.java b/src/main/java/com/newyetai/mq/producer/sender/DefaultMqSender.java new file mode 100644 index 0000000..034dec3 --- /dev/null +++ b/src/main/java/com/newyetai/mq/producer/sender/DefaultMqSender.java @@ -0,0 +1,94 @@ +package com.newyetai.mq.producer.sender; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.mq.config.ExchangeManager; +import com.newyetai.mq.config.RabbitCustomProperties; +import com.newyetai.mq.dto.AbstractMqMessage; +import com.newyetai.mq.dto.DelayedMqMessage; +import com.newyetai.mq.dto.IMqMessage; +import com.newyetai.mq.dto.TopicMqMessage; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.amqp.AmqpException; +import org.springframework.amqp.core.Message; +import org.springframework.amqp.core.MessageProperties; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.concurrent.TimeUnit; + +/** + * @author sr on 2020-07-24 + */ +@Slf4j +public class DefaultMqSender implements IMqSender { + + @Autowired + private RabbitTemplate rabbitTemplate; + + @Autowired + private RabbitCustomProperties rabbitCustomProperties; + + @Autowired + private ExchangeManager exchangeManager; + + @Override + public AlitaResult send(String routingKey, T msg){ + return this.send(TopicMqMessage.builder().routingKey(routingKey).data(msg).build()); + } + + + @Override + public AlitaResult sendDelayed(String routingKey, T msg, Long delayedTime, TimeUnit timeUnit) { + throw new BusinessException("延迟队列不可用"); +// return this.send(DelayedMqMessage.builder().routingKey(routingKey).data(msg) +// .delayedTime(delayedTime).timeUnit(timeUnit).build()); + } + + @Override + public AlitaResult send(AbstractMqMessage iMqMessage) { + try { + iMqMessage.setOperateUserId(UserContextHolder.getLoginUserId()); + iMqMessage.setOperateOrgId(UserContextHolder.getLoginOrgId()); + iMqMessage.setOperateUserType(UserContextHolder.getUserType()); + String routingKey = iMqMessage.getRoutingKey(); + Assert.notBlank(routingKey, "routingKey不能为空"); + // 获取 exchange + String exchangeName = exchangeManager.getExchangeNameByType(iMqMessage.getExchangeType()); + + MessageProperties messageProperties = new MessageProperties(); + // 指定消费者 + String consumerAppId = rabbitCustomProperties.getConsumerAppId(); + if (StringUtils.isNotBlank(consumerAppId)) { + messageProperties.setAppId(consumerAppId); + } + // 处理延时 +// this.dealDelayed(iMqMessage, messageProperties); + + Message msg = rabbitTemplate.getMessageConverter().toMessage(iMqMessage, messageProperties); + log.info("mqSender msg:{}", msg); + rabbitTemplate.send(exchangeName, routingKey, msg); + } catch (AmqpException e) { + log.info("mqSender send error:{}", e.getMessage()); + return AlitaResult.bizError(e.getMessage()); + } + return AlitaResult.success(); + } + + /*private void dealDelayed(IMqMessage mqMessage, MessageProperties messageProperties) { + // 延时消息设置 + if (mqMessage instanceof DelayedMqMessage) { + Long delayedTime = ((DelayedMqMessage) mqMessage).getDelayedTime(); + Assert.notNull(delayedTime, "延时时间不能为空"); + TimeUnit timeUnit = ((DelayedMqMessage) mqMessage).getTimeUnit(); + if (delayedTime != null && delayedTime > 0L) { + messageProperties.setHeader("x-delay", timeUnit.toMillis(delayedTime)); + } + } + }*/ + + +} diff --git a/src/main/java/com/newyetai/mq/producer/sender/IMqSender.java b/src/main/java/com/newyetai/mq/producer/sender/IMqSender.java new file mode 100644 index 0000000..3f9c734 --- /dev/null +++ b/src/main/java/com/newyetai/mq/producer/sender/IMqSender.java @@ -0,0 +1,51 @@ +package com.newyetai.mq.producer.sender; + +import java.util.concurrent.TimeUnit; + +import com.newyetai.common.AlitaResult; +import com.newyetai.mq.dto.AbstractMqMessage; +import com.newyetai.mq.dto.IMqMessage; + +/** + * 消息发送者 + * + * @author sr on 2020-07-24 + */ +public interface IMqSender { + + /** + * 消息发送 + * + * @param + * @param routingKey + * @param msg + * @return + * @author sr on 2020-07-24 + */ + AlitaResult send(String routingKey, T msg); + + /** + * 发送延迟消息 + * + * @param + * @param routingKey + * @param msg + * @param delayedTime + * @param timeUnit + * @return + * @author sr on 2021-01-06 + */ + AlitaResult sendDelayed(String routingKey, T msg, Long delayedTime, TimeUnit timeUnit); + + + /** + * 消息发送 + * + * @param + * @param iMqMessage + * @return + * @author sr on 2020-07-24 + */ + AlitaResult send(AbstractMqMessage iMqMessage); + +} diff --git a/src/main/java/com/newyetai/mq/util/MqSendUtils.java b/src/main/java/com/newyetai/mq/util/MqSendUtils.java new file mode 100644 index 0000000..f91f374 --- /dev/null +++ b/src/main/java/com/newyetai/mq/util/MqSendUtils.java @@ -0,0 +1,64 @@ +package com.newyetai.mq.util; + +import java.util.concurrent.TimeUnit; + +import com.newyetai.common.AlitaResult; +import com.newyetai.mq.dto.AbstractMqMessage; +import com.newyetai.mq.producer.sender.IMqSender; + +/** + * @Author dylanyuan + * @Date 2020/12/1 下午1:58 + * @Version 1.0 + */ +public class MqSendUtils { + + private static IMqSender iMqSender; + + public MqSendUtils(IMqSender iMqSender) { + MqSendUtils.iMqSender = iMqSender; + } + + /** + * 消息发送 + * + * @param + * @param routingKey + * @param msg + * @return + * @author sr on 2020-07-24 + */ + public static AlitaResult send(String routingKey, T msg) { + return iMqSender.send(routingKey, msg); + } + + /** + * 发送延迟消息 + * + * @param + * @param routingKey + * @param msg + * @param delayedTime + * @param timeUnit + * @return + * @author sr on 2021-01-06 + */ +// public static AlitaResult sendDelayed(String routingKey, T msg, Long delayedTime, +// TimeUnit timeUnit) { +// return iMqSender.sendDelayed(routingKey, msg, delayedTime, timeUnit); +// } + + + /** + * 消息发送 + * + * @param + * @param iMqMessage + * @return + * @author sr on 2020-07-24 + */ + public static AlitaResult send(AbstractMqMessage iMqMessage) { + return iMqSender.send(iMqMessage); + } + +} diff --git a/src/main/java/com/newyetai/mybatis/config/MybatisConfig.java b/src/main/java/com/newyetai/mybatis/config/MybatisConfig.java new file mode 100644 index 0000000..cbc900d --- /dev/null +++ b/src/main/java/com/newyetai/mybatis/config/MybatisConfig.java @@ -0,0 +1,47 @@ +package com.newyetai.mybatis.config; + +import java.util.List; + +import org.apache.ibatis.session.SqlSessionFactory; +import org.apache.ibatis.type.TypeHandlerRegistry; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; + +import com.github.pagehelper.autoconfigure.PageHelperAutoConfiguration; +import com.newyetai.mybatis.handle.BaseEnumTypeHandler; +import com.newyetai.mybatis.interceptor.MyPageInterceptor; + +import lombok.extern.slf4j.Slf4j; + +/** + * @author guhong + * @date 2019/8/19 + * 设置mapper扫描的包 + */ +@Configuration +@Slf4j +public class MybatisConfig { + + @Autowired + private List sqlSessionFactoryList; + + /** + * 添加自定义的分页插件,pageHelper 的分页插件PageInterceptor是用@PostConstruct添加的,自定义的应该在其后面添加 + * 真正执行时顺序是反过来,先执行MyPageInterceptor,再执行 PageInterceptor + * + * 所以要保证 PageHelperAutoConfiguration 先执行 + */ + @Autowired + public void addPageInterceptor(PageHelperAutoConfiguration pageHelperAutoConfiguration) { + MyPageInterceptor interceptor = new MyPageInterceptor(); + for (SqlSessionFactory sqlSessionFactory : sqlSessionFactoryList) { + sqlSessionFactory.getConfiguration().addInterceptor(interceptor); + log.info("注册自定义分页插件成功"); + // 取得类型转换注册器 + TypeHandlerRegistry typeHandlerRegistry = sqlSessionFactory.getConfiguration().getTypeHandlerRegistry(); + // 注册默认枚举转换器 + typeHandlerRegistry.setDefaultEnumTypeHandler(BaseEnumTypeHandler.class); + } + } + +} diff --git a/src/main/java/com/newyetai/mybatis/converters/ObjectToBaseEnumConverter.java b/src/main/java/com/newyetai/mybatis/converters/ObjectToBaseEnumConverter.java new file mode 100644 index 0000000..8d482c4 --- /dev/null +++ b/src/main/java/com/newyetai/mybatis/converters/ObjectToBaseEnumConverter.java @@ -0,0 +1,35 @@ +package com.newyetai.mybatis.converters; + +import com.google.common.collect.Sets; +import com.newyetai.mybatis.handle.BaseEnum; +import java.util.Arrays; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; +import org.springframework.core.convert.TypeDescriptor; +import org.springframework.core.convert.converter.GenericConverter; + +/** + * @description: baseEnum转换 + * @author: chenyun.huang + * @create: 2021-04-01 11:52 + **/ +public class ObjectToBaseEnumConverter implements GenericConverter { + @Override + public Set getConvertibleTypes() { + return Sets.newHashSet(new ConvertiblePair(Integer.class, BaseEnum.class),new ConvertiblePair(String.class, BaseEnum.class)); + } + + @Override + public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { + if (Objects.isNull(source)){ + return null; + } + Class type = (Class) targetType.getType(); + BaseEnum[] enumConstants = type.getEnumConstants(); + Map collect = Arrays.stream(enumConstants) + .collect(Collectors.toMap(BaseEnum::getValue, v -> v, (v1, v2) -> v2)); + return collect.get(source); + } +} diff --git a/src/main/java/com/newyetai/mybatis/handle/BaseEnum.java b/src/main/java/com/newyetai/mybatis/handle/BaseEnum.java new file mode 100644 index 0000000..eaed3da --- /dev/null +++ b/src/main/java/com/newyetai/mybatis/handle/BaseEnum.java @@ -0,0 +1,11 @@ +package com.newyetai.mybatis.handle; + +public interface BaseEnum { + + /** + * 获取枚举的值 + * + * @return 枚举的值 + */ + T getValue(); +} diff --git a/src/main/java/com/newyetai/mybatis/handle/BaseEnumTypeHandler.java b/src/main/java/com/newyetai/mybatis/handle/BaseEnumTypeHandler.java new file mode 100644 index 0000000..a9c296d --- /dev/null +++ b/src/main/java/com/newyetai/mybatis/handle/BaseEnumTypeHandler.java @@ -0,0 +1,103 @@ +package com.newyetai.mybatis.handle; + +import org.apache.ibatis.type.BaseTypeHandler; +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.MappedJdbcTypes; +import org.apache.ibatis.type.MappedTypes; + +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.Objects; + +/** + * @description: 通用枚举转换 + * @author: chenyun.huang + * @create: 2020-04-14 20:00 + **/ +@MappedJdbcTypes(value = JdbcType.VARCHAR, includeNullJdbcType = true) +@MappedTypes({BaseEnum.class}) +public class BaseEnumTypeHandler & BaseEnum> extends BaseTypeHandler { + + /** + * 枚举的class + */ + private Class type; + /** + * 枚举的每个子类枚 + */ + private E[] enums; + + /** + * 一定要有默认的构造函数,不然抛出 not found method 异常 + */ + public BaseEnumTypeHandler() { + } + + /** + * 设置配置文件设置的转换类以及枚举类内容,供其他方法更便捷高效的实现 + * + * @param type 配置文件中设置的转换类 + */ + public BaseEnumTypeHandler(Class type) { + if (type == null) { + throw new IllegalArgumentException("Type argument cannot be null"); + } + this.type = type; + this.enums = type.getEnumConstants(); + if (this.enums == null) { + throw new IllegalArgumentException(type.getSimpleName() + + " does not represent an enum type."); + } + } + + @Override + public void setNonNullParameter(PreparedStatement ps, int i, E parameter, + JdbcType jdbcType) throws SQLException { + /* + * BaseTypeHandler已经帮我们做了parameter的null判断 + * 数据库存储的是枚举的值,所以我们这里使用 value , 如果需要存储 name,可以自定义修改 + */ + if (jdbcType == null) { + Object value = parameter.getValue(); + ps.setString(i, Objects.toString(value)); + } else { + ps.setObject(i, parameter.getValue(), jdbcType.TYPE_CODE); + } + } + + @Override + public E getNullableResult(ResultSet rs, String columnName) + throws SQLException { + return locateEnumStatus(rs.getString(columnName)); + } + + @Override + public E getNullableResult(ResultSet rs, int columnIndex) + throws SQLException { + return locateEnumStatus(rs.getString(columnIndex)); + } + + @Override + public E getNullableResult(CallableStatement cs, int columnIndex) + throws SQLException { + return locateEnumStatus(cs.getString(columnIndex)); + } + + /** + * 枚举类型转换,由于构造函数获取了枚举的子类 enums,让遍历更加高效快捷, + *

+ * 我将取出来的值 全部转换成字符串 进行比较, + * + * @param value 数据库中存储的自定义value属性 + * @return value 对应的枚举类 + */ + private E locateEnumStatus(String value) { + return Arrays.stream(enums) + .filter(e -> Objects.toString(e.getValue()).equals(value)) + .findFirst() + .orElse(null); + } +} diff --git a/src/main/java/com/newyetai/mybatis/interceptor/MyPageInterceptor.java b/src/main/java/com/newyetai/mybatis/interceptor/MyPageInterceptor.java new file mode 100644 index 0000000..3e302f1 --- /dev/null +++ b/src/main/java/com/newyetai/mybatis/interceptor/MyPageInterceptor.java @@ -0,0 +1,88 @@ +package com.newyetai.mybatis.interceptor; + +import com.github.pagehelper.Page; +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageRowBounds; +import com.newyetai.common.dto.IPage; +import org.apache.ibatis.cache.CacheKey; +import org.apache.ibatis.executor.Executor; +import org.apache.ibatis.mapping.BoundSql; +import org.apache.ibatis.mapping.MappedStatement; +import org.apache.ibatis.plugin.*; +import org.apache.ibatis.session.ResultHandler; +import org.apache.ibatis.session.RowBounds; + +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Properties; + +/** + * @author guhong + * @date 2019/8/19 + */ +@Intercepts({ + @Signature(type = Executor.class, method = "query", + args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}), + @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, + RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),}) +public class MyPageInterceptor implements Interceptor { + + @SuppressWarnings({"unchecked", "rawtypes"}) + @Override + public Object intercept(Invocation invocation) throws Throwable { + Object[] args = invocation.getArgs(); + Object parameter = args[1]; + IPage page = null; + + if (parameter instanceof IPage) { + page = (IPage) parameter; + } else if (parameter instanceof Map) { + for (Map.Entry entry : ((Map) parameter).entrySet()) { + Object value = entry.getValue(); + if (value instanceof IPage) { + page = (IPage) value; + break; + } + } + } + + PageRowBounds pageRowBounds = null; + if (page != null && page.getNeedPage() && page.getPageSize() > 0) { + pageRowBounds = + new PageRowBounds(page.getPageSize() * (page.getPageNo() - 1), page.getPageSize()); + pageRowBounds.setCount(true); + args[2] = pageRowBounds; + } + + // 判断pageSize=0,兼容老版本=0不分页 + Page pageHelperPage = PageHelper.getLocalPage(); + if (pageHelperPage != null && pageHelperPage.getPageSize() == 0) { + PageHelper.clearPage(); + } + + Object value = invocation.proceed(); + + if (page != null && page.getNeedPage() && page.getPageSize() > 0) { + page.setPageResult(pageRowBounds.getTotal().intValue(), (List)value); + } + + + return value; + } + + @Override + public Object plugin(Object target) { + if (target instanceof Executor) { + return Plugin.wrap(target, this); + } else { + return target; + } + } + + @Override + public void setProperties(Properties properties) { + + } + +} diff --git a/src/main/java/com/newyetai/mybatisplus/config/AutoMetaObjectHandler.java b/src/main/java/com/newyetai/mybatisplus/config/AutoMetaObjectHandler.java new file mode 100644 index 0000000..721dfb1 --- /dev/null +++ b/src/main/java/com/newyetai/mybatisplus/config/AutoMetaObjectHandler.java @@ -0,0 +1,26 @@ +package com.newyetai.mybatisplus.config; + +import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import com.newyetai.common.util.UserContextHolder; +import lombok.extern.slf4j.Slf4j; +import org.apache.ibatis.reflection.MetaObject; +import org.springframework.stereotype.Component; + +import java.util.Date; + +@Slf4j +//@Component +public class AutoMetaObjectHandler implements MetaObjectHandler { + @Override + public void insertFill(MetaObject metaObject) { + this.strictInsertFill(metaObject, "deleted", Boolean.class, Boolean.FALSE); + this.strictInsertFill(metaObject, "createTime", Date.class, new Date()); + this.strictInsertFill(metaObject, "createBy", Long.class, UserContextHolder.getLoginUserId()); + } + + @Override + public void updateFill(MetaObject metaObject) { + this.strictUpdateFill(metaObject, "updateBy", Long.class, UserContextHolder.getLoginUserId()); + this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date()); + } +} diff --git a/src/main/java/com/newyetai/mybatisplus/config/MybatisPlusConfig.java b/src/main/java/com/newyetai/mybatisplus/config/MybatisPlusConfig.java new file mode 100644 index 0000000..3960857 --- /dev/null +++ b/src/main/java/com/newyetai/mybatisplus/config/MybatisPlusConfig.java @@ -0,0 +1,24 @@ +package com.newyetai.mybatisplus.config; + +import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; +import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@MapperScan(basePackages = {"com.newyetai.**.dao.**"}) +public class MybatisPlusConfig { + + @Bean + public PaginationInterceptor paginationInterceptor() { + PaginationInterceptor paginationInterceptor = new PaginationInterceptor(); + // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false + // paginationInterceptor.setOverflow(false); + // 设置最大单页限制数量,默认 500 条,-1 不受限制 + // paginationInterceptor.setLimit(500); + // 开启 count 的 join 优化,只针对部分 left join + paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true)); + return paginationInterceptor; + } +} diff --git a/src/main/java/com/newyetai/mybatisplus/injector/Exists.java b/src/main/java/com/newyetai/mybatisplus/injector/Exists.java new file mode 100644 index 0000000..0db4139 --- /dev/null +++ b/src/main/java/com/newyetai/mybatisplus/injector/Exists.java @@ -0,0 +1,46 @@ +package com.newyetai.mybatisplus.injector; + +import org.apache.ibatis.mapping.MappedStatement; +import org.apache.ibatis.mapping.SqlSource; + +import com.baomidou.mybatisplus.core.enums.SqlMethod; +import com.baomidou.mybatisplus.core.injector.AbstractMethod; +import com.baomidou.mybatisplus.core.metadata.TableInfo; +import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils; + +public class Exists extends AbstractMethod { + + @Override + public MappedStatement injectMappedStatement(Class mapperClass, Class modelClass, + TableInfo tableInfo) { + SqlMethod sqlMethod = SqlMethod.SELECT_COUNT; + String sql = + String.format("", tableInfo.getTableName(), + sqlWhereEntity(true, tableInfo)); + SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass); + return this.addSelectMappedStatementForOther(mapperClass, getMethod(sqlMethod), sqlSource, Boolean.class); + } + + protected String sqlWhereEntity(boolean newLine, TableInfo table) { + + String sqlScript = table.getAllSqlWhere(false, false, ENTITY_DOT); + + String newKeyProperty = ENTITY_DOT + table.getKeyProperty(); + String keySqlScript = + table.getKeyColumn() + HTML_LT + HTML_GT + SqlScriptUtils.safeParam(newKeyProperty); + sqlScript = + SqlScriptUtils.convertIf(keySqlScript, String.format("%s != null", newKeyProperty), false) + + NEWLINE + sqlScript; + + sqlScript = SqlScriptUtils.convertIf(sqlScript, String.format("%s != null", ENTITY), true); + sqlScript = SqlScriptUtils.convertWhere(sqlScript) + NEWLINE; + return newLine ? NEWLINE + sqlScript : sqlScript; + } + + @Override + public String getMethod(SqlMethod sqlMethod) { + // 自定义 mapper 方法名 + return "existsEntity"; + } + +} diff --git a/src/main/java/com/newyetai/mybatisplus/injector/MySqlInjector.java b/src/main/java/com/newyetai/mybatisplus/injector/MySqlInjector.java new file mode 100644 index 0000000..8de6ca2 --- /dev/null +++ b/src/main/java/com/newyetai/mybatisplus/injector/MySqlInjector.java @@ -0,0 +1,25 @@ +package com.newyetai.mybatisplus.injector; + +import java.util.List; + +import org.springframework.stereotype.Component; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.core.injector.AbstractMethod; +import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector; +import com.baomidou.mybatisplus.extension.injector.methods.AlwaysUpdateSomeColumnById; + +@Component +public class MySqlInjector extends DefaultSqlInjector { + @Override + public List getMethodList(Class mapperClass) { + List methodList = super.getMethodList(mapperClass); + /** + * 把两个扩展内置扩展SQL注入器注入 + */ +// methodList.add(new InsertBatchSomeColumn(i -> i.getFieldFill() != FieldFill.UPDATE)); + methodList.add(new AlwaysUpdateSomeColumnById(i -> i.getFieldFill() != FieldFill.INSERT)); + methodList.add(new Exists()); + return methodList; + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/mybatisplus/util/MybatisPlusUtils.java b/src/main/java/com/newyetai/mybatisplus/util/MybatisPlusUtils.java new file mode 100644 index 0000000..f427b71 --- /dev/null +++ b/src/main/java/com/newyetai/mybatisplus/util/MybatisPlusUtils.java @@ -0,0 +1,33 @@ +package com.newyetai.mybatisplus.util; + +import java.lang.reflect.Field; +import java.util.Arrays; + +import com.baomidou.mybatisplus.annotation.EnumValue; + +public class MybatisPlusUtils { + + /** + * 处理枚举字段 + * @param obj + * @return + * @throws IllegalArgumentException + * @throws IllegalAccessException + * @author sr on 2022-02-21 + */ + public static Object dealEnumField(Object obj) throws IllegalArgumentException, IllegalAccessException { + if (obj == null) { + return null; + } + Class clazz = obj.getClass(); + if (!clazz.isEnum()) { + return obj; + } + Field f = Arrays.stream(clazz.getDeclaredFields()) + .filter(field -> field.isAnnotationPresent(EnumValue.class)).findFirst().get(); + f.setAccessible(true); + return f.get(obj); + } + + +} diff --git a/src/main/java/com/newyetai/recruit/company/constant/CompanyConstants.java b/src/main/java/com/newyetai/recruit/company/constant/CompanyConstants.java new file mode 100644 index 0000000..d21b390 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/company/constant/CompanyConstants.java @@ -0,0 +1,14 @@ +package com.newyetai.recruit.company.constant; + +/** + * @description: + * @author: guixinman + * @create: 2023-02-27 14:29 + **/ +public interface CompanyConstants { + /** + * 岗位文件类型 1:图片 2:视频 + */ + String COMPANY_FILE_TYPE_IMG = "1"; + String COMPANY_FILE_TYPE_VIDEO = "2"; +} diff --git a/src/main/java/com/newyetai/recruit/company/controller/HrCompanyController.java b/src/main/java/com/newyetai/recruit/company/controller/HrCompanyController.java new file mode 100644 index 0000000..06ff903 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/company/controller/HrCompanyController.java @@ -0,0 +1,102 @@ +package com.newyetai.recruit.company.controller; + + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; +import com.newyetai.recruit.company.dto.HrCompanyDTO; +import com.newyetai.recruit.company.dto.HrCompanyPageQueryDTO; +import com.newyetai.recruit.company.entity.HrCompany; +import com.newyetai.recruit.company.service.IHrCompanyService; +import com.newyetai.tkmybatis.pojo.Page; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + *

+ * 招聘系统-企业管理 前端控制器 + *

+ * + * @author chenyun + * @since 2021-01-08 + */ +@Api(tags = "企业管理信息") +@RestController +@RequestMapping("/company") +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class HrCompanyController { + + private final IHrCompanyService companyService; + + /** + * 创建 + */ + @PostMapping("/create") + @ApiOperation("创建企业信息") + public AlitaResult create(@Validated(Create.class) @RequestBody HrCompanyDTO hrCompanyDTO) { + companyService.create(hrCompanyDTO); + return AlitaResult.success(); + } + + /** + * 修改 + */ + @PutMapping("/update") + @ApiOperation("修改企业信息") + public AlitaResult update( + @Validated(Update.class) @RequestBody HrCompanyDTO hrCompanyDTO) { + return AlitaResult.success(companyService.update(hrCompanyDTO)); + } + + /** + * 详情 + */ + @GetMapping("/detail") + @ApiOperation("企业信息详情") + public AlitaResult detail(HrCompanyDTO hrCompanyDTO) { + return AlitaResult.success(companyService.detail(hrCompanyDTO)); + } + + /** + * 分页查询 + */ + @GetMapping("/page") + @ApiOperation("分页查询") + public AlitaResult> page(@Validated HrCompanyPageQueryDTO queryDTO) { + queryDTO.check(); + companyService.page(queryDTO); + return AlitaResult.success(queryDTO.getPageResult()); + } + + /** + * 不分页查询 + */ + @GetMapping("/list") + @ApiOperation("不分页查询") + public AlitaResult> list(@Validated HrCompanyPageQueryDTO queryDTO) { + queryDTO.check(); + return AlitaResult.success(companyService.list(queryDTO)); + } + + @GetMapping("/export") + @ApiOperation("导出") + public void export(@Validated HrCompanyPageQueryDTO queryDTO) { + queryDTO.check(); + companyService.export(queryDTO); + } + + @GetMapping("/{id}") + @ApiOperation("查询单个") + public AlitaResult findById(@PathVariable("id") Long id) { + return AlitaResult.success(companyService.findById(id)); + } +} + diff --git a/src/main/java/com/newyetai/recruit/company/dao/HrCompanyMapper.java b/src/main/java/com/newyetai/recruit/company/dao/HrCompanyMapper.java new file mode 100644 index 0000000..8b0917e --- /dev/null +++ b/src/main/java/com/newyetai/recruit/company/dao/HrCompanyMapper.java @@ -0,0 +1,25 @@ +package com.newyetai.recruit.company.dao; + + +import com.newyetai.recruit.company.dto.HrCompanyDTO; +import com.newyetai.recruit.company.dto.HrCompanyPageQueryDTO; +import com.newyetai.recruit.company.entity.HrCompany; +import com.newyetai.tkmybatis.mybatis.MyMapper; + +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + *

+ * 招聘系统-企业信息表 Mapper 接口 + *

+ * + * @author chenyun + * @since 2021-01-08 + */ +@Mapper +public interface HrCompanyMapper extends MyMapper { + List page(HrCompanyPageQueryDTO hrCompanyPageQueryDTO); + +} diff --git a/src/main/java/com/newyetai/recruit/company/dto/HrCompanyDTO.java b/src/main/java/com/newyetai/recruit/company/dto/HrCompanyDTO.java new file mode 100644 index 0000000..463fe28 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/company/dto/HrCompanyDTO.java @@ -0,0 +1,88 @@ +package com.newyetai.recruit.company.dto; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; + +import org.hibernate.validator.constraints.Length; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.SuperBuilder; + +import javax.validation.constraints.NotNull; + +/** + * 人力资源公司dto + * + * @author Carlye + * @date 2021/01/08 + */ +@EqualsAndHashCode(callSuper = true) +@ApiModel("招聘系统客户信息DTO") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public class HrCompanyDTO extends BaseDTO { + + private static final long serialVersionUID = -2216352275325005059L; + + @ApiModelProperty("机构ID") + private Long orgId; + + @ApiModelProperty("统一社会信用代码") + private String creditCode; + + @ApiModelProperty("企业LOGO FileRecord") + private String companyLogo; + + @ApiModelProperty("名称") + @NotNull(message = "名称不能为空", groups = {Create.class, Update.class}) + @Length(max = 32,message = "名称超长", groups = {Create.class, Update.class}) + private String companyName; + + @ApiModelProperty("机构名称") + private String orgName; + + @ApiModelProperty("联系人") + @Length(max = 20,message = "联系人长度超长", groups = {Create.class, Update.class}) + private String contactPerson; + + @Length(max = 50,message = "联系方式长度超长", groups = {Create.class, Update.class}) + @ApiModelProperty("联系方式") + private String contactWay; + + @Length(max = 100,message = "企业简介长度超长", groups = {Create.class, Update.class}) + @ApiModelProperty("公司简介") + private String companyProfile; + + @ApiModelProperty("公司描述") + private String companyDescription; + + @ApiModelProperty("行业 (数据字典)") + private String companyIndustry; + + @ApiModelProperty("规模 (数据字典)") + private String companySize; + + @ApiModelProperty("公司注册地址") + @Length(max = 32,message = "企业地址长度超长", groups = {Create.class, Update.class}) + private String companyRegisterAddress; + + @ApiModelProperty("省份 (数据字典)") + private Integer province; + + @ApiModelProperty("市 (数据字典)") + private Integer city; + + @ApiModelProperty("区 (数据字典)") + private Integer district; + + /** + * 类型(数据字典 1.客户 2.供应商) + */ + @NotNull(message = "类型不能为空", groups = {Create.class, Update.class}) + private String companyType; +} diff --git a/src/main/java/com/newyetai/recruit/company/dto/HrCompanyExportDTO.java b/src/main/java/com/newyetai/recruit/company/dto/HrCompanyExportDTO.java new file mode 100644 index 0000000..a77b1dc --- /dev/null +++ b/src/main/java/com/newyetai/recruit/company/dto/HrCompanyExportDTO.java @@ -0,0 +1,54 @@ +package com.newyetai.recruit.company.dto; + +import com.alibaba.excel.annotation.ExcelProperty; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @description: + * @author: guixinman + * @create: 2024-04-11 15:03 + **/ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class HrCompanyExportDTO implements Serializable { + + @ExcelProperty("名称") + @ApiModelProperty("名称") + private String companyName; + + @ExcelProperty("行业") + @ApiModelProperty("行业 (数据字典)") + private String companyIndustry; + + @ExcelProperty("规模") + @ApiModelProperty("规模 (数据字典)") + private String companySize; + + @ExcelProperty("联系人") + @ApiModelProperty("联系人") + private String contactPerson; + + @ExcelProperty("联系方式") + @ApiModelProperty("联系方式") + private String contactWay; + + @ExcelProperty("公司简介") + @ApiModelProperty("公司简介") + private String companyProfile; + + @ExcelProperty("公司描述") + @ApiModelProperty("公司描述") + private String companyDescription; + + @ExcelProperty("创建时间") + private String createTime; +} diff --git a/src/main/java/com/newyetai/recruit/company/dto/HrCompanyPageQueryDTO.java b/src/main/java/com/newyetai/recruit/company/dto/HrCompanyPageQueryDTO.java new file mode 100644 index 0000000..4748098 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/company/dto/HrCompanyPageQueryDTO.java @@ -0,0 +1,113 @@ +package com.newyetai.recruit.company.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.newyetai.common.dto.PageQueryDTO; +import com.newyetai.common.exception.BusinessException; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.format.annotation.DateTimeFormat; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import java.util.Date; +import java.util.List; + +import javax.validation.constraints.NotNull; + +/** + * 人力资源公司dto + * + * @author Carlye + * @date 2021/01/08 + */ +@EqualsAndHashCode(callSuper = true) +@ApiModel("招聘系统客户信息DTO") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class HrCompanyPageQueryDTO extends PageQueryDTO { + private static final long serialVersionUID = -2216352275325005059L; + + private Long id; + + @ApiModelProperty("机构ID") + private Long orgId; + + @ApiModelProperty("统一社会信用代码") + private String creditCode; + + + @ApiModelProperty("企业LOGO FileRecord") + private String companyLogo; + + + @ApiModelProperty("公司名称") + private String companyName; + + @ApiModelProperty("联系人") + private String contactPerson; + + @ApiModelProperty("联系方式") + private String contactWay; + + + @ApiModelProperty("公司简介") + private String companyProfile; + + + @ApiModelProperty("公司描述") + private String companyDescription; + + + @ApiModelProperty("行业 (数据字典)") + private String companyIndustry; + + + @ApiModelProperty("规模 (数据字典)") + private String companySize; + + + @ApiModelProperty("公司注册地址") + private String companyRegisterAddress; + + + @ApiModelProperty("省份 (数据字典)") + private Integer province; + + + @ApiModelProperty("市 (数据字典)") + private Integer city; + + + @ApiModelProperty("区 (数据字典)") + private Integer district; + + /** + * 类型(数据字典 1.客户 2.供应商) + */ + private String companyType; + + + private List companyTypes; + + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + public void check(){ + if (StringUtils.isBlank(companyType) && CollectionUtils.isEmpty(companyTypes)) { + throw new BusinessException("请选择类型"); + } + } +} diff --git a/src/main/java/com/newyetai/recruit/company/entity/HrCompany.java b/src/main/java/com/newyetai/recruit/company/entity/HrCompany.java new file mode 100644 index 0000000..c37b753 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/company/entity/HrCompany.java @@ -0,0 +1,102 @@ +package com.newyetai.recruit.company.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + + + +/** + *

+ * 招聘系统-企业信息表 + *

+ * + * @author chenyun + * @since 2021-01-08 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@TableName(value = "hr_company") +@Builder +public class HrCompany extends BaseEntity { + + private static final long serialVersionUID = -7847448702358215622L; + /** + * 机构ID + */ + private Long orgId; + + /** + * 统一社会信用代码 + */ + private String creditCode; + + /** + * 企业LOGO FileRecord + */ + private String companyLogo; + + /** + * 公司名称 + */ + private String companyName; + + /** + * 联系人(负责人) + */ + private String contactPerson; + + /** + * 联系方式 + */ + private String contactWay; + + /** + * 公司简介 + */ + private String companyProfile; + + /** + * 公司描述 + */ + private String companyDescription; + + /** + * 行业 (数据字典) + */ + private String companyIndustry; + + /** + * 规模 (数据字典) + */ + private String companySize; + + /** + * 公司注册地址 + */ + private String companyRegisterAddress; + + /** + * 省份 (数据字典) + */ + private Integer province; + + /** + * 市 (数据字典) + */ + private Integer city; + + /** + * 区 (数据字典) + */ + private Integer district; + + /** + * 类型(数据字典 1.客户 2.供应商) + */ + private String companyType; +} diff --git a/src/main/java/com/newyetai/recruit/company/enums/HrCompanyEnum.java b/src/main/java/com/newyetai/recruit/company/enums/HrCompanyEnum.java new file mode 100644 index 0000000..c8760ba --- /dev/null +++ b/src/main/java/com/newyetai/recruit/company/enums/HrCompanyEnum.java @@ -0,0 +1,28 @@ +package com.newyetai.recruit.company.enums; + +public enum HrCompanyEnum { + KH("1","客户"), + GYS("2","供应商"), + SELF("3", "机构本身"), + ; + + private String type; + /** + * 类型描述 + */ + private String desc; + + + HrCompanyEnum(String type, String desc) { + this.type = type; + this.desc = desc; + } + + public String getType() { + return type; + } + + public String getDesc() { + return desc; + } +} diff --git a/src/main/java/com/newyetai/recruit/company/mapper/HrCompanyMapper.xml b/src/main/java/com/newyetai/recruit/company/mapper/HrCompanyMapper.xml new file mode 100644 index 0000000..1d389f6 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/company/mapper/HrCompanyMapper.xml @@ -0,0 +1,62 @@ + + + + + (select org_id + from uc_org_relation + where deleted = 0 + and platform_code = 13 + + and FIND_IN_SET(#{parentOrgId}, path) + + + and FIND_IN_SET(#{orgId}, path) + + + ) + + + + + diff --git a/src/main/java/com/newyetai/recruit/company/mapstruct/HrCompanyMapMapper.java b/src/main/java/com/newyetai/recruit/company/mapstruct/HrCompanyMapMapper.java new file mode 100644 index 0000000..635ec4c --- /dev/null +++ b/src/main/java/com/newyetai/recruit/company/mapstruct/HrCompanyMapMapper.java @@ -0,0 +1,23 @@ +package com.newyetai.recruit.company.mapstruct; + + +import com.newyetai.recruit.company.dto.HrCompanyDTO; +import com.newyetai.recruit.company.entity.HrCompany; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * dto-entity + * + * @author sr on 2019-12-17 + */ +@Mapper +public interface HrCompanyMapMapper { + + HrCompanyMapMapper INSTANCE = Mappers.getMapper(HrCompanyMapMapper.class); + + HrCompanyDTO exchange(HrCompany company); + + HrCompany exchange(HrCompanyDTO hrCompanyDTO); +} diff --git a/src/main/java/com/newyetai/recruit/company/service/IHrCompanyService.java b/src/main/java/com/newyetai/recruit/company/service/IHrCompanyService.java new file mode 100644 index 0000000..b5705ca --- /dev/null +++ b/src/main/java/com/newyetai/recruit/company/service/IHrCompanyService.java @@ -0,0 +1,64 @@ +package com.newyetai.recruit.company.service; + + +import com.newyetai.recruit.company.dto.HrCompanyDTO; +import com.newyetai.recruit.company.dto.HrCompanyPageQueryDTO; +import com.newyetai.recruit.company.entity.HrCompany; + +import java.util.List; + +/** + *

+ * 招聘系统-客户信息表 服务类 + *

+ * + * @author chenyun + * @since 2021-01-08 + */ +public interface IHrCompanyService { + + /** + * 创建 + * + * @param hrCompanyDTO 人力资源公司dto + * @return {@link HrCompanyDTO} + * @throws RuntimeException 运行时异常 + */ + void create(HrCompanyDTO hrCompanyDTO); + + /** + * 更新 + * + * @param hrCompanyDTO 人力资源公司dto + * @return {@link HrCompanyDTO} + * @throws RuntimeException 运行时异常 + */ + Integer update(HrCompanyDTO hrCompanyDTO); + + /** + * 细节 + * + * @param hrCompanyDTO 人力资源公司dto + * @return {@link HrCompanyDTO} + */ + HrCompanyDTO detail(HrCompanyDTO hrCompanyDTO); + + /** + * 分页查询 + * + * @param pageQueryDTO 页面查询dto + * @return {@link List< HrCompanyDTO >} + */ + List page(HrCompanyPageQueryDTO pageQueryDTO); + + void export(HrCompanyPageQueryDTO pageQueryDTO); + + /** + * 不分页查询 + */ + List list(HrCompanyPageQueryDTO pageQueryDTO); + + HrCompany findById(Long id); + + HrCompanyDTO find(HrCompanyPageQueryDTO pageQueryDTO); +} diff --git a/src/main/java/com/newyetai/recruit/company/service/impl/HrCompanyServiceImpl.java b/src/main/java/com/newyetai/recruit/company/service/impl/HrCompanyServiceImpl.java new file mode 100644 index 0000000..1b608f5 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/company/service/impl/HrCompanyServiceImpl.java @@ -0,0 +1,226 @@ +package com.newyetai.recruit.company.service.impl; + + +import com.google.common.collect.Lists; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.dto.ExportHeadDetailInfoDTO; +import com.newyetai.common.dto.ExportHeadInfoDTO; +import com.newyetai.common.easyexcel.ExcelUtil; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.recruit.company.dao.HrCompanyMapper; +import com.newyetai.recruit.company.dto.HrCompanyDTO; +import com.newyetai.recruit.company.dto.HrCompanyExportDTO; +import com.newyetai.recruit.company.dto.HrCompanyPageQueryDTO; +import com.newyetai.recruit.company.entity.HrCompany; +import com.newyetai.recruit.company.enums.HrCompanyEnum; +import com.newyetai.recruit.company.mapstruct.HrCompanyMapMapper; +import com.newyetai.recruit.company.service.IHrCompanyService; +import com.newyetai.component.dict.util.DictUtils; + +import cn.hutool.core.date.DateUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 招聘系统-企业信息表 服务实现类 + */ +@Slf4j +@Service +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class HrCompanyServiceImpl implements IHrCompanyService { + + private final HrCompanyMapper hrCompanyMapper; + + @Override + public void create(HrCompanyDTO hrCompanyDTO) { + List HrCompanyList = hrCompanyMapper.selectList(new LambdaQueryWrapper() + .eq(HrCompany::getOrgId, UserContextHolder.getLoginOrgId()) + .eq(HrCompany::getCompanyName, hrCompanyDTO.getCompanyName()) + .eq(HrCompany::getCompanyType, hrCompanyDTO.getCompanyType()) + .eq(HrCompany::getDeleted, false) + ); + if (CollectionUtils.isNotEmpty(HrCompanyList)) { + throw new BusinessException("名称重复"); + } + + HrCompany HrCompany = HrCompanyMapMapper.INSTANCE.exchange(hrCompanyDTO); + HrCompany.setOrgId(UserContextHolder.getLoginOrgId()); + hrCompanyMapper.saveEntity(HrCompany, UserContextHolder.getLoginUserId()); + } + + @Override + public Integer update(HrCompanyDTO hrCompanyDTO) { + HrCompany hrCompany = hrCompanyMapper.selectOne(new LambdaQueryWrapper() + .eq(HrCompany::getId, hrCompanyDTO.getId()) + .eq(HrCompany::getDeleted, false)); + Assert.notNull(hrCompany, "未查询到要修改的数据"); + + if (!CommonConstants.PLATFORM_ORG_ID.equals(UserContextHolder.getExistLoginOrgId())) { + Assert.isTrue(hrCompany.getOrgId().equals(UserContextHolder.getExistLoginOrgId()), "未查询到要修改的数据"); + } + + List HrCompanyList = hrCompanyMapper.selectList(new LambdaQueryWrapper() + .eq(HrCompany::getOrgId, hrCompany.getOrgId()) + .eq(HrCompany::getCompanyName, hrCompanyDTO.getCompanyName()) + .eq(HrCompany::getCompanyType, hrCompanyDTO.getCompanyType()) + .notIn(HrCompany::getId, hrCompanyDTO.getId()) + .eq(HrCompany::getDeleted, false) + ); + if (CollectionUtils.isNotEmpty(HrCompanyList)) { + throw new BusinessException("名称重复"); + } + + HrCompany HrCompany = HrCompanyMapMapper.INSTANCE.exchange(hrCompanyDTO); + HrCompany.setOrgId(hrCompany.getOrgId()); + return hrCompanyMapper.updateEntity(HrCompany, UserContextHolder.getLoginUserId()); + } + + @Override + public HrCompanyDTO detail(HrCompanyDTO hrCompanyDTO) { + return HrCompanyMapMapper.INSTANCE.exchange(hrCompanyMapper.getById(hrCompanyDTO.getId())); + } + + @Override + public List page(HrCompanyPageQueryDTO pageQueryDTO) { + if (pageQueryDTO.getOrgId() == null) { + if (!CommonConstants.PLATFORM_ORG_ID.equals(UserContextHolder.getExistLoginOrgId())) { + pageQueryDTO.setOrgId(UserContextHolder.getLoginOrgId()); + } + } + return hrCompanyMapper.page(pageQueryDTO); + } + + @Override + public void export(HrCompanyPageQueryDTO pageQueryDTO) { + boolean flag = true; + Integer pageNo = 1; + Integer pageSize = 100; + + List listAll = new ArrayList<>(); + + while (flag) { + pageQueryDTO.setPageNo(pageNo); + pageQueryDTO.setPageSize(pageSize); + List list = this.page(pageQueryDTO); + if (org.springframework.util.CollectionUtils.isEmpty(list)) { + flag = false; + continue; + } + if (list.size() < pageSize) { + flag = false; + } + pageNo = pageNo + 1; + listAll.addAll(list); + } + List collect = listAll.stream().map(dto -> { + HrCompanyExportDTO companyExportDTO = new HrCompanyExportDTO(); + BeanUtils.copyProperties(dto, companyExportDTO); + companyExportDTO.setCreateTime(DateUtil.format(dto.getCreateTime(), "yyyy-MM-dd HH:mm:ss")); + companyExportDTO.setCompanyIndustry(DictUtils.getCodeNameMap("industry_type").get(dto.getCompanyIndustry())); + companyExportDTO.setCompanySize(DictUtils.getCodeNameMap("company_size").get(dto.getCompanySize())); + return companyExportDTO; + }).collect(Collectors.toList()); + + if (org.springframework.util.CollectionUtils.isEmpty(collect)) { + return; + } + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); + String fileName; + + if (pageQueryDTO.getCompanyType().equals(HrCompanyEnum.KH.getType())) { + fileName = HrCompanyEnum.KH.getDesc() + "明细导出" + "(" + formatter.format(LocalDateTime.now()) + ")"; + } else { + fileName = HrCompanyEnum.GYS.getDesc() + "明细导出" + "(" + formatter.format(LocalDateTime.now()) + ")"; + } + + + ExportHeadInfoDTO infoDTO = ExportHeadInfoDTO.builder() + .fileName(fileName) + .build(); + List heads = infoDTO.getHeads(); + List datas = Lists.newArrayList(); + + if (pageQueryDTO.getCompanyType().equals(HrCompanyEnum.KH.getType())) { + heads.add(ExportHeadDetailInfoDTO.builder().head("客户名称").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("所属行业").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("企业规模").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("联系人").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("联系方式").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("创建时间").build()); + for (HrCompanyExportDTO dto : collect) { + List objects = Lists.newArrayList(); + datas.add(objects); + objects.add(dto.getCompanyName()); + objects.add(dto.getCompanyIndustry()); + objects.add(dto.getCompanySize()); + objects.add(dto.getContactPerson()); + objects.add(dto.getContactWay()); + objects.add(dto.getCreateTime()); + } + } else { + heads.add(ExportHeadDetailInfoDTO.builder().head("供应商名称").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("企业规模").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("联系人").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("联系方式").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("创建时间").build()); + for (HrCompanyExportDTO dto : collect) { + List objects = Lists.newArrayList(); + datas.add(objects); + objects.add(dto.getCompanyName()); + objects.add(dto.getCompanySize()); + objects.add(dto.getContactPerson()); + objects.add(dto.getContactWay()); + objects.add(dto.getCreateTime()); + } + } + + infoDTO.setDatas(datas); + + ExcelUtil.dynamicExportTemplate(infoDTO); + } + + @Override + public List list(HrCompanyPageQueryDTO pageQueryDTO) { + pageQueryDTO.disablePage(); + return this.page(pageQueryDTO); + } + + @Override + public HrCompany findById(Long id) { + Assert.notNull(id, "id不能为空"); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper() + .eq(HrCompany::getId, id) + .eq(HrCompany::getDeleted, false); + if (!CommonConstants.PLATFORM_ORG_ID.equals(UserContextHolder.getExistLoginOrgId())) { + queryWrapper.eq(HrCompany::getOrgId, UserContextHolder.getLoginOrgId()); + } + HrCompany hrCompany = hrCompanyMapper.selectOne(queryWrapper); + return hrCompany; + } + + @Override + public HrCompanyDTO find(HrCompanyPageQueryDTO pageQueryDTO) { + pageQueryDTO.disablePage(); + List hrCompanyDTOS = this.page(pageQueryDTO); + if (CollectionUtils.isEmpty(hrCompanyDTOS)) { + return null; + } + return hrCompanyDTOS.get(0); + } +} diff --git a/src/main/java/com/newyetai/recruit/device/controller/DeviceController.java b/src/main/java/com/newyetai/recruit/device/controller/DeviceController.java new file mode 100644 index 0000000..e844cff --- /dev/null +++ b/src/main/java/com/newyetai/recruit/device/controller/DeviceController.java @@ -0,0 +1,67 @@ +package com.newyetai.recruit.device.controller; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +import com.newyetai.common.AlitaResult; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.recruit.device.dto.*; +import com.newyetai.recruit.device.service.DeviceService; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; + +/** + * 设备 + * + * @author guixinman + * @since 1.0.0 2025-01-14 + */ +@Api(tags = "设备") +@RestController +@RequestMapping("/device/") +public class DeviceController { + + @Autowired + private DeviceService deviceService; + + @PostMapping("create") + @ApiOperation("设备-创建") + public AlitaResult create(@RequestBody @Validated DeviceOperatorDTO operatorDTO) { + return AlitaResult.success(deviceService.create(operatorDTO)); + } + + @PutMapping("modify") + @ApiOperation("设备-修改") + public AlitaResult modify(@RequestBody DeviceOperatorDTO operatorDTO) { + return AlitaResult.success(deviceService.modify(operatorDTO)); + } + + @DeleteMapping("{id}") + @ApiOperation("设备-删除") + public AlitaResult delete(@PathVariable("id") Long id) { + return AlitaResult.success(deviceService.delete(id)); + } + + @GetMapping("{id}") + @ApiOperation("设备-查询单个") + public AlitaResult findById(@PathVariable("id") Long id) { + return AlitaResult.success(deviceService.findById(id)); + } + + @GetMapping("list") + @ApiOperation("设备-列表查询") + public AlitaResult> list(DeviceQueryDTO queryDTO) { + return AlitaResult.success(deviceService.list(queryDTO)); + } + + @GetMapping("page") + @ApiOperation("设备-分页查询") + public AlitaResult> page(DevicePageQueryDTO queryDTO) { + deviceService.page(queryDTO); + return AlitaResult.success(queryDTO.getPageResult()); + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/device/convert/DeviceConvert.java b/src/main/java/com/newyetai/recruit/device/convert/DeviceConvert.java new file mode 100644 index 0000000..ca55646 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/device/convert/DeviceConvert.java @@ -0,0 +1,28 @@ +package com.newyetai.recruit.device.convert; + +import com.newyetai.recruit.device.entity.Device; +import com.newyetai.recruit.device.dto.DeviceDTO; +import com.newyetai.recruit.device.dto.DeviceOperatorDTO; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 设备 + * + * @author guixinman + * @since 1.0.0 2025-01-14 + */ +@Mapper +public interface DeviceConvert { + DeviceConvert INSTANCE = Mappers.getMapper(DeviceConvert.class); + + Device convert(DeviceDTO dto); + + DeviceDTO convert(Device entity); + + Device convert(DeviceOperatorDTO dto); + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/device/dao/DeviceMapper.java b/src/main/java/com/newyetai/recruit/device/dao/DeviceMapper.java new file mode 100644 index 0000000..50294ae --- /dev/null +++ b/src/main/java/com/newyetai/recruit/device/dao/DeviceMapper.java @@ -0,0 +1,26 @@ +package com.newyetai.recruit.device.dao; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.recruit.device.entity.Device; +import com.newyetai.recruit.device.dto.DeviceDTO; +import com.newyetai.recruit.device.dto.DeviceQueryDTO; +import com.newyetai.recruit.device.dto.DevicePageQueryDTO; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 设备 + * + * @author guixinman + * @since 1.0.0 2025-01-14 + */ +@Mapper +public interface DeviceMapper extends MyMapper { + + List page(@Param("param") DevicePageQueryDTO queryDTO); + + List list(@Param("param") DeviceQueryDTO queryDTO); +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/device/dto/DeviceDTO.java b/src/main/java/com/newyetai/recruit/device/dto/DeviceDTO.java new file mode 100644 index 0000000..7a92305 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/device/dto/DeviceDTO.java @@ -0,0 +1,38 @@ +package com.newyetai.recruit.device.dto; + +import com.newyetai.common.dto.BaseDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.SuperBuilder; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * 设备 + * + * @author guixinman + * @since 1.0.0 2025-01-14 + */ +@ApiModel("设备") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class DeviceDTO extends BaseDTO { + private static final long serialVersionUID = 1L; + + @ApiModelProperty("编号") + private String code; + + @ApiModelProperty("名称") + private String name; + + @ApiModelProperty("场所地址") + private String address; + + private String geocoderJson; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/device/dto/DeviceOperatorDTO.java b/src/main/java/com/newyetai/recruit/device/dto/DeviceOperatorDTO.java new file mode 100644 index 0000000..e33e276 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/device/dto/DeviceOperatorDTO.java @@ -0,0 +1,59 @@ +package com.newyetai.recruit.device.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * 设备 + * + * @author guixinman + * @since 1.0.0 2025-01-14 + */ +@ApiModel("设备") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class DeviceOperatorDTO implements Serializable { + private static final long serialVersionUID = 1L; + + private Long id; + + @Length(max = 128,message = "编号长度超长") + @NotBlank(message = "请输入编号") + @ApiModelProperty("编号") + private String code; + + @Length(max = 64,message = "名称长度超长") + @NotBlank(message = "请输入名称") + @ApiModelProperty("名称") + private String name; + + @Length(max = 255,message = "场所地址长度超长") + @NotBlank(message = "请输入场所地址") + @ApiModelProperty("场所地址") + private String address; + + private String geocoderJson; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/device/dto/DevicePageQueryDTO.java b/src/main/java/com/newyetai/recruit/device/dto/DevicePageQueryDTO.java new file mode 100644 index 0000000..12dc8be --- /dev/null +++ b/src/main/java/com/newyetai/recruit/device/dto/DevicePageQueryDTO.java @@ -0,0 +1,75 @@ +package com.newyetai.recruit.device.dto; + +import com.newyetai.common.dto.PageQueryDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import java.io.Serializable; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.format.annotation.DateTimeFormat; + + +import java.math.BigDecimal; +import java.util.Date; + +/** + * 设备 + * + * @author guixinman + * @since 1.0.0 2025-01-14 + */ + +@ApiModel("设备") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class DevicePageQueryDTO extends PageQueryDTO { + private static final long serialVersionUID = 1L; + + private Long id; + + private Long notId; + + @ApiModelProperty("编号") + private String code; + + @ApiModelProperty("名称 (模糊匹配)") + private String nameLike; + + private String name; + + @ApiModelProperty("场所地址") + private String address; + + private String addressLike; + + private String geocoderJson; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("更新时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeStart; + + @ApiModelProperty("更新时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeEnd; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/device/dto/DeviceQueryDTO.java b/src/main/java/com/newyetai/recruit/device/dto/DeviceQueryDTO.java new file mode 100644 index 0000000..84df80f --- /dev/null +++ b/src/main/java/com/newyetai/recruit/device/dto/DeviceQueryDTO.java @@ -0,0 +1,76 @@ +package com.newyetai.recruit.device.dto; + +import com.newyetai.common.dto.BaseDTO; + +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; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.format.annotation.DateTimeFormat; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * 设备 + * + * @author guixinman + * @since 1.0.0 2025-01-14 + */ +@ApiModel("设备") +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class DeviceQueryDTO implements Serializable { + private static final long serialVersionUID = 1L; + + private Long id; + + private Long notId; + + @ApiModelProperty("编号") + private String code; + + @ApiModelProperty("名称") + private String name; + + @ApiModelProperty("名称 (模糊匹配)") + private String nameLike; + + @ApiModelProperty("场所地址") + private String address; + + private String addressLike; + + private String geocoderJson; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("更新时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeStart; + + @ApiModelProperty("更新时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeEnd; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/device/entity/Device.java b/src/main/java/com/newyetai/recruit/device/entity/Device.java new file mode 100644 index 0000000..a13c0e5 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/device/entity/Device.java @@ -0,0 +1,37 @@ +package com.newyetai.recruit.device.entity; + +import lombok.*; +import com.baomidou.mybatisplus.annotation.*; +import java.math.BigDecimal; +import com.newyetai.common.entity.BaseEntity; + +/** + * 设备 + * + * @author guixinman + * @since 1.0.0 2025-01-14 + */ +@TableName(value = "hr_device") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class Device extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + private String code; + /** + * 名称 + */ + private String name; + /** + * 场所地址 + */ + private String address; + private String geocoderJson; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/device/mapper/DeviceMapper.xml b/src/main/java/com/newyetai/recruit/device/mapper/DeviceMapper.xml new file mode 100644 index 0000000..b885171 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/device/mapper/DeviceMapper.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + FROM + hr_device t + WHERE t.deleted = 0 + + AND t.id = #{param.id} + + + AND t.id ]]> #{param.notId} + + + AND t.code = #{param.code} + + + AND t.name = #{param.name} + + + + AND t.name like #{nameLike} + + + AND t.address = #{param.address} + + + + AND t.address like #{addressLike} + + + AND t.create_time >= #{param.createTimeStart} + + + AND t.create_time <= #{param.createTimeEnd} + + + AND t.update_time >= #{param.updateTimeStart} + + + AND t.update_time <= #{param.updateTimeEnd} + + ORDER BY t.id DESC + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/device/service/DeviceService.java b/src/main/java/com/newyetai/recruit/device/service/DeviceService.java new file mode 100644 index 0000000..4fb3964 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/device/service/DeviceService.java @@ -0,0 +1,68 @@ +package com.newyetai.recruit.device.service; + +import org.springframework.validation.annotation.Validated; + +import javax.validation.Valid; +import javax.validation.groups.Default; + +import java.util.List; + +import com.newyetai.recruit.device.dto.*; + +/** + * 设备 + * + * @author guixinman + * @since 1.0.0 2025-01-14 + */ +@Validated(Default.class) +public interface DeviceService { + + /** + * 设备 - 创建 + * + * @param operatorDto 操作dto + * @return {@link DeviceDTO} + */ + DeviceDTO create(@Valid DeviceOperatorDTO operatorDto); + + /** + * 设备 - 修改 + * + * @param operatorDto 操作dto + * @return {@link DeviceDTO} + */ + DeviceDTO modify(@Valid DeviceOperatorDTO operatorDto); + + /** + * 设备 - 删除 + * + * @param id id + * @return {@link DeviceDTO} + */ + DeviceDTO delete(Long id); + + /** + * 设备 - 根据ID查询单个 + * + * @param id id + * @return {@link DeviceDTO} + */ + DeviceDTO findById(Long id); + + /** + * 设备 - 列表查询 + * + * @param queryDTO 列表查询dto + * @return {@link List}<{@link DeviceDTO}> + */ + List list(DeviceQueryDTO queryDTO); + + /** + * 设备 - 分页查询 + * + * @param queryDTO 分页查询dto + * @return {@link DeviceDTO} + */ + List page(DevicePageQueryDTO queryDTO); +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/device/service/impl/DeviceServiceImpl.java b/src/main/java/com/newyetai/recruit/device/service/impl/DeviceServiceImpl.java new file mode 100644 index 0000000..8ff18aa --- /dev/null +++ b/src/main/java/com/newyetai/recruit/device/service/impl/DeviceServiceImpl.java @@ -0,0 +1,154 @@ +package com.newyetai.recruit.device.service.impl; + +import lombok.extern.slf4j.Slf4j; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.recruit.device.convert.DeviceConvert; +import com.newyetai.recruit.device.entity.Device; +import com.newyetai.recruit.device.dto.*; +import com.newyetai.recruit.device.dao.DeviceMapper; +import com.newyetai.recruit.device.service.DeviceService; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.sdk.tencent.map.TencentMapContext; +import com.newyetai.sdk.tencent.map.dto.TencentMapGeocoderReqDTO; +import com.newyetai.sdk.tencent.map.dto.TencentMapGeocoderResDTO; +import com.newyetai.sdk.tencent.map.dto.TencentMapLocationV1IpResDTO; + +import javax.annotation.Resource; + +import java.util.*; + +/** + * 设备 + * + * @author guixinman + * @since 1.0.0 2025-01-14 + */ +@Slf4j +@Service +public class DeviceServiceImpl implements DeviceService { + + @Resource + private DeviceMapper deviceMapper; + + @Autowired + private TencentMapContext tencentMapContext; + + + @Override + public DeviceDTO create(DeviceOperatorDTO operatorDto) { + List deviceDTOList = this.list(DeviceQueryDTO.builder().code(operatorDto.getCode()).name(operatorDto.getName()).build()); + if (CollectionUtils.isNotEmpty(deviceDTOList)) { + throw new BusinessException("该设备编码已存在"); + } + + AlitaResult alitaResult = tencentMapContext.webServiceGeocoder(TencentMapGeocoderReqDTO.builder() + .address(operatorDto.getAddress()) + .build()); + + if (Boolean.TRUE.equals(alitaResult.getSuccess())) { + TencentMapGeocoderResDTO resultData = alitaResult.getData(); + + TencentMapGeocoderResDTO.TencentMapGeocoderLocationResDTO location = resultData.getLocation(); + TencentMapGeocoderResDTO.TencentMapGeocoderAddressComponentsDTO address_components = resultData.getAddress_components(); + TencentMapGeocoderResDTO.TencentMapGeocoderAdInfo ad_info = resultData.getAd_info(); + + if (Objects.nonNull(location)) { + TencentMapLocationV1IpResDTO tencentMapLocationV1IpResDTO = new TencentMapLocationV1IpResDTO(); + tencentMapLocationV1IpResDTO.setLocation(TencentMapLocationV1IpResDTO.TencentMapLocationDTO.builder().lat(location.getLat()).lng(location.getLng()).build()); + tencentMapLocationV1IpResDTO.setAd_info(TencentMapLocationV1IpResDTO.TencentMapLocationAdInfoDTO.builder() + .province(address_components.getProvince()) + .city(address_components.getCity()) + .district(address_components.getDistrict()) + .adcode(ad_info.getAdcode()) + .build()); + operatorDto.setGeocoderJson(JsonUtils.toJsonString(tencentMapLocationV1IpResDTO)); + } + } + Device device = DeviceConvert.INSTANCE.convert(operatorDto); + deviceMapper.saveEntity(device); + return DeviceConvert.INSTANCE.convert(device); + } + + @Override + public DeviceDTO modify(DeviceOperatorDTO operatorDto) { + List deviceDTOList = this.list(DeviceQueryDTO.builder().notId(operatorDto.getId()).name(operatorDto.getName()).build()); + if (CollectionUtils.isNotEmpty(deviceDTOList)) { + throw new BusinessException("该设备编码已存在"); + } + + DeviceDTO deviceDto = this.findById(operatorDto.getId()); + if (Objects.isNull(deviceDto)) { + return null; + } + if (!StringUtils.equals(operatorDto.getAddress(), deviceDto.getAddress())) { + AlitaResult alitaResult = tencentMapContext.webServiceGeocoder(TencentMapGeocoderReqDTO.builder() + .address(operatorDto.getAddress()) + .build()); + + if (Boolean.TRUE.equals(alitaResult.getSuccess())) { + TencentMapGeocoderResDTO resultData = alitaResult.getData(); + + TencentMapGeocoderResDTO.TencentMapGeocoderLocationResDTO location = resultData.getLocation(); + TencentMapGeocoderResDTO.TencentMapGeocoderAddressComponentsDTO address_components = resultData.getAddress_components(); + TencentMapGeocoderResDTO.TencentMapGeocoderAdInfo ad_info = resultData.getAd_info(); + + if (Objects.nonNull(location)) { + TencentMapLocationV1IpResDTO tencentMapLocationV1IpResDTO = new TencentMapLocationV1IpResDTO(); + tencentMapLocationV1IpResDTO.setLocation(TencentMapLocationV1IpResDTO.TencentMapLocationDTO.builder().lat(location.getLat()).lng(location.getLng()).build()); + tencentMapLocationV1IpResDTO.setAd_info(TencentMapLocationV1IpResDTO.TencentMapLocationAdInfoDTO.builder() + .province(address_components.getProvince()) + .city(address_components.getCity()) + .district(address_components.getDistrict()) + .adcode(ad_info.getAdcode()) + .build()); + operatorDto.setGeocoderJson(JsonUtils.toJsonString(tencentMapLocationV1IpResDTO)); + } + } + } + + Device device = DeviceConvert.INSTANCE.convert(operatorDto); + device.setCode(null); + deviceMapper.updateEntitySelective(device); + return this.findById(operatorDto.getId()); + } + + @Override + public DeviceDTO delete(Long id) { + DeviceDTO deviceDto = this.findById(id); + if (Objects.isNull(deviceDto)) { + return null; + } + Device device = Device.builder().build(); + device.setId(id); + deviceMapper.deleteEntity(device, UserContextHolder.getLoginUserId()); + return deviceDto; + } + + @Override + public DeviceDTO findById(Long id) { + Device device = deviceMapper.getById(id); + if (Objects.isNull(device)) { + return null; + } + return DeviceConvert.INSTANCE.convert(device); + } + + @Override + public List list(DeviceQueryDTO queryDTO) { + return deviceMapper.list(queryDTO); + } + + @Override + public List page(DevicePageQueryDTO queryDTO) { + return deviceMapper.page(queryDTO); + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/eventtrack/controller/EventTrackController.java b/src/main/java/com/newyetai/recruit/eventtrack/controller/EventTrackController.java new file mode 100644 index 0000000..c16f3e1 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/eventtrack/controller/EventTrackController.java @@ -0,0 +1,71 @@ +package com.newyetai.recruit.eventtrack.controller; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +import com.newyetai.common.AlitaResult; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.recruit.eventtrack.dto.*; +import com.newyetai.recruit.eventtrack.service.EventTrackService; + +import org.springframework.web.bind.annotation.*; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; + +/** + * 埋点 + * + * @author guixinman + * @since 1.0.0 2025-01-22 + */ +@Api(tags = " 埋点") +@RestController +@RequestMapping("/event_track") +public class EventTrackController { + + @Autowired + private EventTrackService eventTrackService; + + @PostMapping("/create") + @ApiOperation(" 埋点-创建") + public AlitaResult create(@RequestBody EventTrackOperatorDTO operatorDTO) { + return AlitaResult.success(eventTrackService.create(operatorDTO)); + } + + @PutMapping("/modify") + @ApiOperation(" 埋点-修改") + public AlitaResult modify(@RequestBody EventTrackOperatorDTO operatorDTO) { + return AlitaResult.success(eventTrackService.modify(operatorDTO)); + } + + @DeleteMapping("{id}") + @ApiOperation(" 埋点-删除") + public AlitaResult delete(@PathVariable("id") Long id) { + return AlitaResult.success(eventTrackService.delete(id)); + } + + @GetMapping("{id}") + @ApiOperation(" 埋点-查询单个") + public AlitaResult findById(@PathVariable("id") Long id) { + return AlitaResult.success(eventTrackService.findById(id)); + } + + @GetMapping("list") + @ApiOperation(" 埋点-列表查询") + public AlitaResult> list(EventTrackQueryDTO queryDTO) { + return AlitaResult.success(eventTrackService.list(queryDTO)); + } + + @GetMapping("page") + @ApiOperation(" 埋点-分页查询") + public AlitaResult> page(EventTrackPageQueryDTO queryDTO) { + eventTrackService.page(queryDTO); + return AlitaResult.success(queryDTO.getPageResult()); + } + + @GetMapping("statistics") + public AlitaResult> statistics(EventTrackStatisticsQueryDTO queryDTO) { + return AlitaResult.success(eventTrackService.statistics(queryDTO)); + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/eventtrack/convert/EventTrackConvert.java b/src/main/java/com/newyetai/recruit/eventtrack/convert/EventTrackConvert.java new file mode 100644 index 0000000..bc137c4 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/eventtrack/convert/EventTrackConvert.java @@ -0,0 +1,28 @@ +package com.newyetai.recruit.eventtrack.convert; + +import com.newyetai.recruit.eventtrack.entity.EventTrack; +import com.newyetai.recruit.eventtrack.dto.EventTrackDTO; +import com.newyetai.recruit.eventtrack.dto.EventTrackOperatorDTO; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 埋点 + * + * @author guixinman + * @since 1.0.0 2025-01-22 + */ +@Mapper +public interface EventTrackConvert { + EventTrackConvert INSTANCE = Mappers.getMapper(EventTrackConvert.class); + + EventTrack convert(EventTrackDTO dto); + + EventTrackDTO convert(EventTrack entity); + + EventTrack convert(EventTrackOperatorDTO dto); + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/eventtrack/dao/EventTrackMapper.java b/src/main/java/com/newyetai/recruit/eventtrack/dao/EventTrackMapper.java new file mode 100644 index 0000000..3907092 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/eventtrack/dao/EventTrackMapper.java @@ -0,0 +1,30 @@ +package com.newyetai.recruit.eventtrack.dao; + +import com.newyetai.recruit.eventtrack.dto.EventTrackStatisticsQueryDTO; +import com.newyetai.recruit.eventtrack.dto.EventTrackStatisticsResDTO; +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.recruit.eventtrack.entity.EventTrack; +import com.newyetai.recruit.eventtrack.dto.EventTrackDTO; +import com.newyetai.recruit.eventtrack.dto.EventTrackQueryDTO; +import com.newyetai.recruit.eventtrack.dto.EventTrackPageQueryDTO; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 埋点 + * + * @author guixinman + * @since 1.0.0 2025-01-22 + */ +@Mapper +public interface EventTrackMapper extends MyMapper { + + List page(@Param("param") EventTrackPageQueryDTO queryDTO); + + List list(@Param("param") EventTrackQueryDTO queryDTO); + + List statistics(@Param("param") EventTrackStatisticsQueryDTO queryDTO); +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/eventtrack/dto/EventTrackDTO.java b/src/main/java/com/newyetai/recruit/eventtrack/dto/EventTrackDTO.java new file mode 100644 index 0000000..6c1ae63 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/eventtrack/dto/EventTrackDTO.java @@ -0,0 +1,37 @@ +package com.newyetai.recruit.eventtrack.dto; + +import com.newyetai.common.dto.BaseDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.SuperBuilder; + +import java.util.Date; + +/** + * 埋点 + * + * @author guixinman + * @since 1.0.0 2025-01-22 + */ +@ApiModel(" 埋点") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class EventTrackDTO extends BaseDTO { + private static final long serialVersionUID = 1L; + + @ApiModelProperty("设备编号") + private String deviceCode; + + @ApiModelProperty("用户id") + private Long userId; + + @ApiModelProperty("类型") + private String type; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/eventtrack/dto/EventTrackMachineReqDTO.java b/src/main/java/com/newyetai/recruit/eventtrack/dto/EventTrackMachineReqDTO.java new file mode 100644 index 0000000..fc7e346 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/eventtrack/dto/EventTrackMachineReqDTO.java @@ -0,0 +1,36 @@ +package com.newyetai.recruit.eventtrack.dto; + +import java.io.Serializable; + +import lombok.Data; + +/** + * @description: + * @author: guixinman + * @create: 2025-01-23 16:43 + **/ +@Data +public class EventTrackMachineReqDTO implements Serializable { + /** + * 机器编号 + */ + private String deviceCode; + + /** + * + */ + private String name; + + private String address; + + /** + * 日期 + */ + private String createDate; + + /** + * 当日使用人数 + */ + private Long userNumber; + +} diff --git a/src/main/java/com/newyetai/recruit/eventtrack/dto/EventTrackOperatorDTO.java b/src/main/java/com/newyetai/recruit/eventtrack/dto/EventTrackOperatorDTO.java new file mode 100644 index 0000000..9163b7c --- /dev/null +++ b/src/main/java/com/newyetai/recruit/eventtrack/dto/EventTrackOperatorDTO.java @@ -0,0 +1,48 @@ +package com.newyetai.recruit.eventtrack.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.format.annotation.DateTimeFormat; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +import java.util.Date; + +/** + * 埋点 + * + * @author guixinman + * @since 1.0.0 2025-01-22 + */ +@ApiModel(" 埋点") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class EventTrackOperatorDTO implements Serializable { + private static final long serialVersionUID = 1L; + + private Long id; + + @ApiModelProperty("设备编号") + private String deviceCode; + + @ApiModelProperty("用户id") + private Long userId; + + @ApiModelProperty("类型") + private String type; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/eventtrack/dto/EventTrackPageQueryDTO.java b/src/main/java/com/newyetai/recruit/eventtrack/dto/EventTrackPageQueryDTO.java new file mode 100644 index 0000000..860d950 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/eventtrack/dto/EventTrackPageQueryDTO.java @@ -0,0 +1,66 @@ +package com.newyetai.recruit.eventtrack.dto; + +import com.newyetai.common.dto.PageQueryDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import java.io.Serializable; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.format.annotation.DateTimeFormat; + + +import java.util.Date; + +/** + * 埋点 + * + * @author guixinman + * @since 1.0.0 2025-01-22 + */ + +@ApiModel(" 埋点") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class EventTrackPageQueryDTO extends PageQueryDTO { + private static final long serialVersionUID = 1L; + + private Long id; + + @ApiModelProperty("设备编号") + private String deviceCode; + + @ApiModelProperty("用户id") + private Long userId; + + @ApiModelProperty("类型") + private String type; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("更新时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeStart; + + @ApiModelProperty("更新时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeEnd; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/eventtrack/dto/EventTrackQueryDTO.java b/src/main/java/com/newyetai/recruit/eventtrack/dto/EventTrackQueryDTO.java new file mode 100644 index 0000000..0dd606f --- /dev/null +++ b/src/main/java/com/newyetai/recruit/eventtrack/dto/EventTrackQueryDTO.java @@ -0,0 +1,66 @@ +package com.newyetai.recruit.eventtrack.dto; + +import com.newyetai.common.dto.BaseDTO; + +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; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +/** + * 埋点 + * + * @author guixinman + * @since 1.0.0 2025-01-22 + */ +@ApiModel(" 埋点") +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class EventTrackQueryDTO implements Serializable { + private static final long serialVersionUID = 1L; + + private Long id; + + @ApiModelProperty("设备编号") + private String deviceCode; + + @ApiModelProperty("用户id") + private Long userId; + + @ApiModelProperty("类型") + private String type; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("更新时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeStart; + + @ApiModelProperty("更新时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeEnd; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/eventtrack/dto/EventTrackStatisticsQueryDTO.java b/src/main/java/com/newyetai/recruit/eventtrack/dto/EventTrackStatisticsQueryDTO.java new file mode 100644 index 0000000..8ac8739 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/eventtrack/dto/EventTrackStatisticsQueryDTO.java @@ -0,0 +1,25 @@ +package com.newyetai.recruit.eventtrack.dto; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @description: + * @author: guixinman + * @create: 2025-01-23 16:04 + **/ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class EventTrackStatisticsQueryDTO implements Serializable { + + private String createTimeStart; + + private String createTimeEnd; +} diff --git a/src/main/java/com/newyetai/recruit/eventtrack/dto/EventTrackStatisticsResDTO.java b/src/main/java/com/newyetai/recruit/eventtrack/dto/EventTrackStatisticsResDTO.java new file mode 100644 index 0000000..80669ad --- /dev/null +++ b/src/main/java/com/newyetai/recruit/eventtrack/dto/EventTrackStatisticsResDTO.java @@ -0,0 +1,21 @@ +package com.newyetai.recruit.eventtrack.dto; + +import java.io.Serializable; + +import lombok.Data; + +/** + * @description: 埋点分组DTO + * @author: guixinman + * @create: 2025-01-23 15:59 + **/ +@Data +public class EventTrackStatisticsResDTO implements Serializable { + private String deviceCode; + private Long userId; + private String type; + private String name; + private String address; + private String createDate; + private Long userNumber; +} diff --git a/src/main/java/com/newyetai/recruit/eventtrack/entity/EventTrack.java b/src/main/java/com/newyetai/recruit/eventtrack/entity/EventTrack.java new file mode 100644 index 0000000..d0a601e --- /dev/null +++ b/src/main/java/com/newyetai/recruit/eventtrack/entity/EventTrack.java @@ -0,0 +1,39 @@ +package com.newyetai.recruit.eventtrack.entity; + +import lombok.*; + +import com.baomidou.mybatisplus.annotation.*; + +import java.util.Date; + +import com.newyetai.common.entity.BaseEntity; + +/** + * 埋点 + * + * @author guixinman + * @since 1.0.0 2025-01-22 + */ +@TableName(value = "hr_event_track") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class EventTrack extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * 设备编号 + */ + private String deviceCode; + /** + * 用户id + */ + private Long userId; + /** + * 类型 + */ + private String type; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/eventtrack/job/EventTrackJob.java b/src/main/java/com/newyetai/recruit/eventtrack/job/EventTrackJob.java new file mode 100644 index 0000000..e63b1ef --- /dev/null +++ b/src/main/java/com/newyetai/recruit/eventtrack/job/EventTrackJob.java @@ -0,0 +1,89 @@ +package com.newyetai.recruit.eventtrack.job; + +import com.newyetai.common.util.JsonUtils; +import com.newyetai.recruit.eventtrack.dto.EventTrackMachineReqDTO; +import com.newyetai.recruit.eventtrack.dto.EventTrackStatisticsQueryDTO; +import com.newyetai.recruit.eventtrack.dto.EventTrackStatisticsResDTO; +import com.newyetai.recruit.eventtrack.service.EventTrackService; +import com.newyetai.sdk.common.dto.DefaultSdkInvokeLogDTO; +import com.newyetai.sdk.common.util.HttpUtils; +import com.newyetai.sdk.tencent.map.dto.TencentMapBaseResDTO; +import com.newyetai.sdk.tencent.map.dto.TencentWsDistanceV1MatrixResDTO; +import com.newyetai.security.util.MockUtils; + +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +import java.util.ArrayList; +import java.util.List; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.http.HttpRequest; +import lombok.extern.slf4j.Slf4j; + +/** + * @description: 埋点job + * @author: guixinman + * @create: 2025-01-23 14:54 + **/ +@Slf4j +@Component +public class EventTrackJob { + + @Autowired + private RestTemplate restTemplate; + + @Autowired + private EventTrackService eventTrackService; + + @Scheduled(cron = "0 0/30 * * * *") + public void statistics() { + String createTimeStart = DateUtil.format(DateUtil.beginOfDay(DateUtil.yesterday()), "yyyy-MM-dd HH:mm:ss"); + String createTimeEnd = DateUtil.format(DateUtil.endOfDay(DateUtil.yesterday()), "yyyy-MM-dd HH:mm:ss"); + + log.info("埋点数据推送宝就业后台 ======开始"); + MockUtils.mockPlatUser(); + try { + List statistics = eventTrackService.statistics(EventTrackStatisticsQueryDTO.builder().createTimeStart(createTimeStart).createTimeEnd(createTimeEnd).build()); + List machineReqDTOList = new ArrayList(); + for (EventTrackStatisticsResDTO statistic : statistics) { + EventTrackMachineReqDTO machineReqDTO = new EventTrackMachineReqDTO(); + BeanUtils.copyProperties(statistic,machineReqDTO); + machineReqDTOList.add(machineReqDTO); + } + String result = null; + if (CollectionUtils.isNotEmpty(machineReqDTOList)) { + try { + result = HttpRequest.post("https://baoanhr-1gj59gl3122cad49-1331397164.ap-shanghai.app.tcloudbase.com/v1/api/machine") + .header("Content-Type", "application/json") // 必须声明 JSON 格式 + .body(JsonUtils.toJsonString(machineReqDTOList)) + .timeout(5000) + .execute() + .body(); + } catch (Exception e) { + log.error("EventTrackJob invoke:{} error:{}",JsonUtils.toJsonString(machineReqDTOList), + e); + } finally { + log.info("EventTrackJob invoke:{}", + JsonUtils + .toJsonString( + DefaultSdkInvokeLogDTO.builder().requestData(machineReqDTOList).responseData(result) + .build())); + } + } + } catch (Exception e) { + log.error(e.getMessage()); + } + + log.info("埋点数据推送宝就业后台 ======结束"); + + } +} diff --git a/src/main/java/com/newyetai/recruit/eventtrack/mapper/EventTrackMapper.xml b/src/main/java/com/newyetai/recruit/eventtrack/mapper/EventTrackMapper.xml new file mode 100644 index 0000000..9da92e2 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/eventtrack/mapper/EventTrackMapper.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + FROM + hr_event_track t + WHERE t.deleted = 0 + + AND t.id = #{param.id} + + + AND t.device_code = #{param.deviceCode} + + + AND t.user_id = #{param.userId} + + + AND t.type = #{param.type} + + + AND t.create_time >= #{param.createTimeStart} + + + AND t.create_time <= #{param.createTimeEnd} + + + AND t.update_time >= #{param.updateTimeStart} + + + AND t.update_time <= #{param.updateTimeEnd} + + ORDER BY t.id DESC + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/eventtrack/service/EventTrackService.java b/src/main/java/com/newyetai/recruit/eventtrack/service/EventTrackService.java new file mode 100644 index 0000000..8068ca5 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/eventtrack/service/EventTrackService.java @@ -0,0 +1,76 @@ +package com.newyetai.recruit.eventtrack.service; + +import org.springframework.validation.annotation.Validated; + +import javax.validation.Valid; +import javax.validation.groups.Default; + +import java.util.List; + +import com.newyetai.recruit.eventtrack.dto.*; + +/** + * 埋点 + * + * @author guixinman + * @since 1.0.0 2025-01-22 + */ +@Validated(Default.class) +public interface EventTrackService { + + /** + * 埋点 - 创建 + * + * @param operatorDto 操作dto + * @return {@link EventTrackDTO} + */ + EventTrackDTO create(@Valid EventTrackOperatorDTO operatorDto); + + /** + * 埋点 - 修改 + * + * @param operatorDto 操作dto + * @return {@link EventTrackDTO} + */ + EventTrackDTO modify(@Valid EventTrackOperatorDTO operatorDto); + + /** + * 埋点 - 删除 + * + * @param id id + * @return {@link EventTrackDTO} + */ + EventTrackDTO delete(Long id); + + /** + * 埋点 - 根据ID查询单个 + * + * @param id id + * @return {@link EventTrackDTO} + */ + EventTrackDTO findById(Long id); + + /** + * 埋点 - 列表查询 + * + * @param queryDTO 列表查询dto + * @return {@link List}<{@link EventTrackDTO}> + */ + List list(EventTrackQueryDTO queryDTO); + + /** + * 埋点 - 分页查询 + * + * @param queryDTO 分页查询dto + * @return {@link EventTrackDTO} + */ + List page(EventTrackPageQueryDTO queryDTO); + + /** + * @description: 按日统计 + * @return: + * @author: guixinman + * @param: + */ + List statistics(EventTrackStatisticsQueryDTO queryDTO); +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/eventtrack/service/impl/EventTrackServiceImpl.java b/src/main/java/com/newyetai/recruit/eventtrack/service/impl/EventTrackServiceImpl.java new file mode 100644 index 0000000..1b4c0fe --- /dev/null +++ b/src/main/java/com/newyetai/recruit/eventtrack/service/impl/EventTrackServiceImpl.java @@ -0,0 +1,89 @@ +package com.newyetai.recruit.eventtrack.service.impl; + +import lombok.extern.slf4j.Slf4j; + +import com.newyetai.common.util.JsonUtils; +import com.newyetai.recruit.eventtrack.convert.EventTrackConvert; +import com.newyetai.recruit.eventtrack.entity.EventTrack; +import com.newyetai.recruit.eventtrack.dto.*; +import com.newyetai.recruit.eventtrack.dao.EventTrackMapper; +import com.newyetai.recruit.eventtrack.service.EventTrackService; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.sdk.tencent.map.dto.TencentMapLocationV1IpResDTO; + +import javax.annotation.Resource; + +import java.util.*; + +/** + * 埋点 + * + * @author guixinman + * @since 1.0.0 2025-01-22 + */ +@Slf4j +@Service +public class EventTrackServiceImpl implements EventTrackService { + + @Resource + private EventTrackMapper eventTrackMapper; + + @Override + public EventTrackDTO create(EventTrackOperatorDTO operatorDto) { + EventTrack eventTrack = EventTrackConvert.INSTANCE.convert(operatorDto); + eventTrackMapper.saveEntity(eventTrack); + return EventTrackConvert.INSTANCE.convert(eventTrack); + } + + @Override + public EventTrackDTO modify(EventTrackOperatorDTO operatorDto) { + EventTrackDTO eventTrackDto = this.findById(operatorDto.getId()); + if (Objects.isNull(eventTrackDto)) { + return null; + } + EventTrack eventTrack = EventTrackConvert.INSTANCE.convert(operatorDto); + eventTrackMapper.updateEntitySelective(eventTrack); + return this.findById(operatorDto.getId()); + } + + @Override + public EventTrackDTO delete(Long id) { + EventTrackDTO eventTrackDto = this.findById(id); + if (Objects.isNull(eventTrackDto)) { + return null; + } + EventTrack eventTrack = EventTrack.builder().build(); + eventTrack.setId(id); + eventTrackMapper.deleteEntity(eventTrack, UserContextHolder.getLoginUserId()); + return eventTrackDto; + } + + @Override + public EventTrackDTO findById(Long id) { + EventTrack eventTrack = eventTrackMapper.getById(id); + if (Objects.isNull(eventTrack)) { + return null; + } + return EventTrackConvert.INSTANCE.convert(eventTrack); + } + + @Override + public List list(EventTrackQueryDTO queryDTO) { + return eventTrackMapper.list(queryDTO); + } + + @Override + public List page(EventTrackPageQueryDTO queryDTO) { + return eventTrackMapper.page(queryDTO); + } + + @Override + public List statistics(EventTrackStatisticsQueryDTO queryDTO) { + List statisticList = eventTrackMapper.statistics(queryDTO); + return statisticList; + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/jobhelp/controller/JobHelpController.java b/src/main/java/com/newyetai/recruit/jobhelp/controller/JobHelpController.java new file mode 100644 index 0000000..9a63ddf --- /dev/null +++ b/src/main/java/com/newyetai/recruit/jobhelp/controller/JobHelpController.java @@ -0,0 +1,76 @@ +package com.newyetai.recruit.jobhelp.controller; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.recruit.jobhelp.dto.*; +import com.newyetai.recruit.jobhelp.service.JobHelpService; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; + +/** + * 就业帮扶 + * + * @author guixinman + * @since 1.0.0 2024-04-17 + */ +@Api(tags = "就业帮扶") +@RestController +@RequestMapping("/jobhelp") +public class JobHelpController { + + @Autowired + private JobHelpService jobHelpService; + + @PostMapping("/create") + @ApiOperation("就业帮扶-创建") + public AlitaResult create(@RequestBody @Validated(value = Create.class) JobHelpOperatorDTO operatorDTO) { + return AlitaResult.success(jobHelpService.create(operatorDTO)); + } + + @PutMapping("/modify") + @ApiOperation("就业帮扶-修改") + public AlitaResult modify(@RequestBody @Validated(value = Update.class) JobHelpOperatorDTO operatorDTO) { + return AlitaResult.success(jobHelpService.modify(operatorDTO)); + } + + @DeleteMapping("/{id}") + @ApiOperation("就业帮扶-删除") + public AlitaResult delete(@PathVariable("id") Long id) { + return AlitaResult.success(jobHelpService.delete(id)); + } + + @GetMapping("/{id}") + @ApiOperation("就业帮扶-查询单个") + public AlitaResult findById(@PathVariable("id") Long id) { + return AlitaResult.success(jobHelpService.findById(id)); + } + + @GetMapping("/list") + @ApiOperation("就业帮扶-列表查询") + public AlitaResult> list(JobHelpQueryDTO queryDTO) { + return AlitaResult.success(jobHelpService.list(queryDTO)); + } + + @GetMapping("/page") + @ApiOperation("就业帮扶-分页查询") + public AlitaResult> page(JobHelpPageQueryDTO queryDTO) { + jobHelpService.page(queryDTO); + return AlitaResult.success(queryDTO.getPageResult()); + } + + @GetMapping("/user_page") + @ApiOperation("就业帮扶-分页查询") + public AlitaResult> userPage(JobHelpPageQueryDTO queryDTO) { + jobHelpService.userPage(queryDTO); + return AlitaResult.success(queryDTO.getPageResult()); + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/jobhelp/convert/JobHelpConvert.java b/src/main/java/com/newyetai/recruit/jobhelp/convert/JobHelpConvert.java new file mode 100644 index 0000000..dd92cbb --- /dev/null +++ b/src/main/java/com/newyetai/recruit/jobhelp/convert/JobHelpConvert.java @@ -0,0 +1,26 @@ +package com.newyetai.recruit.jobhelp.convert; + +import com.newyetai.recruit.jobhelp.entity.JobHelp; +import com.newyetai.recruit.jobhelp.dto.JobHelpDTO; +import com.newyetai.recruit.jobhelp.dto.JobHelpOperatorDTO; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * 就业帮扶 + * + * @author guixinman + * @since 1.0.0 2024-04-17 + */ +@Mapper +public interface JobHelpConvert { + JobHelpConvert INSTANCE = Mappers.getMapper(JobHelpConvert.class); + + JobHelp convert(JobHelpDTO dto); + + JobHelpDTO convert(JobHelp entity); + + JobHelp convert(JobHelpOperatorDTO dto); + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/jobhelp/dao/JobHelpMapper.java b/src/main/java/com/newyetai/recruit/jobhelp/dao/JobHelpMapper.java new file mode 100644 index 0000000..fc27f8c --- /dev/null +++ b/src/main/java/com/newyetai/recruit/jobhelp/dao/JobHelpMapper.java @@ -0,0 +1,26 @@ +package com.newyetai.recruit.jobhelp.dao; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.recruit.jobhelp.entity.JobHelp; +import com.newyetai.recruit.jobhelp.dto.JobHelpDTO; +import com.newyetai.recruit.jobhelp.dto.JobHelpQueryDTO; +import com.newyetai.recruit.jobhelp.dto.JobHelpPageQueryDTO; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 就业帮扶 + * + * @author guixinman + * @since 1.0.0 2024-04-17 + */ +@Mapper +public interface JobHelpMapper extends MyMapper { + + List page(@Param("param") JobHelpPageQueryDTO queryDTO); + + List list(@Param("param") JobHelpQueryDTO queryDTO); +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/jobhelp/dto/JobHelpDTO.java b/src/main/java/com/newyetai/recruit/jobhelp/dto/JobHelpDTO.java new file mode 100644 index 0000000..0bfd645 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/jobhelp/dto/JobHelpDTO.java @@ -0,0 +1,51 @@ +package com.newyetai.recruit.jobhelp.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.newyetai.common.dto.BaseDTO; + +import org.springframework.format.annotation.DateTimeFormat; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.SuperBuilder; + +import java.util.Date; + +/** + * 就业帮扶 + * + * @author guixinman + * @since 1.0.0 2024-04-17 + */ +@ApiModel("就业帮扶") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class JobHelpDTO extends BaseDTO { + private static final long serialVersionUID = 1L; + + private Long userId; + + @ApiModelProperty("问题") + private String question; + + @ApiModelProperty("状态:1、待回复 2、已回复") + private String status; + + @ApiModelProperty("回答") + private String answer; + + @ApiModelProperty("回复时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date answerTime; + + private String nickname; + + private String phone; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/jobhelp/dto/JobHelpOperatorDTO.java b/src/main/java/com/newyetai/recruit/jobhelp/dto/JobHelpOperatorDTO.java new file mode 100644 index 0000000..3b5921e --- /dev/null +++ b/src/main/java/com/newyetai/recruit/jobhelp/dto/JobHelpOperatorDTO.java @@ -0,0 +1,62 @@ +package com.newyetai.recruit.jobhelp.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; + +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import java.util.Date; + +/** + * 就业帮扶 + * + * @author guixinman + * @since 1.0.0 2024-04-17 + */ +@ApiModel("就业帮扶") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class JobHelpOperatorDTO implements Serializable { + private static final long serialVersionUID = 1L; + + @NotNull(message = "参数缺失",groups = Update.class) + private Long id; + + private Long userId; + + @Length(max = 512,message = "问题描述超长了",groups = Create.class) + @NotBlank(message = "请输入问题描述",groups = Create.class) + @ApiModelProperty("问题") + private String question; + + @ApiModelProperty("状态:1、待回复 2、已回复") + private String status; + + @NotBlank(message = "请输入回复内容",groups = Update.class) + @ApiModelProperty("回答") + private String answer; + + @ApiModelProperty("回复时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date answerTime; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/jobhelp/dto/JobHelpPageQueryDTO.java b/src/main/java/com/newyetai/recruit/jobhelp/dto/JobHelpPageQueryDTO.java new file mode 100644 index 0000000..b3930ee --- /dev/null +++ b/src/main/java/com/newyetai/recruit/jobhelp/dto/JobHelpPageQueryDTO.java @@ -0,0 +1,71 @@ +package com.newyetai.recruit.jobhelp.dto; + +import com.newyetai.common.dto.PageQueryDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.format.annotation.DateTimeFormat; + + +import java.util.Date; + +/** + * 就业帮扶 + * + * @author guixinman + * @since 1.0.0 2024-04-17 + */ + +@ApiModel("就业帮扶") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class JobHelpPageQueryDTO extends PageQueryDTO { + private static final long serialVersionUID = 1L; + + private Long id; + + private Long userId; + + @ApiModelProperty("问题") + private String question; + + @ApiModelProperty("状态:1、待回复 2、已回复") + private String status; + + @ApiModelProperty("回答") + private String answer; + + @ApiModelProperty("回复时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date answerTime; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("更新时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeStart; + + @ApiModelProperty("更新时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeEnd; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/jobhelp/dto/JobHelpQueryDTO.java b/src/main/java/com/newyetai/recruit/jobhelp/dto/JobHelpQueryDTO.java new file mode 100644 index 0000000..a838535 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/jobhelp/dto/JobHelpQueryDTO.java @@ -0,0 +1,71 @@ +package com.newyetai.recruit.jobhelp.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; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +/** + * 就业帮扶 + * + * @author guixinman + * @since 1.0.0 2024-04-17 + */ +@ApiModel("就业帮扶") +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class JobHelpQueryDTO implements Serializable { + private static final long serialVersionUID = 1L; + + private Long id; + + private Long userId; + + @ApiModelProperty("问题") + private String question; + + @ApiModelProperty("状态:1、待回复 2、已回复") + private String status; + + @ApiModelProperty("回答") + private String answer; + + @ApiModelProperty("回复时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date answerTime; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("更新时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeStart; + + @ApiModelProperty("更新时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeEnd; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/jobhelp/entity/JobHelp.java b/src/main/java/com/newyetai/recruit/jobhelp/entity/JobHelp.java new file mode 100644 index 0000000..450f586 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/jobhelp/entity/JobHelp.java @@ -0,0 +1,48 @@ +package com.newyetai.recruit.jobhelp.entity; + + +import lombok.*; + +import com.baomidou.mybatisplus.annotation.*; + +import java.util.Date; + +import com.newyetai.common.entity.BaseEntity; + +/** + * 就业帮扶 + * + * @author guixinman + * @since 1.0.0 2024-04-17 + */ +@TableName(value = "hr_job_help") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class JobHelp extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * + */ + private Long userId; + /** + * 问题 + */ + private String question; + /** + * 状态:1、待回复 2、已回复 + */ + private String status; + /** + * 回答 + */ + private String answer; + /** + * 回复时间 + */ + private Date answerTime; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/jobhelp/enums/JobHelpStatusEnum.java b/src/main/java/com/newyetai/recruit/jobhelp/enums/JobHelpStatusEnum.java new file mode 100644 index 0000000..cb64c1a --- /dev/null +++ b/src/main/java/com/newyetai/recruit/jobhelp/enums/JobHelpStatusEnum.java @@ -0,0 +1,27 @@ +package com.newyetai.recruit.jobhelp.enums; + +public enum JobHelpStatusEnum { + INIT("1", "待回复"), + ANSWER("2", "已回复") + ; + + private String status; + /** + * 类型描述 + */ + private String desc; + + + JobHelpStatusEnum(String status, String desc) { + this.status = status; + this.desc = desc; + } + + public String getStatus() { + return status; + } + + public String getDesc() { + return desc; + } +} diff --git a/src/main/java/com/newyetai/recruit/jobhelp/mapper/JobHelpMapper.xml b/src/main/java/com/newyetai/recruit/jobhelp/mapper/JobHelpMapper.xml new file mode 100644 index 0000000..cb2ca96 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/jobhelp/mapper/JobHelpMapper.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + FROM + hr_job_help t + WHERE t.deleted = 0 + + AND t.id = #{param.id} + + + AND t.user_id = #{param.userId} + + + AND t.question = #{param.question} + + + AND t.status = #{param.status} + + + AND t.answer = #{param.answer} + + + AND t.answer_time = #{param.answerTime} + + + AND t.create_time >= #{param.createTimeStart} + + + AND t.create_time <= #{param.createTimeEnd} + + + AND t.update_time >= #{param.updateTimeStart} + + + AND t.update_time <= #{param.updateTimeEnd} + + ORDER BY t.id DESC + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/jobhelp/service/JobHelpService.java b/src/main/java/com/newyetai/recruit/jobhelp/service/JobHelpService.java new file mode 100644 index 0000000..b1ffda3 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/jobhelp/service/JobHelpService.java @@ -0,0 +1,70 @@ +package com.newyetai.recruit.jobhelp.service; + +import org.springframework.validation.annotation.Validated; + +import javax.validation.Valid; +import javax.validation.groups.Default; + +import java.util.List; + +import com.newyetai.recruit.jobhelp.dto.*; + +/** + * 就业帮扶 + * + * @author guixinman + * @since 1.0.0 2024-04-17 + */ +@Validated(Default.class) +public interface JobHelpService { + + /** + * 就业帮扶 - 创建 + * + * @param operatorDto 操作dto + * @return {@link JobHelpDTO} + */ + JobHelpDTO create(@Valid JobHelpOperatorDTO operatorDto); + + /** + * 就业帮扶 - 修改 + * + * @param operatorDto 操作dto + * @return {@link JobHelpDTO} + */ + JobHelpDTO modify(@Valid JobHelpOperatorDTO operatorDto); + + /** + * 就业帮扶 - 删除 + * + * @param id id + * @return {@link JobHelpDTO} + */ + JobHelpDTO delete(Long id); + + /** + * 就业帮扶 - 根据ID查询单个 + * + * @param id id + * @return {@link JobHelpDTO} + */ + JobHelpDTO findById(Long id); + + /** + * 就业帮扶 - 列表查询 + * + * @param queryDTO 列表查询dto + * @return {@link List}<{@link JobHelpDTO}> + */ + List list(JobHelpQueryDTO queryDTO); + + /** + * 就业帮扶 - 分页查询 + * + * @param queryDTO 分页查询dto + * @return {@link JobHelpDTO} + */ + List page(JobHelpPageQueryDTO queryDTO); + + List userPage(JobHelpPageQueryDTO queryDTO); +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/jobhelp/service/impl/JobHelpServiceImpl.java b/src/main/java/com/newyetai/recruit/jobhelp/service/impl/JobHelpServiceImpl.java new file mode 100644 index 0000000..1b83583 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/jobhelp/service/impl/JobHelpServiceImpl.java @@ -0,0 +1,106 @@ +package com.newyetai.recruit.jobhelp.service.impl; + +import lombok.extern.slf4j.Slf4j; + +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.util.SensitiveWordUtils; +import com.newyetai.recruit.jobhelp.convert.JobHelpConvert; +import com.newyetai.recruit.jobhelp.entity.JobHelp; +import com.newyetai.recruit.jobhelp.dto.*; +import com.newyetai.recruit.jobhelp.dao.JobHelpMapper; +import com.newyetai.recruit.jobhelp.enums.JobHelpStatusEnum; +import com.newyetai.recruit.jobhelp.service.JobHelpService; + +import org.springframework.stereotype.Service; + +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.usercenter.enums.OrgTypeEnum; + +import javax.annotation.Resource; + +import java.util.*; + +/** + * 就业帮扶 + * + * @author guixinman + * @since 1.0.0 2024-04-17 + */ +@Slf4j +@Service +public class JobHelpServiceImpl implements JobHelpService { + + @Resource + private JobHelpMapper jobHelpMapper; + + @Override + public JobHelpDTO create(JobHelpOperatorDTO operatorDto) { + if (!SensitiveWordUtils.check(operatorDto.getQuestion())) { + throw new BusinessException("非法问题描述"); + } + Long userId = UserContextHolder.getExistLoginUserId(); + + operatorDto.setUserId(userId); + operatorDto.setStatus(JobHelpStatusEnum.INIT.getStatus()); + JobHelp jobHelp = JobHelpConvert.INSTANCE.convert(operatorDto); + jobHelpMapper.saveEntity(jobHelp); + return JobHelpConvert.INSTANCE.convert(jobHelp); + } + + @Override + public JobHelpDTO modify(JobHelpOperatorDTO operatorDto) { + JobHelpDTO jobHelpDto = this.findById(operatorDto.getId()); + if (Objects.isNull(jobHelpDto)) { + return null; + } + JobHelp jobHelp = new JobHelp(); + jobHelp.setId(operatorDto.getId()); + jobHelp.setAnswer(operatorDto.getAnswer()); + jobHelp.setAnswerTime(new Date()); + jobHelp.setStatus(JobHelpStatusEnum.ANSWER.getStatus()); + jobHelpMapper.updateEntitySelective(jobHelp); + return this.findById(operatorDto.getId()); + } + + @Override + public JobHelpDTO delete(Long id) { + JobHelpDTO jobHelpDto = this.findById(id); + if (Objects.isNull(jobHelpDto)) { + return null; + } + JobHelp jobHelp = JobHelp.builder().build(); + jobHelp.setId(id); + jobHelpMapper.deleteEntity(jobHelp, UserContextHolder.getLoginUserId()); + return jobHelpDto; + } + + @Override + public JobHelpDTO findById(Long id) { + JobHelp jobHelp = jobHelpMapper.getById(id); + if (Objects.isNull(jobHelp)) { + return null; + } + return JobHelpConvert.INSTANCE.convert(jobHelp); + } + + @Override + public List list(JobHelpQueryDTO queryDTO) { + return jobHelpMapper.list(queryDTO); + } + + @Override + public List page(JobHelpPageQueryDTO queryDTO) { + if (OrgTypeEnum.ORG_TYPE_PLATFORM.getType().equals(UserContextHolder.getOrgType()) || OrgTypeEnum.ORG_TYPE_GOV.getType().equals(UserContextHolder.getOrgType()) ) { + return jobHelpMapper.page(queryDTO); + }else { + return new ArrayList<>(); + } + } + + @Override + public List userPage(JobHelpPageQueryDTO queryDTO) { + queryDTO.setUserId(UserContextHolder.getExistLoginUserId()); + return jobHelpMapper.page(queryDTO); + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/orgapply/controller/OrgApplyController.java b/src/main/java/com/newyetai/recruit/orgapply/controller/OrgApplyController.java new file mode 100644 index 0000000..c7c87bd --- /dev/null +++ b/src/main/java/com/newyetai/recruit/orgapply/controller/OrgApplyController.java @@ -0,0 +1,89 @@ +package com.newyetai.recruit.orgapply.controller; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +import com.newyetai.common.AlitaResult; +import com.newyetai.recruit.orgapply.entity.OrgApply; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.recruit.orgapply.dto.*; +import com.newyetai.recruit.orgapply.service.OrgApplyService; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; + +/** + * 入驻申请表 + * + * @author guixinman + * @since 1.0.0 2024-04-08 + */ +@Api(tags = "入驻申请表") +@RestController +public class OrgApplyController { + + @Autowired + private OrgApplyService orgApplyService; + + @PostMapping("/anon/org_apply/create") + @ApiOperation("入驻申请表-创建") + public AlitaResult create(@RequestBody @Validated OrgApplyOperatorDTO operatorDTO) { + return AlitaResult.success(orgApplyService.create(operatorDTO)); + } + + @PostMapping("/org_apply/modify") + @ApiOperation("入驻申请表-修改") + public AlitaResult modify(@RequestBody OrgApplyOperatorDTO operatorDTO) { + return AlitaResult.success(orgApplyService.modify(operatorDTO)); + } + + @DeleteMapping("/org_apply/{id}") + @ApiOperation("入驻申请表-删除") + public AlitaResult delete(@PathVariable("id") Long id) { + return AlitaResult.success(orgApplyService.delete(id)); + } + + @GetMapping("/org_apply/{id}") + @ApiOperation("入驻申请表-查询单个") + public AlitaResult findById(@PathVariable("id") Long id) { + return AlitaResult.success(orgApplyService.findById(id)); + } + + @GetMapping("/org_apply/list") + @ApiOperation("入驻申请表-列表查询") + public AlitaResult> list(OrgApplyQueryDTO queryDTO) { + return AlitaResult.success(orgApplyService.list(queryDTO)); + } + + @GetMapping("/org_apply/page") + @ApiOperation("入驻申请表-分页查询") + public AlitaResult> page(OrgApplyPageQueryDTO queryDTO) { + orgApplyService.page(queryDTO); + return AlitaResult.success(queryDTO.getPageResult()); + } + + @PostMapping("/org_apply/approve") + @ApiOperation("审批") + public AlitaResult approve(@RequestBody @Validated OrgApplyApproveDTO applyApproveDTO) { + orgApplyService.approve(applyApproveDTO); + return AlitaResult.success(); + } + + @ApiOperation("查看审批单") + @GetMapping("/anon/org_apply/getInfo") + public AlitaResult> getInfoByPhone(@RequestParam("phone") String phone) { + List infoByPhone = orgApplyService.getInfoByPhone(phone); + return AlitaResult.success(infoByPhone); + } + + @ApiOperation("分享") + @GetMapping("/org_apply/user/share") + public AlitaResult share(){ + return AlitaResult.success(orgApplyService.share()); + } + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/orgapply/convert/OrgApplyConvert.java b/src/main/java/com/newyetai/recruit/orgapply/convert/OrgApplyConvert.java new file mode 100644 index 0000000..35a672e --- /dev/null +++ b/src/main/java/com/newyetai/recruit/orgapply/convert/OrgApplyConvert.java @@ -0,0 +1,26 @@ +package com.newyetai.recruit.orgapply.convert; + +import com.newyetai.recruit.orgapply.entity.OrgApply; +import com.newyetai.recruit.orgapply.dto.OrgApplyDTO; +import com.newyetai.recruit.orgapply.dto.OrgApplyOperatorDTO; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * 入驻申请表 + * + * @author guixinman + * @since 1.0.0 2024-04-08 + */ +@Mapper +public interface OrgApplyConvert { + OrgApplyConvert INSTANCE = Mappers.getMapper(OrgApplyConvert.class); + + OrgApply convert(OrgApplyDTO dto); + + OrgApplyDTO convert(OrgApply entity); + + OrgApply convert(OrgApplyOperatorDTO dto); + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/orgapply/dao/OrgApplyMapper.java b/src/main/java/com/newyetai/recruit/orgapply/dao/OrgApplyMapper.java new file mode 100644 index 0000000..6c8c784 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/orgapply/dao/OrgApplyMapper.java @@ -0,0 +1,28 @@ +package com.newyetai.recruit.orgapply.dao; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.recruit.orgapply.entity.OrgApply; +import com.newyetai.recruit.orgapply.dto.OrgApplyDTO; +import com.newyetai.recruit.orgapply.dto.OrgApplyQueryDTO; +import com.newyetai.recruit.orgapply.dto.OrgApplyPageQueryDTO; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 入驻申请表 + * + * @author guixinman + * @since 1.0.0 2024-04-08 + */ +@Mapper +public interface OrgApplyMapper extends MyMapper { + + List page(@Param("param") OrgApplyPageQueryDTO queryDTO); + + List list(@Param("param") OrgApplyQueryDTO queryDTO); + + int approve(@Param("id") Long id, @Param("oldStatus") String oldStatus, @Param("newStatus") String newStatus, @Param("cause") String cause, @Param("operateUserId") Long operateUserId); +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/orgapply/dto/OrgApplyApproveDTO.java b/src/main/java/com/newyetai/recruit/orgapply/dto/OrgApplyApproveDTO.java new file mode 100644 index 0000000..3778f3c --- /dev/null +++ b/src/main/java/com/newyetai/recruit/orgapply/dto/OrgApplyApproveDTO.java @@ -0,0 +1,24 @@ +package com.newyetai.recruit.orgapply.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotNull; + +import lombok.Data; + +/** + * @description: 入驻审批 + * @author: guixinman + * @create: 2024-04-08 14:55 + **/ +@Data +public class OrgApplyApproveDTO implements Serializable { + + @NotNull(message = "请选择要处理的数据") + private Long id; + + @NotNull(message = "请选择状态") + private String status; + + private String cause; +} diff --git a/src/main/java/com/newyetai/recruit/orgapply/dto/OrgApplyDTO.java b/src/main/java/com/newyetai/recruit/orgapply/dto/OrgApplyDTO.java new file mode 100644 index 0000000..7dbad37 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/orgapply/dto/OrgApplyDTO.java @@ -0,0 +1,81 @@ +package com.newyetai.recruit.orgapply.dto; + +import com.newyetai.common.dto.BaseDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.SuperBuilder; + +/** + * 入驻申请表 + * + * @author guixinman + * @since 1.0.0 2024-04-08 + */ +@ApiModel("入驻申请表") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class OrgApplyDTO extends BaseDTO { + private static final long serialVersionUID = 1L; + + @ApiModelProperty("统一社会信用代码") + private String creditCode; + + @ApiModelProperty("公司名称") + private String companyName; + + @ApiModelProperty("企业所在地") + private String areaCode; + + private String areaCodeName; + + @ApiModelProperty("邀请人") + private Long inviterUserId; + + @ApiModelProperty("邀请机构") + private Long inviterOrgId; + + private String inviterOrgName; + + @ApiModelProperty("企业联系手机") + private String phone; + + @ApiModelProperty("企业类型") + private String companyType; + + @ApiModelProperty("状态 1:待处理 2:已通过 3:已驳回") + private String status; + + @ApiModelProperty("营业执照") + private String businessLicenseCode; + + /** + * 原因 + */ + private String cause; + + /** + * 招聘岗位类型 + */ + private String recruitPositionType; + + private String recruitPositionTypeName; + + /** + * 注册地址 + */ + private String registeredAddress; + + /** + * 企业所在地:文本 + */ + private String addressName; + + @ApiModelProperty("管理员姓名") + private String realName; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/orgapply/dto/OrgApplyInviterDTO.java b/src/main/java/com/newyetai/recruit/orgapply/dto/OrgApplyInviterDTO.java new file mode 100644 index 0000000..734fdc5 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/orgapply/dto/OrgApplyInviterDTO.java @@ -0,0 +1,23 @@ +package com.newyetai.recruit.orgapply.dto; + +import java.io.Serializable; + +import lombok.Data; + +/** + * @description: 入驻邀请人dto + * @author: guixinman + * @create: 2024-04-10 17:16 + **/ +@Data +public class OrgApplyInviterDTO implements Serializable { + + /** + * 邀请人 + */ + private Long inviterUserId; + /** + * 邀请机构 + */ + private Long inviterOrgId; +} diff --git a/src/main/java/com/newyetai/recruit/orgapply/dto/OrgApplyOperatorDTO.java b/src/main/java/com/newyetai/recruit/orgapply/dto/OrgApplyOperatorDTO.java new file mode 100644 index 0000000..82ab182 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/orgapply/dto/OrgApplyOperatorDTO.java @@ -0,0 +1,94 @@ +package com.newyetai.recruit.orgapply.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import org.hibernate.validator.constraints.Length; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + * 入驻申请表 + * + * @author guixinman + * @since 1.0.0 2024-04-08 + */ +@ApiModel("入驻申请表") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class OrgApplyOperatorDTO implements Serializable { + private static final long serialVersionUID = 1L; + + private Long id; + + @Length(max = 64,message = "统一社会信用代码超长了") + @ApiModelProperty("统一社会信用代码") + private String creditCode; + + @NotBlank(message = "企业名称不能为空") + @Length(max = 32,message = "企业名称超长了") + @ApiModelProperty("公司名称") + private String companyName; + + @Length(max = 50,message = "企业所在地超长了") + @ApiModelProperty("企业所在地") + private String areaCode; + + @ApiModelProperty("邀请人") + private Long inviterUserId; + + @ApiModelProperty("邀请机构") + private Long inviterOrgId; + + @NotBlank(message = "企业联系手机不能为空") + @Length(max = 20,message = "企业联系手机超长了") + @ApiModelProperty("企业联系手机") + private String phone; + + @NotBlank(message = "管理员姓名不能为空") + @ApiModelProperty("管理员姓名") + private String realName; + + @NotNull(message = "企业类型不能为空") + @ApiModelProperty("企业类型") + private String companyType; + + @ApiModelProperty("状态 1:待处理 2:已通过 3:已驳回") + private String status; + + @NotBlank(message = "营业执照不能为空") + @ApiModelProperty("营业执照") + private String businessLicenseCode; + + private String uniqueCode; + + private String smsCode; + + /** + * 招聘岗位类型 + */ + private String recruitPositionType; + + /** + * 注册地址 + */ + @Length(max = 128,message = "注册地址超长了") + @NotBlank(message = "企业注册地址不能为空") + private String registeredAddress; + + /** + * 企业所在地:文本 + */ + @Length(max = 128,message = "企业所在地超长了") + private String addressName; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/orgapply/dto/OrgApplyPageQueryDTO.java b/src/main/java/com/newyetai/recruit/orgapply/dto/OrgApplyPageQueryDTO.java new file mode 100644 index 0000000..443884f --- /dev/null +++ b/src/main/java/com/newyetai/recruit/orgapply/dto/OrgApplyPageQueryDTO.java @@ -0,0 +1,82 @@ +package com.newyetai.recruit.orgapply.dto; + +import com.newyetai.common.dto.PageQueryDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.format.annotation.DateTimeFormat; + + +import java.util.Date; + +/** + * 入驻申请表 + * + * @author guixinman + * @since 1.0.0 2024-04-08 + */ + +@ApiModel("入驻申请表") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class OrgApplyPageQueryDTO extends PageQueryDTO { + private static final long serialVersionUID = 1L; + + private Long id; + + @ApiModelProperty("统一社会信用代码") + private String creditCode; + + @ApiModelProperty("公司名称 (模糊匹配)") + private String companyNameLike; + + @ApiModelProperty("企业所在地") + private String areaCode; + + @ApiModelProperty("邀请人") + private Long inviterUserId; + + @ApiModelProperty("邀请机构") + private Long inviterOrgId; + + @ApiModelProperty("企业联系手机") + private String phone; + + @ApiModelProperty("企业类型") + private String companyType; + + @ApiModelProperty("状态 1:待处理 2:已通过 3:已驳回") + private String status; + + @ApiModelProperty("营业执照") + private String businessLicenseCode; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("更新时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeStart; + + @ApiModelProperty("更新时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeEnd; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/orgapply/dto/OrgApplyQueryDTO.java b/src/main/java/com/newyetai/recruit/orgapply/dto/OrgApplyQueryDTO.java new file mode 100644 index 0000000..c27d123 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/orgapply/dto/OrgApplyQueryDTO.java @@ -0,0 +1,82 @@ +package com.newyetai.recruit.orgapply.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; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +/** + * 入驻申请表 + * + * @author guixinman + * @since 1.0.0 2024-04-08 + */ +@ApiModel("入驻申请表") +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class OrgApplyQueryDTO implements Serializable { + private static final long serialVersionUID = 1L; + + private Long id; + + @ApiModelProperty("统一社会信用代码") + private String creditCode; + + @ApiModelProperty("公司名称 (模糊匹配)") + private String companyNameLike; + + @ApiModelProperty("企业所在地") + private String areaCode; + + @ApiModelProperty("邀请人") + private Long inviterUserId; + + @ApiModelProperty("邀请机构") + private Long inviterOrgId; + + @ApiModelProperty("企业联系手机") + private String phone; + + @ApiModelProperty("企业类型") + private String companyType; + + @ApiModelProperty("状态 1:待处理 2:已通过 3:已驳回") + private String status; + + @ApiModelProperty("营业执照") + private String businessLicenseCode; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("更新时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeStart; + + @ApiModelProperty("更新时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeEnd; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/orgapply/entity/OrgApply.java b/src/main/java/com/newyetai/recruit/orgapply/entity/OrgApply.java new file mode 100644 index 0000000..2499c34 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/orgapply/entity/OrgApply.java @@ -0,0 +1,85 @@ +package com.newyetai.recruit.orgapply.entity; + +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.SuperBuilder; + +import com.baomidou.mybatisplus.annotation.*; + +import com.newyetai.common.entity.BaseEntity; + +/** + * 入驻申请表 + * + * @author guixinman + * @since 1.0.0 2024-04-08 + */ +@TableName(value = "org_apply") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class OrgApply extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * 统一社会信用代码 + */ + private String creditCode; + /** + * 公司名称 + */ + private String companyName; + /** + * 企业所在地 + */ + private String areaCode; + /** + * 邀请人 + */ + private Long inviterUserId; + /** + * 邀请机构 + */ + private Long inviterOrgId; + /** + * 企业联系手机 + */ + private String phone; + /** + * 企业类型 + */ + private String companyType; + /** + * 状态 1:待处理 2:已通过 3:已驳回 + */ + private String status; + /** + * 营业执照 + */ + private String businessLicenseCode; + /** + * 原因 + */ + private String cause; + + /** + * 招聘岗位类型 + */ + private String recruitPositionType; + + /** + * 注册地址 + */ + private String registeredAddress; + + /** + * 企业所在地:文本 + */ + private String addressName; + + @ApiModelProperty("管理员姓名") + private String realName; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/orgapply/enums/OrgApplyEnum.java b/src/main/java/com/newyetai/recruit/orgapply/enums/OrgApplyEnum.java new file mode 100644 index 0000000..87d8c8c --- /dev/null +++ b/src/main/java/com/newyetai/recruit/orgapply/enums/OrgApplyEnum.java @@ -0,0 +1,28 @@ +package com.newyetai.recruit.orgapply.enums; + +public enum OrgApplyEnum { + INIT("1","待处理"), + SUCCESS("2","已通过"), + REJECT("3","已驳回") + ; + + private String status; + /** + * 类型描述 + */ + private String desc; + + + OrgApplyEnum(String status, String desc) { + this.status = status; + this.desc = desc; + } + + public String getStatus() { + return status; + } + + public String getDesc() { + return desc; + } +} diff --git a/src/main/java/com/newyetai/recruit/orgapply/mapper/OrgApplyMapper.xml b/src/main/java/com/newyetai/recruit/orgapply/mapper/OrgApplyMapper.xml new file mode 100644 index 0000000..fdb4e76 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/orgapply/mapper/OrgApplyMapper.xml @@ -0,0 +1,97 @@ + + + + + + update org_apply set status = #{newStatus}, cause=#{cause}, update_by = #{operateUserId}, update_time = now() where id = #{id} and status = #{oldStatus} + + + + + + + + FROM + org_apply t + WHERE t.deleted = 0 + + AND t.id = #{param.id} + + + AND t.credit_code = #{param.creditCode} + + + + AND t.company_name like #{companyNameLike} + + + AND t.area_code = #{param.areaCode} + + + AND t.inviter_user_id = #{param.inviterUserId} + + + AND t.inviter_org_id = #{param.inviterOrgId} + + + AND t.phone = #{param.phone} + + + AND t.company_type = #{param.companyType} + + + AND t.status = #{param.status} + + + AND t.business_license_code = #{param.businessLicenseCode} + + + AND t.create_time >= #{param.createTimeStart} + + + AND t.create_time <= #{param.createTimeEnd} + + + AND t.update_time >= #{param.updateTimeStart} + + + AND t.update_time <= #{param.updateTimeEnd} + + ORDER BY t.id DESC + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/orgapply/service/OrgApplyService.java b/src/main/java/com/newyetai/recruit/orgapply/service/OrgApplyService.java new file mode 100644 index 0000000..13acd49 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/orgapply/service/OrgApplyService.java @@ -0,0 +1,88 @@ +package com.newyetai.recruit.orgapply.service; + +import org.springframework.validation.annotation.Validated; + +import javax.validation.Valid; +import javax.validation.groups.Default; + +import java.util.List; + +import com.newyetai.recruit.orgapply.dto.*; +import com.newyetai.recruit.orgapply.entity.OrgApply; + +/** + * 入驻申请表 + * + * @author guixinman + * @since 1.0.0 2024-04-08 + */ +@Validated(Default.class) +public interface OrgApplyService { + + /** + * 入驻申请表 - 创建 + * + * @param operatorDto 操作dto + * @return {@link OrgApplyDTO} + */ + OrgApplyDTO create(@Valid OrgApplyOperatorDTO operatorDto); + + /** + * 入驻申请表 - 修改 + * + * @param operatorDto 操作dto + * @return {@link OrgApplyDTO} + */ + OrgApplyDTO modify(@Valid OrgApplyOperatorDTO operatorDto); + + /** + * 入驻申请表 - 删除 + * + * @param id id + * @return {@link OrgApplyDTO} + */ + OrgApplyDTO delete(Long id); + + /** + * 入驻申请表 - 根据ID查询单个 + * + * @param id id + * @return {@link OrgApplyDTO} + */ + OrgApplyDTO findById(Long id); + + /** + * 入驻申请表 - 列表查询 + * + * @param queryDTO 列表查询dto + * @return {@link List}<{@link OrgApplyDTO}> + */ + List list(OrgApplyQueryDTO queryDTO); + + /** + * 入驻申请表 - 分页查询 + * + * @param queryDTO 分页查询dto + * @return {@link OrgApplyDTO} + */ + List page(OrgApplyPageQueryDTO queryDTO); + + /** + * @description: 审批 + * @return: + * @author: guixinman + * @param: + */ + void approve(OrgApplyApproveDTO orgApplyApproveDTO); + + /** + * @description: 根据手机号获取 入驻申请单 + * @return: + * @author: guixinman + * @param: + */ + + List getInfoByPhone(String phone); + + String share(); +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/orgapply/service/impl/OrgApplyServiceImpl.java b/src/main/java/com/newyetai/recruit/orgapply/service/impl/OrgApplyServiceImpl.java new file mode 100644 index 0000000..30ba66d --- /dev/null +++ b/src/main/java/com/newyetai/recruit/orgapply/service/impl/OrgApplyServiceImpl.java @@ -0,0 +1,297 @@ +package com.newyetai.recruit.orgapply.service.impl; + +import com.google.common.collect.Maps; + +import lombok.extern.slf4j.Slf4j; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.function.TransactionAfterCommit; +import com.newyetai.component.dict.util.DictUtils; +import com.newyetai.config.service.ConfigService; +import com.newyetai.frame.redis.aop.annotation.AutoUnLock; +import com.newyetai.frame.redis.dto.LockDTO; +import com.newyetai.frame.redis.redisson.RedissonUtils; +import com.newyetai.recruit.orgapply.convert.OrgApplyConvert; +import com.newyetai.recruit.orgapply.entity.OrgApply; +import com.newyetai.recruit.orgapply.dto.*; +import com.newyetai.recruit.orgapply.dao.OrgApplyMapper; +import com.newyetai.recruit.orgapply.enums.OrgApplyEnum; +import com.newyetai.recruit.orgapply.service.OrgApplyService; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.compress.utils.Lists; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.security.expection.BadLoginException; +import com.newyetai.usercenter.common.dto.SlickParamCreateDTO; +import com.newyetai.usercenter.common.service.SlickParamService; +import com.newyetai.usercenter.enums.OrgTypeEnum; +import com.newyetai.usercenter.enums.SmsTemplateCodeEnum; +import com.newyetai.usercenter.org.dto.OrgCreateDTO; +import com.newyetai.usercenter.org.service.OrgService; +import com.newyetai.usercenter.user.dto.UserRegisterCodeInfoDTO; +import com.newyetai.usercenter.user.phone.constant.PhoneCodeProviderEnum; +import com.newyetai.usercenter.user.phone.dto.PhoneCodeDTO; +import com.newyetai.usercenter.user.phone.dto.SmsSimpleSendDTO; +import com.newyetai.usercenter.user.phone.dto.SmsSimpleSendDetailDTO; +import com.newyetai.usercenter.user.phone.provider.simple.ISimpleSms; +import com.newyetai.usercenter.user.phone.util.PhoneCodeUtils; + +import javax.annotation.Resource; + +import java.util.*; + +/** + * 入驻申请表 + * + * @author guixinman + * @since 1.0.0 2024-04-08 + */ +@Slf4j +@Service +public class OrgApplyServiceImpl implements OrgApplyService { + + @Resource + private OrgApplyMapper orgApplyMapper; + + @Autowired + private ISimpleSms simpleSms; + + @Autowired + private SlickParamService slickParamService; + + @Autowired + private OrgService orgService; + + @Autowired + private ConfigService configService; + + + + /** + * @description: 企业名称 + 手机号只能申请一次,不能重复申请,驳回后可以重新提交 + * @return: + * @author: guixinman + * @param: + */ + + @AutoUnLock + @Override + public OrgApplyDTO create(OrgApplyOperatorDTO operatorDto) { + Assert.isTrue( + RedissonUtils.tryLockAutomatically( + LockDTO.builder() + .tryLockWaitTime(0L) + .lockTimeout(60 * 5L) + .methodName("org_apply:create") + .arg(operatorDto.getCompanyName()) + .arg(operatorDto.getPhone()) + .build() + ), + "请稍后再试"); + String inviterOrgId = configService.getConfigValue("org_apply_inviter_org_id", CommonConstants.PLATFORM_ORG_ID, true); + operatorDto.setInviterOrgId(Long.parseLong(inviterOrgId)); + + //取消验证码 + /*boolean match = PhoneCodeUtils.match(PhoneCodeDTO.builder().phone(operatorDto.getPhone()) + .code(operatorDto.getSmsCode()) + .providerType(PhoneCodeProviderEnum.ORG_APPLY.getType()).build()); + Assert.isTrue(match, new BadLoginException("验证码错误"));*/ + + Map companyTypeMap = DictUtils.getCodeNameMap("company_type"); + Assert.notNull(companyTypeMap.get(operatorDto.getCompanyType()),"企业类型错误"); + + Map recruitPositionTypeMap = DictUtils.getCodeNameMap("recruit_position_type"); + Assert.notNull(recruitPositionTypeMap.get(operatorDto.getRecruitPositionType()),"招聘岗位类型错误"); + + List orgApplys = orgApplyMapper.selectList(new LambdaQueryWrapper().eq(OrgApply::getDeleted, false).in(OrgApply::getStatus, OrgApplyEnum.INIT.getStatus(), OrgApplyEnum.SUCCESS.getStatus()).eq(OrgApply::getCompanyName, operatorDto.getCompanyName()).eq(OrgApply::getPhone, operatorDto.getPhone())); + if (CollectionUtils.isNotEmpty(orgApplys)) { + throw new BusinessException("(企业名称 + 手机号)已存在入驻申请,请勿重复提交!"); + } + + OrgApply orgApply = OrgApplyConvert.INSTANCE.convert(operatorDto); + orgApply.setStatus(OrgApplyEnum.INIT.getStatus()); + + if (StringUtils.isNotBlank(operatorDto.getUniqueCode())) { + OrgApplyInviterDTO orgApplyInviterDTO = slickParamService.parseCode(operatorDto.getUniqueCode(), OrgApplyInviterDTO.class); + orgApply.setInviterOrgId(orgApplyInviterDTO.getInviterOrgId()); + orgApply.setInviterUserId(orgApplyInviterDTO.getInviterUserId()); + }else { + Assert.notNull(operatorDto.getInviterOrgId(),"请选择邀请机构"); + orgApply.setInviterOrgId(operatorDto.getInviterOrgId()); + } + + orgApplyMapper.saveEntity(orgApply); + return OrgApplyConvert.INSTANCE.convert(orgApply); + } + + @Override + public OrgApplyDTO modify(OrgApplyOperatorDTO operatorDto) { + OrgApplyDTO orgApplyDto = this.findById(operatorDto.getId()); + if (Objects.isNull(orgApplyDto)) { + return null; + } + OrgApply orgApply = OrgApplyConvert.INSTANCE.convert(operatorDto); + orgApplyMapper.updateEntitySelective(orgApply); + return this.findById(operatorDto.getId()); + } + + @Override + public OrgApplyDTO delete(Long id) { + OrgApplyDTO orgApplyDto = this.findById(id); + if (Objects.isNull(orgApplyDto)) { + return null; + } + OrgApply orgApply = OrgApply.builder().build(); + orgApply.setId(id); + orgApplyMapper.deleteEntity(orgApply, UserContextHolder.getLoginUserId()); + return orgApplyDto; + } + + @Override + public OrgApplyDTO findById(Long id) { + OrgApply orgApply = orgApplyMapper.getById(id); + if (Objects.isNull(orgApply)) { + return null; + } + if (!CommonConstants.PLATFORM_ORG_ID.equals(UserContextHolder.getExistLoginOrgId())) { + Assert.isTrue(orgApply.getInviterOrgId().equals(UserContextHolder.getExistLoginOrgId()),"未查询到数据"); + } + return OrgApplyConvert.INSTANCE.convert(orgApply); + } + + @Override + public List list(OrgApplyQueryDTO queryDTO) { + return orgApplyMapper.list(queryDTO); + } + + @Override + public List page(OrgApplyPageQueryDTO queryDTO) { + if (!CommonConstants.PLATFORM_ORG_ID.equals(UserContextHolder.getExistLoginOrgId())) { + queryDTO.setInviterOrgId(UserContextHolder.getExistLoginOrgId()); + } + + List list = orgApplyMapper.page(queryDTO); + for (OrgApplyDTO orgApplyDTO : list) { + orgApplyDTO.setRecruitPositionTypeName(DictUtils.getCodeNameMap("recruit_position_type").get(orgApplyDTO.getRecruitPositionType())); + } + return list; + } + + @AutoUnLock + @Transactional(rollbackFor = Exception.class) + @Override + public void approve(OrgApplyApproveDTO orgApplyApproveDTO) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper() + .eq(OrgApply::getDeleted, false) + .eq(OrgApply::getId, orgApplyApproveDTO.getId()); + + if (!CommonConstants.PLATFORM_ORG_ID.equals(UserContextHolder.getExistLoginOrgId())) { + queryWrapper.eq(OrgApply::getInviterOrgId, UserContextHolder.getExistLoginOrgId()); + } + + OrgApply orgApply = orgApplyMapper.selectOne(queryWrapper); + Assert.notNull(orgApply, "未查询到数据"); + if (!orgApply.getStatus().equals(OrgApplyEnum.INIT.getStatus())) { + throw new BusinessException("正在处理中...请稍后再试!"); + } + Assert.isTrue( + RedissonUtils.tryLockAutomatically( + LockDTO.builder() + .tryLockWaitTime(0L) + .lockTimeout(60 * 5L) + .methodName("org_apply:approve") + .arg(String.valueOf(orgApplyApproveDTO.getId())) + .build() + ), + "正在处理中,请稍后再试"); + + if (orgApplyApproveDTO.getStatus().equals(OrgApplyEnum.REJECT.getStatus())) { + Assert.isTrue(StringUtils.isNotBlank(orgApplyApproveDTO.getCause()), "请输入驳回原因"); + } + + int rows = orgApplyMapper.approve(orgApplyApproveDTO.getId(), OrgApplyEnum.INIT.getStatus(), orgApplyApproveDTO.getStatus(), orgApplyApproveDTO.getCause(), UserContextHolder.getExistLoginUserId()); + if (rows != 1) { + throw new BusinessException("审批失败,请稍后再试!"); + } + + SmsSimpleSendDTO sendDTO = new SmsSimpleSendDTO(); + + if (orgApplyApproveDTO.getStatus().equals(OrgApplyEnum.REJECT.getStatus())) { + /*//是驳回 短信通知联系人审核结果 + sendDTO.setTemplateCode(SmsTemplateCodeEnum.ORG_APPLY_REJECT.getTemplateCodeKey()); + List detailDTOS = Lists.newArrayList(); + sendDTO.setDetailDTOS(detailDTOS); + Map params = Maps.newHashMap(); + params.put("companyName", orgApply.getCompanyName()); + detailDTOS.add(SmsSimpleSendDetailDTO.builder() + .phone(orgApply.getPhone()) + .parameters(params) + .build()); + TransactionAfterCommit.doSomeThingAfterCommit(()->{ + simpleSms.send(sendDTO); + });*/ + } else if (orgApplyApproveDTO.getStatus().equals(OrgApplyEnum.SUCCESS.getStatus())) { + //审核通过了根据提交的企业信息去创建对应的机构 + OrgCreateDTO orgCreateDTO = OrgCreateDTO.builder() + .type(orgApply.getCompanyType()) + .orgName(orgApply.getCompanyName()) + .phone(orgApply.getPhone()) + .creditCode(orgApply.getCreditCode()) + .addressCode(orgApply.getAreaCode()) + .addressName(orgApply.getAddressName()) + .parentId(orgApply.getInviterOrgId()) + .recruitPositionType(orgApply.getRecruitPositionType()) + .businessLicense(orgApply.getBusinessLicenseCode()) + .registeredAddress(orgApply.getRegisteredAddress()) + .realName(orgApply.getRealName()) + .build(); + orgService.create(orgCreateDTO); + + /*sendDTO.setTemplateCode(SmsTemplateCodeEnum.ORG_APPLY_SUCCESS.getTemplateCodeKey()); + List detailDTOS = Lists.newArrayList(); + sendDTO.setDetailDTOS(detailDTOS); + Map params = Maps.newHashMap(); + params.put("companyName", orgApply.getCompanyName()); + detailDTOS.add(SmsSimpleSendDetailDTO.builder() + .phone(orgApply.getPhone()) + .parameters(params) + .build()); + TransactionAfterCommit.doSomeThingAfterCommit(()->{ + simpleSms.send(sendDTO); + });*/ + } + + } + + @Override + public List getInfoByPhone(String phone) { + /*boolean match = PhoneCodeUtils.match(PhoneCodeDTO.builder().phone(phone) + .code(code) + .providerType(PhoneCodeProviderEnum.GET_ORG_APPLY.getType()).build()); + Assert.isTrue(match, new BadLoginException("验证码错误"));*/ + List orgApplyList = orgApplyMapper.selectList(new LambdaQueryWrapper().eq(OrgApply::getPhone, phone).eq(OrgApply::getDeleted, false)); + return orgApplyList; + } + + @Override + public String share() { + + Assert.isTrue(StringUtils.equals(OrgTypeEnum.ORG_TYPE_GOV.getType(),UserContextHolder.getOrgType()),"没有操作权限"); + + UserRegisterCodeInfoDTO codeDTO = UserRegisterCodeInfoDTO.builder() + .inviterId(UserContextHolder.getLoginUserId()) + .inviterOrgId(UserContextHolder.getExistLoginOrgId()) + .build(); + + return slickParamService.create(SlickParamCreateDTO.builder().paramData(codeDTO).build()) + .getUniqueCode(); + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/constant/PositionConstants.java b/src/main/java/com/newyetai/recruit/position/constant/PositionConstants.java new file mode 100644 index 0000000..c186779 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/constant/PositionConstants.java @@ -0,0 +1,37 @@ +package com.newyetai.recruit.position.constant; + +/** + * 职位类型常量 + * + * @author Carlye + * @date 2022/01/24 + */ +public interface PositionConstants { + + String POSITION_TYPE_CACHE = "ptc"; + + + /** + * 工作性质 0:不限 1:兼职 2:全职 + */ + Integer JOB_CATEGORY_ALL = 0; + Integer JOB_CATEGORY_PART = 1; + /** + * 工作性质完全 + */ + Integer JOB_CATEGORY_FULL = 2; + + /** + * 结算类型 1日结 2周结 3月结 4完工结 + */ + Integer SETTLEMENT_TYPE_DAY = 1; + Integer SETTLEMENT_TYPE_WEEK = 2; + Integer SETTLEMENT_TYPE_MONTH = 3; + Integer SETTLEMENT_TYPE_END = 4; + + /** + * 岗位文件类型 1:图片 2:视频 + */ + String POSITION_FILE_TYPE_IMG = "1"; + String POSITION_FILE_TYPE_VIDEO = "2"; +} diff --git a/src/main/java/com/newyetai/recruit/position/controller/HrPositionFileController.java b/src/main/java/com/newyetai/recruit/position/controller/HrPositionFileController.java new file mode 100644 index 0000000..dc74782 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/controller/HrPositionFileController.java @@ -0,0 +1,70 @@ +package com.newyetai.recruit.position.controller; + + + +import com.newyetai.common.AlitaResult; +import com.newyetai.recruit.position.dto.PositionFileDTO; +import com.newyetai.recruit.position.dto.PositionFilePageQueryDTO; +import com.newyetai.recruit.position.entity.PositionFile; +import com.newyetai.recruit.position.service.PositionFileService; +import com.newyetai.tkmybatis.pojo.Page; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; + +@Api(tags = "岗位附件") +@RestController +@RequestMapping("/position/file") +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class HrPositionFileController { + + + private final PositionFileService positionFileService; + + @GetMapping("/page") + @ApiOperation("分页查询岗位文件") + public AlitaResult> filePage(PositionFilePageQueryDTO queryDTO) { + positionFileService.filePage(queryDTO); + return AlitaResult.success(queryDTO.getPageResult()); + } + + @PostMapping("/create") + @ApiOperation("创建岗位文件信息") + public AlitaResult create(@RequestBody PositionFileDTO queryDTO) { + return AlitaResult.success(positionFileService.create(queryDTO)); + } + + @PostMapping("/update") + @ApiOperation("修改岗位文件信息") + public AlitaResult update(@RequestBody PositionFileDTO queryDTO) { + positionFileService.update(queryDTO); + return AlitaResult.success(); + } + + @DeleteMapping("/delete/{id}") + @ApiOperation("根据文件Id删除企业文件信息") + public AlitaResult delete(@PathVariable("id") Long id) { + positionFileService.delete(id); + return AlitaResult.success(); + } + + @PutMapping("/setDefault/{id}") + @ApiOperation("设置为默认") + public AlitaResult setDefault(@PathVariable("id") Long id) { + positionFileService.setDefault(id); + return AlitaResult.success(); + } + +} + diff --git a/src/main/java/com/newyetai/recruit/position/controller/PositionAddressController.java b/src/main/java/com/newyetai/recruit/position/controller/PositionAddressController.java new file mode 100644 index 0000000..d2bbf8a --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/controller/PositionAddressController.java @@ -0,0 +1,66 @@ +package com.newyetai.recruit.position.controller; + + +import com.newyetai.common.AlitaResult; +import com.newyetai.recruit.position.dto.PositionAddressDTO; +import com.newyetai.recruit.position.dto.PositionAddressOperatorDTO; +import com.newyetai.recruit.position.dto.PositionAddressQueryDTO; +import com.newyetai.recruit.position.service.PositionAddressService; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; + +/** + *

+ * 招聘系统-岗位地址信息表 前端控制器 + *

+ * + * @author chenyun + * @since 2021-01-08 + */ +@Api(tags = "岗位地址信息") +@RestController +@RequestMapping("/hr/position/address") +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class PositionAddressController { + + private final PositionAddressService positionAddressService; + + @PostMapping("/create") + @ApiOperation("新增岗位地址") + public AlitaResult create(@RequestBody PositionAddressOperatorDTO queryDTO) { + return AlitaResult.success(positionAddressService.createOrUpdate(queryDTO)); + } + + @PostMapping("/update") + @ApiOperation("修改岗位地址") + public AlitaResult update(@RequestBody PositionAddressOperatorDTO queryDTO) { + return AlitaResult.success(positionAddressService.createOrUpdate(queryDTO)); + } + + @GetMapping("/list") + @ApiOperation("岗位地址列表") + public AlitaResult> positionList(PositionAddressQueryDTO queryDTO) { + return AlitaResult.success(positionAddressService.list(queryDTO)); + } + + @ApiOperation("删除岗位地址") + @DeleteMapping("/delete/{id}") + public AlitaResult delete(@PathVariable("id") Long id) { + positionAddressService.delete(id); + return AlitaResult.success(); + } +} + diff --git a/src/main/java/com/newyetai/recruit/position/controller/PositionAuditController.java b/src/main/java/com/newyetai/recruit/position/controller/PositionAuditController.java new file mode 100644 index 0000000..a95c8c9 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/controller/PositionAuditController.java @@ -0,0 +1,110 @@ +package com.newyetai.recruit.position.controller; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +import com.newyetai.common.AlitaResult; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.recruit.position.dto.*; +import com.newyetai.recruit.position.service.PositionAuditService; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; +import java.util.Set; + +/** + * 岗位审核表 + * + * @author guixinman + * @since 1.0.0 2024-07-05 + */ +@Api(tags = "岗位审核表") +@RestController +@RequestMapping("/position/audit") +public class PositionAuditController { + + @Autowired + private PositionAuditService positionAuditService; + + @PostMapping("/position_create") + @ApiOperation("岗位审核表-创建") + public AlitaResult positionCreate(@RequestBody @Validated PositionNewOperatorDTO operatorDTO) { + return AlitaResult.success(positionAuditService.positionCreate(operatorDTO)); + } + + @PutMapping("/position_modify") + @ApiOperation("岗位审核表-修改") + public AlitaResult positionModify(@RequestBody @Validated PositionNewOperatorDTO operatorDTO) { + positionAuditService.positionModify(operatorDTO); + return AlitaResult.success(); + } + + @GetMapping("/position_find/{id}") + @ApiOperation("岗位审核表-查询单个") + public AlitaResult positionFindById(@PathVariable("id") Long id) { + return AlitaResult.success(positionAuditService.positionFindById(id)); + } + + /** + * @description: PC端 岗位列表分页查询 + * @return: + * @author: guixinman + * @param: + */ + @GetMapping("/position_page") + @ApiOperation("岗位-分页查询") + public AlitaResult> positionPage(PositionNewPageQueryDTO queryDTO) { + positionAuditService.positionPage(queryDTO); + return AlitaResult.success(queryDTO.getPageResult()); + } + + @GetMapping("/position_export") + @ApiOperation("岗位信息表-导出") + public void positionExport(PositionNewPageQueryDTO queryDTO) { + positionAuditService.export(queryDTO); + } + + @PutMapping("/position_modify_status") + @ApiOperation("岗位信息表开启或者关闭招聘") + public AlitaResult positionModifyStatus(@RequestParam("ids") Set ids, @RequestParam("status") String status) { + positionAuditService.positionModifyStatus(ids, status); + return AlitaResult.success(); + } + + /** + * 复制 + */ + @GetMapping("/position_copy/{id}") + public AlitaResult positionCopy(@PathVariable("id") Long id){ + return AlitaResult.success(positionAuditService.positionCopy(id)); + } + + @GetMapping("list") + @ApiOperation("岗位审核表-列表查询") + public AlitaResult> list(PositionAuditQueryDTO queryDTO) { + return AlitaResult.success(positionAuditService.list(queryDTO)); + } + + @GetMapping("/page") + @ApiOperation("岗位审核表-分页查询") + public AlitaResult> page(PositionAuditPageQueryDTO queryDTO) { + positionAuditService.page(queryDTO); + return AlitaResult.success(queryDTO.getPageResult()); + } + + @GetMapping("/{id}") + @ApiOperation("岗位审核信息表-查询单个") + public AlitaResult findById(@PathVariable("id") Long id) { + return AlitaResult.success(positionAuditService.findById(id)); + } + + @PostMapping("") + @ApiOperation("审核") + public AlitaResult audit(@RequestBody @Validated PositionAuditReqDTO reqDTO) { + positionAuditService.audit(reqDTO); + return AlitaResult.success(); + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/controller/PositionController.java b/src/main/java/com/newyetai/recruit/position/controller/PositionController.java new file mode 100644 index 0000000..20c8bd6 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/controller/PositionController.java @@ -0,0 +1,94 @@ +package com.newyetai.recruit.position.controller; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +import com.newyetai.common.AlitaResult; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.recruit.position.dto.*; +import com.newyetai.recruit.position.service.PositionService; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; + +/** + * 岗位信息表;岗位信息表 + * + * @author guixinman + * @since 1.0.0 2024-04-11 + */ +@Api(tags = "岗位信息表;岗位信息表") +@RestController +@RequestMapping("/position") +public class PositionController { + + @Autowired + private PositionService positionService; + + @PostMapping("/create") + @ApiOperation("岗位信息表;岗位信息表-创建") + public AlitaResult create(@RequestBody @Validated PositionOperatorDTO operatorDTO) { + return AlitaResult.success(positionService.create(operatorDTO)); + } + + @PutMapping("/modify") + @ApiOperation("岗位信息表;岗位信息表-修改") + public AlitaResult modify(@RequestBody @Validated PositionOperatorDTO operatorDTO) { + return AlitaResult.success(positionService.modify(operatorDTO)); + } + + @DeleteMapping("/{id}") + @ApiOperation("岗位信息表;岗位信息表-删除") + public AlitaResult delete(@PathVariable("id") Long id) { + return AlitaResult.success(positionService.delete(id)); + } + + @GetMapping("/{id}") + @ApiOperation("岗位信息表;岗位信息表-查询单个") + public AlitaResult findById(@PathVariable("id") Long id) { + return AlitaResult.success(positionService.findById(id)); + } + + @GetMapping("/list") + @ApiOperation("岗位信息表;岗位信息表-列表查询") + public AlitaResult> list(PositionPageQueryDTO queryDTO) { + return AlitaResult.success(positionService.list(queryDTO)); + } + + @GetMapping("/page") + @ApiOperation("岗位信息表;岗位信息表-分页查询") + public AlitaResult> page(PositionPageQueryDTO queryDTO) { + positionService.page(queryDTO); + return AlitaResult.success(queryDTO.getPageResult()); + } + + @GetMapping("/export") + @ApiOperation("岗位信息表;岗位信息表-导出") + public void export(PositionPageQueryDTO queryDTO) { + positionService.export(queryDTO); + } + + @PutMapping("/modify_status") + @ApiOperation("岗位信息表开启或者关闭招聘") + public AlitaResult modifyStatus(@RequestBody PositionOperatorDTO dto){ + positionService.modifyStatus(dto); + return AlitaResult.success(); + } + + @GetMapping("/template") + @ApiOperation("岗位 - 模板下载") + public void template() { + positionService.template(); + } + + /** + * 复制 + */ + @GetMapping("/copy/{id}") + public AlitaResult copy(@PathVariable("id") Long id){ + return AlitaResult.success(positionService.copy(id)); + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/controller/PositionRegistrationController.java b/src/main/java/com/newyetai/recruit/position/controller/PositionRegistrationController.java new file mode 100644 index 0000000..68f4417 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/controller/PositionRegistrationController.java @@ -0,0 +1,194 @@ +package com.newyetai.recruit.position.controller; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.recruit.position.dto.*; +import com.newyetai.recruit.position.service.PositionRegistrationService; + +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; + +/** + * 岗位报名信息表 + * + * @author guixinman + * @since 1.0.0 2024-04-15 + */ +@Api(tags = "岗位报名信息表") +@RestController +@RequestMapping("/position_registration") +@Slf4j +public class PositionRegistrationController { + + @Autowired + private PositionRegistrationService positionRegistrationService; + + @PostMapping("/create") + @ApiOperation("岗位报名信息表-创建") + public AlitaResult create(@RequestBody @Validated PositionRegistrationOperatorDTO operatorDTO) { + if (CollectionUtils.isEmpty(operatorDTO.getUserIds())) { + throw new BusinessException("缺失参数"); + } + int successrows = operatorDTO.getUserIds().size(); + for (Long userId : operatorDTO.getUserIds()) { + try { + operatorDTO.setUserId(userId); + positionRegistrationService.create(operatorDTO); + } catch (Exception e) { + successrows = successrows - 1; + log.error(String.format("用户id:%s 操作加入招聘失败,失败原因:%s",userId,e.getMessage())); + } + } + return AlitaResult.success(String.format("成功数: %s条,失败数: %s条", successrows, operatorDTO.getUserIds().size() - successrows)); + } + + @PutMapping("/modify") + @ApiOperation("岗位报名信息表-修改") + public AlitaResult modify(@RequestBody PositionRegistrationOperatorDTO operatorDTO) { + return AlitaResult.success(positionRegistrationService.modify(operatorDTO)); + } + + @DeleteMapping("/{id}") + @ApiOperation("岗位报名信息表-删除") + public AlitaResult delete(@PathVariable("id") Long id) { + return AlitaResult.success(positionRegistrationService.delete(id)); + } + + @GetMapping("/{id}") + @ApiOperation("岗位报名信息表-查询单个") + public AlitaResult findById(@PathVariable("id") Long id, @RequestParam("childrenOrgAll") Boolean childrenOrgAll) { + return AlitaResult.success(positionRegistrationService.findByIdAndChildrenOrgAll(id,childrenOrgAll)); + } + + @GetMapping("/list") + @ApiOperation("岗位报名信息表-列表查询") + public AlitaResult> list(PositionRegistrationPageQueryDTO queryDTO) { + return AlitaResult.success(positionRegistrationService.list(queryDTO)); + } + + @GetMapping("/page") + @ApiOperation("岗位报名信息表-分页查询") + public AlitaResult> page(PositionRegistrationPageQueryDTO queryDTO) { + positionRegistrationService.page(queryDTO); + return AlitaResult.success(queryDTO.getPageResult()); + } + + /** + * @description: 用户端报名岗位 + * @return: + * @author: guixinman + * @param: + */ + @PostMapping("/user_create") + public AlitaResult userCreate(@RequestBody @Validated UserPositionRegistrationDTO dto) { + positionRegistrationService.userCreate(dto); + return AlitaResult.success(); + } + + @PostMapping("/invite") + @ApiOperation("岗位报名信息表-邀约面试") + public AlitaResult invite(@RequestBody PositionRegistrationOperatorDTO operatorDTO) { + if (CollectionUtils.isEmpty(operatorDTO.getIds())) { + throw new BusinessException("缺失参数"); + } + int successrows = operatorDTO.getIds().size(); + for (Long id : operatorDTO.getIds()) { + try { + operatorDTO.setId(id); + positionRegistrationService.invite(operatorDTO); + } catch (Exception e) { + successrows = successrows - 1; + log.error(String.format("邀约面试id:%s 操作邀约面试,失败原因:%s",id,e.getMessage())); + } + } + return AlitaResult.success(String.format("成功数: %s条,失败数: %s条", successrows, operatorDTO.getIds().size() - successrows)); + } + + @PostMapping("/termination") + @ApiOperation("岗位报名信息表-结束招聘") + public AlitaResult termination(@RequestBody PositionRegistrationOperatorDTO operatorDTO) { + if (CollectionUtils.isEmpty(operatorDTO.getIds())) { + throw new BusinessException("缺失参数"); + } + int successrows = operatorDTO.getIds().size(); + for (Long id : operatorDTO.getIds()) { + try { + operatorDTO.setId(id); + positionRegistrationService.termination(operatorDTO); + } catch (Exception e) { + successrows = successrows - 1; + log.error(String.format("结束招聘id:%s 操作结束招聘,失败原因:%s",id,e.getMessage())); + } + } + return AlitaResult.success(String.format("成功数: %s条,失败数: %s条", successrows, operatorDTO.getIds().size() - successrows)); + } + + @PostMapping("/fulfillInterview") + @ApiOperation("岗位报名信息表-完成面试") + public AlitaResult fulfillInterview(@RequestBody PositionRegistrationOperatorDTO operatorDTO) { + if (CollectionUtils.isEmpty(operatorDTO.getIds())) { + throw new BusinessException("缺失参数"); + } + int successrows = operatorDTO.getIds().size(); + for (Long id : operatorDTO.getIds()) { + try { + operatorDTO.setId(id); + positionRegistrationService.fulfillInterview(operatorDTO); + } catch (Exception e) { + successrows = successrows - 1; + log.error(String.format("完成面试id:%s 操作完成面试,失败原因:%s",id,e.getMessage())); + } + } + return AlitaResult.success(String.format("成功数: %s条,失败数: %s条", successrows, operatorDTO.getIds().size() - successrows)); + } + + @PostMapping("/onTheJob") + @ApiOperation("岗位报名信息表-入职") + public AlitaResult onTheJob(@RequestBody @Validated OnTheJobDTO dto) { + positionRegistrationService.onTheJob(dto); + return AlitaResult.success(); + } + + @PostMapping("/resigned") + @ApiOperation("岗位报名信息表-离职") + public AlitaResult resigned(@RequestBody @Validated ResignedDTO dto) { + positionRegistrationService.resigned(dto); + return AlitaResult.success(); + } + + @GetMapping("/export") + @ApiOperation("岗位报名信息表-导出") + public void export(PositionRegistrationPageQueryDTO queryDTO) { + positionRegistrationService.export(queryDTO); + } + + @GetMapping("/userPage") + @ApiOperation("岗位报名信息表-用户端分页查询") + public AlitaResult> userPage(UserPositionRegistrationPageQueryDTO queryDTO) { + positionRegistrationService.userPage(queryDTO); + return AlitaResult.success(queryDTO.getPageResult()); + } + + @GetMapping("/user_cancel") + @ApiOperation("岗位报名信息表-用户端取消报名") + public AlitaResult cancel(@RequestParam("positionId") Long positionId) { + positionRegistrationService.cancel(positionId); + return AlitaResult.success(); + } + + @ApiOperation("查看") + @PutMapping("/show") + public AlitaResult show(@RequestParam("id") Long id){ + positionRegistrationService.show(id); + return AlitaResult.success(); + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/controller/PositionTypeController.java b/src/main/java/com/newyetai/recruit/position/controller/PositionTypeController.java new file mode 100644 index 0000000..0aab10c --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/controller/PositionTypeController.java @@ -0,0 +1,42 @@ +package com.newyetai.recruit.position.controller; + + +import com.newyetai.common.AlitaResult; +import com.newyetai.recruit.position.dto.PositionTypeDTO; +import com.newyetai.recruit.position.dto.PositionTypeQueryDTO; +import com.newyetai.recruit.position.service.PositionTypeService; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; + +/** + *

+ * 招聘系统-岗位信息表 前端控制器 + *

+ * + * @author chenyun + * @since 2021-01-08 + */ +@Api(tags = "岗位类型信息") +@RestController +@RequestMapping("/anon/hr/position/type") +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class PositionTypeController { + + private final PositionTypeService positionTypeService; + + @GetMapping("/tree") + @ApiOperation("岗位类型树形列表") + public AlitaResult> positionList(PositionTypeQueryDTO queryDTO) { + return AlitaResult.success(positionTypeService.query(queryDTO)); + } +} + diff --git a/src/main/java/com/newyetai/recruit/position/controller/UserPositionController.java b/src/main/java/com/newyetai/recruit/position/controller/UserPositionController.java new file mode 100644 index 0000000..bf5cd63 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/controller/UserPositionController.java @@ -0,0 +1,60 @@ +package com.newyetai.recruit.position.controller; + +import com.newyetai.common.AlitaResult; +import com.newyetai.recruit.position.dto.PositionDTO; +import com.newyetai.recruit.position.dto.PositionPageQueryDTO; +import com.newyetai.recruit.position.service.PositionService; +import com.newyetai.security.util.MockUtils; +import com.newyetai.tkmybatis.pojo.Page; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; +import java.util.Set; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +/** + * @description: 用户端岗位信息查询 + * @author: guixinman + * @create: 2024-04-18 15:48 + **/ +@Api(tags = "岗位信息表;岗位信息表") +@RestController +public class UserPositionController { + + @Autowired + private PositionService positionService; + + + @GetMapping("/anon/user/position/page") + @ApiOperation("岗位信息表;岗位信息表-分页查询") + public AlitaResult> page(PositionPageQueryDTO queryDTO) { + positionService.userPage(queryDTO); + return AlitaResult.success(queryDTO.getPageResult()); + } + + @GetMapping("/anon/tencent_map/user/position/page") + @ApiOperation("岗位信息腾讯地图-分页查询") + public AlitaResult> tencentMapUserPage(PositionPageQueryDTO queryDTO) { + return AlitaResult.success(positionService.tencentMapUserPage(queryDTO)); + } + + @GetMapping("/anon/user/position/{id}") + @ApiOperation("岗位信息表;岗位信息表-查询单个") + public AlitaResult userFindById(@PathVariable("id") Long id) { + return AlitaResult.success(positionService.userFindById(id)); + } + + @GetMapping("/user/position/personPostMatching") + @ApiOperation("人岗匹配") + public AlitaResult> personPostMatching(@RequestParam("id") Long id) { + return AlitaResult.success(positionService.personPostMatching(id)); + } + +} diff --git a/src/main/java/com/newyetai/recruit/position/convert/ImportDetailPositionConvert.java b/src/main/java/com/newyetai/recruit/position/convert/ImportDetailPositionConvert.java new file mode 100644 index 0000000..5bcfef0 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/convert/ImportDetailPositionConvert.java @@ -0,0 +1,26 @@ +package com.newyetai.recruit.position.convert; + +import com.newyetai.recruit.position.entity.ImportDetailPosition; +import com.newyetai.recruit.position.dto.ImportDetailPositionDTO; +import com.newyetai.recruit.position.dto.ImportDetailPositionOperatorDTO; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * 岗位导入 + * + * @author guixinman + * @since 1.0.0 2024-04-12 + */ +@Mapper +public interface ImportDetailPositionConvert { + ImportDetailPositionConvert INSTANCE = Mappers.getMapper(ImportDetailPositionConvert.class); + + ImportDetailPosition convert(ImportDetailPositionDTO dto); + + ImportDetailPositionDTO convert(ImportDetailPosition entity); + + ImportDetailPosition convert(ImportDetailPositionOperatorDTO dto); + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/convert/PositionAuditConvert.java b/src/main/java/com/newyetai/recruit/position/convert/PositionAuditConvert.java new file mode 100644 index 0000000..25c36d6 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/convert/PositionAuditConvert.java @@ -0,0 +1,35 @@ +package com.newyetai.recruit.position.convert; + +import com.newyetai.recruit.position.dto.PositionDTO; +import com.newyetai.recruit.position.dto.PositionNewDTO; +import com.newyetai.recruit.position.dto.PositionOperatorDTO; +import com.newyetai.recruit.position.entity.PositionAudit; +import com.newyetai.recruit.position.dto.PositionAuditDTO; +import com.newyetai.recruit.position.dto.PositionAuditOperatorDTO; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 岗位审核表 + * + * @author guixinman + * @since 1.0.0 2024-07-05 + */ +@Mapper +public interface PositionAuditConvert { + PositionAuditConvert INSTANCE = Mappers.getMapper(PositionAuditConvert.class); + + PositionAudit convert(PositionAuditDTO dto); + + PositionAuditDTO convert(PositionAudit entity); + + PositionAudit convert(PositionAuditOperatorDTO dto); + + PositionNewDTO convert(PositionOperatorDTO dto); + + PositionNewDTO convert(PositionDTO dto); + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/convert/PositionConvert.java b/src/main/java/com/newyetai/recruit/position/convert/PositionConvert.java new file mode 100644 index 0000000..f2eb71a --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/convert/PositionConvert.java @@ -0,0 +1,26 @@ +package com.newyetai.recruit.position.convert; + +import com.newyetai.recruit.position.entity.Position; +import com.newyetai.recruit.position.dto.PositionDTO; +import com.newyetai.recruit.position.dto.PositionOperatorDTO; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * 岗位信息表;岗位信息表 + * + * @author guixinman + * @since 1.0.0 2024-04-11 + */ +@Mapper +public interface PositionConvert { + PositionConvert INSTANCE = Mappers.getMapper(PositionConvert.class); + + Position convert(PositionDTO dto); + + PositionDTO convert(Position entity); + + Position convert(PositionOperatorDTO dto); + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/convert/PositionRegistrationConvert.java b/src/main/java/com/newyetai/recruit/position/convert/PositionRegistrationConvert.java new file mode 100644 index 0000000..04bb812 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/convert/PositionRegistrationConvert.java @@ -0,0 +1,27 @@ +package com.newyetai.recruit.position.convert; + +import com.newyetai.recruit.position.entity.PositionRegistration; +import com.newyetai.recruit.position.dto.PositionRegistrationDTO; +import com.newyetai.recruit.position.dto.PositionRegistrationOperatorDTO; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + + +/** + * 岗位报名信息表 + * + * @author guixinman + * @since 1.0.0 2024-04-15 + */ +@Mapper +public interface PositionRegistrationConvert { + PositionRegistrationConvert INSTANCE = Mappers.getMapper(PositionRegistrationConvert.class); + + PositionRegistration convert(PositionRegistrationDTO dto); + + PositionRegistrationDTO convert(PositionRegistration entity); + + PositionRegistration convert(PositionRegistrationOperatorDTO dto); + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/dao/ImportDetailPositionMapper.java b/src/main/java/com/newyetai/recruit/position/dao/ImportDetailPositionMapper.java new file mode 100644 index 0000000..800705b --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dao/ImportDetailPositionMapper.java @@ -0,0 +1,26 @@ +package com.newyetai.recruit.position.dao; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.recruit.position.entity.ImportDetailPosition; +import com.newyetai.recruit.position.dto.ImportDetailPositionDTO; +import com.newyetai.recruit.position.dto.ImportDetailPositionQueryDTO; +import com.newyetai.recruit.position.dto.ImportDetailPositionPageQueryDTO; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 岗位导入 + * + * @author guixinman + * @since 1.0.0 2024-04-12 + */ +@Mapper +public interface ImportDetailPositionMapper extends MyMapper { + + List page(@Param("param") ImportDetailPositionPageQueryDTO queryDTO); + + List list(@Param("param") ImportDetailPositionQueryDTO queryDTO); +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/dao/PositionAddressMapper.java b/src/main/java/com/newyetai/recruit/position/dao/PositionAddressMapper.java new file mode 100644 index 0000000..65b2471 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dao/PositionAddressMapper.java @@ -0,0 +1,16 @@ +package com.newyetai.recruit.position.dao; + + +import com.newyetai.recruit.position.entity.PositionAddress; +import com.newyetai.tkmybatis.mybatis.MyMapper; + + +/** + * 位置地址映射器 + * + * @author Carlye + * @date 2022/03/29 + */ +public interface PositionAddressMapper extends MyMapper { + +} diff --git a/src/main/java/com/newyetai/recruit/position/dao/PositionAuditMapper.java b/src/main/java/com/newyetai/recruit/position/dao/PositionAuditMapper.java new file mode 100644 index 0000000..3948a68 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dao/PositionAuditMapper.java @@ -0,0 +1,49 @@ +package com.newyetai.recruit.position.dao; + +import com.newyetai.recruit.position.dto.PositionAuditReqDTO; +import com.newyetai.recruit.position.dto.PositionNewDTO; +import com.newyetai.recruit.position.dto.PositionNewPageQueryDTO; +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.recruit.position.entity.PositionAudit; +import com.newyetai.recruit.position.dto.PositionAuditDTO; +import com.newyetai.recruit.position.dto.PositionAuditQueryDTO; +import com.newyetai.recruit.position.dto.PositionAuditPageQueryDTO; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 岗位审核表 + * + * @author guixinman + * @since 1.0.0 2024-07-05 + */ +@Mapper +public interface PositionAuditMapper extends MyMapper { + + List page(@Param("param") PositionAuditPageQueryDTO queryDTO); + + List list(@Param("param") PositionAuditQueryDTO queryDTO); + + /** + * @description: 岗位分页查询 + * @return: + * @author: guixinman + * @param: + */ + List positionPage(@Param("param") PositionNewPageQueryDTO queryDTO); + + int modifyById(@Param("param") PositionAudit positionAudit); + + int audit(@Param("param") PositionAuditReqDTO reqDTO); + + /** + * @description: 根据岗位id获取审核表id + * @return: + * @author: guixinman + * @param: + */ + Long getIdByPositionId(@Param("positionId") Long positionId); +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/dao/PositionFileMapper.java b/src/main/java/com/newyetai/recruit/position/dao/PositionFileMapper.java new file mode 100644 index 0000000..6db682e --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dao/PositionFileMapper.java @@ -0,0 +1,28 @@ +package com.newyetai.recruit.position.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.newyetai.recruit.position.dto.PositionFileDTO; +import com.newyetai.recruit.position.dto.PositionFilePageQueryDTO; +import com.newyetai.recruit.position.entity.PositionFile; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 用户岗位访问记录表 Mapper 接口 + *

+ * + * @author Carlye + * @since 2021-01-21 + */ +@Mapper +public interface PositionFileMapper extends BaseMapper { + + + List filePage(PositionFilePageQueryDTO queryDTO); + + void setDefault(@Param("positionId") Long positionId, @Param("id") Long id); +} diff --git a/src/main/java/com/newyetai/recruit/position/dao/PositionMapper.java b/src/main/java/com/newyetai/recruit/position/dao/PositionMapper.java new file mode 100644 index 0000000..645b57b --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dao/PositionMapper.java @@ -0,0 +1,41 @@ +package com.newyetai.recruit.position.dao; + +import com.newyetai.recruit.position.dto.PersonPostMatchingQueryDTO; +import com.newyetai.recruit.statistics.dto.StatisticsBaseDTO; +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.recruit.position.entity.Position; +import com.newyetai.recruit.position.dto.PositionDTO; +import com.newyetai.recruit.position.dto.PositionPageQueryDTO; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; +import java.util.Map; + +/** + * 岗位信息表;岗位信息表 + * + * @author guixinman + * @since 1.0.0 2024-04-11 + */ +@Mapper +public interface PositionMapper extends MyMapper { + + List page(@Param("param") PositionPageQueryDTO queryDTO); + + + List userPage(@Param("param") PositionPageQueryDTO queryDTO); + + /** + * 岗位类型分组求数量 + */ + List positionTypeGroupMap(@Param("recruitPositionType") String recruitPositionType); + + List personPostMatching(@Param("param") PersonPostMatchingQueryDTO queryDTO); + + /** + * 岗位过期 + */ + void positionExpiry(); +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/dao/PositionRegistrationMapper.java b/src/main/java/com/newyetai/recruit/position/dao/PositionRegistrationMapper.java new file mode 100644 index 0000000..aa98b13 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dao/PositionRegistrationMapper.java @@ -0,0 +1,30 @@ +package com.newyetai.recruit.position.dao; + +import com.newyetai.recruit.position.dto.UserPositionRegistrationPageQueryDTO; +import com.newyetai.recruit.position.dto.UserPositionRegistrationResDTO; +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.recruit.position.entity.PositionRegistration; +import com.newyetai.recruit.position.dto.PositionRegistrationDTO; +import com.newyetai.recruit.position.dto.PositionRegistrationPageQueryDTO; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 岗位报名信息表 + * + * @author guixinman + * @since 1.0.0 2024-04-15 + */ +@Mapper +public interface PositionRegistrationMapper extends MyMapper { + + List page(@Param("param") PositionRegistrationPageQueryDTO queryDTO); + + long updateStatus(@Param("param") PositionRegistration positionRegistration, @Param("oldStatus") String oldStatus); + + List userPage(@Param("param") UserPositionRegistrationPageQueryDTO queryDTO); + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/dao/PositionTypeMapper.java b/src/main/java/com/newyetai/recruit/position/dao/PositionTypeMapper.java new file mode 100644 index 0000000..7425640 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dao/PositionTypeMapper.java @@ -0,0 +1,25 @@ +package com.newyetai.recruit.position.dao; + + +import com.newyetai.recruit.position.dto.PositionTypeDTO; +import com.newyetai.recruit.position.dto.PositionTypeQueryDTO; +import com.newyetai.recruit.position.entity.PositionType; +import com.newyetai.tkmybatis.mybatis.MyMapper; + +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + *

+ * 用户岗位访问记录表 Mapper 接口 + *

+ * + * @author Carlye + * @since 2021-01-21 + */ +@Mapper +public interface PositionTypeMapper extends MyMapper { + + List queryByDto(PositionTypeQueryDTO queryDTO); +} diff --git a/src/main/java/com/newyetai/recruit/position/dto/ImportDetailPositionDTO.java b/src/main/java/com/newyetai/recruit/position/dto/ImportDetailPositionDTO.java new file mode 100644 index 0000000..7a1bf75 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/ImportDetailPositionDTO.java @@ -0,0 +1,142 @@ +package com.newyetai.recruit.position.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.newyetai.component.commonimport.dto.ImportDetailSuperDTO; + +import org.springframework.format.annotation.DateTimeFormat; + +import java.math.BigDecimal; +import java.util.Date; + +import cn.hutool.core.util.StrUtil; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.SuperBuilder; + +/** + * 岗位导入 + * + * @author guixinman + * @since 1.0.0 2024-04-12 + */ +@ApiModel("岗位导入") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class ImportDetailPositionDTO extends ImportDetailSuperDTO { + private static final long serialVersionUID = 1L; + + @ApiModelProperty("导入任务ID") + private Long mainId; + + @ApiModelProperty("机构ID") + private Long orgId; + + @ApiModelProperty("模板全量数据") + private String dataJson; + + @ApiModelProperty("用工企业ID ;hr_company") + private Long companyId; + + private String companyName; + + @ApiModelProperty("岗位名称") + private String positionName; + + @ApiModelProperty("招聘标题") + private String recruitTitle; + + @ApiModelProperty("岗位招聘人数") + private Integer positionNumber; + + @ApiModelProperty("工作地址") + private String positionAddress; + + /** + * 岗位性质 数据字典 + */ + private String recruitPositionType; + + @ApiModelProperty("岗位类型") + private String positionTypeName; + + @ApiModelProperty("岗位标签") + private String positionTag; + + @ApiModelProperty("发薪日") + private String payDate; + + @ApiModelProperty("性别要求") + private String sexRequire; + + @ApiModelProperty("学历要求") + private String educationRequire; + + @ApiModelProperty("经验要求") + private String experienceRequire; + + @ApiModelProperty("证件要求") + private String certificatesRequire; + + @ApiModelProperty("其他要求") + private String otherRequire; + + @ApiModelProperty("工作内容") + private String jobContent; + + @ApiModelProperty("明细状态") + private Integer detailStatus; + + @ApiModelProperty("失败原因") + private String failReason; + + @ApiModelProperty("外部生成明细id") + private Long extraDetailId; + + @ApiModelProperty("备注") + private String remark; + + /** + * 年龄上限 + */ + private Integer ageUp; + + /** + * 年龄下限 + */ + private Integer ageLow; + + /** + * 薪资上限 + */ + private BigDecimal salaryUp; + + /** + * 薪资下限 + */ + private BigDecimal salaryLow; + + /** + * 薪资类型 + */ + private String salaryType; + + /** + * 结束日期 + */ + private String endTime; + + public void appendFailMsg(String msg) { + if (StrUtil.isEmpty(msg)) { + return; + } + if (StrUtil.isEmpty(getFailReason())) { + setFailReason(msg); + } else { + setFailReason(String.join(",", getFailReason(), msg)); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/dto/ImportDetailPositionExecuteDTO.java b/src/main/java/com/newyetai/recruit/position/dto/ImportDetailPositionExecuteDTO.java new file mode 100644 index 0000000..17c5993 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/ImportDetailPositionExecuteDTO.java @@ -0,0 +1,14 @@ +package com.newyetai.recruit.position.dto; + +import com.newyetai.component.commonimport.dto.ImportExecuteSuperDTO; + +import lombok.Data; + +/** + * @description: 确定导入DTO + * @author: guixinman + * @create: 2024-04-12 10:25 + **/ +@Data +public class ImportDetailPositionExecuteDTO extends ImportExecuteSuperDTO { +} diff --git a/src/main/java/com/newyetai/recruit/position/dto/ImportDetailPositionExportDTO.java b/src/main/java/com/newyetai/recruit/position/dto/ImportDetailPositionExportDTO.java new file mode 100644 index 0000000..fe6d504 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/ImportDetailPositionExportDTO.java @@ -0,0 +1,94 @@ +package com.newyetai.recruit.position.dto; + +import com.alibaba.excel.annotation.ExcelProperty; +import java.io.Serializable; +import java.math.BigDecimal; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @description: + * @author: guixinman + * @create: 2024-06-12 13:57 + **/ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ImportDetailPositionExportDTO implements Serializable { + + @ExcelProperty("用工企业") + private String companyName; + + @ExcelProperty("岗位名称") + private String positionName; + + @ExcelProperty("招聘标题") + private String recruitTitle; + + @ExcelProperty("招聘人数") + private Integer positionNumber; + + @ExcelProperty("工作地址") + private String positionAddress; + + /** + * 岗位性质 数据字典 + */ + @ExcelProperty("岗位性质") + private String recruitPositionType; + + @ExcelProperty("岗位类型") + private String positionTypeName; + + @ExcelProperty("岗位标签") + private String positionTag; + + @ExcelProperty("薪资下限") + private BigDecimal salaryLow; + + @ExcelProperty("薪资上限") + private BigDecimal salaryUp; + + @ExcelProperty("薪资类型") + private String salaryType; + + @ExcelProperty("发薪日") + private String payDate; + + @ExcelProperty("性别") + private String sexRequire; + + @ExcelProperty("年龄(下限)") + private Integer ageLow; + + @ExcelProperty("年龄(上限)") + private Integer ageUp; + + @ExcelProperty("学历") + private String educationRequire; + + @ExcelProperty("经验") + private String experienceRequire; + + @ExcelProperty("证件") + private String certificatesRequire; + + @ExcelProperty("其他") + private String otherRequire; + + @ExcelProperty("工作") + private String jobContent; + + @ExcelProperty("有效期截止时间") + private String endTime; + + @ExcelProperty("失败原因") + private String failReason; + + @ExcelProperty("备注") + private String remark; +} diff --git a/src/main/java/com/newyetai/recruit/position/dto/ImportDetailPositionListenerDTO.java b/src/main/java/com/newyetai/recruit/position/dto/ImportDetailPositionListenerDTO.java new file mode 100644 index 0000000..c5d535a --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/ImportDetailPositionListenerDTO.java @@ -0,0 +1,86 @@ +package com.newyetai.recruit.position.dto; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.newyetai.component.commonimport.service.IImportDetailForm; + +import java.math.BigDecimal; +import java.util.Date; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @description: 岗位导入dto + * @author: guixinman + * @create: 2024-04-12 10:26 + **/ +@Data +public class ImportDetailPositionListenerDTO implements IImportDetailForm { + + @ApiModelProperty("用工企业") + private String companyName; + + @ApiModelProperty("岗位名称") + private String positionName; + + @ApiModelProperty("招聘标题") + private String recruitTitle; + + @ApiModelProperty("招聘人数") + private Integer positionNumber; + + @ApiModelProperty("工作地址") + private String positionAddress; + + /** + * 岗位性质 数据字典 + */ + private String recruitPositionType; + + @ApiModelProperty("岗位类型") + private String positionTypeName; + + @ApiModelProperty("岗位标签") + private String positionTag; + + @ApiModelProperty("薪资下限") + private BigDecimal salaryLow; + + @ApiModelProperty("薪资上限") + private BigDecimal salaryUp; + + @ApiModelProperty("薪资类型") + private String salaryType; + + @ApiModelProperty("发薪日") + private String payDate; + + @ApiModelProperty("性别要求") + private String sexRequire; + + @ApiModelProperty("年龄(下限)") + private Integer ageLow; + + @ApiModelProperty("年龄(上限)") + private Integer ageUp; + + @ApiModelProperty("学历要求") + private String educationRequire; + + @ApiModelProperty("经验要求") + private String experienceRequire; + + @ApiModelProperty("证件要求") + private String certificatesRequire; + + @ApiModelProperty("其他要求") + private String otherRequire; + + @ApiModelProperty("工作内容") + private String jobContent; + + /** + * 结束日期 + */ + private String endTime; +} diff --git a/src/main/java/com/newyetai/recruit/position/dto/ImportDetailPositionOperatorDTO.java b/src/main/java/com/newyetai/recruit/position/dto/ImportDetailPositionOperatorDTO.java new file mode 100644 index 0000000..2e2e6db --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/ImportDetailPositionOperatorDTO.java @@ -0,0 +1,121 @@ +package com.newyetai.recruit.position.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; +import java.math.BigDecimal; +import java.util.Date; + +/** + * 岗位导入 + * + * @author guixinman + * @since 1.0.0 2024-04-12 + */ +@ApiModel("岗位导入") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ImportDetailPositionOperatorDTO implements Serializable { + private static final long serialVersionUID = 1L; + + private Long id; + + @ApiModelProperty("导入任务ID") + private Long mainId; + + @ApiModelProperty("机构ID") + private Long orgId; + + @ApiModelProperty("模板全量数据") + private String dataJson; + + @ApiModelProperty("公司ID ;hr_company") + private Long companyId; + + @ApiModelProperty("岗位名称") + private String positionName; + + @ApiModelProperty("招聘标题") + private String recruitTitle; + + @ApiModelProperty("岗位招聘人数") + private Integer positionNumber; + + @ApiModelProperty("工作地址") + private String positionAddress; + + /** + * 岗位性质 数据字典 + */ + private String recruitPositionType; + + + @ApiModelProperty("发薪日") + private String payDate; + + @ApiModelProperty("性别要求") + private Integer sexRequire; + + + @ApiModelProperty("学历要求") + private Integer educationRequire; + + @ApiModelProperty("经验要求") + private String experienceRequire; + + @ApiModelProperty("证件要求") + private String certificatesRequire; + + @ApiModelProperty("其他要求") + private String otherRequire; + + @ApiModelProperty("工作内容") + private String jobContent; + + @ApiModelProperty("明细状态") + private Integer detailStatus; + + @ApiModelProperty("失败原因") + private String failReason; + + @ApiModelProperty("外部生成明细id") + private Long extraDetailId; + + @ApiModelProperty("备注") + private String remark; + + /** + * 年龄上限 + */ + private Integer ageUp; + + /** + * 年龄下限 + */ + private Integer ageLow; + + /** + * 薪资上限 + */ + private BigDecimal salaryUp; + + /** + * 薪资下限 + */ + private BigDecimal salaryLow; + + /** + * 薪资类型 + */ + private String salaryType; + + private Date endTime; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/dto/ImportDetailPositionPageQueryDTO.java b/src/main/java/com/newyetai/recruit/position/dto/ImportDetailPositionPageQueryDTO.java new file mode 100644 index 0000000..68f3f1b --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/ImportDetailPositionPageQueryDTO.java @@ -0,0 +1,119 @@ +package com.newyetai.recruit.position.dto; + +import com.newyetai.common.dto.PageQueryDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.format.annotation.DateTimeFormat; + + +import java.util.Date; + +/** + * 岗位导入 + * + * @author guixinman + * @since 1.0.0 2024-04-12 + */ + +@ApiModel("岗位导入") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class ImportDetailPositionPageQueryDTO extends PageQueryDTO { + private static final long serialVersionUID = 1L; + + private Long id; + + @ApiModelProperty("导入任务ID") + private Long mainId; + + @ApiModelProperty("机构ID") + private Long orgId; + + @ApiModelProperty("模板全量数据") + private String dataJson; + + @ApiModelProperty("公司ID ;hr_company") + private Long companyId; + + @ApiModelProperty("岗位名称 (模糊匹配)") + private String positionNameLike; + + @ApiModelProperty("招聘标题") + private String recruitTitle; + + @ApiModelProperty("岗位招聘人数") + private Integer positionNumber; + + @ApiModelProperty("工作地址") + private String positionAddress; + + /** + * 岗位性质 数据字典 + */ + private String recruitPositionType; + + + @ApiModelProperty("发薪日") + private String payDate; + + @ApiModelProperty("性别要求") + private Integer sexRequire; + + + @ApiModelProperty("学历要求") + private Integer educationRequire; + + @ApiModelProperty("经验要求") + private String experienceRequire; + + @ApiModelProperty("证件要求") + private String certificatesRequire; + + @ApiModelProperty("其他要求") + private String otherRequire; + + @ApiModelProperty("工作内容") + private String jobContent; + + @ApiModelProperty("明细状态") + private Integer detailStatus; + + @ApiModelProperty("失败原因") + private String failReason; + + @ApiModelProperty("外部生成明细id") + private Long extraDetailId; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("更新时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeStart; + + @ApiModelProperty("更新时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeEnd; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/dto/ImportDetailPositionQueryDTO.java b/src/main/java/com/newyetai/recruit/position/dto/ImportDetailPositionQueryDTO.java new file mode 100644 index 0000000..a60f6cb --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/ImportDetailPositionQueryDTO.java @@ -0,0 +1,119 @@ +package com.newyetai.recruit.position.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; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +/** + * 岗位导入 + * + * @author guixinman + * @since 1.0.0 2024-04-12 + */ +@ApiModel("岗位导入") +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ImportDetailPositionQueryDTO implements Serializable { + private static final long serialVersionUID = 1L; + + private Long id; + + @ApiModelProperty("导入任务ID") + private Long mainId; + + @ApiModelProperty("机构ID") + private Long orgId; + + @ApiModelProperty("模板全量数据") + private String dataJson; + + @ApiModelProperty("公司ID ;hr_company") + private Long companyId; + + @ApiModelProperty("岗位名称 (模糊匹配)") + private String positionNameLike; + + @ApiModelProperty("招聘标题") + private String recruitTitle; + + @ApiModelProperty("岗位招聘人数") + private Integer positionNumber; + + @ApiModelProperty("工作地址") + private String positionAddress; + + /** + * 岗位性质 数据字典 + */ + private String recruitPositionType; + + + @ApiModelProperty("发薪日") + private String payDate; + + @ApiModelProperty("性别要求") + private Integer sexRequire; + + + @ApiModelProperty("学历要求") + private Integer educationRequire; + + @ApiModelProperty("经验要求") + private String experienceRequire; + + @ApiModelProperty("证件要求") + private String certificatesRequire; + + @ApiModelProperty("其他要求") + private String otherRequire; + + @ApiModelProperty("工作内容") + private String jobContent; + + @ApiModelProperty("明细状态") + private Integer detailStatus; + + @ApiModelProperty("失败原因") + private String failReason; + + @ApiModelProperty("外部生成明细id") + private Long extraDetailId; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("更新时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeStart; + + @ApiModelProperty("更新时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeEnd; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/dto/OnTheJobDTO.java b/src/main/java/com/newyetai/recruit/position/dto/OnTheJobDTO.java new file mode 100644 index 0000000..db3e22d --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/OnTheJobDTO.java @@ -0,0 +1,46 @@ +package com.newyetai.recruit.position.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.format.annotation.DateTimeFormat; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; + +import javax.validation.Valid; +import javax.validation.constraints.NotNull; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @description: 入职DTO + * @author: guixinman + * @create: 2024-04-16 14:47 + **/ +@Data +public class OnTheJobDTO implements Serializable { + + + @NotNull(message = "入职时间不能为空") + @ApiModelProperty("入职时间") + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "GMT+8") + private Date inductionTime; + + @NotNull(message = "明细数据不能为空") + private List<@Valid OnTheJobDetailDTO> detailDTOS; + + @Data + public static class OnTheJobDetailDTO { + + @NotNull(message = "请选择数据") + private Long id; + + @NotNull(message = "入职薪水不能为空") + @ApiModelProperty("入职薪水") + private BigDecimal salary; + } +} diff --git a/src/main/java/com/newyetai/recruit/position/dto/PersonPostMatchingQueryDTO.java b/src/main/java/com/newyetai/recruit/position/dto/PersonPostMatchingQueryDTO.java new file mode 100644 index 0000000..a865b20 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/PersonPostMatchingQueryDTO.java @@ -0,0 +1,57 @@ +package com.newyetai.recruit.position.dto; + +import com.newyetai.common.dto.PageQueryDTO; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.List; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @description: + * @author: guixinman + * @create: 2024-09-11 16:51 + **/ +@ApiModel("人岗匹配") +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class PersonPostMatchingQueryDTO extends PageQueryDTO { + + /** + * 性别 + */ + private String sexRequire; + + /** + * 年龄 + */ + private Integer age; + + /** + * 学历 + */ + private String educationRequire; + + /** + * 薪水 + */ + private BigDecimal salary; + + /** + * 岗位类型 + */ + private String positionType; + private String positionNameLike; + + /** + * 工作地 + */ + private String detailAddressLike; +} diff --git a/src/main/java/com/newyetai/recruit/position/dto/PositionAddressDTO.java b/src/main/java/com/newyetai/recruit/position/dto/PositionAddressDTO.java new file mode 100644 index 0000000..5d53e8f --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/PositionAddressDTO.java @@ -0,0 +1,51 @@ +package com.newyetai.recruit.position.dto; + +import com.newyetai.common.dto.BaseDTO; + +import java.math.BigDecimal; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + *

+ * 招聘系统-岗位地址信息表 + *

+ * + * @author chenyun + * @since 2021-01-08 + */ +@EqualsAndHashCode(callSuper = true) +@ApiModel("招聘系统岗位地址信息DTO") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public class PositionAddressDTO extends BaseDTO { + + private static final long serialVersionUID = -350362178226190054L; + + @ApiModelProperty("岗位ID") + private Long companyId; + + @ApiModelProperty("区域编码") + private String districtCode; + + @ApiModelProperty("区域名称") + private String districtName; + + @ApiModelProperty("详细地址") + private String detailAddress; + + @ApiModelProperty("经度") + private BigDecimal longitude; + + @ApiModelProperty("纬度") + private BigDecimal latitude; +} diff --git a/src/main/java/com/newyetai/recruit/position/dto/PositionAddressOperatorDTO.java b/src/main/java/com/newyetai/recruit/position/dto/PositionAddressOperatorDTO.java new file mode 100644 index 0000000..50d3f65 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/PositionAddressOperatorDTO.java @@ -0,0 +1,60 @@ +package com.newyetai.recruit.position.dto; + +import com.newyetai.common.dto.BaseDTO; + +import java.math.BigDecimal; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + *

+ * 招聘系统-岗位地址信息表 + *

+ * + * @author chenyun + * @since 2021-01-08 + */ +@EqualsAndHashCode(callSuper = true) +@ApiModel("招聘系统岗位地址信息 - 创建DTO") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public class PositionAddressOperatorDTO extends BaseDTO { + + private static final long serialVersionUID = -350362178226190054L; + + @ApiModelProperty("企业ID") + @NotNull(message = "企业ID不能为空") + private Long companyId; + + @ApiModelProperty("区域编码") +// @NotEmpty(message = "区域编码不能为空") + private String districtCode; + + @ApiModelProperty("区域名称") +// @NotEmpty(message = "区域名称不能为空") + private String districtName; + + @ApiModelProperty("详细地址") + @NotEmpty(message = "详细地址不能为空") + private String detailAddress; + + @ApiModelProperty("经度") +// @NotEmpty(message = "经度不能为空") + private BigDecimal longitude; + + @ApiModelProperty("纬度") +// @NotEmpty(message = "纬度不能为空") + private BigDecimal latitude; +} diff --git a/src/main/java/com/newyetai/recruit/position/dto/PositionAddressQueryDTO.java b/src/main/java/com/newyetai/recruit/position/dto/PositionAddressQueryDTO.java new file mode 100644 index 0000000..3048578 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/PositionAddressQueryDTO.java @@ -0,0 +1,36 @@ +package com.newyetai.recruit.position.dto; + +import java.io.Serializable; +import java.util.Set; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + *

+ * 招聘系统-岗位地址信息表 + *

+ * + * @author chenyun + * @since 2021-01-08 + */ +@ApiModel("招聘系统岗位地址信息 - 查询DTO") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PositionAddressQueryDTO implements Serializable { + + private static final long serialVersionUID = -6376035694183055706L; + + @ApiModelProperty("岗位ID") + private Long companyId; + + @ApiModelProperty("ID集合") + private Set ids; + +} diff --git a/src/main/java/com/newyetai/recruit/position/dto/PositionAuditDTO.java b/src/main/java/com/newyetai/recruit/position/dto/PositionAuditDTO.java new file mode 100644 index 0000000..97f0abb --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/PositionAuditDTO.java @@ -0,0 +1,181 @@ +package com.newyetai.recruit.position.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.component.dict.util.DictUtils; + +import org.springframework.format.annotation.DateTimeFormat; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.SuperBuilder; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.Objects; + +/** + * 岗位审核表 + * + * @author guixinman + * @since 1.0.0 2024-07-05 + */ +@ApiModel("岗位审核表") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class PositionAuditDTO extends BaseDTO { + private static final long serialVersionUID = 1L; + + private Long positionId; + + private Long orgId; + + private String orgName; + + @ApiModelProperty("hr_company主键") + private Long companyId; + + private String companyName; + + @ApiModelProperty("岗位名称") + private String positionName; + + @ApiModelProperty("招聘标题") + private String recruitTitle; + + @ApiModelProperty("岗位类型") + private String positionType; + + private String positionTypeName; + + @ApiModelProperty("工作性质 1:短工 2:全职") + private String jobCategory; + + @ApiModelProperty("岗位招聘人数") + private Integer positionNumber; + + @ApiModelProperty("工作地址") + private String positionAddress; + + @ApiModelProperty("招聘专员") + private Long recruitUserId; + + @ApiModelProperty("发薪日") + private String payDate; + + @ApiModelProperty("性别要求") + private String sexRequire; + + @ApiModelProperty("学历要求") + private String educationRequire; + + @ApiModelProperty("经验要求") + private String experienceRequire; + + @ApiModelProperty("证件要求") + private String certificatesRequire; + + @ApiModelProperty("其他要求") + private String otherRequire; + + @ApiModelProperty("工作内容") + private String jobContent; + + @ApiModelProperty("岗位标签") + private String positionTag; + + private Long addressId; + + @ApiModelProperty("招聘岗位类型数据字典") + private String recruitPositionType; + + @ApiModelProperty("审核状态 1:待审核 2.审核成功 3.审核失败") + private String auditStatus; + + @ApiModelProperty("审核失败原因") + private String auditFailMsg; + + @ApiModelProperty("版本号") + private Integer version; + + @ApiModelProperty("工作地址") + private String detailAddress; + + private String fileJson; + + + /** + * 年龄上限 + */ + private Integer ageUp; + + /** + * 年龄下限 + */ + private Integer ageLow; + + /** + * 薪资上限 + */ + private BigDecimal salaryUp; + + /** + * 薪资下限 + */ + private BigDecimal salaryLow; + + /** + * 薪资类型 + */ + private String salaryType; + + private String salaryStr; + + private String ageStr; + + + /** + * 结束日期 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date endTime; + + public String getSalaryStr() { + String salary = ""; + if (Objects.nonNull(this.getSalaryUp()) && Objects.nonNull(this.getSalaryLow())) { + salary = String.format("%s~%s元/%s", this.getSalaryLow(), this.getSalaryUp(), DictUtils.getCodeNameMap("salary_type").get(String.valueOf(this.getSalaryType()))); + if (this.getSalaryLow().compareTo(this.getSalaryUp()) == 0) { + salary = String.format("%s元/%s", this.getSalaryUp(), DictUtils.getCodeNameMap("salary_type").get(String.valueOf(this.getSalaryType()))); + } + } else if (Objects.nonNull(this.getSalaryLow()) && Objects.isNull(this.getSalaryUp())) { + salary = String.format("%s元/%s", this.getSalaryLow(), DictUtils.getCodeNameMap("salary_type").get(String.valueOf(this.getSalaryType()))); + } else if (Objects.isNull(this.getSalaryLow()) && Objects.nonNull(this.getSalaryUp())) { + salary = String.format("%s元/%s", this.getSalaryUp(), DictUtils.getCodeNameMap("salary_type").get(String.valueOf(this.getSalaryType()))); + } else if (Objects.isNull(this.getSalaryLow()) && Objects.isNull(this.getSalaryUp())) { + salary = "薪资面议"; + } + return salary; + } + + public String getAgeStr() { + String age = ""; + if (Objects.nonNull(this.getAgeLow()) && Objects.nonNull(this.getAgeUp())) { + age = String.format("%s至%s岁", this.getAgeLow(), this.getAgeUp()); + if (this.getAgeLow().intValue() == this.getAgeUp().intValue()) { + age = String.format("%s岁", this.getAgeUp()); + } + } else if (Objects.nonNull(this.getAgeLow()) && Objects.isNull(this.getAgeUp())) { + age = String.format("%s岁以上", this.getAgeLow()); + } else if (Objects.isNull(this.getAgeLow()) && Objects.nonNull(this.getAgeUp())) { + age = String.format("18至%s岁", this.getAgeUp()); + } else if (Objects.isNull(this.getAgeLow()) && Objects.isNull(this.getAgeUp())) { + age = "18岁以上"; + } + return age; + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/dto/PositionAuditOperatorDTO.java b/src/main/java/com/newyetai/recruit/position/dto/PositionAuditOperatorDTO.java new file mode 100644 index 0000000..4570781 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/PositionAuditOperatorDTO.java @@ -0,0 +1,130 @@ +package com.newyetai.recruit.position.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.format.annotation.DateTimeFormat; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * 岗位审核表 + * + * @author guixinman + * @since 1.0.0 2024-07-05 + */ +@ApiModel("岗位审核表") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PositionAuditOperatorDTO implements Serializable { + private static final long serialVersionUID = 1L; + + private Long id; + + private Long positionId; + + private Long orgId; + + @ApiModelProperty("hr_company主键") + private Long companyId; + + @ApiModelProperty("岗位名称") + private String positionName; + + @ApiModelProperty("招聘标题") + private String recruitTitle; + + @ApiModelProperty("岗位类型") + private String positionType; + + @ApiModelProperty("工作性质 1:短工 2:全职") + private String jobCategory; + + @ApiModelProperty("岗位招聘人数") + private Integer positionNumber; + + @ApiModelProperty("工作地址") + private String positionAddress; + + @ApiModelProperty("招聘专员") + private Long recruitUserId; + + @ApiModelProperty("发薪日") + private String payDate; + + @ApiModelProperty("性别要求") + private String sexRequire; + + @ApiModelProperty("学历要求") + private String educationRequire; + + @ApiModelProperty("经验要求") + private String experienceRequire; + + @ApiModelProperty("证件要求") + private String certificatesRequire; + + @ApiModelProperty("其他要求") + private String otherRequire; + + @ApiModelProperty("工作内容") + private String jobContent; + + @ApiModelProperty("岗位标签") + private String positionTag; + + private Long addressId; + + @ApiModelProperty("招聘岗位类型数据字典") + private String recruitPositionType; + + @ApiModelProperty("审核状态 1:待审核 2.审核成功 3.审核失败") + private String auditStatus; + + @ApiModelProperty("审核失败原因") + private String auditFailMsg; + + @ApiModelProperty("版本号") + private Integer version; + + + /** + * 年龄上限 + */ + private Integer ageUp; + + /** + * 年龄下限 + */ + private Integer ageLow; + + /** + * 薪资上限 + */ + private BigDecimal salaryUp; + + /** + * 薪资下限 + */ + private BigDecimal salaryLow; + + /** + * 薪资类型 + */ + private String salaryType; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/dto/PositionAuditPageQueryDTO.java b/src/main/java/com/newyetai/recruit/position/dto/PositionAuditPageQueryDTO.java new file mode 100644 index 0000000..cceec5b --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/PositionAuditPageQueryDTO.java @@ -0,0 +1,128 @@ +package com.newyetai.recruit.position.dto; + +import com.newyetai.common.dto.PageQueryDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import java.io.Serializable; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.format.annotation.DateTimeFormat; + + +import java.util.Date; +import java.util.Set; + +/** + * 岗位审核表 + * + * @author guixinman + * @since 1.0.0 2024-07-05 + */ + +@ApiModel("岗位审核表") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class PositionAuditPageQueryDTO extends PageQueryDTO { + private static final long serialVersionUID = 1L; + + private Long id; + + private Long positionId; + + private Long orgId; + + private Set orgIds; + + private String orgNameLike; + + @ApiModelProperty("hr_company主键") + private Long companyId; + + @ApiModelProperty("岗位名称 (模糊匹配)") + private String positionNameLike; + + @ApiModelProperty("招聘标题") + private String recruitTitle; + + @ApiModelProperty("岗位类型") + private String positionType; + + @ApiModelProperty("工作性质 1:短工 2:全职") + private String jobCategory; + + @ApiModelProperty("岗位招聘人数") + private Integer positionNumber; + + @ApiModelProperty("工作地址") + private String positionAddress; + + @ApiModelProperty("招聘专员") + private Long recruitUserId; + + @ApiModelProperty("发薪日") + private String payDate; + + @ApiModelProperty("性别要求") + private String sexRequire; + + @ApiModelProperty("学历要求") + private String educationRequire; + + @ApiModelProperty("经验要求") + private String experienceRequire; + + @ApiModelProperty("证件要求") + private String certificatesRequire; + + @ApiModelProperty("其他要求") + private String otherRequire; + + @ApiModelProperty("工作内容") + private String jobContent; + + @ApiModelProperty("岗位标签") + private String positionTag; + + private Long addressId; + + @ApiModelProperty("招聘岗位类型数据字典") + private String recruitPositionType; + + @ApiModelProperty("审核状态 1:待审核 2.审核成功 3.审核失败") + private String auditStatus; + + @ApiModelProperty("审核失败原因") + private String auditFailMsg; + + @ApiModelProperty("版本号") + private Integer version; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("更新时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeStart; + + @ApiModelProperty("更新时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeEnd; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/dto/PositionAuditQueryDTO.java b/src/main/java/com/newyetai/recruit/position/dto/PositionAuditQueryDTO.java new file mode 100644 index 0000000..74bb4b7 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/PositionAuditQueryDTO.java @@ -0,0 +1,123 @@ +package com.newyetai.recruit.position.dto; + +import com.newyetai.common.dto.BaseDTO; + +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; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +/** + * 岗位审核表 + * + * @author guixinman + * @since 1.0.0 2024-07-05 + */ +@ApiModel("岗位审核表") +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class PositionAuditQueryDTO implements Serializable { + private static final long serialVersionUID = 1L; + + private Long id; + + private Long positionId; + + private Long orgId; + + @ApiModelProperty("hr_company主键") + private Long companyId; + + @ApiModelProperty("岗位名称 (模糊匹配)") + private String positionNameLike; + + @ApiModelProperty("招聘标题") + private String recruitTitle; + + @ApiModelProperty("岗位类型") + private String positionType; + + @ApiModelProperty("工作性质 1:短工 2:全职") + private String jobCategory; + + @ApiModelProperty("岗位招聘人数") + private Integer positionNumber; + + @ApiModelProperty("工作地址") + private String positionAddress; + + @ApiModelProperty("招聘专员") + private Long recruitUserId; + + @ApiModelProperty("发薪日") + private String payDate; + + @ApiModelProperty("性别要求") + private String sexRequire; + + @ApiModelProperty("学历要求") + private String educationRequire; + + @ApiModelProperty("经验要求") + private String experienceRequire; + + @ApiModelProperty("证件要求") + private String certificatesRequire; + + @ApiModelProperty("其他要求") + private String otherRequire; + + @ApiModelProperty("工作内容") + private String jobContent; + + @ApiModelProperty("岗位标签") + private String positionTag; + + private Long addressId; + + @ApiModelProperty("招聘岗位类型数据字典") + private String recruitPositionType; + + @ApiModelProperty("审核状态 1:待审核 2.审核成功 3.审核失败") + private String auditStatus; + + @ApiModelProperty("审核失败原因") + private String auditFailMsg; + + @ApiModelProperty("版本号") + private Integer version; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("更新时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeStart; + + @ApiModelProperty("更新时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeEnd; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/dto/PositionAuditReqDTO.java b/src/main/java/com/newyetai/recruit/position/dto/PositionAuditReqDTO.java new file mode 100644 index 0000000..be74fba --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/PositionAuditReqDTO.java @@ -0,0 +1,34 @@ +package com.newyetai.recruit.position.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @description: + * @author: guixinman + * @create: 2024-07-05 15:39 + **/ +@Data +public class PositionAuditReqDTO implements Serializable { + + @NotNull(message = "id不能为空") + private Long id; + + @NotBlank(message = "请选择审核状态") + @ApiModelProperty("审核状态 1:待审核 2.审核成功 3.审核失败") + private String auditStatus; + + @ApiModelProperty("审核失败原因") + private String auditFailMsg; + + @NotNull(message = "版本号不能为空") + private Integer version; + + private Long updateBy; + +} diff --git a/src/main/java/com/newyetai/recruit/position/dto/PositionDTO.java b/src/main/java/com/newyetai/recruit/position/dto/PositionDTO.java new file mode 100644 index 0000000..2059b20 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/PositionDTO.java @@ -0,0 +1,248 @@ +package com.newyetai.recruit.position.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.component.dict.util.DictUtils; + +import org.springframework.format.annotation.DateTimeFormat; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; +import java.util.Objects; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.SuperBuilder; + +/** + * 岗位信息表;岗位信息表 + * + * @author guixinman + * @since 1.0.0 2024-04-11 + */ +@ApiModel("岗位信息表;岗位信息表") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class PositionDTO extends BaseDTO { + private static final long serialVersionUID = 1L; + + @ApiModelProperty("机构ID") + private Long orgId; + + @ApiModelProperty("公司ID ;hr_company") + private Long companyId; + + private String companyName; + + @ApiModelProperty("岗位状态:1:开启 2:关闭") + private String status; + + @ApiModelProperty("岗位名称") + private String positionName; + + @ApiModelProperty("招聘标题") + private String recruitTitle; + + @ApiModelProperty("岗位类型") + private String positionType; + + private String positionTypeName; + + @ApiModelProperty("岗位标签") + private String positionTag; + + @ApiModelProperty("工作性质;工作性质 1:短工 2:全职") + private String jobCategory; + + @ApiModelProperty("岗位招聘人数") + private Integer positionNumber; + + @ApiModelProperty("工作地址") + private String positionAddress; + + @ApiModelProperty("招聘专员") + private Long recruitUserId; + + @ApiModelProperty("发薪日") + private String payDate; + + @ApiModelProperty("性别要求") + private String sexRequire; + + @ApiModelProperty("学历要求") + private String educationRequire; + + @ApiModelProperty("经验要求") + private String experienceRequire; + + @ApiModelProperty("证件要求") + private String certificatesRequire; + + @ApiModelProperty("其他要求") + private String otherRequire; + + @ApiModelProperty("工作内容") + private String jobContent; + + private String companyLogo; + + @ApiModelProperty("招聘负责人名称") + private String recruitUserRealName; + + private String recruitUserAvatar; + + private String recruitUserPhone; + + private String positionFileCode; + + private String companyRegisterAddress; + + private List positionFileDTOS; + + @ApiModelProperty("状态:1已报名、2待面试、3面试不通过、4待入职、5已入职、 6已离职、 7结束招聘") + private String positionRegistrationStatus; + /** + * 是否收藏 + */ + private Boolean isCollection; + + @ApiModelProperty("工作地址id") + private Long addressId; + + /** + * 区域编码(31) + */ + private String districtCode; + + /** + * 区域名称 (上海市) + */ + private String districtName; + + /** + * 详细地址 (浦东新区黄金大厦B座) + */ + private String detailAddress; + /** + * 经度 + */ + private BigDecimal longitude; + /** + * 纬度 + */ + private BigDecimal latitude; + + /** + * 招聘岗位类型 + */ + private String recruitPositionType; + + private String recruitPositionTypeName; + + /** + * 年龄上限 + */ + private Integer ageUp; + + /** + * 年龄下限 + */ + private Integer ageLow; + + /** + * 薪资上限 + */ + private BigDecimal salaryUp; + + /** + * 薪资下限 + */ + private BigDecimal salaryLow; + + /** + * 薪资类型 + */ + private String salaryType; + + + private String salaryStr; + + private String ageStr; + + private Boolean show; + + @ApiModelProperty("报名时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date positionRegistrationCreateTime; + + @ApiModelProperty("面试时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date interviewTime; + + @ApiModelProperty("面试地点") + private String interviewLocation; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("入职时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date inductionTime; + + @ApiModelProperty("入职薪资") + private BigDecimal positionRegistrationSalary; + + /** + * 结束日期 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date endTime; + + /** + * 米 + */ + private Long distance; + + public String getSalaryStr() { + String salary = ""; + if (Objects.nonNull(this.getSalaryUp()) && Objects.nonNull(this.getSalaryLow())) { + salary = String.format("%s~%s元/%s", this.getSalaryLow(), this.getSalaryUp(), DictUtils.getCodeNameMap("salary_type").get(String.valueOf(this.getSalaryType()))); + if (this.getSalaryLow().compareTo(this.getSalaryUp()) == 0) { + salary = String.format("%s元/%s", this.getSalaryUp(), DictUtils.getCodeNameMap("salary_type").get(String.valueOf(this.getSalaryType()))); + } + } else if (Objects.nonNull(this.getSalaryLow()) && Objects.isNull(this.getSalaryUp())) { + salary = String.format("%s元/%s", this.getSalaryLow(), DictUtils.getCodeNameMap("salary_type").get(String.valueOf(this.getSalaryType()))); + } else if (Objects.isNull(this.getSalaryLow()) && Objects.nonNull(this.getSalaryUp())) { + salary = String.format("%s元/%s", this.getSalaryUp(), DictUtils.getCodeNameMap("salary_type").get(String.valueOf(this.getSalaryType()))); + } else if (Objects.isNull(this.getSalaryLow()) && Objects.isNull(this.getSalaryUp())) { + salary = "薪资面议"; + } + return salary; + } + + public String getAgeStr() { + String age = ""; + if (Objects.nonNull(this.getAgeLow()) && Objects.nonNull(this.getAgeUp())) { + age = String.format("%s至%s岁", this.getAgeLow(), this.getAgeUp()); + if (this.getAgeLow().intValue() == this.getAgeUp().intValue()) { + age = String.format("%s岁", this.getAgeUp()); + } + } else if (Objects.nonNull(this.getAgeLow()) && Objects.isNull(this.getAgeUp())) { + age = String.format("%s岁以上", this.getAgeLow()); + } else if (Objects.isNull(this.getAgeLow()) && Objects.nonNull(this.getAgeUp())) { + age = String.format("18至%s岁", this.getAgeUp()); + } else if (Objects.isNull(this.getAgeLow()) && Objects.isNull(this.getAgeUp())) { + age = "18岁以上"; + } + return age; + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/dto/PositionExportDTO.java b/src/main/java/com/newyetai/recruit/position/dto/PositionExportDTO.java new file mode 100644 index 0000000..6f6fec7 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/PositionExportDTO.java @@ -0,0 +1,59 @@ +package com.newyetai.recruit.position.dto; + +import com.alibaba.excel.annotation.ExcelProperty; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @description: + * @author: guixinman + * @create: 2024-04-11 17:04 + **/ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PositionExportDTO implements Serializable { + + @ExcelProperty("招聘岗位类型") + @ApiModelProperty("招聘岗位类型") + private String recruitPositionTypeName; + + @ExcelProperty("岗位名称") + @ApiModelProperty("岗位名称") + private String positionName; + + @ExcelProperty("用工企业") + @ApiModelProperty("用工企业") + private String companyName; + + @ExcelProperty("岗位状态") + @ApiModelProperty("岗位状态:1:开启 2:关闭") + private String status; + + @ExcelProperty("招聘人数") + @ApiModelProperty("招聘人数") + private Integer positionNumber; + + @ExcelProperty("综合薪资") + @ApiModelProperty("综合薪资") + private String salary; + + @ExcelProperty("工作地址") + @ApiModelProperty("工作地址") + private String positionAddress; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private String createTime; + + @ApiModelProperty("有效期截止时间") + @ExcelProperty("有效期截止时间") + private String endTime; +} diff --git a/src/main/java/com/newyetai/recruit/position/dto/PositionFileDTO.java b/src/main/java/com/newyetai/recruit/position/dto/PositionFileDTO.java new file mode 100644 index 0000000..7f98e4b --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/PositionFileDTO.java @@ -0,0 +1,58 @@ +package com.newyetai.recruit.position.dto; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + *

+ * 招聘系统-岗位文件 + *

+ * + * @author chenyun + * @since 2021-01-08 + */ +@ApiModel("招聘系统岗位文件DTO") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PositionFileDTO implements Serializable { + + + private static final long serialVersionUID = 8851173648134487125L; + + @ApiModelProperty("主键") + private Long id; + + @ApiModelProperty("文件名称") + private String fileName; + + @ApiModelProperty("文件编码") + private String fileCode; + + @ApiModelProperty("文件后缀") + private String fileSuffix; + + @ApiModelProperty("文件描述") + private String description; + + @ApiModelProperty("文件类型") + private String fileType; + + @ApiModelProperty("默认显示") + private Boolean defaultShow; + + @ApiModelProperty("排序") + private Integer sort; + + @ApiModelProperty("岗位ID") + private Long positionId; + + +} diff --git a/src/main/java/com/newyetai/recruit/position/dto/PositionFilePageQueryDTO.java b/src/main/java/com/newyetai/recruit/position/dto/PositionFilePageQueryDTO.java new file mode 100644 index 0000000..65e5c5a --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/PositionFilePageQueryDTO.java @@ -0,0 +1,36 @@ +package com.newyetai.recruit.position.dto; + +import com.newyetai.common.dto.PageQueryDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + *

+ * 招聘系统-岗位相关分页请求DTO + *

+ * + * @author chenyun + * @since 2021-01-08 + */ +@EqualsAndHashCode(callSuper = true) +@ApiModel("招聘系统岗位相关分页查询DTO") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PositionFilePageQueryDTO extends PageQueryDTO { + + private static final long serialVersionUID = -6211701785572927530L; + + @ApiModelProperty("岗位ID") + private Long positionId; + + @ApiModelProperty("文件类型") + private String fileType; +} diff --git a/src/main/java/com/newyetai/recruit/position/dto/PositionNewDTO.java b/src/main/java/com/newyetai/recruit/position/dto/PositionNewDTO.java new file mode 100644 index 0000000..e474b99 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/PositionNewDTO.java @@ -0,0 +1,237 @@ +package com.newyetai.recruit.position.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.component.dict.util.DictUtils; + +import org.springframework.format.annotation.DateTimeFormat; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; +import java.util.Objects; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 岗位信息表;岗位信息表 + * + * @author guixinman + * @since 1.0.0 2024-04-11 + */ +@ApiModel("岗位信息表;岗位信息表") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class PositionNewDTO extends BaseDTO { + private static final long serialVersionUID = 1L; + + @ApiModelProperty("机构ID") + private Long orgId; + + @ApiModelProperty("公司ID ;hr_company") + private Long companyId; + + private String companyName; + + @ApiModelProperty("岗位状态:1:开启 2:关闭") + private String status; + + @ApiModelProperty("岗位名称") + private String positionName; + + @ApiModelProperty("招聘标题") + private String recruitTitle; + + @ApiModelProperty("岗位类型") + private String positionType; + + private String positionTypeName; + + @ApiModelProperty("岗位标签") + private String positionTag; + + @ApiModelProperty("工作性质;工作性质 1:短工 2:全职") + private String jobCategory; + + @ApiModelProperty("岗位招聘人数") + private Integer positionNumber; + + @ApiModelProperty("工作地址") + private String positionAddress; + + @ApiModelProperty("招聘专员") + private Long recruitUserId; + + @ApiModelProperty("发薪日") + private String payDate; + + @ApiModelProperty("性别要求") + private String sexRequire; + + @ApiModelProperty("学历要求") + private String educationRequire; + + @ApiModelProperty("经验要求") + private String experienceRequire; + + @ApiModelProperty("证件要求") + private String certificatesRequire; + + @ApiModelProperty("其他要求") + private String otherRequire; + + @ApiModelProperty("工作内容") + private String jobContent; + + private String companyLogo; + + @ApiModelProperty("招聘负责人名称") + private String recruitUserRealName; + + private String recruitUserAvatar; + + private String recruitUserPhone; + + private String positionFileCode; + + private String companyRegisterAddress; + + private List positionFileDTOS; + + @ApiModelProperty("状态:1已报名、2待面试、3面试不通过、4待入职、5已入职、 6已离职、 7结束招聘") + private String positionRegistrationStatus; + /** + * 是否收藏 + */ + private Boolean isCollection; + + @ApiModelProperty("工作地址id") + private Long addressId; + + /** + * 区域编码(31) + */ + private String districtCode; + + /** + * 区域名称 (上海市) + */ + private String districtName; + + /** + * 详细地址 (浦东新区黄金大厦B座) + */ + private String detailAddress; + /** + * 经度 + */ + private BigDecimal longitude; + /** + * 纬度 + */ + private BigDecimal latitude; + + /** + * 招聘岗位类型 + */ + private String recruitPositionType; + + private String recruitPositionTypeName; + + private Long positionAuditId; + + /** + * 审核状态 1:待审核 2.审核成功 3.审核失败 + */ + private String auditStatus; + + @ApiModelProperty("审核失败原因") + private String auditFailMsg; + + private Integer version; + + /** + * 岗位相册json + */ + private String fileJson; + + /** + * 年龄上限 + */ + private Integer ageUp; + + /** + * 年龄下限 + */ + private Integer ageLow; + + /** + * 薪资上限 + */ + private BigDecimal salaryUp; + + /** + * 薪资下限 + */ + private BigDecimal salaryLow; + + /** + * 薪资类型 + */ + private String salaryType; + + + private String salaryStr; + + private String ageStr; + + /** + * 结束日期 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date endTime; + + public String getSalaryStr() { + String salary = ""; + if (Objects.nonNull(this.getSalaryUp()) && Objects.nonNull(this.getSalaryLow())) { + salary = String.format("%s~%s元/%s", this.getSalaryLow(), this.getSalaryUp(), DictUtils.getCodeNameMap("salary_type").get(String.valueOf(this.getSalaryType()))); + if (this.getSalaryLow().compareTo(this.getSalaryUp()) == 0) { + salary = String.format("%s元/%s", this.getSalaryUp(), DictUtils.getCodeNameMap("salary_type").get(String.valueOf(this.getSalaryType()))); + } + } else if (Objects.nonNull(this.getSalaryLow()) && Objects.isNull(this.getSalaryUp())) { + salary = String.format("%s元/%s", this.getSalaryLow(), DictUtils.getCodeNameMap("salary_type").get(String.valueOf(this.getSalaryType()))); + } else if (Objects.isNull(this.getSalaryLow()) && Objects.nonNull(this.getSalaryUp())) { + salary = String.format("%s元/%s", this.getSalaryUp(), DictUtils.getCodeNameMap("salary_type").get(String.valueOf(this.getSalaryType()))); + } else if (Objects.isNull(this.getSalaryLow()) && Objects.isNull(this.getSalaryUp())) { + salary = "薪资面议"; + } + return salary; + } + + public String getAgeStr() { + String age = ""; + if (Objects.nonNull(this.getAgeLow()) && Objects.nonNull(this.getAgeUp())) { + age = String.format("%s至%s岁", this.getAgeLow(), this.getAgeUp()); + if (this.getAgeLow().intValue() == this.getAgeUp().intValue()) { + age = String.format("%s岁", this.getAgeUp()); + } + } else if (Objects.nonNull(this.getAgeLow()) && Objects.isNull(this.getAgeUp())) { + age = String.format("%s岁以上", this.getAgeLow()); + } else if (Objects.isNull(this.getAgeLow()) && Objects.nonNull(this.getAgeUp())) { + age = String.format("18至%s岁", this.getAgeUp()); + } else if (Objects.isNull(this.getAgeLow()) && Objects.isNull(this.getAgeUp())) { + age = "18岁以上"; + } + return age; + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/dto/PositionNewOperatorDTO.java b/src/main/java/com/newyetai/recruit/position/dto/PositionNewOperatorDTO.java new file mode 100644 index 0000000..cd13ef6 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/PositionNewOperatorDTO.java @@ -0,0 +1,171 @@ +package com.newyetai.recruit.position.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.newyetai.common.annotation.trimAndUpper.TrimAndUpper; + +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; +import java.util.Objects; +import java.util.Set; + +import javax.validation.constraints.Max; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import cn.hutool.core.date.DateUtil; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @description: + * @author: guixinman + * @create: 2024-07-08 10:18 + **/ +@ApiModel("岗位审核表") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PositionNewOperatorDTO implements Serializable { + private static final long serialVersionUID = 1L; + + private Long id; + + //开启招聘 关闭招聘用 + private Set ids; + + @ApiModelProperty("机构ID") + private Long orgId; + + @NotNull(message = "请选择用工企业") + @ApiModelProperty("公司ID ;hr_company") + private Long companyId; + + @ApiModelProperty("岗位状态:1:开启 2:关闭") + private String status; + + @Length(max = 50,message = "岗位名称超长") + @TrimAndUpper(value = TrimAndUpper.ExecuteType.TRIM) + @NotBlank(message = "岗位名称不能为空") + @ApiModelProperty("岗位名称") + private String positionName; + + @Length(max = 255,message = "招聘标题超长") + @TrimAndUpper(value = TrimAndUpper.ExecuteType.TRIM) + @ApiModelProperty("招聘标题") + private String recruitTitle; + + @ApiModelProperty("岗位类型") + private String positionType; + + /** + * 岗位标签 + */ + @Length(max = 512,message = "岗位标签超长") + private String positionTag; + + @ApiModelProperty("工作性质;工作性质 1:短工 2:全职") + private String jobCategory; + + @Max(value = 30000,message = "岗位招聘人数超长") + @ApiModelProperty("岗位招聘人数") + private Integer positionNumber; + + @Length(max = 255,message = "工作地址超长") + @ApiModelProperty("工作地址") + private String positionAddress; + + @ApiModelProperty("招聘专员") + private Long recruitUserId; + + @Length(max = 32,message = "发薪日超长") + @ApiModelProperty("发薪日") + private String payDate; + + @Length(max = 2,message = "性别要求超长") + @ApiModelProperty("性别要求") + private String sexRequire; + + @Length(max = 32,message = "学历要求超长") + @ApiModelProperty("学历要求") + private String educationRequire; + + @Length(max = 32,message = "经验要求超长") + @ApiModelProperty("经验要求") + private String experienceRequire; + + @Length(max = 32,message = "证件要求超长") + @ApiModelProperty("证件要求") + private String certificatesRequire; + + @Length(max = 32,message = "其他要求超长") + @ApiModelProperty("其他要求") + private String otherRequire; + + @ApiModelProperty("工作内容") + private String jobContent; + + private Long addressId; + + /** + * 招聘岗位类型 + */ + @Length(max = 2,message = "招聘岗位类型超长") + @NotBlank(message = "请选择招聘岗位类型") + private String recruitPositionType; + + private Long positionAuditId; + + /** + * 版本号 + */ + private Integer version; + + + /** + * 岗位相册json + */ + private String fileJson; + + /** + * 年龄上限 + */ + private Integer ageUp; + + /** + * 年龄下限 + */ + private Integer ageLow; + + /** + * 薪资上限 + */ + private BigDecimal salaryUp; + + /** + * 薪资下限 + */ + private BigDecimal salaryLow; + + /** + * 薪资类型 + */ + private String salaryType; + + + /** + * 结束日期 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + @NotNull(message = "有效期截止日期不能为空") + private Date endTime; +} diff --git a/src/main/java/com/newyetai/recruit/position/dto/PositionNewPageQueryDTO.java b/src/main/java/com/newyetai/recruit/position/dto/PositionNewPageQueryDTO.java new file mode 100644 index 0000000..3a14609 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/PositionNewPageQueryDTO.java @@ -0,0 +1,121 @@ +package com.newyetai.recruit.position.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.newyetai.common.dto.PageQueryDTO; + +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; +import java.util.List; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * 岗位信息表;岗位信息表 + * + * @author guixinman + * @since 1.0.0 2024-04-11 + */ + +@ApiModel("岗位信息表;岗位信息表") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class PositionNewPageQueryDTO extends PageQueryDTO { + private static final long serialVersionUID = 1L; + + private Long id; + + private List ids; + + @ApiModelProperty("机构ID") + private Long orgId; + + @ApiModelProperty("公司ID ;hr_company") + private Long companyId; + + @ApiModelProperty("岗位状态:1:开启 2:关闭") + private String status; + + @ApiModelProperty("岗位名称 (模糊匹配)") + private String positionNameLike; + + @ApiModelProperty("招聘标题") + private String recruitTitle; + + private String recruitTitleLike; + + private String positionTagLike; + + @ApiModelProperty("岗位类型") + private String positionType; + + @ApiModelProperty("工作性质;工作性质 1:短工 2:全职") + private String jobCategory; + + @ApiModelProperty("岗位招聘人数") + private Integer positionNumber; + + @ApiModelProperty("工作地址") + private String positionAddress; + + @ApiModelProperty("招聘专员") + private Long recruitUserId; + + @ApiModelProperty("发薪日") + private String payDate; + + @ApiModelProperty("性别要求") + private String sexRequire; + + @ApiModelProperty("学历要求") + private String educationRequire; + + @ApiModelProperty("经验要求") + private String experienceRequire; + + @ApiModelProperty("证件要求") + private String certificatesRequire; + + @ApiModelProperty("其他要求") + private String otherRequire; + + @ApiModelProperty("工作内容") + private String jobContent; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("更新时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeStart; + + @ApiModelProperty("更新时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeEnd; + + /** + * 招聘岗位类型 + */ + private String recruitPositionType; + + private String recruitPositionTypeName; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/dto/PositionOperatorDTO.java b/src/main/java/com/newyetai/recruit/position/dto/PositionOperatorDTO.java new file mode 100644 index 0000000..9b23bd2 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/PositionOperatorDTO.java @@ -0,0 +1,161 @@ +package com.newyetai.recruit.position.dto; + +import cn.hutool.core.date.DateUtil; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.newyetai.common.annotation.trimAndUpper.TrimAndUpper; + +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.Objects; +import java.util.Set; + +/** + * 岗位信息表;岗位信息表 + * + * @author guixinman + * @since 1.0.0 2024-04-11 + */ +@ApiModel("岗位信息表;岗位信息表") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PositionOperatorDTO implements Serializable { + private static final long serialVersionUID = 1L; + + private Long id; + + //开启招聘 关闭招聘用 + private Set ids; + + @ApiModelProperty("机构ID") + private Long orgId; + + @NotNull(message = "请选择用工企业") + @ApiModelProperty("公司ID ;hr_company") + private Long companyId; + + @ApiModelProperty("岗位状态:1:开启 2:关闭") + private String status; + + @Length(max = 50,message = "岗位名称超长") + @TrimAndUpper(value = TrimAndUpper.ExecuteType.TRIM) + @NotBlank(message = "岗位名称不能为空") + @ApiModelProperty("岗位名称") + private String positionName; + + @Length(max = 255,message = "招聘标题超长") + @TrimAndUpper(value = TrimAndUpper.ExecuteType.TRIM) + @ApiModelProperty("招聘标题") + private String recruitTitle; + + @ApiModelProperty("岗位类型") + private String positionType; + + /** + * 岗位标签 + */ + @Length(max = 512,message = "岗位标签超长") + private String positionTag; + + @ApiModelProperty("工作性质;工作性质 1:短工 2:全职") + private String jobCategory; + + @Max(value = 30000,message = "岗位招聘人数超长") + @ApiModelProperty("岗位招聘人数") + private Integer positionNumber; + + @Length(max = 255,message = "工作地址超长") + @ApiModelProperty("工作地址") + private String positionAddress; + + @ApiModelProperty("招聘专员") + private Long recruitUserId; + + @Length(max = 32,message = "发薪日超长") + @ApiModelProperty("发薪日") + private String payDate; + + @Length(max = 2,message = "性别要求超长") + @ApiModelProperty("性别要求") + private String sexRequire; + + @Length(max = 32,message = "学历要求超长") + @ApiModelProperty("学历要求") + private String educationRequire; + + @Length(max = 32,message = "经验要求超长") + @ApiModelProperty("经验要求") + private String experienceRequire; + + @Length(max = 32,message = "证件要求超长") + @ApiModelProperty("证件要求") + private String certificatesRequire; + + @Length(max = 32,message = "其他要求超长") + @ApiModelProperty("其他要求") + private String otherRequire; + + @ApiModelProperty("工作内容") + private String jobContent; + + private Long addressId; + + /** + * 招聘岗位类型 + */ + @Length(max = 2,message = "招聘岗位类型超长") + @NotBlank(message = "请选择招聘岗位类型") + private String recruitPositionType; + + /** + * 年龄上限 + */ + private Integer ageUp; + + /** + * 年龄下限 + */ + @Min(value = 18,message = "年龄下限不低于18周岁") + private Integer ageLow; + + /** + * 薪资上限 + */ + private BigDecimal salaryUp; + + /** + * 薪资下限 + */ + private BigDecimal salaryLow; + + /** + * 薪资类型 + */ + private String salaryType; + + /** + * 结束日期 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date endTime; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/dto/PositionPageQueryDTO.java b/src/main/java/com/newyetai/recruit/position/dto/PositionPageQueryDTO.java new file mode 100644 index 0000000..dffd2ed --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/PositionPageQueryDTO.java @@ -0,0 +1,151 @@ +package com.newyetai.recruit.position.dto; + +import com.newyetai.common.dto.PageQueryDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.format.annotation.DateTimeFormat; + + +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; + +/** + * 岗位信息表;岗位信息表 + * + * @author guixinman + * @since 1.0.0 2024-04-11 + */ + +@ApiModel("岗位信息表;岗位信息表") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class PositionPageQueryDTO extends PageQueryDTO { + private static final long serialVersionUID = 1L; + + private Long id; + + private List ids; + + @ApiModelProperty("机构ID") + private Long orgId; + + @ApiModelProperty("公司ID ;hr_company") + private Long companyId; + + @ApiModelProperty("岗位状态:1:开启 2:关闭") + private String status; + + @ApiModelProperty("岗位名称 (模糊匹配)") + private String positionNameLike; + + @ApiModelProperty("招聘标题") + private String recruitTitle; + + private String recruitTitleLike; + + private String positionTagLike; + + @ApiModelProperty("岗位类型") + private String positionType; + + @ApiModelProperty("工作性质;工作性质 1:短工 2:全职") + private String jobCategory; + + @ApiModelProperty("岗位招聘人数") + private Integer positionNumber; + + @ApiModelProperty("工作地址") + private String positionAddress; + + @ApiModelProperty("招聘专员") + private Long recruitUserId; + + @ApiModelProperty("发薪日") + private String payDate; + + @ApiModelProperty("性别要求") + private String sexRequire; + + @ApiModelProperty("学历要求") + private String educationRequire; + + @ApiModelProperty("经验要求") + private String experienceRequire; + + @ApiModelProperty("证件要求") + private String certificatesRequire; + + @ApiModelProperty("其他要求") + private String otherRequire; + + @ApiModelProperty("工作内容") + private String jobContent; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("更新时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeStart; + + @ApiModelProperty("更新时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeEnd; + + /** + * 招聘岗位类型 + */ + private String recruitPositionType; + + private String recruitPositionTypeName; + + /** + * 查询sql是否判断 有效期 + */ + @Builder.Default + private Boolean useEndTime = Boolean.TRUE; + + /** + * 经度 + */ + private BigDecimal longitude; + /** + * 纬度 + */ + private BigDecimal latitude; + + /** + * 千米 + */ + private int radius; + + private BigDecimal minX; + + private BigDecimal maxX; + + private BigDecimal minY; + + private BigDecimal maxY; + + private BigDecimal salaryUp; + + private BigDecimal salaryLow; +} diff --git a/src/main/java/com/newyetai/recruit/position/dto/PositionQueryDTO.java b/src/main/java/com/newyetai/recruit/position/dto/PositionQueryDTO.java new file mode 100644 index 0000000..9c71d85 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/PositionQueryDTO.java @@ -0,0 +1,106 @@ +package com.newyetai.recruit.position.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; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +/** + * 岗位信息表;岗位信息表 + * + * @author guixinman + * @since 1.0.0 2024-04-11 + */ +@ApiModel("岗位信息表;岗位信息表") +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class PositionQueryDTO implements Serializable { + private static final long serialVersionUID = 1L; + + private Long id; + + @ApiModelProperty("机构ID") + private Long orgId; + + @ApiModelProperty("公司ID ;hr_company") + private Long companyId; + + @ApiModelProperty("岗位状态:1:开启 2:关闭") + private String status; + + @ApiModelProperty("岗位名称 (模糊匹配)") + private String positionNameLike; + + @ApiModelProperty("招聘标题") + private String recruitTitle; + + @ApiModelProperty("岗位类型") + private String positionType; + + @ApiModelProperty("工作性质;工作性质 1:短工 2:全职") + private String jobCategory; + + @ApiModelProperty("岗位招聘人数") + private Integer positionNumber; + + @ApiModelProperty("工作地址") + private String positionAddress; + + @ApiModelProperty("招聘专员") + private Long recruitUserId; + + @ApiModelProperty("发薪日") + private String payDate; + + @ApiModelProperty("性别要求") + private String sexRequire; + + @ApiModelProperty("学历要求") + private String educationRequire; + + @ApiModelProperty("经验要求") + private String experienceRequire; + + @ApiModelProperty("证件要求") + private String certificatesRequire; + + @ApiModelProperty("其他要求") + private String otherRequire; + + @ApiModelProperty("工作内容") + private String jobContent; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("更新时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeStart; + + @ApiModelProperty("更新时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeEnd; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/dto/PositionRegistrationDTO.java b/src/main/java/com/newyetai/recruit/position/dto/PositionRegistrationDTO.java new file mode 100644 index 0000000..ef408ce --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/PositionRegistrationDTO.java @@ -0,0 +1,123 @@ +package com.newyetai.recruit.position.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.common.util.IdcardUtils; +import com.newyetai.recruit.user.dto.JobExpectDTO; +import com.newyetai.recruit.user.dto.UserCertificateDTO; + +import org.springframework.format.annotation.DateTimeFormat; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.SuperBuilder; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; + +/** + * 岗位报名信息表 + * + * @author guixinman + * @since 1.0.0 2024-04-15 + */ +@ApiModel("岗位报名信息表") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class PositionRegistrationDTO extends BaseDTO { + private static final long serialVersionUID = 1L; + + @ApiModelProperty("岗位ID") + private Long positionId; + + @ApiModelProperty("用户ID ") + private Long userId; + + @ApiModelProperty("状态:1已报名、2待面试、3面试不通过、4待入职、5已入职、 6已离职、 7结束招聘") + private String status; + + @ApiModelProperty("面试时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date interviewTime; + + @ApiModelProperty("面试地点") + private String interviewLocation; + + @ApiModelProperty("入职时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date inductionTime; + + @ApiModelProperty("离职时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date quitTime; + + @ApiModelProperty("终止时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date terminationTime; + + @ApiModelProperty("入职薪水") + private BigDecimal salary; + + @ApiModelProperty("备注") + private String remark; + + private String positionName; + + private Long companyId; + + private String companyName; + + private String realName; + + private String cardNo; + + private String phone; + + /** + * 招聘专员 + */ + private String recruitUserName; + + @ApiModelProperty("性别") + private String gender; + + @ApiModelProperty("年龄") + private Integer age; + + @ApiModelProperty("所在城市") + private String cityCode; + + private String cityCodeName; + + @ApiModelProperty("简历") + private String resumeFileCode; + + @ApiModelProperty("求职期望") + private List jobExpectDTOList; + + @ApiModelProperty("证书") + private List userCertificateDTOList; + + private Boolean show; + + @ApiModelProperty("所属街道名称") + private String streetName; + + @ApiModelProperty("发布机构名称") + private String publishOrgName; + + public void setCardNo(String cardNo) { + this.setAge(IdcardUtils.getAgeByIDNumber(cardNo)); + this.setGender(IdcardUtils.judgeGender(cardNo)); + this.cardNo = cardNo; + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/dto/PositionRegistrationExportDTO.java b/src/main/java/com/newyetai/recruit/position/dto/PositionRegistrationExportDTO.java new file mode 100644 index 0000000..f2ac801 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/PositionRegistrationExportDTO.java @@ -0,0 +1,88 @@ +package com.newyetai.recruit.position.dto; + +import com.alibaba.excel.annotation.ExcelProperty; + +import java.io.Serializable; +import java.math.BigDecimal; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @description: 招聘管理导出dto(全部) + * @author: guixinman + * @create: 2024-04-16 17:17 + **/ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PositionRegistrationExportDTO implements Serializable { + + @ExcelProperty("岗位名称") + @ApiModelProperty("岗位名称") + private String positionName; + + @ApiModelProperty("姓名") + @ExcelProperty("姓名") + private String realName; + + @ApiModelProperty("性别") + @ExcelProperty("性别") + private String gender; + + @ApiModelProperty("年龄") + @ExcelProperty("年龄") + private Integer age; + + @ApiModelProperty("手机号") + @ExcelProperty("手机号") + private String phone; + + @ApiModelProperty("身份证号") + @ExcelProperty("身份证号") + private String cardNo; + + @ExcelProperty("用工企业") + @ApiModelProperty("用工企业") + private String companyName; + + @ExcelProperty("招聘状态") + @ApiModelProperty("招聘状态") + private String status; + + @ExcelProperty("所属街道") + @ApiModelProperty("所属街道名称") + private String streetName; + + @ExcelProperty("发布机构") + @ApiModelProperty("发布机构名称") + private String publishOrgName; + + @ExcelProperty("面试时间") + @ApiModelProperty("面试时间") + private String interviewTime; + + @ExcelProperty("面试地点") + @ApiModelProperty("面试地点") + private String interviewLocation; + + @ExcelProperty("入职薪资") + @ApiModelProperty("入职薪资") + private BigDecimal salary; + + @ApiModelProperty("报名时间") + @ExcelProperty("报名时间") + private String createTime; + + @ApiModelProperty("入职时间") + @ExcelProperty("入职时间") + private String inductionTime; + + @ApiModelProperty("离职时间") + @ExcelProperty("离职时间") + private String quitTime; +} diff --git a/src/main/java/com/newyetai/recruit/position/dto/PositionRegistrationOperatorDTO.java b/src/main/java/com/newyetai/recruit/position/dto/PositionRegistrationOperatorDTO.java new file mode 100644 index 0000000..b5f0b53 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/PositionRegistrationOperatorDTO.java @@ -0,0 +1,82 @@ +package com.newyetai.recruit.position.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; +import java.util.Set; + +import javax.validation.constraints.NotNull; + +/** + * 岗位报名信息表 + * + * @author guixinman + * @since 1.0.0 2024-04-15 + */ +@ApiModel("岗位报名信息表") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PositionRegistrationOperatorDTO implements Serializable { + private static final long serialVersionUID = 1L; + + private Long id; + + private Set ids; + + private Set userIds; + + @NotNull(message = "请选择岗位") + @ApiModelProperty("岗位ID") + private Long positionId; + + @ApiModelProperty("用户ID ") + private Long userId; + + @NotNull(message = "请选择招聘状态") + @ApiModelProperty("状态:1已报名、2待面试、3面试不通过、4待入职、5已入职、 6已离职、 7结束招聘") + private String status; + + @ApiModelProperty("面试时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date interviewTime; + + @Length(max = 100,message = "面试地点长度超过最大限制") + @ApiModelProperty("面试地点") + private String interviewLocation; + + @ApiModelProperty("入职时间") + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "GMT+8") + private Date inductionTime; + + @ApiModelProperty("离职时间") + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "GMT+8") + private Date quitTime; + + @ApiModelProperty("终止时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date terminationTime; + + @ApiModelProperty("入职薪水") + private BigDecimal salary; + + @ApiModelProperty("备注") + private String remark; + + private Boolean show; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/dto/PositionRegistrationPageQueryDTO.java b/src/main/java/com/newyetai/recruit/position/dto/PositionRegistrationPageQueryDTO.java new file mode 100644 index 0000000..9a0f776 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/PositionRegistrationPageQueryDTO.java @@ -0,0 +1,136 @@ +package com.newyetai.recruit.position.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.newyetai.common.dto.PageQueryDTO; + +import org.springframework.format.annotation.DateTimeFormat; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; +import java.util.Set; + +/** + * 岗位报名信息表 + * + * @author guixinman + * @since 1.0.0 2024-04-15 + */ + +@ApiModel("岗位报名信息表") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class PositionRegistrationPageQueryDTO extends PageQueryDTO { + private static final long serialVersionUID = 1L; + + private Long id; + + private Long orgId; + + @ApiModelProperty("发布机构id") + private Long publishOrgId; + + @ApiModelProperty("所属街道机构id") + private Long queryStreetOrgId; + + @ApiModelProperty("所属街道机构子级orgids") + private Set queryStreetChildrenAllOrgIds; + + private Set orgIds; + + @ApiModelProperty("岗位ID") + private Long positionId; + + @ApiModelProperty("用户ID ") + private Long userId; + + @ApiModelProperty("状态:1已报名、2待面试、3面试不通过、4待入职、5已入职、 6已离职、 7结束招聘") + private String status; + + private List statusList; + + @ApiModelProperty("面试时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date interviewTime; + + @ApiModelProperty("入职时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date inductionTime; + + @ApiModelProperty("离职时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date quitTime; + + @ApiModelProperty("终止时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date terminationTime; + + @ApiModelProperty("入职薪水") + private BigDecimal salary; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("更新时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeStart; + + @ApiModelProperty("更新时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeEnd; + + /** + * 用工企业id + **/ + private Long companyId; + /** + * 姓名 + **/ + private String realNameLike; + + private Set realNames; + + /** + * 手机号 + **/ + private String phoneLike; + + private Set phones; + /** + * 身份证 + **/ + private String cardNoLike; + + private Set cardNos; + + private Boolean show; + + /** + * 是否查看自己+子级orgId + */ + private Boolean childrenOrgAll; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/dto/PositionTypeDTO.java b/src/main/java/com/newyetai/recruit/position/dto/PositionTypeDTO.java new file mode 100644 index 0000000..3031c0e --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/PositionTypeDTO.java @@ -0,0 +1,106 @@ +package com.newyetai.recruit.position.dto; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.common.util.TreeNode; + +import org.apache.commons.compress.utils.Lists; +import org.apache.commons.lang3.StringUtils; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import cn.hutool.core.collection.CollUtil; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + *

+ * 用户岗位类型 + *

+ * + * @author Carlye + * @since 2021-01-21 + */ +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class PositionTypeDTO extends BaseDTO implements TreeNode { + + private static final long serialVersionUID = 2154317236704975221L; + + /** + * 文件名称 + */ + private String name; + + /** + * 文件编码 + */ + private String code; + + /** + * 岗位ID + */ + private Long parentId; + /** + * 招聘岗位类型 + */ + private String recruitPositionType; + + private List childrenSet; + + public List getChildrenSet() { + if (Objects.isNull(childrenSet)) { + childrenSet = Lists.newArrayList(); + } + return childrenSet; + } + + @Override + public void addChildren(PositionTypeDTO node) { + getChildrenSet().add(node); + } + + /** + * 复制,不复制子元素 + * + * @return {@link PositionTypeDTO} + */ + public PositionTypeDTO copy() { + PositionTypeDTO positionTypeDTO = new PositionTypeDTO(); + positionTypeDTO.setCode(code); + positionTypeDTO.setName(name); + positionTypeDTO.setParentId(parentId); + return positionTypeDTO; + } + + public static PositionTypeDTO search(PositionTypeDTO parent, PositionTypeQueryDTO queryDTO) { + String name = parent.getName(); + String code = parent.getCode(); + List childrenSet = parent.getChildrenSet(); + if ((StringUtils.isNotEmpty(queryDTO.getNameLike()) && StringUtils.contains(name, queryDTO.getNameLike())) || (CollUtil.isNotEmpty(queryDTO.getTypeCodes()) && queryDTO.getTypeCodes().contains(code))) { + if (CollUtil.isNotEmpty(childrenSet)) { + parent.setChildrenSet(null); + } + return parent; + } else { + if (CollUtil.isNotEmpty(childrenSet)) { + List collect = childrenSet.stream().map(child -> search(child, queryDTO)) + .filter(Objects::nonNull).collect( + Collectors.toList()); + if (CollUtil.isEmpty(collect)) { + return null; + } + parent.setChildrenSet(collect); + return parent; + } + } + return null; + } +} diff --git a/src/main/java/com/newyetai/recruit/position/dto/PositionTypeQueryDTO.java b/src/main/java/com/newyetai/recruit/position/dto/PositionTypeQueryDTO.java new file mode 100644 index 0000000..9b94f28 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/PositionTypeQueryDTO.java @@ -0,0 +1,40 @@ +package com.newyetai.recruit.position.dto; + +import java.io.Serializable; +import java.util.Set; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + *

+ * 用户岗位类型 - 查询DTO + *

+ * + * @author Carlye + * @since 2021-01-21 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PositionTypeQueryDTO implements Serializable { + + private static final long serialVersionUID = -618123250962943084L; + /** + * 文件名称 + */ + private String nameLike; + + /** + * 类型编码 + */ + private Set typeCodes; + + /** + * 招聘岗位类型 + */ + private String recruitPositionType; +} diff --git a/src/main/java/com/newyetai/recruit/position/dto/ResignedDTO.java b/src/main/java/com/newyetai/recruit/position/dto/ResignedDTO.java new file mode 100644 index 0000000..b020246 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/ResignedDTO.java @@ -0,0 +1,32 @@ +package com.newyetai.recruit.position.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.format.annotation.DateTimeFormat; + +import java.io.Serializable; +import java.util.Date; +import java.util.Set; + +import javax.validation.constraints.NotNull; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @description: 离职dto + * @author: guixinman + * @create: 2024-04-16 15:17 + **/ +@Data +public class ResignedDTO implements Serializable { + + @NotNull(message = "请选择离职时间") + @ApiModelProperty("离职时间") + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "GMT+8") + private Date quitTime; + + @NotNull(message = "请选择数据") + private Set ids; +} diff --git a/src/main/java/com/newyetai/recruit/position/dto/UserPositionRegistrationDTO.java b/src/main/java/com/newyetai/recruit/position/dto/UserPositionRegistrationDTO.java new file mode 100644 index 0000000..b4415d3 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/UserPositionRegistrationDTO.java @@ -0,0 +1,19 @@ +package com.newyetai.recruit.position.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotNull; + +import lombok.Data; + +/** + * @description: 用户端报名岗位 + * @author: guixinman + * @create: 2024-04-15 16:29 + **/ +@Data +public class UserPositionRegistrationDTO implements Serializable { + + @NotNull(message = "请选择岗位") + private Long positionId; +} diff --git a/src/main/java/com/newyetai/recruit/position/dto/UserPositionRegistrationPageQueryDTO.java b/src/main/java/com/newyetai/recruit/position/dto/UserPositionRegistrationPageQueryDTO.java new file mode 100644 index 0000000..0a7c144 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/UserPositionRegistrationPageQueryDTO.java @@ -0,0 +1,33 @@ +package com.newyetai.recruit.position.dto; + +import com.newyetai.common.dto.PageQueryDTO; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @description: 用户端查询我的报名 + * @author: guixinman + * @create: 2024-04-19 09:31 + **/ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class UserPositionRegistrationPageQueryDTO extends PageQueryDTO { + + private Long id; + + private Long userId; + + @ApiModelProperty("状态:1已报名、2待面试、3面试不通过、4待入职、5已入职、 6已离职、 7结束招聘") + private String status; + + private Long positionId; + +} diff --git a/src/main/java/com/newyetai/recruit/position/dto/UserPositionRegistrationResDTO.java b/src/main/java/com/newyetai/recruit/position/dto/UserPositionRegistrationResDTO.java new file mode 100644 index 0000000..cb28ae4 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/dto/UserPositionRegistrationResDTO.java @@ -0,0 +1,122 @@ +package com.newyetai.recruit.position.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.newyetai.component.dict.util.DictUtils; + +import org.springframework.format.annotation.DateTimeFormat; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; +import java.util.Objects; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @description: 用户端我的报名 + * @author: guixinman + * @create: 2024-04-19 09:26 + **/ +@Data +public class UserPositionRegistrationResDTO implements Serializable { + + private Long id; + + private Long positionId; + + @ApiModelProperty("岗位名称") + private String positionName; + + @ApiModelProperty("招聘标题") + private String recruitTitle; + + @ApiModelProperty("岗位标签") + private String positionTag; + + @ApiModelProperty("工作地址") + private String positionAddress; + + @ApiModelProperty("招聘专员") + private String recruitUserName; + + private String companyName; + + private String companyLogo; + + private String positionFileCode; + + private String status; + + @ApiModelProperty("报名时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTime; + + @ApiModelProperty("面试时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date interviewTime; + + @ApiModelProperty("面试地点") + private String interviewLocation; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("入职时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date inductionTime; + + @ApiModelProperty("入职薪资") + private BigDecimal salary; + + /** + * 招聘岗位类型 + */ + private String recruitPositionType; + + private String recruitPositionTypeName; + + + /** + * 薪资上限 + */ + private BigDecimal salaryUp; + /** + * 薪资下限 + */ + private BigDecimal salaryLow; + + /** + * 薪资类型 + */ + private String salaryType; + + + private String salaryStr; + + private Boolean show; + + /** + * 详细地址 + */ + private String detailAddress; + public String getSalaryStr() { + String salary = ""; + if (Objects.nonNull(this.getSalaryUp()) && Objects.nonNull(this.getSalaryLow())) { + salary = String.format("%s~%s元/%s", this.getSalaryLow(), this.getSalaryUp(), DictUtils.getCodeNameMap("salary_type").get(String.valueOf(this.getSalaryType()))); + if (this.getSalaryLow().compareTo(this.getSalaryUp()) == 0) { + salary = String.format("%s元/%s", this.getSalaryUp(), DictUtils.getCodeNameMap("salary_type").get(String.valueOf(this.getSalaryType()))); + } + } else if (Objects.nonNull(this.getSalaryLow()) && Objects.isNull(this.getSalaryUp())) { + salary = String.format("%s元/%s", this.getSalaryLow(), DictUtils.getCodeNameMap("salary_type").get(String.valueOf(this.getSalaryType()))); + } else if (Objects.isNull(this.getSalaryLow()) && Objects.nonNull(this.getSalaryUp())) { + salary = String.format("%s元/%s", this.getSalaryUp(), DictUtils.getCodeNameMap("salary_type").get(String.valueOf(this.getSalaryType()))); + } else if (Objects.isNull(this.getSalaryLow()) && Objects.isNull(this.getSalaryUp())) { + salary = "薪资面议"; + } + return salary; + } +} diff --git a/src/main/java/com/newyetai/recruit/position/entity/ImportDetailPosition.java b/src/main/java/com/newyetai/recruit/position/entity/ImportDetailPosition.java new file mode 100644 index 0000000..b86b6bd --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/entity/ImportDetailPosition.java @@ -0,0 +1,145 @@ +package com.newyetai.recruit.position.entity; + +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import com.baomidou.mybatisplus.annotation.*; +import com.newyetai.common.entity.BaseEntity; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * 岗位导入 + * + * @author guixinman + * @since 1.0.0 2024-04-12 + */ +@TableName(value = "hr_import_detail_position") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class ImportDetailPosition extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * 导入任务ID + */ + private Long mainId; + /** + * 机构ID + */ + private Long orgId; + /** + * 模板全量数据 + */ + private String dataJson; + /** + * 公司ID ;hr_company + */ + private Long companyId; + /** + * 岗位名称 + */ + private String positionName; + /** + * 招聘标题 + */ + private String recruitTitle; + /** + * 岗位招聘人数 + */ + private Integer positionNumber; + /** + * 工作地址 + */ + private String positionAddress; + /** + * 岗位性质 数据字典 + */ + private String recruitPositionType; + /** + * 发薪日 + */ + private String payDate; + /** + * 性别要求 + */ + private String sexRequire; + /** + * 学历要求 + */ + private String educationRequire; + /** + * 经验要求 + */ + private String experienceRequire; + /** + * 证件要求 + */ + private String certificatesRequire; + /** + * 其他要求 + */ + private String otherRequire; + /** + * 工作内容 + */ + private String jobContent; + /** + * 明细状态 + */ + private Integer detailStatus; + /** + * 失败原因 + */ + private String failReason; + /** + * 外部生成明细id + */ + private Long extraDetailId; + /** + * 备注 + */ + private String remark; + + @ApiModelProperty("岗位类型") + private String positionTypeName; + + @ApiModelProperty("岗位标签") + private String positionTag; + + /** + * 年龄上限 + */ + private Integer ageUp; + + /** + * 年龄下限 + */ + private Integer ageLow; + + /** + * 薪资上限 + */ + private BigDecimal salaryUp; + + /** + * 薪资下限 + */ + private BigDecimal salaryLow; + + /** + * 薪资类型 + */ + private String salaryType; + + + /** + * 结束日期 + */ + private Date endTime; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/entity/Position.java b/src/main/java/com/newyetai/recruit/position/entity/Position.java new file mode 100644 index 0000000..c63e725 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/entity/Position.java @@ -0,0 +1,142 @@ +package com.newyetai.recruit.position.entity; + + +import lombok.*; +import lombok.experimental.SuperBuilder; + +import com.baomidou.mybatisplus.annotation.*; + +import com.newyetai.common.entity.BaseEntity; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * 岗位信息表;岗位信息表 + * + * @author guixinman + * @since 1.0.0 2024-04-11 + */ +@TableName(value = "hr_position") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class Position extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * 机构ID + */ + private Long orgId; + /** + * 公司ID ;hr_company + */ + private Long companyId; + /** + * 岗位状态:1:开启 2:关闭 + */ + private String status; + /** + * 岗位名称 + */ + private String positionName; + /** + * 招聘标题 + */ + private String recruitTitle; + /** + * 岗位类型 + */ + private String positionType; + /** + * 岗位标签 + */ + private String positionTag; + /** + * 工作性质;工作性质 1:短工 2:全职 + */ + private String jobCategory; + /** + * 岗位招聘人数 + */ + private Integer positionNumber; + /** + * 工作地址 + */ + private String positionAddress; + /** + * 招聘专员 + */ + private Long recruitUserId; + + /** + * 发薪日 + */ + private String payDate; + /** + * 性别要求 + */ + private String sexRequire; + + /** + * 学历要求 + */ + private String educationRequire; + /** + * 经验要求 + */ + private String experienceRequire; + /** + * 证件要求 + */ + private String certificatesRequire; + /** + * 其他要求 + */ + private String otherRequire; + /** + * 工作内容 + */ + private String jobContent; + + private Long addressId; + + /** + * 招聘岗位类型 + */ + private String recruitPositionType; + + /** + * 年龄上限 + */ + private Integer ageUp; + + /** + * 年龄下限 + */ + private Integer ageLow; + + /** + * 薪资上限 + */ + private BigDecimal salaryUp; + + /** + * 薪资下限 + */ + private BigDecimal salaryLow; + + /** + * 薪资类型 + */ + private String salaryType; + + + /** + * 结束日期 + */ + private Date endTime; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/entity/PositionAddress.java b/src/main/java/com/newyetai/recruit/position/entity/PositionAddress.java new file mode 100644 index 0000000..914cb0b --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/entity/PositionAddress.java @@ -0,0 +1,59 @@ +package com.newyetai.recruit.position.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + + +import java.math.BigDecimal; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + + +/** + * 岗位地址 + * + * @author Carlye + * @date 2022/03/29 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@TableName(value = "hr_position_address") +public class PositionAddress extends BaseEntity { + + private static final long serialVersionUID = -4055388034868470586L; + /** + * 公司ID + */ + private Long companyId; + + /** + * 区域编码(31) + */ + private String districtCode; + + /** + * 区域名称 (上海市) + */ + private String districtName; + /** + * 详细地址 (浦东新区黄金大厦B座) + */ + private String detailAddress; + /** + * 经度 + */ + private BigDecimal longitude; + /** + * 纬度 + */ + private BigDecimal latitude; +} diff --git a/src/main/java/com/newyetai/recruit/position/entity/PositionAudit.java b/src/main/java/com/newyetai/recruit/position/entity/PositionAudit.java new file mode 100644 index 0000000..11654f4 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/entity/PositionAudit.java @@ -0,0 +1,158 @@ +package com.newyetai.recruit.position.entity; + +import lombok.*; + +import com.baomidou.mybatisplus.annotation.*; + +import java.math.BigDecimal; +import java.util.Date; + +import com.newyetai.common.entity.BaseEntity; + +/** + * 岗位审核表 + * + * @author guixinman + * @since 1.0.0 2024-07-05 + */ +@TableName(value = "hr_position_audit") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class PositionAudit extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * + */ + private Long positionId; + /** + * + */ + private Long orgId; + /** + * hr_company主键 + */ + private Long companyId; + + /** + * 岗位名称 + */ + private String positionName; + /** + * 招聘标题 + */ + private String recruitTitle; + /** + * 岗位类型 + */ + private String positionType; + /** + * 工作性质 1:短工 2:全职 + */ + private String jobCategory; + /** + * 岗位招聘人数 + */ + private Integer positionNumber; + /** + * 工作地址 + */ + private String positionAddress; + /** + * 招聘专员 + */ + private Long recruitUserId; + + /** + * 发薪日 + */ + private String payDate; + /** + * 性别要求 + */ + private String sexRequire; + + /** + * 学历要求 + */ + private String educationRequire; + /** + * 经验要求 + */ + private String experienceRequire; + /** + * 证件要求 + */ + private String certificatesRequire; + /** + * 其他要求 + */ + private String otherRequire; + /** + * 工作内容 + */ + private String jobContent; + /** + * 岗位标签 + */ + private String positionTag; + /** + * + */ + private Long addressId; + /** + * 招聘岗位类型数据字典 + */ + private String recruitPositionType; + /** + * 审核状态 1:待审核 2.审核成功 3.审核失败 + */ + private String auditStatus; + /** + * 审核失败原因 + */ + private String auditFailMsg; + /** + * 版本号 + */ + private Integer version; + + /** + * 岗位相册json + */ + private String fileJson; + + /** + * 年龄上限 + */ + private Integer ageUp; + + /** + * 年龄下限 + */ + private Integer ageLow; + + /** + * 薪资上限 + */ + private BigDecimal salaryUp; + + /** + * 薪资下限 + */ + private BigDecimal salaryLow; + + /** + * 薪资类型 + */ + private String salaryType; + + /** + * 结束日期 + */ + private Date endTime; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/entity/PositionFile.java b/src/main/java/com/newyetai/recruit/position/entity/PositionFile.java new file mode 100644 index 0000000..3713870 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/entity/PositionFile.java @@ -0,0 +1,70 @@ +package com.newyetai.recruit.position.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; +import lombok.experimental.SuperBuilder; + +/** + *

+ * 用户岗位 文件 + *

+ * + * @author Carlye + * @since 2021-01-21 + */ +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@TableName("hr_position_file") +public class PositionFile extends BaseEntity { + + private static final long serialVersionUID = -1475024067817143931L; + /** + * 岗位ID + */ + private Long positionId; + + /** + * 文件名称 + */ + private String fileName; + + /** + * 文件编码 + */ + private String fileCode; + + /** + * 文件后缀 + */ + private String fileSuffix; + + /** + * 默认显示 + */ + private Boolean defaultShow; + + /** + * 文件类型 + */ + private String fileType; + + /** + * 排序 + */ + private Integer sort; + + /** + * 描述 + */ + private String description; +} diff --git a/src/main/java/com/newyetai/recruit/position/entity/PositionRegistration.java b/src/main/java/com/newyetai/recruit/position/entity/PositionRegistration.java new file mode 100644 index 0000000..3634ccb --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/entity/PositionRegistration.java @@ -0,0 +1,78 @@ +package com.newyetai.recruit.position.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; +import com.newyetai.component.action.annotation.ActionField; +import com.newyetai.component.action.annotation.ActionModel; + +import java.math.BigDecimal; +import java.util.Date; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 岗位报名信息表 + * + * @author guixinman + * @since 1.0.0 2024-04-15 + */ +@TableName(value = "hr_position_registration") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@ActionModel(type = "hr_position_registration") +public class PositionRegistration extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * 岗位ID + */ + private Long positionId; + /** + * 用户ID + */ + private Long userId; + /** + * 状态:1已报名、2待面试、3面试不通过、4待入职、5已入职、 6已离职、 7结束招聘 + */ + @ActionField(alias = "报名状态", dictCode = "position_registration_status") + private String status; + /** + * 面试时间 + */ + private Date interviewTime; + + @ApiModelProperty("面试地点") + private String interviewLocation; + + /** + * 入职时间 + */ + private Date inductionTime; + /** + * 离职时间 + */ + private Date quitTime; + /** + * 终止时间 + */ + private Date terminationTime; + /** + * 入职薪水 + */ + private BigDecimal salary; + /** + * 备注 + */ + private String remark; + + private Boolean show; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/entity/PositionType.java b/src/main/java/com/newyetai/recruit/position/entity/PositionType.java new file mode 100644 index 0000000..21c163f --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/entity/PositionType.java @@ -0,0 +1,60 @@ +package com.newyetai.recruit.position.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +/** + *

+ * 用户岗位类型 + *

+ * + * @author Carlye + * @since 2021-01-21 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@TableName(value = "hr_position_type") +public class PositionType extends BaseEntity { + + private static final long serialVersionUID = 2154317236704975221L; + /** + * 岗位ID + */ + private Long parentId; + + /** + * 文件名称 + */ + private String name; + + /** + * 文件编码 + */ + private String code; + + /** + * 全名 + */ + private String fullName; + + /** + * 完成code + */ + private String fullCode; + + /** + * 招聘岗位类型 + */ + private String recruitPositionType; +} diff --git a/src/main/java/com/newyetai/recruit/position/enums/PositionAuditStatusEnum.java b/src/main/java/com/newyetai/recruit/position/enums/PositionAuditStatusEnum.java new file mode 100644 index 0000000..e14067b --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/enums/PositionAuditStatusEnum.java @@ -0,0 +1,28 @@ +package com.newyetai.recruit.position.enums; + +public enum PositionAuditStatusEnum { + + INIT("1", "待审核"), + SUCCESS("2", "审核成功"), + FAIL("3", "审核失败"); + + private String status; + /** + * 类型描述 + */ + private String desc; + + + PositionAuditStatusEnum(String status, String desc) { + this.status = status; + this.desc = desc; + } + + public String getStatus() { + return status; + } + + public String getDesc() { + return desc; + } +} diff --git a/src/main/java/com/newyetai/recruit/position/enums/PositionRegistrationStatusEnum.java b/src/main/java/com/newyetai/recruit/position/enums/PositionRegistrationStatusEnum.java new file mode 100644 index 0000000..76c3fa1 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/enums/PositionRegistrationStatusEnum.java @@ -0,0 +1,43 @@ +package com.newyetai.recruit.position.enums; + +import java.util.Arrays; +import java.util.Objects; + +public enum PositionRegistrationStatusEnum { + ALREADY_REGISTERED("1", "已报名"), + WAIT_FOR_AN_INTERVIEW("2", "待面试"), + FAIL_THE_INTERVIEW("3", "面试不通过"), + TO_BE_HIRED("4", "待入职"), + ON_THE_JOB("5", "已入职"), + RESIGNED("6", "已离职"), + TERMINATION("7", "结束招聘"), + CANCEL("8", "取消报名") + ; + + private String status; + /** + * 类型描述 + */ + private String desc; + + + PositionRegistrationStatusEnum(String status, String desc) { + this.status = status; + this.desc = desc; + } + + public String getStatus() { + return status; + } + + public String getDesc() { + return desc; + } + + public static PositionRegistrationStatusEnum find(String status){ + if (Objects.isNull(status)){ + return null; + } + return Arrays.stream(PositionRegistrationStatusEnum.values()).filter(e->e.getStatus().equals(status)).findFirst().orElse(null); + } +} diff --git a/src/main/java/com/newyetai/recruit/position/enums/PositionStatusEnum.java b/src/main/java/com/newyetai/recruit/position/enums/PositionStatusEnum.java new file mode 100644 index 0000000..098453c --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/enums/PositionStatusEnum.java @@ -0,0 +1,27 @@ +package com.newyetai.recruit.position.enums; + +public enum PositionStatusEnum { + OPEN("1", "开启"), + CLOSE("2", "关闭") + ; + + private String status; + /** + * 类型描述 + */ + private String desc; + + + PositionStatusEnum(String status, String desc) { + this.status = status; + this.desc = desc; + } + + public String getStatus() { + return status; + } + + public String getDesc() { + return desc; + } +} diff --git a/src/main/java/com/newyetai/recruit/position/job/PositionExpiryJob.java b/src/main/java/com/newyetai/recruit/position/job/PositionExpiryJob.java new file mode 100644 index 0000000..6ef33a0 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/job/PositionExpiryJob.java @@ -0,0 +1,42 @@ +package com.newyetai.recruit.position.job; + +import com.newyetai.recruit.position.dto.PositionDTO; +import com.newyetai.recruit.position.dto.PositionPageQueryDTO; +import com.newyetai.recruit.position.enums.PositionStatusEnum; +import com.newyetai.recruit.position.service.PositionService; +import com.newyetai.security.util.MockUtils; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + + +import lombok.extern.slf4j.Slf4j; + +/** + * @description: 岗位失效Job + * @author: guixinman + * @create: 2024-11-12 16:23 + **/ +@Slf4j +@Component +public class PositionExpiryJob { + + @Autowired + private PositionService positionService; + + @Scheduled(cron = "01 10 00 * * ?") + public void statistics() { + + log.info("岗位有效期检测 ======开始"); + MockUtils.mockPlatUser(); + try { + positionService.positionExpiry(); + } catch (Exception e) { + log.error(e.getMessage()); + } + + log.info("岗位有效期检测 ======结束"); + + } +} diff --git a/src/main/java/com/newyetai/recruit/position/mapper/ImportDetailPositionMapper.xml b/src/main/java/com/newyetai/recruit/position/mapper/ImportDetailPositionMapper.xml new file mode 100644 index 0000000..f9b92d2 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/mapper/ImportDetailPositionMapper.xml @@ -0,0 +1,97 @@ + + + + + + + + + + + FROM + hr_import_detail_position t + LEFT JOIN hr_company hc ON t.company_id = hc.id AND hc.deleted = 0 + WHERE t.deleted = 0 + + AND t.id = #{param.id} + + + AND t.main_id = #{param.mainId} + + + AND t.org_id = #{param.orgId} + + + AND t.data_json = #{param.dataJson} + + + AND t.company_id = #{param.companyId} + + + + AND t.position_name like #{positionNameLike} + + + AND t.recruit_title = #{param.recruitTitle} + + + AND t.position_number = #{param.positionNumber} + + + AND t.position_address = #{param.positionAddress} + + + AND t.pay_date = #{param.payDate} + + + AND t.sex_require = #{param.sexRequire} + + + AND t.education_require = #{param.educationRequire} + + + AND t.experience_require = #{param.experienceRequire} + + + AND t.certificates_require = #{param.certificatesRequire} + + + AND t.other_require = #{param.otherRequire} + + + AND t.job_content = #{param.jobContent} + + + AND t.detail_status = #{param.detailStatus} + + + AND t.fail_reason = #{param.failReason} + + + AND t.extra_detail_id = #{param.extraDetailId} + + + AND t.remark = #{param.remark} + + + AND t.create_time >= #{param.createTimeStart} + + + AND t.create_time <= #{param.createTimeEnd} + + + AND t.update_time >= #{param.updateTimeStart} + + + AND t.update_time <= #{param.updateTimeEnd} + + ORDER BY t.id DESC + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/mapper/PositionAddressMapper.xml b/src/main/java/com/newyetai/recruit/position/mapper/PositionAddressMapper.xml new file mode 100644 index 0000000..f04f685 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/mapper/PositionAddressMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/java/com/newyetai/recruit/position/mapper/PositionAuditMapper.xml b/src/main/java/com/newyetai/recruit/position/mapper/PositionAuditMapper.xml new file mode 100644 index 0000000..a744af7 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/mapper/PositionAuditMapper.xml @@ -0,0 +1,292 @@ + + + + + + + update hr_position_audit + set company_id = #{param.companyId}, + position_name = #{param.positionName}, + recruit_title = #{param.recruitTitle}, + position_type = #{param.positionType}, + job_category = #{param.jobCategory}, + position_number = #{param.positionNumber}, + position_address = #{param.positionAddress}, + recruit_user_id = #{param.recruitUserId}, + pay_date = #{param.payDate}, + sex_require = #{param.sexRequire}, + education_require = #{param.educationRequire}, + experience_require = #{param.experienceRequire}, + certificates_require = #{param.certificatesRequire}, + other_require = #{param.otherRequire}, + job_content = #{param.jobContent}, + position_tag = #{param.positionTag}, + address_id = #{param.addressId}, + recruit_position_type = #{param.recruitPositionType}, + file_json = #{param.fileJson}, + age_up = #{param.ageUp}, + age_low = #{param.ageLow}, + salary_up = #{param.salaryUp}, + salary_low = #{param.salaryLow}, + salary_type = #{param.salaryType}, + + audit_status = #{param.auditStatus}, + + version = version + 1, + update_by = #{param.updateBy}, + update_time = now() + where id = #{param.id} and position_id = #{param.positionId} and deleted = 0 and version = + #{param.version} and audit_status = 1 + + + + + + + + + + + update hr_position_audit + set version = version + 1, + update_by = #{param.updateBy}, + update_time = now(), + audit_status = #{param.auditStatus}, + audit_fail_msg = #{param.auditFailMsg} + where deleted = 0 + and id = #{param.id} + and version = #{param.version} + + + + + + FROM + hr_position_audit t + WHERE t.deleted = 0 + + AND t.id = #{param.id} + + + AND t.position_id = #{param.positionId} + + + AND t.org_id = #{param.orgId} + + + AND t.company_id = #{param.companyId} + + + AND t.status = #{param.status} + + + + AND t.position_name like #{positionNameLike} + + + AND t.recruit_title = #{param.recruitTitle} + + + AND t.position_type = #{param.positionType} + + + AND t.job_category = #{param.jobCategory} + + + AND t.position_number = #{param.positionNumber} + + + AND t.position_address = #{param.positionAddress} + + + AND t.recruit_user_id = #{param.recruitUserId} + + + AND t.pay_date = #{param.payDate} + + + AND t.sex_require = #{param.sexRequire} + + + AND t.education_require = #{param.educationRequire} + + + AND t.experience_require = #{param.experienceRequire} + + + AND t.certificates_require = #{param.certificatesRequire} + + + AND t.other_require = #{param.otherRequire} + + + AND t.job_content = #{param.jobContent} + + + AND t.position_tag = #{param.positionTag} + + + AND t.address_id = #{param.addressId} + + + AND t.recruit_position_type = #{param.recruitPositionType} + + + AND t.audit_status = #{param.auditStatus} + + + AND t.audit_fail_msg = #{param.auditFailMsg} + + + AND t.version = #{param.version} + + + AND t.create_time >= #{param.createTimeStart} + + + AND t.create_time <= #{param.createTimeEnd} + + + AND t.update_time >= #{param.updateTimeStart} + + + AND t.update_time <= #{param.updateTimeEnd} + + ORDER BY t.id DESC + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/mapper/PositionFileMapper.xml b/src/main/java/com/newyetai/recruit/position/mapper/PositionFileMapper.xml new file mode 100644 index 0000000..0f4865d --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/mapper/PositionFileMapper.xml @@ -0,0 +1,34 @@ + + + + + UPDATE hr_position_file + SET default_show = + CASE + + WHEN default_show = 1 THEN + 0 + ELSE 1 + END, + update_time = NOW() + WHERE deleted = 0 + AND file_type = '1' + AND position_id = #{positionId} + AND ( + id = #{id} + OR default_show = 1) + + + + diff --git a/src/main/java/com/newyetai/recruit/position/mapper/PositionMapper.xml b/src/main/java/com/newyetai/recruit/position/mapper/PositionMapper.xml new file mode 100644 index 0000000..e7037f4 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/mapper/PositionMapper.xml @@ -0,0 +1,303 @@ + + + + + + update hr_position set status = 2, "update_by" = 1, "update_time" = now() where "deleted" = 0 and status = 1 and "end_time" <= now() + + + + + + + + + + + + + FROM + hr_position t + WHERE t.deleted = 0 + + AND t.id = #{param.id} + + + AND t.org_id = #{param.orgId} + + + AND t.company_id = #{param.companyId} + + + AND t.status = #{param.status} + + + + AND t.position_name like #{positionNameLike} + + + AND t.recruit_title = #{param.recruitTitle} + + + AND t.position_type = #{param.positionType} + + + AND t.job_category = #{param.jobCategory} + + + AND t.position_number = #{param.positionNumber} + + + AND t.position_address = #{param.positionAddress} + + + AND t.recruit_user_id = #{param.recruitUserId} + + + AND t.pay_date = #{param.payDate} + + + AND t.education_require = #{param.educationRequire} + + + AND t.experience_require = #{param.experienceRequire} + + + AND t.certificates_require = #{param.certificatesRequire} + + + AND t.other_require = #{param.otherRequire} + + + AND t.job_content = #{param.jobContent} + + + AND t.create_time >= #{param.createTimeStart} + + + AND t.create_time <= #{param.createTimeEnd} + + + AND t.update_time >= #{param.updateTimeStart} + + + AND t.update_time <= #{param.updateTimeEnd} + + ORDER BY t.id DESC + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/mapper/PositionRegistrationMapper.xml b/src/main/java/com/newyetai/recruit/position/mapper/PositionRegistrationMapper.xml new file mode 100644 index 0000000..4f56e00 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/mapper/PositionRegistrationMapper.xml @@ -0,0 +1,239 @@ + + + + + + update hr_position_registration + set status = #{param.status},update_time = now(),update_by = #{param.updateBy} + + ,interview_time = #{param.interviewTime} + + + ,interview_location = #{param.interviewLocation} + + + ,induction_time = #{param.inductionTime} + + + ,quit_time = #{param.quitTime} + + + ,termination_time = #{param.terminationTime} + + + ,salary = #{param.salary} + + + ,remark = #{param.remark} + + where + id = #{param.id} + + and status = #{oldStatus} + + + + + + + + + + FROM + hr_position_registration t + WHERE t.deleted = 0 + + AND t.id = #{param.id} + + + AND t.position_id = #{param.positionId} + + + AND t.user_id = #{param.userId} + + + AND t.status = #{param.status} + + + AND t.interview_time = #{param.interviewTime} + + + AND t.induction_time = #{param.inductionTime} + + + AND t.quit_time = #{param.quitTime} + + + AND t.termination_time = #{param.terminationTime} + + + AND t.salary = #{param.salary} + + + AND t.remark = #{param.remark} + + + AND t.create_time >= #{param.createTimeStart} + + + AND t.create_time <= #{param.createTimeEnd} + + + AND t.update_time >= #{param.updateTimeStart} + + + AND t.update_time <= #{param.updateTimeEnd} + + ORDER BY t.id DESC + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/mapper/PositionTypeMapper.xml b/src/main/java/com/newyetai/recruit/position/mapper/PositionTypeMapper.xml new file mode 100644 index 0000000..ae07bc3 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/mapper/PositionTypeMapper.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/src/main/java/com/newyetai/recruit/position/service/ImportDetailPositionService.java b/src/main/java/com/newyetai/recruit/position/service/ImportDetailPositionService.java new file mode 100644 index 0000000..2efc015 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/service/ImportDetailPositionService.java @@ -0,0 +1,70 @@ +package com.newyetai.recruit.position.service; + +import org.springframework.validation.annotation.Validated; + +import javax.validation.Valid; +import javax.validation.groups.Default; + +import java.util.List; + +import com.newyetai.recruit.position.dto.*; + +/** + * 岗位导入 + * + * @author guixinman + * @since 1.0.0 2024-04-12 + */ +@Validated(Default.class) +public interface ImportDetailPositionService { + + /** + * 岗位导入 - 创建 + * + * @param operatorDto 操作dto + * @return {@link ImportDetailPositionDTO} + */ + ImportDetailPositionDTO create(@Valid ImportDetailPositionOperatorDTO operatorDto); + + /** + * 岗位导入 - 修改 + * + * @param operatorDto 操作dto + * @return {@link ImportDetailPositionDTO} + */ + ImportDetailPositionDTO modify(@Valid ImportDetailPositionOperatorDTO operatorDto); + + /** + * 岗位导入 - 删除 + * + * @param id id + * @return {@link ImportDetailPositionDTO} + */ + ImportDetailPositionDTO delete(Long id); + + /** + * 岗位导入 - 根据ID查询单个 + * + * @param id id + * @return {@link ImportDetailPositionDTO} + */ + ImportDetailPositionDTO findById(Long id); + + /** + * 岗位导入 - 列表查询 + * + * @param queryDTO 列表查询dto + * @return {@link List}<{@link ImportDetailPositionDTO}> + */ + List list(ImportDetailPositionQueryDTO queryDTO); + + /** + * 岗位导入 - 分页查询 + * + * @param queryDTO 分页查询dto + * @return {@link ImportDetailPositionDTO} + */ + List page(ImportDetailPositionPageQueryDTO queryDTO); + + void batchCreate(List importDetailPositionDTOS); +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/service/PositionAddressService.java b/src/main/java/com/newyetai/recruit/position/service/PositionAddressService.java new file mode 100644 index 0000000..d7004b8 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/service/PositionAddressService.java @@ -0,0 +1,50 @@ +package com.newyetai.recruit.position.service; + + + +import com.newyetai.recruit.position.dto.PositionAddressDTO; +import com.newyetai.recruit.position.dto.PositionAddressOperatorDTO; +import com.newyetai.recruit.position.dto.PositionAddressQueryDTO; + +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import javax.validation.Valid; +import javax.validation.groups.Default; + +/** + *

+ * 招聘系统-岗位报名信息表 服务类 + *

+ * + * @author chenyun + * @since 2021-01-08 + */ +@Validated(Default.class) +public interface PositionAddressService { + + + /** + * 创建或更新 + * + * @param operatorDTO 运营商dto + * @return {@link Long} + */ + Long createOrUpdate(@Valid PositionAddressOperatorDTO operatorDTO); + + /** + * 列表 + * + * @param queryDTO 查询dto + * @return {@link List}<{@link PositionAddressDTO}> + */ + List list(PositionAddressQueryDTO queryDTO); + + /** + * 删除 + * + * @param id id + */ + void delete(Long id); +} diff --git a/src/main/java/com/newyetai/recruit/position/service/PositionAuditService.java b/src/main/java/com/newyetai/recruit/position/service/PositionAuditService.java new file mode 100644 index 0000000..43c8264 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/service/PositionAuditService.java @@ -0,0 +1,99 @@ +package com.newyetai.recruit.position.service; + +import org.springframework.validation.annotation.Validated; + +import javax.validation.Valid; +import javax.validation.groups.Default; + +import java.util.List; +import java.util.Set; + +import com.newyetai.recruit.position.dto.*; + +/** + * 岗位审核表 + * + * @author guixinman + * @since 1.0.0 2024-07-05 + */ +@Validated(Default.class) +public interface PositionAuditService { + + /** + * 岗位审核表 - 创建 + * + * @param operatorDto 操作dto + * @return {@link PositionAuditDTO} + */ + PositionNewDTO positionCreate(@Valid PositionNewOperatorDTO operatorDto); + + /** + * 岗位审核表 - 修改 + * + * @param operatorDto 操作dto + * @return {@link PositionAuditDTO} + */ + void positionModify(@Valid PositionNewOperatorDTO operatorDto); + + + /** + * 岗位审核表 - 根据ID查询单个 + * + * @param id id + * @return {@link PositionAuditDTO} + */ + PositionNewDTO positionFindById(Long id); + + /** + * 岗位审核表 - 列表查询 + * + * @param queryDTO 列表查询dto + * @return {@link List}<{@link PositionAuditDTO}> + */ + List list(PositionAuditQueryDTO queryDTO); + + /** + * 岗位审核表 - 分页查询 + * + * @param queryDTO 分页查询dto + * @return {@link PositionAuditDTO} + */ + List page(PositionAuditPageQueryDTO queryDTO); + + /** + * 岗位审核表 - 分页查询 + * + * @param queryDTO 分页查询dto + * @return {@link PositionAuditDTO} + */ + List positionPage(PositionNewPageQueryDTO queryDTO); + + void export(PositionNewPageQueryDTO queryDTO); + + /** + * @description: 审核 + * @return: + * @author: guixinman + * @param: + */ + void audit(PositionAuditReqDTO reqDTO); + + + PositionAuditDTO findById(Long id); + + /** + * @description: 开启招聘关闭招聘 + * @return: + * @author: guixinman + * @param: + */ + void positionModifyStatus(Set ids, String status); + + /** + * @description: 复制岗位 + * @return: + * @author: guixinman + * @param: + */ + Long positionCopy(Long id); +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/service/PositionFileService.java b/src/main/java/com/newyetai/recruit/position/service/PositionFileService.java new file mode 100644 index 0000000..55b13ee --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/service/PositionFileService.java @@ -0,0 +1,46 @@ +package com.newyetai.recruit.position.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.newyetai.recruit.position.dto.PositionFileDTO; +import com.newyetai.recruit.position.dto.PositionFilePageQueryDTO; +import com.newyetai.recruit.position.entity.PositionFile; + +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import javax.validation.groups.Default; + +/** + *

+ * 招聘系统-岗位报名信息表 服务类 + *

+ * + * @author chenyun + * @since 2021-01-08 + */ +@Validated(Default.class) +public interface PositionFileService extends IService { + + /** + * 岗位文件列表 + * + * @param queryDTO 查询dto + * @return {@link List}<{@link PositionFileDTO}> + */ + List filePage(PositionFilePageQueryDTO queryDTO); + + PositionFile create(PositionFileDTO queryDTO); + + void update(PositionFileDTO dto); + + void delete(Long id); + void deleteByPositionId(Long positionId); + + /** + * 设置默认展示 (封面) + * + * @param id id + */ + void setDefault(Long id); +} diff --git a/src/main/java/com/newyetai/recruit/position/service/PositionRegistrationService.java b/src/main/java/com/newyetai/recruit/position/service/PositionRegistrationService.java new file mode 100644 index 0000000..26cb066 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/service/PositionRegistrationService.java @@ -0,0 +1,138 @@ +package com.newyetai.recruit.position.service; + +import org.springframework.validation.annotation.Validated; + +import javax.validation.Valid; +import javax.validation.groups.Default; + +import java.util.List; + +import com.newyetai.recruit.position.dto.*; + +/** + * 岗位报名信息表 + * + * @author guixinman + * @since 1.0.0 2024-04-15 + */ +@Validated(Default.class) +public interface PositionRegistrationService { + + /** + * 岗位报名信息表 - 创建 + * + * @param operatorDto 操作dto + * @return {@link PositionRegistrationDTO} + */ + PositionRegistrationDTO create(@Valid PositionRegistrationOperatorDTO operatorDto); + + /** + * 岗位报名信息表 - 修改 + * + * @param operatorDto 操作dto + * @return {@link PositionRegistrationDTO} + */ + PositionRegistrationDTO modify(@Valid PositionRegistrationOperatorDTO operatorDto); + + /** + * 岗位报名信息表 - 删除 + * + * @param id id + * @return {@link PositionRegistrationDTO} + */ + PositionRegistrationDTO delete(Long id); + + /** + * 岗位报名信息表 - 根据ID查询单个 + * + * @param id id + * @return {@link PositionRegistrationDTO} + */ + PositionRegistrationDTO findById(Long id); + PositionRegistrationDTO findByIdAndChildrenOrgAll(Long id, Boolean childrenOrgAll); + + + /** + * 岗位报名信息表 - 列表查询 + * + * @param queryDTO 列表查询dto + * @return {@link List}<{@link PositionRegistrationDTO}> + */ + List list(PositionRegistrationPageQueryDTO queryDTO); + + /** + * 岗位报名信息表 - 分页查询 + * + * @param queryDTO 分页查询dto + * @return {@link PositionRegistrationDTO} + */ + List page(PositionRegistrationPageQueryDTO queryDTO); + + /** + * @description: 用户端报名岗位 + * @return: + * @author: guixinman + * @param: + */ + void userCreate(UserPositionRegistrationDTO dto); + + /** + * @description: 邀约面试 + * @return: + * @author: guixinman + * @param: + */ + void invite(PositionRegistrationOperatorDTO operatorDTO); + + /** + * @description: 结束招聘 + * @return: + * @author: guixinman + * @param: + */ + void termination(PositionRegistrationOperatorDTO operatorDTO); + + /** + * @description: 完成面试 + * @return: + * @author: guixinman + * @param: + */ + void fulfillInterview(PositionRegistrationOperatorDTO operatorDTO); + + /** + * @description: 入职 + * @return: + * @author: guixinman + * @param: + */ + void onTheJob(OnTheJobDTO dto); + + /** + * @description: 离职 + * @return: + * @author: guixinman + * @param: + */ + void resigned(ResignedDTO dto); + + void export(PositionRegistrationPageQueryDTO queryDTO); + + /** + * @description: 用户端查看我的报名 + * @return: + * @author: guixinman + * @param: + */ + List userPage(UserPositionRegistrationPageQueryDTO queryDTO); + + void cancel(Long positionId); + + /** + * @description: 查看 + * @return: + * @author: guixinman + * @param: + */ + void show(Long id); +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/service/PositionService.java b/src/main/java/com/newyetai/recruit/position/service/PositionService.java new file mode 100644 index 0000000..a6e8636 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/service/PositionService.java @@ -0,0 +1,104 @@ +package com.newyetai.recruit.position.service; + +import org.springframework.validation.annotation.Validated; + +import javax.validation.Valid; +import javax.validation.groups.Default; + +import java.util.List; +import java.util.Set; + +import com.newyetai.recruit.position.dto.*; + +/** + * 岗位信息表;岗位信息表 + * + * @author guixinman + * @since 1.0.0 2024-04-11 + */ +@Validated(Default.class) +public interface PositionService { + + /** + * 岗位信息表;岗位信息表 - 创建 + * + * @param operatorDto 操作dto + * @return {@link PositionDTO} + */ + PositionDTO create(@Valid PositionOperatorDTO operatorDto); + + /** + * 岗位信息表;岗位信息表 - 修改 + * + * @param operatorDto 操作dto + * @return {@link PositionDTO} + */ + PositionDTO modify(@Valid PositionOperatorDTO operatorDto); + + /** + * 岗位信息表;岗位信息表 - 删除 + * + * @param id id + * @return {@link PositionDTO} + */ + PositionDTO delete(Long id); + + /** + * 岗位信息表;岗位信息表 - 根据ID查询单个 + * + * @param id id + * @return {@link PositionDTO} + */ + PositionDTO findById(Long id); + + PositionDTO userFindById(Long id); + + /** + * 岗位信息表;岗位信息表 - 列表查询 + * + * @param queryDTO 列表查询dto + * @return {@link List}<{@link PositionDTO}> + */ + List list(PositionPageQueryDTO queryDTO); + + /** + * 岗位信息表;岗位信息表 - 分页查询 + * + * @param queryDTO 分页查询dto + * @return {@link PositionDTO} + */ + List page(PositionPageQueryDTO queryDTO); + List userPage(PositionPageQueryDTO queryDTO); + + /** + * @description: 岗位信息腾讯地图-分页查询" + * @return: + * @author: guixinman + * @param: + */ + List tencentMapUserPage(PositionPageQueryDTO queryDTO); + + void export(PositionPageQueryDTO queryDTO); + + /** + * @description: 开启或者关闭招聘 + * @return: + * @author: guixinman + * @param: + */ + void modifyStatus(PositionOperatorDTO dto); + + void template(); + + Long copy(Long id); + + /** + * @description: 人岗匹配 + * @return: + * @author: guixinman + * @param: + */ + List personPostMatching(Long id); + + void positionExpiry(); +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/service/PositionTypeService.java b/src/main/java/com/newyetai/recruit/position/service/PositionTypeService.java new file mode 100644 index 0000000..9912ea2 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/service/PositionTypeService.java @@ -0,0 +1,40 @@ +package com.newyetai.recruit.position.service; + + + +import com.newyetai.recruit.position.dto.PositionTypeDTO; +import com.newyetai.recruit.position.dto.PositionTypeQueryDTO; + +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import javax.validation.groups.Default; + +/** + *

+ * 招聘系统-岗位报名信息表 服务类 + *

+ * + * @author chenyun + * @since 2021-01-08 + */ +@Validated(Default.class) +public interface PositionTypeService { + + /** + * 批量创建 + * + * @param positionTypeDTOS 位置式dto + * @return {@link List}<{@link PositionTypeDTO}> + */ + List batchCreate(List positionTypeDTOS); + + /** + * 查询 + * + * @param queryDTO 查询dto + * @return {@link List}<{@link PositionTypeDTO}> + */ + List query(PositionTypeQueryDTO queryDTO); +} diff --git a/src/main/java/com/newyetai/recruit/position/service/impl/ImportDetailPositionAdminProvider.java b/src/main/java/com/newyetai/recruit/position/service/impl/ImportDetailPositionAdminProvider.java new file mode 100644 index 0000000..7d03d1e --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/service/impl/ImportDetailPositionAdminProvider.java @@ -0,0 +1,567 @@ +package com.newyetai.recruit.position.service.impl; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; + +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.read.builder.ExcelReaderBuilder; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.newyetai.common.AlitaResult; +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.dto.ExportHeadDetailInfoDTO; +import com.newyetai.common.dto.ExportHeadInfoDTO; +import com.newyetai.common.easyexcel.ExcelUtil; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.component.commonimport.constant.ImportDetailStatusEnum; +import com.newyetai.component.commonimport.constant.ImportStatusEnum; +import com.newyetai.component.commonimport.constant.ImportTypeEnum; +import com.newyetai.component.commonimport.dto.ImportDetailPageDTO; +import com.newyetai.component.commonimport.dto.ImportMainDTO; +import com.newyetai.component.commonimport.dto.ImportMainQueryDTO; +import com.newyetai.component.commonimport.dto.ImportMainUpdateDTO; +import com.newyetai.component.commonimport.service.ImportMainService; +import com.newyetai.component.commonimport.service.impl.AbstractCommonImportProvider; +import com.newyetai.component.dict.util.DictUtils; +import com.newyetai.component.file.entity.FileRecord; +import com.newyetai.component.file.service.FileRecordService; +import com.newyetai.recruit.company.dto.HrCompanyDTO; +import com.newyetai.recruit.company.dto.HrCompanyPageQueryDTO; +import com.newyetai.recruit.company.enums.HrCompanyEnum; +import com.newyetai.recruit.company.service.IHrCompanyService; +import com.newyetai.recruit.position.dao.PositionAddressMapper; +import com.newyetai.recruit.position.dao.PositionMapper; +import com.newyetai.recruit.position.dao.PositionTypeMapper; +import com.newyetai.recruit.position.dto.ImportDetailPositionDTO; +import com.newyetai.recruit.position.dto.ImportDetailPositionExecuteDTO; +import com.newyetai.recruit.position.dto.ImportDetailPositionExportDTO; +import com.newyetai.recruit.position.dto.ImportDetailPositionListenerDTO; +import com.newyetai.recruit.position.dto.ImportDetailPositionOperatorDTO; +import com.newyetai.recruit.position.dto.ImportDetailPositionPageQueryDTO; +import com.newyetai.recruit.position.dto.PositionNewDTO; +import com.newyetai.recruit.position.dto.PositionNewOperatorDTO; +import com.newyetai.recruit.position.dto.PositionOperatorDTO; +import com.newyetai.recruit.position.entity.Position; +import com.newyetai.recruit.position.entity.PositionAddress; +import com.newyetai.recruit.position.entity.PositionType; +import com.newyetai.recruit.position.service.ImportDetailPositionService; +import com.newyetai.recruit.position.service.PositionAuditService; +import com.newyetai.sdk.tencent.map.TencentMapContext; +import com.newyetai.sdk.tencent.map.dto.TencentMapGeocoderReqDTO; +import com.newyetai.sdk.tencent.map.dto.TencentMapGeocoderResDTO; +import com.newyetai.sdk.tencent.map.dto.TencentMapLocationV1IpResDTO; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.org.dao.OrgMapper; +import com.newyetai.usercenter.org.entity.Org; +import com.newyetai.usercenter.org.enums.RecruitPositionTypeEnum; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.InputStream; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import javax.annotation.Resource; + +import cn.hutool.core.date.DateUtil; +import lombok.extern.slf4j.Slf4j; + +/** + * @description: admin导入岗位 + * @author: guixinman + * @create: 2024-04-11 17:45 + **/ +@Service +@Slf4j +public class ImportDetailPositionAdminProvider extends AbstractCommonImportProvider { + + @Autowired + private ImportDetailPositionService importDetailPositionService; + + @Autowired + private ImportMainService importMainService; + + @Autowired + private FileRecordService fileRecordService; + + @Autowired + private IHrCompanyService hrCompanyService; + + @Autowired + private PositionAuditService positionAuditService; + + @Resource + private PositionMapper positionMapper; + + @Resource + private PositionTypeMapper positionTypeMapper; + + @Resource + private PositionAddressMapper positionAddressMapper; + + @Resource + private OrgMapper orgMapper; + + @Autowired + private TencentMapContext tencentMapContext; + + public ImportDetailPositionAdminProvider(ImportMainService imprImportMainService) { + super(imprImportMainService); + } + + @Override + public String getType() { + return ImportTypeEnum.ADMIN_POSITION.getType(); + } + + @Override + public Page pageDetail(ImportDetailPageDTO importDetailPageDTO) { + ImportDetailPositionPageQueryDTO queryDTO = new ImportDetailPositionPageQueryDTO(); + BeanUtils.copyProperties(importDetailPageDTO, queryDTO); + importDetailPositionService.page(queryDTO); + return queryDTO.getPageResult(); + } + + @Override + public void importDetailExport(ImportDetailPageDTO importDetailPageDTO) { + ImportDetailPositionPageQueryDTO queryDTO = new ImportDetailPositionPageQueryDTO(); + BeanUtils.copyProperties(importDetailPageDTO, queryDTO); + queryDTO.disablePage(); + List list = importDetailPositionService.page(queryDTO); + + List exportDTOList = list.stream().map(dto -> { + ImportDetailPositionExportDTO importDetailPositionExportDTO = JsonUtils.toObject(dto.getDataJson(), ImportDetailPositionExportDTO.class); + importDetailPositionExportDTO.setRemark(dto.getRemark()); + importDetailPositionExportDTO.setFailReason(dto.getFailReason()); + return importDetailPositionExportDTO; + }).collect(Collectors.toList()); + + if (org.springframework.util.CollectionUtils.isEmpty(exportDTOList)) { + return; + } + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); + String commonImportDetailStatus = DictUtils.getCodeNameMap("common_import_detail_status").get(String.valueOf(importDetailPageDTO.getDetailStatus())); + + String fileName = "岗位导入" + (StringUtils.isNotBlank(commonImportDetailStatus) ? commonImportDetailStatus : "") + "明细导出" + "(" + formatter.format(LocalDateTime.now()) + ")"; + + ExportHeadInfoDTO infoDTO = ExportHeadInfoDTO.builder() + .fileName(fileName) + .build(); + List heads = infoDTO.getHeads(); + heads.add(ExportHeadDetailInfoDTO.builder().head("用工企业").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("岗位名称").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("招聘标题").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("招聘人数").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("工作地址").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("岗位性质").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("岗位类型").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("岗位标签").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("薪资下限").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("薪资上限").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("薪资类型").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("发薪日").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("性别").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("年龄(下限)").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("年龄(上限)").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("学历").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("经验").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("证件").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("其他").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("工作内容").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("有效期截止时间").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("失败原因").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("备注").build()); + + List datas = Lists.newArrayList(); + for (ImportDetailPositionExportDTO dto : exportDTOList) { + List objects = Lists.newArrayList(); + datas.add(objects); + objects.add(dto.getCompanyName()); + objects.add(dto.getPositionName()); + objects.add(dto.getRecruitTitle()); + objects.add(dto.getPositionNumber()); + objects.add(dto.getPositionAddress()); + objects.add(dto.getRecruitPositionType()); + objects.add(dto.getPositionTypeName()); + objects.add(dto.getPositionTag()); + objects.add(dto.getSalaryLow()); + objects.add(dto.getSalaryUp()); + objects.add(dto.getSalaryType()); + objects.add(dto.getPayDate()); + objects.add(dto.getSexRequire()); + objects.add(dto.getAgeLow()); + objects.add(dto.getAgeUp()); + objects.add(dto.getEducationRequire()); + objects.add(dto.getExperienceRequire()); + objects.add(dto.getCertificatesRequire()); + objects.add(dto.getOtherRequire()); + objects.add(dto.getJobContent()); + objects.add(dto.getEndTime()); + objects.add(dto.getFailReason()); + objects.add(dto.getRemark()); + + } + infoDTO.setDatas(datas); + + ExcelUtil.dynamicExportTemplate(infoDTO); + + } + + @Override + public List analy(Long mainId) { + // 解析文件+明细 + ImportMainDTO importMainDTO = importMainService.find(ImportMainQueryDTO.builder().id(mainId).build()); + Assert.notNull(importMainDTO, "未查询到导入的数据"); + + FileRecord fileRecord; + try { + fileRecord = fileRecordService.find(FileRecord.builder().fileCode(importMainDTO.getFileCode()).build()); + } catch (Exception e) { + log.info("导入文件异常,", e); + fileRecord = null; + } + Assert.notNull(fileRecord, "上传文件不存在"); + try (InputStream is = fileRecordService.getFile(importMainDTO.getFileCode())) { + ImportPositionExcelListener listener = new ImportPositionExcelListener(); + ExcelReaderBuilder reader = EasyExcel.read(is, ImportDetailPositionListenerDTO.class, listener); + reader.sheet().doRead(); + List dtos = listener.getDtos(); + Assert.isTrue(!dtos.isEmpty(), "导入文件无有效数据"); + return dtos; + } catch (Exception e) { + throw new BusinessException(e.getMessage()); + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void checkAndSave(Long mainId, List detailCreateDtos) { + //更改状态为校验中 + ImportMainUpdateDTO updateDto = ImportMainUpdateDTO.builder().id(mainId) + .oldStatusSet(Sets.newHashSet(ImportStatusEnum.INIT.getStatus())) + .newStatus(ImportStatusEnum.CHECKING.getStatus()) + .build(); + importMainService.modify(updateDto); + + List importDetailPositionDTOS = new ArrayList<>(); + + //存储用工企业+岗位名称。用于校验 导入的数据中有没有重复的 + List companyIdPositionNames = new ArrayList<>(); + + for (ImportDetailPositionListenerDTO importDetailPositionListenerDTO : detailCreateDtos) { + ImportDetailPositionDTO importDetailPositionDTO = new ImportDetailPositionDTO(); + + this.checkAndFill(importDetailPositionDTO, importDetailPositionListenerDTO); + + if (StringUtils.isBlank(importDetailPositionDTO.getFailReason())) { + if (companyIdPositionNames.contains(StringUtils.join(importDetailPositionListenerDTO.getCompanyName(), importDetailPositionListenerDTO.getPositionName()))) { + importDetailPositionDTO.appendFailMsg("用工企业+岗位名称出现多次"); + } + //存储用工企业+岗位名称 + companyIdPositionNames.add(StringUtils.join(importDetailPositionListenerDTO.getCompanyName(), importDetailPositionListenerDTO.getPositionName())); + } + + if (StringUtils.isNotBlank(importDetailPositionDTO.getFailReason())) { + importDetailPositionDTO.setDetailStatus(ImportDetailStatusEnum.CHECK_FAIL.getStatus()); + } else { + importDetailPositionDTO.setDetailStatus(ImportDetailStatusEnum.CHECK_SUCCESS.getStatus()); + } + importDetailPositionDTO.setMainId(mainId); + importDetailPositionDTOS.add(importDetailPositionDTO); + } + importDetailPositionService.batchCreate(importDetailPositionDTOS); + super.finishCheck(mainId, importDetailPositionDTOS); + } + + private void checkAndFill(ImportDetailPositionDTO importDetailPositionDTO, ImportDetailPositionListenerDTO importDetailPositionListenerDTO) { + BeanUtils.copyProperties(importDetailPositionListenerDTO, importDetailPositionDTO); + importDetailPositionDTO.setDataJson(JsonUtils.toJsonString(importDetailPositionListenerDTO)); + + if (StringUtils.isBlank(importDetailPositionDTO.getPositionName())) { + importDetailPositionDTO.appendFailMsg("岗位名称不能为空"); + } else if (importDetailPositionDTO.getPositionName().length() > 50) { + importDetailPositionDTO.appendFailMsg("岗位名称超过最大限制长度"); + importDetailPositionDTO.setPositionName(null); + } + + if (StringUtils.isBlank(importDetailPositionListenerDTO.getCompanyName())) { + importDetailPositionDTO.appendFailMsg("用工企业不能为空"); + } else { + HrCompanyDTO hrCompanyDTO = hrCompanyService.find(HrCompanyPageQueryDTO.builder().companyTypes(Arrays.asList(HrCompanyEnum.SELF.getType())).companyName(importDetailPositionListenerDTO.getCompanyName()).build()); + if (Objects.isNull(hrCompanyDTO)) { + importDetailPositionDTO.appendFailMsg("未查询到对应的用工企业"); + } else { + importDetailPositionDTO.setCompanyId(hrCompanyDTO.getId()); + importDetailPositionDTO.setOrgId(hrCompanyDTO.getOrgId()); + + if (StringUtils.isNotBlank(importDetailPositionDTO.getPositionName())) { + //当前机构下,相同的用工企业,不能存在相同的岗位名称 + List positions = positionMapper.selectList(new LambdaQueryWrapper() + .eq(Position::getCompanyId, importDetailPositionDTO.getCompanyId()) + .eq(Position::getOrgId, hrCompanyDTO.getOrgId()) + .eq(Position::getPositionName, importDetailPositionDTO.getPositionName()) + ); + if (CollectionUtils.isNotEmpty(positions)) { + importDetailPositionDTO.appendFailMsg("该用工企业已存在相同的岗位名称"); + } + } + } + } + if (StringUtils.isBlank(importDetailPositionDTO.getRecruitTitle())) { + importDetailPositionDTO.appendFailMsg("招聘标题不能为空"); + } else if (importDetailPositionDTO.getRecruitTitle().length() > 255) { + importDetailPositionDTO.appendFailMsg("招聘标题超过最大限制长度"); + importDetailPositionDTO.setRecruitTitle(null); + } + + if (!Objects.isNull(importDetailPositionDTO.getPositionNumber()) && importDetailPositionDTO.getPositionNumber() > 30000) { + importDetailPositionDTO.appendFailMsg("招聘人数超过最大限制"); + importDetailPositionDTO.setPositionNumber(null); + } + + if (StringUtils.isBlank(importDetailPositionDTO.getPositionAddress())) { + importDetailPositionDTO.appendFailMsg("工作地址不能为空"); + } else if (importDetailPositionDTO.getPositionAddress().length() > 255) { + importDetailPositionDTO.appendFailMsg("工作地址超过最大限制长度"); + importDetailPositionDTO.setPositionAddress(null); + } + + if (StringUtils.isBlank(importDetailPositionDTO.getRecruitPositionType())) { + importDetailPositionDTO.appendFailMsg("岗位性质不能为空"); + } else { + String recruitPositionTypeCode = DictUtils.getNameCodeMap("recruit_position_type").get(importDetailPositionDTO.getRecruitPositionType()); + if (StringUtils.isBlank(recruitPositionTypeCode)) { + importDetailPositionDTO.appendFailMsg("岗位性质有误,请重新操作"); + importDetailPositionDTO.setRecruitPositionType(null); + } else { + importDetailPositionDTO.setRecruitPositionType(recruitPositionTypeCode); + if (Objects.nonNull(importDetailPositionDTO.getOrgId())) { + Org org = orgMapper.selectOne(new LambdaQueryWrapper().eq(Org::getDeleted, false).eq(Org::getId, importDetailPositionDTO.getOrgId())); + //判断招聘岗位类型权限 + if (!org.getRecruitPositionType().equals(RecruitPositionTypeEnum.ODD_JOB_OR_GENERAL_WORKER.getType())) { + if (!StringUtils.equals(org.getRecruitPositionType(), importDetailPositionDTO.getRecruitPositionType())) { + if (StringUtils.equals(org.getRecruitPositionType(), RecruitPositionTypeEnum.ODD_JOB.getType())) { + importDetailPositionDTO.appendFailMsg("当前企业仅支持维护零工性质岗位。"); + importDetailPositionDTO.setRecruitPositionType(null); + } + if (StringUtils.equals(org.getRecruitPositionType(), RecruitPositionTypeEnum.GENERAL_WORKER.getType())) { + importDetailPositionDTO.appendFailMsg("当前企业仅支持维护普工性质岗位。"); + importDetailPositionDTO.setRecruitPositionType(null); + } + } + } + + } + } + } + + if (StringUtils.isNotBlank(importDetailPositionDTO.getPositionTypeName())) { + if (importDetailPositionDTO.getPositionTypeName().length() > 32) { + importDetailPositionDTO.appendFailMsg("岗位类型超过最大限制长度"); + importDetailPositionDTO.setPositionTypeName(null); + } + } + + if (StringUtils.isNotBlank(importDetailPositionDTO.getPositionTag()) && importDetailPositionDTO.getPositionTag().length() > 512) { + importDetailPositionDTO.appendFailMsg("岗位标签超过最大限制长度"); + importDetailPositionDTO.setPositionTag(null); + } + + + if (StringUtils.isNotBlank(importDetailPositionDTO.getPayDate()) && importDetailPositionDTO.getPayDate().length() > 32) { + importDetailPositionDTO.appendFailMsg("发薪日超过最大限制长度"); + importDetailPositionDTO.setPayDate(null); + } + + if (StringUtils.isBlank(importDetailPositionDTO.getSexRequire())) { + importDetailPositionDTO.appendFailMsg("性别不能为空"); + } else { + if (importDetailPositionDTO.getSexRequire().length() > 2) { + importDetailPositionDTO.appendFailMsg("性别超过最大限制长度"); + importDetailPositionDTO.setSexRequire(null); + }else { + String gender = DictUtils.getNameCodeMap("gender_require").get(importDetailPositionDTO.getSexRequire()); + if (StringUtils.isBlank(gender)) { + importDetailPositionDTO.appendFailMsg("性别有误,请重新操作"); + importDetailPositionDTO.setSexRequire(null); + } else { + importDetailPositionDTO.setSexRequire(gender); + } + } + } + + if (StringUtils.isBlank(importDetailPositionDTO.getEducationRequire())) { + importDetailPositionDTO.appendFailMsg("学历不能为空"); + } else { + if (importDetailPositionDTO.getEducationRequire().length() > 64) { + importDetailPositionDTO.appendFailMsg("学历超过最大限制长度"); + importDetailPositionDTO.setEducationRequire(null); + } else { + String educationCode = DictUtils.getNameCodeMap("education").get(importDetailPositionDTO.getEducationRequire()); + if (StringUtils.isBlank(educationCode)) { + importDetailPositionDTO.appendFailMsg("学历有误,请重新操作"); + importDetailPositionDTO.setEducationRequire(null); + } else { + importDetailPositionDTO.setEducationRequire(educationCode); + } + } + } + + if (StringUtils.isBlank(importDetailPositionDTO.getExperienceRequire())) { + importDetailPositionDTO.appendFailMsg("经验不能为空"); + } else { + if (importDetailPositionDTO.getExperienceRequire().length() > 32) { + importDetailPositionDTO.appendFailMsg("经验超过最大限制长度"); + importDetailPositionDTO.setExperienceRequire(null); + }else { + String experienceCode = DictUtils.getNameCodeMap("RECRUIT_WORK_YEAR").get(importDetailPositionDTO.getExperienceRequire()); + if (StringUtils.isBlank(experienceCode)) { + importDetailPositionDTO.appendFailMsg("经验有误,请重新操作"); + importDetailPositionDTO.setExperienceRequire(null); + } else { + importDetailPositionDTO.setExperienceRequire(experienceCode); + } + } + } + if (StringUtils.isNotBlank(importDetailPositionDTO.getCertificatesRequire()) && importDetailPositionDTO.getCertificatesRequire().length() > 32) { + importDetailPositionDTO.appendFailMsg("证件超过最大限制长度"); + importDetailPositionDTO.setCertificatesRequire(null); + } + if (StringUtils.isNotBlank(importDetailPositionDTO.getOtherRequire()) && importDetailPositionDTO.getOtherRequire().length() > 32) { + importDetailPositionDTO.appendFailMsg("其它超过最大限制长度"); + importDetailPositionDTO.setOtherRequire(null); + } + + if (StringUtils.isBlank(importDetailPositionDTO.getJobContent())) { + importDetailPositionDTO.appendFailMsg("工作内容不能为空"); + } + + if (StringUtils.isNotBlank(importDetailPositionDTO.getSalaryType())) { + String salaryTypeCode = DictUtils.getNameCodeMap("salary_type").get(importDetailPositionDTO.getSalaryType()); + if (StringUtils.isBlank(salaryTypeCode)) { + importDetailPositionDTO.appendFailMsg("薪资类型有误,请重新操作"); + importDetailPositionDTO.setSalaryType(null); + } else { + importDetailPositionDTO.setSalaryType(salaryTypeCode); + } + } + + if (StringUtils.isBlank(importDetailPositionDTO.getEndTime())) { + importDetailPositionDTO.appendFailMsg("有效期截止时间不能为空"); + }else { + try { + if (DateUtil.endOfDay(DateUtil.parse(importDetailPositionDTO.getEndTime())).getTime() <= DateUtil.endOfDay(new Date()).getTime()) { + importDetailPositionDTO.appendFailMsg("岗位有效期不能小于等于当前日期"); + } + importDetailPositionDTO.setEndTime(DateUtil.format(DateUtil.endOfDay(DateUtil.parse(importDetailPositionDTO.getEndTime())),"yyyy-MM-dd HH:mm:ss")); + }catch (Exception e) { + importDetailPositionDTO.appendFailMsg("有效期截止时间格式不正确"); + importDetailPositionDTO.setEndTime(null); + } + } + + } + + @Transactional(rollbackFor = Exception.class) + @Override + public Long execute(ImportDetailPositionExecuteDTO executeDto) { + Long mainId = executeDto.getMainId(); + Assert.notNull(mainId, "参数异常"); + + ImportMainDTO importMainDTO = importMainService.find(ImportMainQueryDTO.builder().id(mainId).build()); + Assert.notNull(importMainDTO, "未查询到导入数据"); + + ImportDetailPositionPageQueryDTO queryDTO = new ImportDetailPositionPageQueryDTO(); + queryDTO.disablePage(); + queryDTO.setMainId(mainId); + queryDTO.setDetailStatus(ImportDetailStatusEnum.CHECK_SUCCESS.getStatus()); + List importDetailPositionDTOS = importDetailPositionService.page(queryDTO); + if (CollectionUtils.isEmpty(importDetailPositionDTOS)) { + throw new BusinessException("未查询到成功的明细数据"); + } + + for (ImportDetailPositionDTO importDetailPositionDTO : importDetailPositionDTOS) { + PositionOperatorDTO position = new PositionOperatorDTO(); + BeanUtils.copyProperties(importDetailPositionDTO, position); + position.setEndTime(DateUtil.parse(importDetailPositionDTO.getEndTime())); + //工作地址匹配当前用工企业下的工作地址,有就用,没有就创建一个, 地图控件要是返回多条记录,取第一个。 + //先直接创建。后续接了地图在改 + + List positionAddressList = positionAddressMapper.selectList(new LambdaQueryWrapper() + .eq(PositionAddress::getDeleted, false) + .eq(PositionAddress::getCompanyId, importDetailPositionDTO.getCompanyId()) + .eq(PositionAddress::getDetailAddress, importDetailPositionDTO.getPositionAddress()) + ); + if (CollectionUtils.isEmpty(positionAddressList)) { + PositionAddress positionAddress = new PositionAddress(); + positionAddress.setCompanyId(importDetailPositionDTO.getCompanyId()); + positionAddress.setDetailAddress(importDetailPositionDTO.getPositionAddress()); + + AlitaResult alitaResult = tencentMapContext.webServiceGeocoder(TencentMapGeocoderReqDTO.builder() + .address(importDetailPositionDTO.getPositionAddress()) + .build()); + + if (Boolean.TRUE.equals(alitaResult.getSuccess())) { + TencentMapGeocoderResDTO resultData = alitaResult.getData(); + TencentMapGeocoderResDTO.TencentMapGeocoderLocationResDTO location = resultData.getLocation(); + if (Objects.nonNull(location)) { + positionAddress.setLatitude(location.getLat()); + positionAddress.setLongitude(location.getLng()); + } + } + positionAddressMapper.saveEntity(positionAddress); + position.setAddressId(positionAddress.getId()); + } else { + position.setAddressId(positionAddressList.get(0).getId()); + } + + + //岗位类型 名称匹配,存code, 匹配不到就不存此字段 + List positionTypeList = positionTypeMapper.selectList(new LambdaQueryWrapper().eq(PositionType::getDeleted, false).eq(PositionType::getName, importDetailPositionDTO.getPositionTypeName())); + if (CollectionUtils.isNotEmpty(positionTypeList)) { + position.setPositionType(positionTypeList.get(0).getCode()); + } + + //工作性质:短工、全职、实习 + //岗位性质:零工、普通岗 + //招聘岗位类型:零工、普通岗、零工+普通岗 + if (StringUtils.isNotBlank(position.getRecruitPositionType())) { + String jobCategory = null; + switch (position.getRecruitPositionType()) { + case "1": + jobCategory = "2"; + break; + case "2": + jobCategory = "1"; + break; + default: + break; + } + position.setJobCategory(jobCategory); + } + PositionNewOperatorDTO positionNewOperatorDTO = new PositionNewOperatorDTO(); + BeanUtils.copyProperties(position, positionNewOperatorDTO); + PositionNewDTO positionNewDTO = positionAuditService.positionCreate(positionNewOperatorDTO); + ImportDetailPositionOperatorDTO updateImportDetailPositionDTO = new ImportDetailPositionOperatorDTO(); + BeanUtils.copyProperties(importDetailPositionDTO, updateImportDetailPositionDTO); + updateImportDetailPositionDTO.setExtraDetailId(positionNewDTO.getId()); + updateImportDetailPositionDTO.setEndTime(DateUtil.parse(importDetailPositionDTO.getEndTime())); + importDetailPositionService.modify(updateImportDetailPositionDTO); + } + + return null; + } +} diff --git a/src/main/java/com/newyetai/recruit/position/service/impl/ImportDetailPositionProvider.java b/src/main/java/com/newyetai/recruit/position/service/impl/ImportDetailPositionProvider.java new file mode 100644 index 0000000..19a3e20 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/service/impl/ImportDetailPositionProvider.java @@ -0,0 +1,550 @@ +package com.newyetai.recruit.position.service.impl; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; + +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.read.builder.ExcelReaderBuilder; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.dto.ExportHeadDetailInfoDTO; +import com.newyetai.common.dto.ExportHeadInfoDTO; +import com.newyetai.common.easyexcel.ExcelUtil; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.component.dict.util.DictUtils; +import com.newyetai.recruit.company.dto.HrCompanyDTO; +import com.newyetai.recruit.company.dto.HrCompanyPageQueryDTO; +import com.newyetai.recruit.company.enums.HrCompanyEnum; +import com.newyetai.recruit.company.service.IHrCompanyService; +import com.newyetai.component.commonimport.constant.ImportDetailStatusEnum; +import com.newyetai.component.commonimport.constant.ImportStatusEnum; +import com.newyetai.component.commonimport.constant.ImportTypeEnum; +import com.newyetai.component.commonimport.dto.ImportDetailPageDTO; +import com.newyetai.component.commonimport.dto.ImportMainDTO; +import com.newyetai.component.commonimport.dto.ImportMainQueryDTO; +import com.newyetai.component.commonimport.dto.ImportMainUpdateDTO; +import com.newyetai.component.commonimport.service.ImportMainService; +import com.newyetai.component.commonimport.service.impl.AbstractCommonImportProvider; +import com.newyetai.component.file.entity.FileRecord; +import com.newyetai.component.file.service.FileRecordService; +import com.newyetai.recruit.position.dao.PositionAddressMapper; +import com.newyetai.recruit.position.dao.PositionMapper; +import com.newyetai.recruit.position.dao.PositionTypeMapper; +import com.newyetai.recruit.position.dto.ImportDetailPositionDTO; +import com.newyetai.recruit.position.dto.ImportDetailPositionExecuteDTO; +import com.newyetai.recruit.position.dto.ImportDetailPositionExportDTO; +import com.newyetai.recruit.position.dto.ImportDetailPositionListenerDTO; +import com.newyetai.recruit.position.dto.ImportDetailPositionOperatorDTO; +import com.newyetai.recruit.position.dto.ImportDetailPositionPageQueryDTO; +import com.newyetai.recruit.position.dto.PositionDTO; +import com.newyetai.recruit.position.dto.PositionExportDTO; +import com.newyetai.recruit.position.dto.PositionNewDTO; +import com.newyetai.recruit.position.dto.PositionNewOperatorDTO; +import com.newyetai.recruit.position.dto.PositionOperatorDTO; +import com.newyetai.recruit.position.entity.Position; +import com.newyetai.recruit.position.entity.PositionAddress; +import com.newyetai.recruit.position.entity.PositionType; +import com.newyetai.recruit.position.service.ImportDetailPositionService; +import com.newyetai.recruit.position.service.PositionAuditService; +import com.newyetai.recruit.position.service.PositionService; +import com.newyetai.recruit.talent.dto.ImportDetailTalentPageQueryDTO; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.org.dao.OrgMapper; +import com.newyetai.usercenter.org.entity.Org; +import com.newyetai.usercenter.org.enums.RecruitPositionTypeEnum; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.InputStream; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import javax.annotation.Resource; + +import cn.hutool.core.date.DateUtil; +import lombok.extern.slf4j.Slf4j; + +/** + * @description: + * @author: guixinman + * @create: 2024-04-11 17:45 + **/ +@Service +@Slf4j +public class ImportDetailPositionProvider extends AbstractCommonImportProvider { + + @Autowired + private ImportDetailPositionService importDetailPositionService; + + @Autowired + private ImportMainService importMainService; + + @Autowired + private FileRecordService fileRecordService; + + @Autowired + private IHrCompanyService hrCompanyService; + + @Autowired + private PositionAuditService positionAuditService; + + @Resource + private PositionMapper positionMapper; + + @Resource + private PositionTypeMapper positionTypeMapper; + + @Resource + private PositionAddressMapper positionAddressMapper; + + @Resource + private OrgMapper orgMapper; + + + public ImportDetailPositionProvider(ImportMainService imprImportMainService) { + super(imprImportMainService); + } + + @Override + public String getType() { + return ImportTypeEnum.POSITION.getType(); + } + + @Override + public Page pageDetail(ImportDetailPageDTO importDetailPageDTO) { + ImportDetailPositionPageQueryDTO queryDTO = new ImportDetailPositionPageQueryDTO(); + BeanUtils.copyProperties(importDetailPageDTO, queryDTO); + importDetailPositionService.page(queryDTO); + return queryDTO.getPageResult(); + } + + @Override + public void importDetailExport(ImportDetailPageDTO importDetailPageDTO) { + ImportDetailPositionPageQueryDTO queryDTO = new ImportDetailPositionPageQueryDTO(); + BeanUtils.copyProperties(importDetailPageDTO, queryDTO); + queryDTO.disablePage(); + List list = importDetailPositionService.page(queryDTO); + + List exportDTOList = list.stream().map(dto -> { + ImportDetailPositionExportDTO importDetailPositionExportDTO = JsonUtils.toObject(dto.getDataJson(), ImportDetailPositionExportDTO.class); + importDetailPositionExportDTO.setRemark(dto.getRemark()); + importDetailPositionExportDTO.setFailReason(dto.getFailReason()); + return importDetailPositionExportDTO; + }).collect(Collectors.toList()); + + if (org.springframework.util.CollectionUtils.isEmpty(exportDTOList)) { + return; + } + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); + String commonImportDetailStatus = DictUtils.getCodeNameMap("common_import_detail_status").get(String.valueOf(importDetailPageDTO.getDetailStatus())); + + String fileName = "岗位导入" + (StringUtils.isNotBlank(commonImportDetailStatus) ? commonImportDetailStatus : "") + "明细导出" + "(" + formatter.format(LocalDateTime.now()) + ")"; + + ExportHeadInfoDTO infoDTO = ExportHeadInfoDTO.builder() + .fileName(fileName) + .build(); + List heads = infoDTO.getHeads(); + heads.add(ExportHeadDetailInfoDTO.builder().head("用工企业").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("岗位名称").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("招聘标题").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("招聘人数").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("工作地址").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("岗位性质").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("岗位类型").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("岗位标签").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("薪资下限").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("薪资上限").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("薪资类型").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("发薪日").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("性别").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("年龄(下限)").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("年龄(上限)").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("学历").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("经验").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("证件").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("其他").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("工作内容").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("失败原因").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("备注").build()); + + List datas = Lists.newArrayList(); + for (ImportDetailPositionExportDTO dto : exportDTOList) { + List objects = Lists.newArrayList(); + datas.add(objects); + objects.add(dto.getCompanyName()); + objects.add(dto.getPositionName()); + objects.add(dto.getRecruitTitle()); + objects.add(dto.getPositionNumber()); + objects.add(dto.getPositionAddress()); + objects.add(dto.getRecruitPositionType()); + objects.add(dto.getPositionTypeName()); + objects.add(dto.getPositionTag()); + objects.add(dto.getSalaryLow()); + objects.add(dto.getSalaryUp()); + objects.add(dto.getSalaryType()); + objects.add(dto.getPayDate()); + objects.add(dto.getSexRequire()); + objects.add(dto.getAgeLow()); + objects.add(dto.getAgeUp()); + objects.add(dto.getEducationRequire()); + objects.add(dto.getExperienceRequire()); + objects.add(dto.getCertificatesRequire()); + objects.add(dto.getOtherRequire()); + objects.add(dto.getJobContent()); + objects.add(dto.getFailReason()); + objects.add(dto.getRemark()); + + } + infoDTO.setDatas(datas); + + ExcelUtil.dynamicExportTemplate(infoDTO); + + } + + @Override + public List analy(Long mainId) { + // 解析文件+明细 + ImportMainDTO importMainDTO = importMainService.find(ImportMainQueryDTO.builder().id(mainId).build()); + Assert.notNull(importMainDTO, "未查询到导入的数据"); + + FileRecord fileRecord; + try { + fileRecord = fileRecordService.find(FileRecord.builder().fileCode(importMainDTO.getFileCode()).build()); + } catch (Exception e) { + log.info("导入文件异常,", e); + fileRecord = null; + } + Assert.notNull(fileRecord, "上传文件不存在"); + try (InputStream is = fileRecordService.getFile(importMainDTO.getFileCode())) { + ImportPositionExcelListener listener = new ImportPositionExcelListener(); + ExcelReaderBuilder reader = EasyExcel.read(is, ImportDetailPositionListenerDTO.class, listener); + reader.sheet().doRead(); + List dtos = listener.getDtos(); + Assert.isTrue(!dtos.isEmpty(), "导入文件无有效数据"); + return dtos; + } catch (Exception e) { + throw new BusinessException(e.getMessage()); + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void checkAndSave(Long mainId, List detailCreateDtos) { + //更改状态为校验中 + ImportMainUpdateDTO updateDto = ImportMainUpdateDTO.builder().id(mainId) + .oldStatusSet(Sets.newHashSet(ImportStatusEnum.INIT.getStatus())) + .newStatus(ImportStatusEnum.CHECKING.getStatus()) + .build(); + importMainService.modify(updateDto); + + List importDetailPositionDTOS = new ArrayList<>(); + + //存储用工企业+岗位名称。用于校验 导入的数据中有没有重复的 + List companyIdPositionNames = new ArrayList<>(); + + for (ImportDetailPositionListenerDTO importDetailPositionListenerDTO : detailCreateDtos) { + ImportDetailPositionDTO importDetailPositionDTO = new ImportDetailPositionDTO(); + + this.checkAndFill(importDetailPositionDTO, importDetailPositionListenerDTO); + + if (StringUtils.isBlank(importDetailPositionDTO.getFailReason())) { + if (companyIdPositionNames.contains(StringUtils.join(importDetailPositionListenerDTO.getCompanyName(), importDetailPositionListenerDTO.getPositionName()))) { + importDetailPositionDTO.appendFailMsg("用工企业+岗位名称出现多次"); + } + //存储用工企业+岗位名称 + companyIdPositionNames.add(StringUtils.join(importDetailPositionListenerDTO.getCompanyName(), importDetailPositionListenerDTO.getPositionName())); + } + + if (StringUtils.isNotBlank(importDetailPositionDTO.getFailReason())) { + importDetailPositionDTO.setDetailStatus(ImportDetailStatusEnum.CHECK_FAIL.getStatus()); + } else { + importDetailPositionDTO.setDetailStatus(ImportDetailStatusEnum.CHECK_SUCCESS.getStatus()); + } + importDetailPositionDTO.setMainId(mainId); + importDetailPositionDTO.setOrgId(UserContextHolder.getExistLoginOrgId()); + importDetailPositionDTOS.add(importDetailPositionDTO); + } + importDetailPositionService.batchCreate(importDetailPositionDTOS); + super.finishCheck(mainId, importDetailPositionDTOS); + } + + private void checkAndFill(ImportDetailPositionDTO importDetailPositionDTO, ImportDetailPositionListenerDTO importDetailPositionListenerDTO) { + BeanUtils.copyProperties(importDetailPositionListenerDTO, importDetailPositionDTO); + importDetailPositionDTO.setDataJson(JsonUtils.toJsonString(importDetailPositionListenerDTO)); + + if (StringUtils.isBlank(importDetailPositionDTO.getPositionName())) { + importDetailPositionDTO.appendFailMsg("岗位名称不能为空"); + } else if (importDetailPositionDTO.getPositionName().length() > 50) { + importDetailPositionDTO.appendFailMsg("岗位名称超过最大限制长度"); + importDetailPositionDTO.setPositionName(null); + } + + if (StringUtils.isBlank(importDetailPositionListenerDTO.getCompanyName())) { + importDetailPositionDTO.appendFailMsg("用工企业不能为空"); + } else { + HrCompanyDTO hrCompanyDTO = hrCompanyService.find(HrCompanyPageQueryDTO.builder().orgId(UserContextHolder.getExistLoginOrgId()).companyTypes(Arrays.asList(HrCompanyEnum.KH.getType(), HrCompanyEnum.SELF.getType())).companyName(importDetailPositionListenerDTO.getCompanyName()).build()); + if (Objects.isNull(hrCompanyDTO)) { + importDetailPositionDTO.appendFailMsg("未查询到对应的用工企业"); + } else { + importDetailPositionDTO.setCompanyId(hrCompanyDTO.getId()); + + if (StringUtils.isNotBlank(importDetailPositionDTO.getPositionName())) { + //当前机构下,相同的用工企业,不能存在相同的岗位名称 + List positions = positionMapper.selectList(new LambdaQueryWrapper() + .eq(Position::getCompanyId, importDetailPositionDTO.getCompanyId()) + .eq(Position::getOrgId, UserContextHolder.getExistLoginOrgId()) + .eq(Position::getPositionName, importDetailPositionDTO.getPositionName()) + ); + if (CollectionUtils.isNotEmpty(positions)) { + importDetailPositionDTO.appendFailMsg("该用工企业已存在相同的岗位名称"); + } + } + } + } + if (StringUtils.isBlank(importDetailPositionDTO.getRecruitTitle())) { + importDetailPositionDTO.appendFailMsg("招聘标题不能为空"); + } else if (importDetailPositionDTO.getRecruitTitle().length() > 255) { + importDetailPositionDTO.appendFailMsg("招聘标题超过最大限制长度"); + importDetailPositionDTO.setRecruitTitle(null); + } + + if (!Objects.isNull(importDetailPositionDTO.getPositionNumber()) && importDetailPositionDTO.getPositionNumber() > 30000) { + importDetailPositionDTO.appendFailMsg("招聘人数超过最大限制"); + importDetailPositionDTO.setPositionNumber(null); + } + + if (StringUtils.isBlank(importDetailPositionDTO.getPositionAddress())) { + importDetailPositionDTO.appendFailMsg("工作地址不能为空"); + } else if (importDetailPositionDTO.getPositionAddress().length() > 255) { + importDetailPositionDTO.appendFailMsg("工作地址超过最大限制长度"); + importDetailPositionDTO.setPositionAddress(null); + } + + if (StringUtils.isBlank(importDetailPositionDTO.getRecruitPositionType())) { + importDetailPositionDTO.appendFailMsg("岗位性质不能为空"); + } else { + String recruitPositionTypeCode = DictUtils.getNameCodeMap("recruit_position_type").get(importDetailPositionDTO.getRecruitPositionType()); + if (StringUtils.isBlank(recruitPositionTypeCode)) { + importDetailPositionDTO.appendFailMsg("岗位性质有误,请重新操作"); + importDetailPositionDTO.setRecruitPositionType(null); + } else { + importDetailPositionDTO.setRecruitPositionType(recruitPositionTypeCode); + + Org org = orgMapper.selectOne(new LambdaQueryWrapper().eq(Org::getDeleted, false).eq(Org::getId, UserContextHolder.getExistLoginOrgId())); + + //判断招聘岗位类型权限 + if (!org.getRecruitPositionType().equals(RecruitPositionTypeEnum.ODD_JOB_OR_GENERAL_WORKER.getType())) { + if (!StringUtils.equals(org.getRecruitPositionType(), importDetailPositionDTO.getRecruitPositionType())) { + if (StringUtils.equals(org.getRecruitPositionType(), RecruitPositionTypeEnum.ODD_JOB.getType())) { + importDetailPositionDTO.appendFailMsg("当前企业仅支持维护零工性质岗位。"); + importDetailPositionDTO.setRecruitPositionType(null); + } + if (StringUtils.equals(org.getRecruitPositionType(), RecruitPositionTypeEnum.GENERAL_WORKER.getType())) { + importDetailPositionDTO.appendFailMsg("当前企业仅支持维护普工性质岗位。"); + importDetailPositionDTO.setRecruitPositionType(null); + } + } + } + + + } + } + + if (StringUtils.isNotBlank(importDetailPositionDTO.getPositionTypeName())) { + if (importDetailPositionDTO.getPositionTypeName().length() > 32) { + importDetailPositionDTO.appendFailMsg("岗位类型超过最大限制长度"); + importDetailPositionDTO.setPositionTypeName(null); + } + } + + if (StringUtils.isNotBlank(importDetailPositionDTO.getPositionTag()) && importDetailPositionDTO.getPositionTag().length() > 512) { + importDetailPositionDTO.appendFailMsg("岗位标签超过最大限制长度"); + importDetailPositionDTO.setPositionTag(null); + } + + + if (StringUtils.isNotBlank(importDetailPositionDTO.getPayDate()) && importDetailPositionDTO.getPayDate().length() > 32) { + importDetailPositionDTO.appendFailMsg("发薪日超过最大限制长度"); + importDetailPositionDTO.setPayDate(null); + } + + if (StringUtils.isBlank(importDetailPositionDTO.getSexRequire())) { + importDetailPositionDTO.appendFailMsg("性别不能为空"); + } else { + if (importDetailPositionDTO.getSexRequire().length() > 2) { + importDetailPositionDTO.appendFailMsg("性别超过最大限制长度"); + importDetailPositionDTO.setSexRequire(null); + }else { + String gender = DictUtils.getNameCodeMap("gender_require").get(importDetailPositionDTO.getSexRequire()); + if (StringUtils.isBlank(gender)) { + importDetailPositionDTO.appendFailMsg("性别有误,请重新操作"); + importDetailPositionDTO.setSexRequire(null); + } else { + importDetailPositionDTO.setSexRequire(gender); + } + } + } + + if (StringUtils.isBlank(importDetailPositionDTO.getEducationRequire())) { + importDetailPositionDTO.appendFailMsg("学历不能为空"); + } else { + if (importDetailPositionDTO.getEducationRequire().length() > 64) { + importDetailPositionDTO.appendFailMsg("学历超过最大限制长度"); + importDetailPositionDTO.setEducationRequire(null); + } else { + String educationCode = DictUtils.getNameCodeMap("education").get(importDetailPositionDTO.getEducationRequire()); + if (StringUtils.isBlank(educationCode)) { + importDetailPositionDTO.appendFailMsg("学历有误,请重新操作"); + importDetailPositionDTO.setEducationRequire(null); + } else { + importDetailPositionDTO.setEducationRequire(educationCode); + } + } + } + + if (StringUtils.isBlank(importDetailPositionDTO.getExperienceRequire())) { + importDetailPositionDTO.appendFailMsg("经验不能为空"); + } else { + if (importDetailPositionDTO.getExperienceRequire().length() > 32) { + importDetailPositionDTO.appendFailMsg("经验超过最大限制长度"); + importDetailPositionDTO.setExperienceRequire(null); + }else { + String experienceCode = DictUtils.getNameCodeMap("RECRUIT_WORK_YEAR").get(importDetailPositionDTO.getExperienceRequire()); + if (StringUtils.isBlank(experienceCode)) { + importDetailPositionDTO.appendFailMsg("经验有误,请重新操作"); + importDetailPositionDTO.setExperienceRequire(null); + } else { + importDetailPositionDTO.setExperienceRequire(experienceCode); + } + } + } + if (StringUtils.isNotBlank(importDetailPositionDTO.getCertificatesRequire()) && importDetailPositionDTO.getCertificatesRequire().length() > 32) { + importDetailPositionDTO.appendFailMsg("证件超过最大限制长度"); + importDetailPositionDTO.setCertificatesRequire(null); + } + if (StringUtils.isNotBlank(importDetailPositionDTO.getOtherRequire()) && importDetailPositionDTO.getOtherRequire().length() > 32) { + importDetailPositionDTO.appendFailMsg("其它超过最大限制长度"); + importDetailPositionDTO.setOtherRequire(null); + } + + if (StringUtils.isBlank(importDetailPositionDTO.getJobContent())) { + importDetailPositionDTO.appendFailMsg("工作内容不能为空"); + } + + if (StringUtils.isNotBlank(importDetailPositionDTO.getSalaryType())) { + String salaryTypeCode = DictUtils.getNameCodeMap("salary_type").get(importDetailPositionDTO.getSalaryType()); + if (StringUtils.isBlank(salaryTypeCode)) { + importDetailPositionDTO.appendFailMsg("薪资类型有误,请重新操作"); + importDetailPositionDTO.setSalaryType(null); + } else { + importDetailPositionDTO.setSalaryType(salaryTypeCode); + } + } + + if (StringUtils.isBlank(importDetailPositionDTO.getEndTime())) { + importDetailPositionDTO.appendFailMsg("有效期截止时间不能为空"); + }else { + try { + if (DateUtil.endOfDay(DateUtil.parse(importDetailPositionDTO.getEndTime())).getTime() <= DateUtil.endOfDay(new Date()).getTime()) { + importDetailPositionDTO.appendFailMsg("岗位有效期不能小于等于当前日期"); + } + importDetailPositionDTO.setEndTime(DateUtil.format(DateUtil.endOfDay(DateUtil.parse(importDetailPositionDTO.getEndTime())),"yyyy-MM-dd HH:mm:ss")); + }catch (Exception e) { + importDetailPositionDTO.appendFailMsg("有效期截止时间格式不正确"); + importDetailPositionDTO.setEndTime(null); + } + } + + } + + @Transactional(rollbackFor = Exception.class) + @Override + public Long execute(ImportDetailPositionExecuteDTO executeDto) { + Long mainId = executeDto.getMainId(); + Assert.notNull(mainId, "参数异常"); + + ImportMainDTO importMainDTO = importMainService.find(ImportMainQueryDTO.builder().id(mainId).build()); + Assert.notNull(importMainDTO, "未查询到导入数据"); + + ImportDetailPositionPageQueryDTO queryDTO = new ImportDetailPositionPageQueryDTO(); + queryDTO.disablePage(); + queryDTO.setMainId(mainId); + queryDTO.setDetailStatus(ImportDetailStatusEnum.CHECK_SUCCESS.getStatus()); + List importDetailPositionDTOS = importDetailPositionService.page(queryDTO); + if (CollectionUtils.isEmpty(importDetailPositionDTOS)) { + throw new BusinessException("未查询到成功的明细数据"); + } + + for (ImportDetailPositionDTO importDetailPositionDTO : importDetailPositionDTOS) { + PositionOperatorDTO position = new PositionOperatorDTO(); + BeanUtils.copyProperties(importDetailPositionDTO, position); + position.setEndTime(DateUtil.parse(importDetailPositionDTO.getEndTime())); + //工作地址匹配当前用工企业下的工作地址,有就用,没有就创建一个, 地图控件要是返回多条记录,取第一个。 + //先直接创建。后续接了地图在改 + + List positionAddressList = positionAddressMapper.selectList(new LambdaQueryWrapper() + .eq(PositionAddress::getDeleted, false) + .eq(PositionAddress::getCompanyId, importDetailPositionDTO.getCompanyId()) + .eq(PositionAddress::getDetailAddress, importDetailPositionDTO.getPositionAddress()) + ); + if (CollectionUtils.isEmpty(positionAddressList)) { + PositionAddress positionAddress = new PositionAddress(); + positionAddress.setCompanyId(importDetailPositionDTO.getCompanyId()); + positionAddress.setDetailAddress(importDetailPositionDTO.getPositionAddress()); + positionAddressMapper.saveEntity(positionAddress); + position.setAddressId(positionAddress.getId()); + } else { + position.setAddressId(positionAddressList.get(0).getId()); + } + + + //岗位类型 名称匹配,存code, 匹配不到就不存此字段 + List positionTypeList = positionTypeMapper.selectList(new LambdaQueryWrapper().eq(PositionType::getDeleted, false).eq(PositionType::getName, importDetailPositionDTO.getPositionTypeName())); + if (CollectionUtils.isNotEmpty(positionTypeList)) { + position.setPositionType(positionTypeList.get(0).getCode()); + } + + //工作性质:短工、全职、实习 + //岗位性质:零工、普通岗 + //招聘岗位类型:零工、普通岗、零工+普通岗 + if (StringUtils.isNotBlank(position.getRecruitPositionType())) { + String jobCategory = null; + switch (position.getRecruitPositionType()) { + case "1": + jobCategory = "2"; + break; + case "2": + jobCategory = "1"; + break; + default: + break; + } + position.setJobCategory(jobCategory); + } + PositionNewOperatorDTO positionNewOperatorDTO = new PositionNewOperatorDTO(); + BeanUtils.copyProperties(position, positionNewOperatorDTO); + PositionNewDTO positionNewDTO = positionAuditService.positionCreate(positionNewOperatorDTO); + ImportDetailPositionOperatorDTO updateImportDetailPositionDTO = new ImportDetailPositionOperatorDTO(); + BeanUtils.copyProperties(importDetailPositionDTO, updateImportDetailPositionDTO); + updateImportDetailPositionDTO.setEndTime(DateUtil.parse(importDetailPositionDTO.getEndTime())); + updateImportDetailPositionDTO.setExtraDetailId(positionNewDTO.getId()); + importDetailPositionService.modify(updateImportDetailPositionDTO); + } + + return null; + } +} diff --git a/src/main/java/com/newyetai/recruit/position/service/impl/ImportDetailPositionServiceImpl.java b/src/main/java/com/newyetai/recruit/position/service/impl/ImportDetailPositionServiceImpl.java new file mode 100644 index 0000000..bb2e6c6 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/service/impl/ImportDetailPositionServiceImpl.java @@ -0,0 +1,106 @@ +package com.newyetai.recruit.position.service.impl; + +import cn.hutool.core.date.DateUtil; +import lombok.extern.slf4j.Slf4j; + +import com.newyetai.component.commonimport.constant.ImportDetailStatusEnum; +import com.newyetai.recruit.position.convert.ImportDetailPositionConvert; +import com.newyetai.recruit.position.entity.ImportDetailPosition; +import com.newyetai.recruit.position.dto.*; +import com.newyetai.recruit.position.dao.ImportDetailPositionMapper; +import com.newyetai.recruit.position.service.ImportDetailPositionService; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.common.util.UserContextHolder; + +import javax.annotation.Resource; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * 岗位导入 + * + * @author guixinman + * @since 1.0.0 2024-04-12 + */ +@Slf4j +@Service +public class ImportDetailPositionServiceImpl implements ImportDetailPositionService { + + @Resource + private ImportDetailPositionMapper importDetailPositionMapper; + + @Override + public ImportDetailPositionDTO create(ImportDetailPositionOperatorDTO operatorDto) { + ImportDetailPosition importDetailPosition = ImportDetailPositionConvert.INSTANCE.convert(operatorDto); + importDetailPositionMapper.saveEntity(importDetailPosition); + return ImportDetailPositionConvert.INSTANCE.convert(importDetailPosition); + } + + @Override + public ImportDetailPositionDTO modify(ImportDetailPositionOperatorDTO operatorDto) { + ImportDetailPositionDTO importDetailPositionDto = this.findById(operatorDto.getId()); + if (Objects.isNull(importDetailPositionDto)) { + return null; + } + ImportDetailPosition importDetailPosition = ImportDetailPositionConvert.INSTANCE.convert(operatorDto); + importDetailPositionMapper.updateEntity(importDetailPosition); + return this.findById(operatorDto.getId()); + } + + @Override + public ImportDetailPositionDTO delete(Long id) { + ImportDetailPositionDTO importDetailPositionDto = this.findById(id); + if (Objects.isNull(importDetailPositionDto)) { + return null; + } + ImportDetailPosition importDetailPosition = ImportDetailPosition.builder().build(); + importDetailPosition.setId(id); + importDetailPositionMapper.deleteEntity(importDetailPosition, UserContextHolder.getLoginUserId()); + return importDetailPositionDto; + } + + @Override + public ImportDetailPositionDTO findById(Long id) { + ImportDetailPosition importDetailPosition = importDetailPositionMapper.getById(id); + if (Objects.isNull(importDetailPosition)) { + return null; + } + return ImportDetailPositionConvert.INSTANCE.convert(importDetailPosition); + } + + @Override + public List list(ImportDetailPositionQueryDTO queryDTO) { + return importDetailPositionMapper.list(queryDTO); + } + + @Override + public List page(ImportDetailPositionPageQueryDTO queryDTO) { + return importDetailPositionMapper.page(queryDTO); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void batchCreate(List importDetailPositionDTOS) { + if (CollectionUtils.isEmpty(importDetailPositionDTOS)) { + return; + } + + List importDetailPositions= importDetailPositionDTOS.stream().map(dto -> { + ImportDetailPosition importDetailPosition = new ImportDetailPosition(); + BeanUtils.copyProperties(dto, importDetailPosition); + if (ImportDetailStatusEnum.CHECK_SUCCESS.getStatus().intValue() == dto.getDetailStatus().intValue()) { + importDetailPosition.setEndTime(DateUtil.parse(dto.getEndTime())); + } + return importDetailPosition; + }).collect(Collectors.toList()); + + importDetailPositionMapper.saveEntites(importDetailPositions); + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/service/impl/ImportPositionExcelListener.java b/src/main/java/com/newyetai/recruit/position/service/impl/ImportPositionExcelListener.java new file mode 100644 index 0000000..2828202 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/service/impl/ImportPositionExcelListener.java @@ -0,0 +1,75 @@ +package com.newyetai.recruit.position.service.impl; + +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.event.AnalysisEventListener; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.recruit.position.dto.ImportDetailPositionListenerDTO; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @description: 岗位导入 + * @author: guixinman + * @create: 2024-04-09 16:49 + **/ +public class ImportPositionExcelListener extends AnalysisEventListener { + + private List dtos; + private Map headMap = new HashMap<>(); + + public ImportPositionExcelListener() { + this.dtos = new ArrayList<>(); + } + + @Override + public void invoke(ImportDetailPositionListenerDTO data, AnalysisContext context) { + dtos.add(data); + } + + @Override + public void doAfterAllAnalysed(AnalysisContext context) { + + } + + @Override + public void invokeHeadMap(Map headMap, AnalysisContext context) { + this.headMap = headMap; + if (headMap.isEmpty()) { + throw new BusinessException("导入模板表头有误"); + } + //姓名、身份证号、发放金额、备注 + if (headMap.size() != 21) { + throw new BusinessException("导入模板表头有误"); + } + Assert.isTrue(headMap.get(0).toString().contains("用工企业"), "导入模板表头有误"); + Assert.isTrue(headMap.get(1).toString().contains("岗位名称"), "导入模板表头有误"); + Assert.isTrue(headMap.get(2).toString().contains("招聘标题"), "导入模板表头有误"); + Assert.isTrue(headMap.get(3).toString().contains("招聘人数"), "导入模板表头有误"); + Assert.isTrue(headMap.get(4).toString().contains("工作地址"), "导入模板表头有误"); + Assert.isTrue(headMap.get(5).toString().contains("岗位性质"), "导入模板表头有误"); + Assert.isTrue(headMap.get(6).toString().contains("岗位类型"), "导入模板表头有误"); + Assert.isTrue(headMap.get(7).toString().contains("岗位标签"), "导入模板表头有误"); + Assert.isTrue(headMap.get(8).toString().contains("薪资下限"), "导入模板表头有误"); + Assert.isTrue(headMap.get(9).toString().contains("薪资上限"), "导入模板表头有误"); + Assert.isTrue(headMap.get(10).toString().contains("薪资类型"), "导入模板表头有误"); + Assert.isTrue(headMap.get(11).toString().contains("发薪日"), "导入模板表头有误"); + Assert.isTrue(headMap.get(12).toString().contains("性别"), "导入模板表头有误"); + Assert.isTrue(headMap.get(13).toString().contains("年龄(下限)"), "导入模板表头有误"); + Assert.isTrue(headMap.get(14).toString().contains("年龄(上限)"), "导入模板表头有误"); + Assert.isTrue(headMap.get(15).toString().contains("学历"), "导入模板表头有误"); + Assert.isTrue(headMap.get(16).toString().contains("经验"), "导入模板表头有误"); + Assert.isTrue(headMap.get(17).toString().contains("证件"), "导入模板表头有误"); + Assert.isTrue(headMap.get(18).toString().contains("其他"), "导入模板表头有误"); + Assert.isTrue(headMap.get(19).toString().contains("工作内容"), "导入模板表头有误"); + Assert.isTrue(headMap.get(20).toString().contains("有效期截止时间"), "导入模板表头有误"); + + } + + public List getDtos() { + return dtos; + } +} diff --git a/src/main/java/com/newyetai/recruit/position/service/impl/PositionAddressServiceImpl.java b/src/main/java/com/newyetai/recruit/position/service/impl/PositionAddressServiceImpl.java new file mode 100644 index 0000000..554be35 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/service/impl/PositionAddressServiceImpl.java @@ -0,0 +1,97 @@ +package com.newyetai.recruit.position.service.impl; + + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.SensitiveWordUtils; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.recruit.position.dao.PositionAddressMapper; +import com.newyetai.recruit.position.dto.PositionAddressDTO; +import com.newyetai.recruit.position.dto.PositionAddressOperatorDTO; +import com.newyetai.recruit.position.dto.PositionAddressQueryDTO; +import com.newyetai.recruit.position.entity.PositionAddress; +import com.newyetai.recruit.position.service.PositionAddressService; + +import org.apache.commons.compress.utils.Lists; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +import java.util.Date; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import javax.annotation.Resource; + +import cn.hutool.core.collection.CollUtil; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class PositionAddressServiceImpl implements PositionAddressService { + + @Resource + private PositionAddressMapper positionAddressMapper; + + @Override + public Long createOrUpdate(PositionAddressOperatorDTO operatorDTO) { + if (!SensitiveWordUtils.check(operatorDTO.getDetailAddress())) { + throw new BusinessException("非法详细地址"); + } + + Long id = operatorDTO.getId(); + if (Objects.isNull(id)) { + PositionAddress positionAddress = new PositionAddress(); + BeanUtils.copyProperties(operatorDTO, positionAddress); + + positionAddressMapper.saveEntity(positionAddress); + return positionAddress.getId(); + } else { + PositionAddress positionAddress = positionAddressMapper.getById(operatorDTO.getId()); + Assert.notNull(positionAddress, "地址信息不存在"); + PositionAddress positionAddressUpdate = new PositionAddress(); + BeanUtils.copyProperties(operatorDTO, positionAddressUpdate); + positionAddressUpdate.setId(positionAddress.getId()); + positionAddressUpdate.setUpdateBy(UserContextHolder.getExistLoginUserId()); + positionAddressUpdate.setUpdateTime(new Date()); + positionAddressMapper.updateEntitySelective(positionAddressUpdate); + return positionAddress.getId(); + } + } + + @Override + public List list(PositionAddressQueryDTO queryDTO) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PositionAddress::getDeleted, false); + + + if (Objects.nonNull(queryDTO.getCompanyId())) { + lambdaQueryWrapper.eq(PositionAddress::getCompanyId, queryDTO.getCompanyId()); + } + if (CollUtil.isNotEmpty(queryDTO.getIds())) { + lambdaQueryWrapper.in(PositionAddress::getId, queryDTO.getIds()); + } + + List positionAddresses = positionAddressMapper.selectList(lambdaQueryWrapper); + if (CollUtil.isNotEmpty(positionAddresses)) { + return positionAddresses.stream().map(positionAddress -> { + PositionAddressDTO positionAddressDTO = new PositionAddressDTO(); + BeanUtils.copyProperties(positionAddress, positionAddressDTO); + return positionAddressDTO; + }).collect( + Collectors.toList()); + } + return Lists.newArrayList(); + } + + @Override + public void delete(Long id) { + PositionAddress positionAddress = positionAddressMapper.getById(id); + if (Objects.nonNull(positionAddress)) { + PositionAddress deletePositionAddress = new PositionAddress(); + deletePositionAddress.setId(id); + positionAddressMapper.deleteEntity(deletePositionAddress); + } + } +} diff --git a/src/main/java/com/newyetai/recruit/position/service/impl/PositionAuditServiceImpl.java b/src/main/java/com/newyetai/recruit/position/service/impl/PositionAuditServiceImpl.java new file mode 100644 index 0000000..57d73ce --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/service/impl/PositionAuditServiceImpl.java @@ -0,0 +1,485 @@ +package com.newyetai.recruit.position.service.impl; + +import com.google.common.collect.Lists; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.RandomUtil; +import cn.hutool.json.JSONUtil; +import lombok.extern.slf4j.Slf4j; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.dto.ExportHeadDetailInfoDTO; +import com.newyetai.common.dto.ExportHeadInfoDTO; +import com.newyetai.common.easyexcel.ExcelUtil; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.common.util.SensitiveWordUtils; +import com.newyetai.component.dict.util.DictUtils; +import com.newyetai.config.entity.Config; +import com.newyetai.config.service.ConfigService; +import com.newyetai.frame.redis.aop.annotation.AutoUnLock; +import com.newyetai.frame.redis.dto.LockDTO; +import com.newyetai.frame.redis.redisson.RedissonUtils; +import com.newyetai.recruit.company.dto.HrCompanyPageQueryDTO; +import com.newyetai.recruit.company.enums.HrCompanyEnum; +import com.newyetai.recruit.company.service.IHrCompanyService; +import com.newyetai.recruit.position.convert.PositionAuditConvert; +import com.newyetai.recruit.position.dao.PositionMapper; +import com.newyetai.recruit.position.entity.Position; +import com.newyetai.recruit.position.entity.PositionAudit; +import com.newyetai.recruit.position.dto.*; +import com.newyetai.recruit.position.dao.PositionAuditMapper; +import com.newyetai.recruit.position.enums.PositionAuditStatusEnum; +import com.newyetai.recruit.position.enums.PositionStatusEnum; +import com.newyetai.recruit.position.service.PositionAuditService; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.recruit.position.service.PositionFileService; +import com.newyetai.recruit.position.service.PositionService; +import com.newyetai.usercenter.org.service.OrgService; + +import javax.annotation.Resource; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.stream.Collectors; + +/** + * 岗位审核表 + * + * @author guixinman + * @since 1.0.0 2024-07-05 + */ +@Slf4j +@Service +public class PositionAuditServiceImpl implements PositionAuditService { + + @Resource + private PositionAuditMapper positionAuditMapper; + + @Autowired + private PositionService positionService; + + @Autowired + private ConfigService configService; + + @Resource + private PositionMapper positionMapper; + + @Autowired + private PositionFileService positionFileService; + + @Autowired + private IHrCompanyService hrCompanyService; + + @Autowired + private OrgService orgService; + + + @Transactional(rollbackFor = Exception.class) + @Override + public PositionNewDTO positionCreate(PositionNewOperatorDTO operatorDto) { + //校验 敏感词 and 其他 + this.check(operatorDto); + + PositionOperatorDTO positionOperatorDTO = new PositionOperatorDTO(); + BeanUtils.copyProperties(operatorDto, positionOperatorDTO); + positionOperatorDTO.setStatus(PositionStatusEnum.CLOSE.getStatus()); + PositionDTO positionDTO = positionService.create(positionOperatorDTO); + + PositionAudit positionAudit = new PositionAudit(); + BeanUtils.copyProperties(positionDTO, positionAudit); + positionAudit.setId(null); + positionAudit.setPositionId(positionDTO.getId()); + positionAudit.setVersion(1); + + Config config = configService.getConfig("position_audit_enable", CommonConstants.PLATFORM_ORG_ID, true); + if (Objects.nonNull(config)) { + positionAudit.setAuditStatus(PositionAuditStatusEnum.INIT.getStatus()); + } else { + BeanUtils.copyProperties(positionDTO, positionOperatorDTO); + + positionAudit.setAuditStatus(PositionAuditStatusEnum.SUCCESS.getStatus()); + //需要修改岗位表 审核通过会更新岗位表。 + positionOperatorDTO.setStatus(PositionStatusEnum.OPEN.getStatus()); + positionDTO.setStatus(PositionStatusEnum.OPEN.getStatus()); + positionOperatorDTO.setId(positionDTO.getId()); + positionService.modify(positionOperatorDTO); + } + + positionAuditMapper.saveEntity(positionAudit); + return PositionAuditConvert.INSTANCE.convert(positionDTO); + } + + private void check(PositionNewOperatorDTO operatorDto) { + if (Objects.nonNull(operatorDto.getEndTime())) { + Assert.isTrue(! (DateUtil.endOfDay(operatorDto.getEndTime()).getTime() <= DateUtil.endOfDay(new Date()).getTime()),"岗位有效期不能小于等于当前日期"); + } + StringBuilder sb = new StringBuilder(); + if (!SensitiveWordUtils.check(operatorDto.getPositionName())) { + sb.append("非法岗位名称"); + } + if (!SensitiveWordUtils.check(operatorDto.getRecruitTitle())) { + sb.append("非法招聘标题"); + } + if (!SensitiveWordUtils.check(operatorDto.getPositionTag())) { + sb.append("非法岗位标签"); + } + if (!SensitiveWordUtils.check(operatorDto.getPayDate())) { + sb.append("非法发薪日"); + } + if (!SensitiveWordUtils.check(operatorDto.getOtherRequire())) { + sb.append("非法其他"); + } + if (!SensitiveWordUtils.check(operatorDto.getJobContent())) { + sb.append("非法工作内容"); + } + if (StringUtils.isNotBlank(sb.toString())) { + throw new BusinessException(sb.toString()); + } + } + + /** + * @description: 具体看禅道需求 + * @return: + * @author: guixinman + * @param: + */ + @AutoUnLock + @Transactional(rollbackFor = Exception.class) + @Override + public void positionModify(PositionNewOperatorDTO operatorDto) { + Assert.notNull(operatorDto.getId(), "岗位id不能为空"); + Assert.notNull(operatorDto.getPositionAuditId(), "审核id不能为空"); + Assert.notNull(operatorDto.getVersion(), "版本号不能为空"); + //校验敏感词 + this.check(operatorDto); + + //对审核表id加锁 + Assert.isTrue( + RedissonUtils.tryLockAutomatically( + LockDTO.builder() + .tryLockWaitTime(0L) + .lockTimeout(60 * 5L) + .arg(operatorDto.getPositionAuditId() + "") + .methodName("position:audit:modify") + .build() + ), + "岗位编辑正在处理, 请稍后再试"); + + PositionDTO positionDto = positionService.findById(operatorDto.getId()); + if (Objects.isNull(positionDto)) { + throw new BusinessException("未查询到对应岗位数据"); + } + //因为admin能修改。所以orgId取岗位表的orgId + operatorDto.setOrgId(positionDto.getOrgId()); + + Assert.notNull(hrCompanyService.find(HrCompanyPageQueryDTO.builder().id(operatorDto.getCompanyId()).companyTypes(Arrays.asList(HrCompanyEnum.KH.getType(), HrCompanyEnum.SELF.getType())).orgId(positionDto.getOrgId()).build()), "未查询到用工企业"); + List positions = positionMapper.selectList(new LambdaQueryWrapper() + .eq(Position::getCompanyId, operatorDto.getCompanyId()) + .eq(Position::getOrgId, positionDto.getOrgId()) + .eq(Position::getPositionName, operatorDto.getPositionName()) + .notIn(Position::getId, operatorDto.getId()) + ); + if (CollectionUtils.isNotEmpty(positions)) { + throw new BusinessException("该用工企业已存在相同的岗位名称,添加失败"); + } + + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper().eq(PositionAudit::getDeleted, 0) + .eq(PositionAudit::getId, operatorDto.getPositionAuditId()); + if (!CommonConstants.PLATFORM_ORG_ID.equals(UserContextHolder.getExistLoginOrgId())) { + queryWrapper.eq(PositionAudit::getOrgId, UserContextHolder.getExistLoginOrgId()); + } + PositionAudit positionAuditOld = positionAuditMapper.selectOne(queryWrapper); + Assert.notNull(positionAuditOld, "网络异常,请刷新页面重试"); + + Long positionAuditId = positionAuditMapper.getIdByPositionId(operatorDto.getId()); + Assert.notNull(positionAuditId, "网络异常,请刷新页面重试"); + Assert.isTrue(positionAuditId == operatorDto.getPositionAuditId().longValue(), "该页面信息已被变更,请刷新页面重试!"); + + /* + * 修改岗位先进审核表。审核通过后反向更新岗位表。 + * 1.如果审核状态是 成功or失败。就新增一条 审核表的记录(看配置对应的状态) + 2.如果审核状态是 待审核 ,就修改审核表的记录,如果配置是不审核就修改审核状态是 成功 + */ + PositionAudit positionAudit = new PositionAudit(); + BeanUtils.copyProperties(operatorDto, positionAudit); + positionAudit.setId(operatorDto.getPositionAuditId()); + positionAudit.setPositionId(operatorDto.getId()); + Config config = configService.getConfig("position_audit_enable", CommonConstants.PLATFORM_ORG_ID, true); + if (Objects.isNull(config)) { + positionAudit.setAuditStatus(PositionAuditStatusEnum.SUCCESS.getStatus()); + //需要修改岗位表 审核通过会更新岗位表。主要是要 更新时间,H5用的 + PositionOperatorDTO positionOperatorDTO = new PositionOperatorDTO(); + BeanUtils.copyProperties(operatorDto, positionOperatorDTO); + positionOperatorDTO.setStatus(PositionStatusEnum.OPEN.getStatus()); + positionService.modify(positionOperatorDTO); + + //先删除岗位相册 + positionFileService.deleteByPositionId(operatorDto.getId()); + if (StringUtils.isNotBlank(operatorDto.getFileJson())) { + List positionFileDTOS = JsonUtils.toList(operatorDto.getFileJson(), PositionFileDTO.class); + for (PositionFileDTO positionFileDTO : positionFileDTOS) { + positionFileDTO.setId(null); + positionFileDTO.setPositionId(operatorDto.getId()); + positionFileService.create(positionFileDTO); + } + } + } else { + positionAudit.setAuditStatus(PositionAuditStatusEnum.INIT.getStatus()); + } + + if (PositionAuditStatusEnum.INIT.getStatus().equals(positionAuditOld.getAuditStatus())) { + positionAudit.setUpdateBy(UserContextHolder.getExistLoginUserId()); + int row = positionAuditMapper.modifyById(positionAudit); + if (row == 0) { + PositionAudit positionAudit1 = positionAuditMapper.selectOne(queryWrapper); + if (!PositionAuditStatusEnum.INIT.getStatus().equals(positionAudit1.getAuditStatus())) { + positionAudit.setVersion(1); + positionAuditMapper.saveEntity(positionAudit); + } else { + if (operatorDto.getVersion().intValue() != positionAudit1.getVersion().intValue()) { + throw new BusinessException("该页面信息已被变更,请刷新页面重试!"); + } + } + } + } else { + positionAudit.setVersion(1); + positionAuditMapper.saveEntity(positionAudit); + } + } + + + @Override + public PositionNewDTO positionFindById(Long id) { + Assert.notNull(id, "参数缺失"); + + PositionNewPageQueryDTO queryDTO = new PositionNewPageQueryDTO(); + queryDTO.disablePage(); + queryDTO.setId(id); + List list = this.positionPage(queryDTO); + return CollectionUtils.isNotEmpty(list) ? list.get(0) : null; + } + + @Override + public List list(PositionAuditQueryDTO queryDTO) { + return positionAuditMapper.list(queryDTO); + } + + @Override + public List page(PositionAuditPageQueryDTO queryDTO) { + if (!CommonConstants.PLATFORM_ORG_ID.equals(UserContextHolder.getExistLoginOrgId())) { + if (Objects.isNull(queryDTO.getOrgId())) { + queryDTO.setOrgIds(orgService.childrenOrgIdList(UserContextHolder.getLoginOrgId())); + } + } + return positionAuditMapper.page(queryDTO); + } + + @Override + public List positionPage(PositionNewPageQueryDTO queryDTO) { + if (!CommonConstants.PLATFORM_ORG_ID.equals(UserContextHolder.getExistLoginOrgId())) { + queryDTO.setOrgId(UserContextHolder.getExistLoginOrgId()); + } + List list = positionAuditMapper.positionPage(queryDTO); + for (PositionNewDTO positionNewDTO : list) { + positionNewDTO.setRecruitPositionTypeName(DictUtils.getCodeNameMap("recruit_position_type").get(positionNewDTO.getRecruitPositionType())); + } + return list; + } + + @Override + public void export(PositionNewPageQueryDTO queryDTO) { + boolean flag = true; + Integer pageNo = 1; + Integer pageSize = 100; + + List listAll = new ArrayList<>(); + + while (flag) { + queryDTO.setPageNo(pageNo); + queryDTO.setPageSize(pageSize); + List list = this.positionPage(queryDTO); + if (org.springframework.util.CollectionUtils.isEmpty(list)) { + flag = false; + continue; + } + if (list.size() < pageSize) { + flag = false; + } + pageNo = pageNo + 1; + listAll.addAll(list); + } + List collect = listAll.stream().map(dto -> { + PositionExportDTO exportDTO = new PositionExportDTO(); + BeanUtils.copyProperties(dto, exportDTO); + exportDTO.setCreateTime(DateUtil.format(dto.getCreateTime(), "yyyy-MM-dd HH:mm:ss")); + exportDTO.setEndTime(DateUtil.format(dto.getEndTime(), "yyyy-MM-dd")); + exportDTO.setStatus(DictUtils.getCodeNameMap("position_status").get(String.valueOf(dto.getStatus()))); + exportDTO.setSalary(dto.getSalaryStr()); + return exportDTO; + }).collect(Collectors.toList()); + + if (org.springframework.util.CollectionUtils.isEmpty(collect)) { + return; + } + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); + String fileName = "岗位明细导出" + "(" + formatter.format(LocalDateTime.now()) + ")"; + + ExportHeadInfoDTO infoDTO = ExportHeadInfoDTO.builder() + .fileName(fileName) + .build(); + List heads = infoDTO.getHeads(); + heads.add(ExportHeadDetailInfoDTO.builder().head("招聘岗位类型").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("岗位名称").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("用工企业").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("岗位状态").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("招聘人数").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("综合薪资").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("工作地址").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("创建时间").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("有效期截止时间").build()); + + List datas = Lists.newArrayList(); + for (PositionExportDTO dto : collect) { + List objects = Lists.newArrayList(); + datas.add(objects); + objects.add(dto.getRecruitPositionTypeName()); + objects.add(dto.getPositionName()); + objects.add(dto.getCompanyName()); + objects.add(dto.getStatus()); + objects.add(dto.getPositionNumber()); + objects.add(dto.getSalary()); + objects.add(dto.getPositionAddress()); + objects.add(dto.getCreateTime()); + objects.add(dto.getEndTime()); + } + infoDTO.setDatas(datas); + + ExcelUtil.dynamicExportTemplate(infoDTO); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void audit(PositionAuditReqDTO reqDTO) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper() + .eq(PositionAudit::getDeleted, false) + .eq(PositionAudit::getId, reqDTO.getId()) + .eq(PositionAudit::getVersion, reqDTO.getVersion()); + + PositionAudit positionAudit = positionAuditMapper.selectOne(queryWrapper); + if (Objects.isNull(positionAudit)) { + throw new BusinessException("岗位信息已更新,请刷新页面重新审核。"); + } + reqDTO.setUpdateBy(UserContextHolder.getExistLoginUserId()); + int row = positionAuditMapper.audit(reqDTO); + if (row == 0) { + throw new BusinessException("岗位信息已更新,请刷新页面重新审核。"); + } + + if (PositionAuditStatusEnum.SUCCESS.getStatus().equals(reqDTO.getAuditStatus())) { + //需要修改岗位表 审核通过会更新岗位表。H5用的 + PositionOperatorDTO positionOperatorDTO = new PositionOperatorDTO(); + BeanUtils.copyProperties(positionAudit, positionOperatorDTO); + positionOperatorDTO.setStatus(PositionStatusEnum.OPEN.getStatus()); + positionOperatorDTO.setId(positionAudit.getPositionId()); + positionService.modify(positionOperatorDTO); + + //先删除岗位相册 + positionFileService.deleteByPositionId(positionAudit.getPositionId()); + if (StringUtils.isNotBlank(positionAudit.getFileJson())) { + List positionFileDTOS = JSONUtil.toList(positionAudit.getFileJson(), PositionFileDTO.class); + for (PositionFileDTO positionFileDTO : positionFileDTOS) { + positionFileDTO.setId(null); + positionFileDTO.setPositionId(positionAudit.getPositionId()); + positionFileService.create(positionFileDTO); + } + } + } + + } + + @Override + public PositionAuditDTO findById(Long id) { + Assert.notNull(id, "参数缺失"); + PositionAuditPageQueryDTO queryDTO = new PositionAuditPageQueryDTO(); + queryDTO.disablePage(); + queryDTO.setId(id); + List list = this.page(queryDTO); + return CollectionUtils.isNotEmpty(list) ? list.get(0) : null; + } + + @Override + public void positionModifyStatus(Set ids, String status) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper() + .in(Position::getId, ids) + .eq(Position::getDeleted, false); + + if (!CommonConstants.PLATFORM_ORG_ID.equals(UserContextHolder.getExistLoginOrgId())) { + queryWrapper.eq(Position::getOrgId, UserContextHolder.getExistLoginOrgId()); + } + + Integer count = positionMapper.selectCount(queryWrapper); + Assert.isTrue(count == ids.size(), "网络异常,请刷新后再试"); + + List positions = new ArrayList<>(); + for (Long id : ids) { + if (PositionStatusEnum.OPEN.getStatus().equals(status)) { + Integer positionAuditCount = positionAuditMapper.selectCount(new LambdaQueryWrapper() + .eq(PositionAudit::getDeleted, false) + .eq(PositionAudit::getAuditStatus, PositionAuditStatusEnum.SUCCESS.getStatus()) + .eq(PositionAudit::getPositionId, id) + ); + if (positionAuditCount != null && positionAuditCount >= 1) { + Position positionOld = positionMapper.selectById(id); + if (Objects.nonNull(positionOld) && Objects.nonNull(positionOld.getEndTime())) { + Assert.isTrue(! (DateUtil.endOfDay(positionOld.getEndTime()).getTime() <= DateUtil.endOfDay(new Date()).getTime()),"岗位有效期不能小于等于当前日期"); + } + Position position = new Position(); + position.setId(id); + position.setStatus(status); + positions.add(position); + } + } else { + Position position = new Position(); + position.setId(id); + position.setStatus(status); + positions.add(position); + } + } + positionMapper.updateEntitysSelective(positions, UserContextHolder.getExistLoginUserId()); + } + + @Override + public Long positionCopy(Long id) { + PositionNewDTO oldPositionDTO = this.positionFindById(id); + if (Objects.isNull(oldPositionDTO)) { + throw new BusinessException("未查询到岗位信息"); + } + PositionNewOperatorDTO positionNewOperatorDTO = new PositionNewOperatorDTO(); + BeanUtils.copyProperties(oldPositionDTO, positionNewOperatorDTO); + positionNewOperatorDTO.setPositionName(String.format("%s复制%s", RandomUtil.randomString(3), StringUtils.substring(oldPositionDTO.getPositionName(), 0, 45))); + PositionNewDTO positionNewDTO = ((PositionAuditServiceImpl) AopContext.currentProxy()).positionCreate(positionNewOperatorDTO); + + List oldPositionFileDTOS = positionFileService.filePage(PositionFilePageQueryDTO.builder().positionId(id).build()); + for (PositionFileDTO oldPositionFileDTO : oldPositionFileDTOS) { + PositionFileDTO positionFileDTO = new PositionFileDTO(); + BeanUtils.copyProperties(oldPositionFileDTO, positionFileDTO); + positionFileDTO.setPositionId(positionNewDTO.getId()); + positionFileService.create(positionFileDTO); + } + return positionNewDTO.getId(); + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/service/impl/PositionFileServiceImpl.java b/src/main/java/com/newyetai/recruit/position/service/impl/PositionFileServiceImpl.java new file mode 100644 index 0000000..3bc4908 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/service/impl/PositionFileServiceImpl.java @@ -0,0 +1,89 @@ +package com.newyetai.recruit.position.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.recruit.position.constant.PositionConstants; +import com.newyetai.recruit.position.dao.PositionFileMapper; +import com.newyetai.recruit.position.dto.PositionFileDTO; +import com.newyetai.recruit.position.dto.PositionFilePageQueryDTO; +import com.newyetai.recruit.position.entity.PositionFile; +import com.newyetai.recruit.position.service.PositionFileService; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Date; +import java.util.List; + +import cn.hutool.core.util.StrUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + + +@Slf4j +@Service +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class PositionFileServiceImpl extends ServiceImpl implements PositionFileService { + + + @Override + public List filePage(PositionFilePageQueryDTO queryDTO) { + return getBaseMapper().filePage(queryDTO); + } + + @Override + public PositionFile create(PositionFileDTO queryDTO) { + List fileList = filePage(PositionFilePageQueryDTO.builder() + .positionId(queryDTO.getPositionId()) + .fileType(queryDTO.getFileType()).build()); + + int maxFileOrder = 0; + if (fileList.size() > 0) { + maxFileOrder = fileList.stream().mapToInt(PositionFileDTO::getSort).max().getAsInt(); + } + + PositionFile file = JsonUtils.toObject(JsonUtils.toJsonString(queryDTO), PositionFile.class); + file.setSort(maxFileOrder); + Assert.isTrue(save(file), queryDTO.getFileName() + "保存失败!"); + return file; + } + + @Override + public void update(PositionFileDTO dto) { + PositionFile file = JsonUtils.toObject(JsonUtils.toJsonString(dto), PositionFile.class); + Assert.isTrue(updateById(file), dto.getFileName() + "更新失败!"); + } + + @Override + public void delete(Long id) { + PositionFile file = getBaseMapper().selectById(id); + file.setDeleted(true); + Assert.notNull(file, "未找到要删除的文件信息"); + Assert.isTrue(updateById(file), "删除失败!"); + } + + @Override + public void deleteByPositionId(Long positionId) { + PositionFile positionFile = new PositionFile(); + positionFile.setDeleted(true); + positionFile.setUpdateBy(UserContextHolder.getExistLoginUserId()); + positionFile.setUpdateTime(new Date()); + getBaseMapper().update(positionFile,new LambdaQueryWrapper().eq(PositionFile::getDeleted,false).eq(PositionFile::getPositionId,positionId)); + } + + @Override + public void setDefault(Long id) { + PositionFile file = getOne(Wrappers.lambdaQuery() + .eq(PositionFile::getDeleted, false) + .eq(PositionFile::getId, id) + ); + Assert.notNull(file, "文件不存在"); + String fileType = file.getFileType(); + Assert.isTrue(StrUtil.equals(fileType, PositionConstants.POSITION_FILE_TYPE_IMG), "只支持设置图片"); + getBaseMapper().setDefault(file.getPositionId(), file.getId()); + } +} diff --git a/src/main/java/com/newyetai/recruit/position/service/impl/PositionRegistrationServiceImpl.java b/src/main/java/com/newyetai/recruit/position/service/impl/PositionRegistrationServiceImpl.java new file mode 100644 index 0000000..a197f09 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/service/impl/PositionRegistrationServiceImpl.java @@ -0,0 +1,648 @@ +package com.newyetai.recruit.position.service.impl; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; + +import cn.hutool.core.date.DateUtil; +import lombok.extern.slf4j.Slf4j; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.dto.ExportHeadDetailInfoDTO; +import com.newyetai.common.dto.ExportHeadInfoDTO; +import com.newyetai.common.easyexcel.ExcelUtil; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.component.action.util.ActionUtils; +import com.newyetai.component.dict.util.DictUtils; +import com.newyetai.frame.redis.aop.annotation.AutoUnLock; +import com.newyetai.frame.redis.dto.LockDTO; +import com.newyetai.frame.redis.redisson.RedissonUtils; +import com.newyetai.recruit.company.dao.HrCompanyMapper; +import com.newyetai.recruit.company.entity.HrCompany; +import com.newyetai.recruit.company.enums.HrCompanyEnum; +import com.newyetai.recruit.position.convert.PositionRegistrationConvert; +import com.newyetai.recruit.position.entity.PositionRegistration; +import com.newyetai.recruit.position.dto.*; +import com.newyetai.recruit.position.dao.PositionRegistrationMapper; +import com.newyetai.recruit.position.enums.PositionRegistrationStatusEnum; +import com.newyetai.recruit.position.enums.PositionStatusEnum; +import com.newyetai.recruit.position.service.PositionRegistrationService; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.recruit.position.service.PositionService; +import com.newyetai.recruit.talent.entity.Talent; +import com.newyetai.recruit.talent.service.TalentService; +import com.newyetai.recruit.user.dto.JobExpectQueryDTO; +import com.newyetai.recruit.user.dto.ResumeDTO; +import com.newyetai.recruit.user.dto.ResumeQueryDTO; +import com.newyetai.recruit.user.dto.UserCertificateQueryDTO; +import com.newyetai.recruit.user.service.JobExpectService; +import com.newyetai.recruit.user.service.ResumeService; +import com.newyetai.recruit.user.service.UserCertificateService; +import com.newyetai.usercenter.enums.OrgTypeEnum; +import com.newyetai.usercenter.org.dto.OrgDTO; +import com.newyetai.usercenter.org.dto.OrgQueryDTO; +import com.newyetai.usercenter.org.service.OrgService; +import com.newyetai.usercenter.user.dto.UserDTO; +import com.newyetai.usercenter.user.service.UserService; + +import javax.annotation.Resource; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.stream.Collectors; + +/** + * 岗位报名信息表 + * + * @author guixinman + * @since 1.0.0 2024-04-15 + */ +@Slf4j +@Service +public class PositionRegistrationServiceImpl implements PositionRegistrationService { + + @Resource + private PositionRegistrationMapper positionRegistrationMapper; + + @Autowired + private PositionService positionService; + + @Autowired + private UserService userService; + + @Autowired + private TalentService talentService; + + @Autowired + private UserCertificateService userCertificateService; + @Autowired + private JobExpectService jobExpectService; + + @Autowired + private ResumeService resumeService; + + @Resource + private HrCompanyMapper hrCompanyMapper; + + @Autowired + private OrgService orgService; + + + @AutoUnLock + @Transactional(rollbackFor = Exception.class) + @Override + public PositionRegistrationDTO create(PositionRegistrationOperatorDTO operatorDto) { + + Assert.isTrue( + RedissonUtils.tryLockAutomatically( + LockDTO.builder() + .tryLockWaitTime(0L) + .lockTimeout(60 * 5L) + .methodName("positionRegistration:create") + .arg(String.valueOf(operatorDto.getUserId())) + .arg(String.valueOf(operatorDto.getPositionId())) + .build() + ), + "请稍后再试"); + + UserDTO userDTO = userService.get(operatorDto.getUserId()); + Assert.notNull(userDTO, "用户不存在"); + Assert.notNull(PositionRegistrationStatusEnum.find(operatorDto.getStatus()), "请选择正确的招聘状态"); + + PositionDTO positionDTO = positionService.findById(operatorDto.getPositionId()); + if (Objects.isNull(positionDTO)) { + throw new BusinessException("未查询到岗位信息"); + } + if (Objects.nonNull(positionDTO.getEndTime())) { + Assert.isTrue(DateUtil.endOfDay(positionDTO.getEndTime()).getTime() >= new Date().getTime(), "岗位已失效,禁止报名"); + } + + Assert.isTrue(PositionStatusEnum.OPEN.getStatus().equals(positionDTO.getStatus()), "岗位未开启"); + + Integer count = positionRegistrationMapper.selectCount(new LambdaQueryWrapper() + .eq(PositionRegistration::getDeleted, false) + .eq(PositionRegistration::getUserId, operatorDto.getUserId()) + .eq(PositionRegistration::getPositionId, operatorDto.getPositionId()) + .notIn(PositionRegistration::getStatus, Arrays.asList(PositionRegistrationStatusEnum.CANCEL.getStatus(), PositionRegistrationStatusEnum.RESIGNED.getStatus(), PositionRegistrationStatusEnum.TERMINATION.getStatus())) + ); + if (count > 0) { + throw new BusinessException("请勿报名相同岗位"); + } + + PositionRegistration positionRegistration = PositionRegistrationConvert.INSTANCE.convert(operatorDto); + positionRegistrationMapper.saveEntity(positionRegistration); + return PositionRegistrationConvert.INSTANCE.convert(positionRegistration); + } + + @Override + public PositionRegistrationDTO modify(PositionRegistrationOperatorDTO operatorDto) { + PositionRegistrationDTO positionRegistrationDto = this.findById(operatorDto.getId()); + if (Objects.isNull(positionRegistrationDto)) { + return null; + } + PositionRegistration positionRegistration = PositionRegistrationConvert.INSTANCE.convert(operatorDto); + positionRegistrationMapper.updateEntity(positionRegistration); + return this.findById(operatorDto.getId()); + } + + @Override + public PositionRegistrationDTO delete(Long id) { + PositionRegistrationDTO positionRegistrationDto = this.findById(id); + if (Objects.isNull(positionRegistrationDto)) { + return null; + } + PositionRegistration positionRegistration = PositionRegistration.builder().build(); + positionRegistration.setId(id); + positionRegistrationMapper.deleteEntity(positionRegistration, UserContextHolder.getLoginUserId()); + return positionRegistrationDto; + } + + @Override + public PositionRegistrationDTO findById(Long id) { + Assert.notNull(id, "参数缺失"); + PositionRegistrationPageQueryDTO queryDTO = new PositionRegistrationPageQueryDTO(); + queryDTO.setId(id); + List list = this.page(queryDTO); + if (CollectionUtils.isEmpty(list)) { + return null; + } + PositionRegistrationDTO positionRegistrationDTO = list.get(0); + positionRegistrationDTO.setUserCertificateDTOList(userCertificateService.list(UserCertificateQueryDTO.builder().userId(positionRegistrationDTO.getUserId()).build())); + positionRegistrationDTO.setJobExpectDTOList(jobExpectService.list(JobExpectQueryDTO.builder().userId(positionRegistrationDTO.getUserId()).build())); + List resumeDTOList = resumeService.list(ResumeQueryDTO.builder().userId(positionRegistrationDTO.getUserId()).build()); + if (CollectionUtils.isNotEmpty(resumeDTOList)) { + positionRegistrationDTO.setCityCode(resumeDTOList.get(0).getCityCode()); + positionRegistrationDTO.setCityCodeName(resumeDTOList.get(0).getCityCodeName()); + positionRegistrationDTO.setResumeFileCode(resumeDTOList.get(0).getFileCode()); + } + return positionRegistrationDTO; + } + + @Override + public PositionRegistrationDTO findByIdAndChildrenOrgAll(Long id, Boolean childrenOrgAll) { + Assert.notNull(id, "参数缺失"); + PositionRegistrationPageQueryDTO queryDTO = new PositionRegistrationPageQueryDTO(); + queryDTO.setId(id); + queryDTO.setChildrenOrgAll(childrenOrgAll); + List list = this.page(queryDTO); + if (CollectionUtils.isEmpty(list)) { + return null; + } + PositionRegistrationDTO positionRegistrationDTO = list.get(0); + positionRegistrationDTO.setUserCertificateDTOList(userCertificateService.list(UserCertificateQueryDTO.builder().userId(positionRegistrationDTO.getUserId()).build())); + positionRegistrationDTO.setJobExpectDTOList(jobExpectService.list(JobExpectQueryDTO.builder().userId(positionRegistrationDTO.getUserId()).build())); + List resumeDTOList = resumeService.list(ResumeQueryDTO.builder().userId(positionRegistrationDTO.getUserId()).build()); + if (CollectionUtils.isNotEmpty(resumeDTOList)) { + positionRegistrationDTO.setCityCode(resumeDTOList.get(0).getCityCode()); + positionRegistrationDTO.setCityCodeName(resumeDTOList.get(0).getCityCodeName()); + positionRegistrationDTO.setResumeFileCode(resumeDTOList.get(0).getFileCode()); + } + return positionRegistrationDTO; + } + + @Override + public List list(PositionRegistrationPageQueryDTO queryDTO) { + queryDTO.disablePage(); + return this.page(queryDTO); + } + + @Override + public List page(PositionRegistrationPageQueryDTO queryDTO) { + queryDTO.setOrgId(null); + + if (!CommonConstants.PLATFORM_ORG_ID.equals(UserContextHolder.getExistLoginOrgId())) { + //如果是 数据管理页面进来 这个参数就是true + if (Boolean.TRUE.equals(queryDTO.getChildrenOrgAll())) { + //查自己和下级机构 + queryDTO.setOrgIds(orgService.childrenOrgIdList(UserContextHolder.getExistLoginOrgId())); + } else { + queryDTO.setOrgId(UserContextHolder.getExistLoginOrgId()); + } + } + //如果是 数据管理页面进来 这个参数就是true + if (Boolean.TRUE.equals(queryDTO.getChildrenOrgAll())) { + //如果前端给了指定 就按指定的(政府机构) + if (Objects.nonNull(queryDTO.getQueryStreetOrgId())) { + //选定一个政府机构,找出这个政府机构下所有的用工\服务机构,在列出这些用工\服务机构的报名记录 + Set orgIdList = orgService.childrenOrgIdList(queryDTO.getQueryStreetOrgId()); + if (CollectionUtils.isEmpty(orgIdList)) { + return new ArrayList<>(); + } + Set finalOrgIds = orgService.list(OrgQueryDTO.builder().orgIds(orgIdList).types(Sets.newHashSet(OrgTypeEnum.ORG_TYPE_SIMPLE.getType(), OrgTypeEnum.ORG_TYPE_HR.getType())).build()) + .stream().map(orgDTOs -> orgDTOs.getId()).collect(Collectors.toSet()); + if (CollectionUtils.isEmpty(finalOrgIds)) { + return new ArrayList<>(); + } + //所属街道所有子级的机构id + queryDTO.setQueryStreetChildrenAllOrgIds(finalOrgIds); + } + } + + List page = positionRegistrationMapper.page(queryDTO); + return page; + } + + @Transactional(rollbackFor = Exception.class) + @AutoUnLock + @Override + public void userCreate(UserPositionRegistrationDTO dto) { + Assert.isTrue( + RedissonUtils.tryLockAutomatically( + LockDTO.builder() + .tryLockWaitTime(0L) + .lockTimeout(60 * 5L) + .methodName("positionRegistration:create") + .arg(String.valueOf(UserContextHolder.getExistLoginUserId())) + .arg(String.valueOf(dto.getPositionId())) + .build() + ), + "请稍后再试"); + + PositionDTO positionDTO = positionService.findById(dto.getPositionId()); + if (Objects.isNull(positionDTO)) { + throw new BusinessException("未查询到岗位信息"); + } + Assert.isTrue(PositionStatusEnum.OPEN.getStatus().equals(positionDTO.getStatus()), "岗位未开启"); + if (Objects.nonNull(positionDTO.getEndTime())) { + Assert.isTrue(DateUtil.endOfDay(positionDTO.getEndTime()).getTime() >= new Date().getTime(), "岗位已失效,禁止报名"); + } + Integer count = positionRegistrationMapper.selectCount(new LambdaQueryWrapper() + .eq(PositionRegistration::getDeleted, false) + .eq(PositionRegistration::getUserId, UserContextHolder.getExistLoginUserId()) + .eq(PositionRegistration::getPositionId, dto.getPositionId()) + .notIn(PositionRegistration::getStatus, Arrays.asList(PositionRegistrationStatusEnum.CANCEL.getStatus(), PositionRegistrationStatusEnum.RESIGNED.getStatus(), PositionRegistrationStatusEnum.TERMINATION.getStatus())) + ); + if (count > 0) { + throw new BusinessException("请勿报名相同岗位"); + } + PositionRegistration positionRegistration = new PositionRegistration(); + positionRegistration.setUserId(UserContextHolder.getExistLoginUserId()); + positionRegistration.setPositionId(dto.getPositionId()); + positionRegistration.setStatus(PositionRegistrationStatusEnum.ALREADY_REGISTERED.getStatus()); + positionRegistrationMapper.saveEntity(positionRegistration); + + HrCompany hrCompany = hrCompanyMapper.selectOne(new LambdaQueryWrapper().eq(HrCompany::getDeleted, false).eq(HrCompany::getOrgId, positionDTO.getOrgId()).eq(HrCompany::getCompanyType, HrCompanyEnum.SELF.getType())); + Assert.notNull(hrCompany, "数据异常,报名失败"); + + Talent talent = new Talent(); + talent.setOrgId(positionDTO.getOrgId()); + talent.setUserId(UserContextHolder.getExistLoginUserId()); + talent.setCompanyId(hrCompany.getId()); + talentService.importCreate(talent); + } + + @Override + public void invite(PositionRegistrationOperatorDTO operatorDTO) { + Assert.notNull(operatorDTO.getId(), "id不能为空"); + if (StringUtils.isNotBlank(operatorDTO.getInterviewLocation())) { + Assert.isTrue(!(operatorDTO.getInterviewLocation().length() > 100), "面试地点长度超限"); + } + + PositionRegistrationDTO positionRegistrationDTO = this.findById(operatorDTO.getId()); + Assert.notNull(positionRegistrationDTO, "未查询到数据"); + Assert.isTrue(PositionRegistrationStatusEnum.ALREADY_REGISTERED.getStatus().equals(positionRegistrationDTO.getStatus()), "已报名状态才能邀约面试"); + + PositionDTO positionDTO = positionService.findById(positionRegistrationDTO.getPositionId()); + if (Objects.isNull(positionDTO)) { + throw new BusinessException("未查询到岗位信息"); + } + + PositionRegistration positionRegistration = new PositionRegistration(); + positionRegistration.setId(operatorDTO.getId()); + positionRegistration.setStatus(PositionRegistrationStatusEnum.WAIT_FOR_AN_INTERVIEW.getStatus()); + positionRegistration.setInterviewTime(operatorDTO.getInterviewTime()); + positionRegistration.setInterviewLocation(operatorDTO.getInterviewLocation()); + positionRegistration.setUpdateBy(UserContextHolder.getLoginUserId()); + long row = positionRegistrationMapper.updateStatus(positionRegistration, PositionRegistrationStatusEnum.ALREADY_REGISTERED.getStatus()); + Assert.isTrue(row == 1, "邀约面试失败,状态已被变更,请刷新页面重试"); + + ActionUtils.diff(operatorDTO.getId(), PositionRegistration.builder().status(PositionRegistrationStatusEnum.ALREADY_REGISTERED.getStatus()).build() + , PositionRegistration.builder().status(PositionRegistrationStatusEnum.WAIT_FOR_AN_INTERVIEW.getStatus()).build()); + } + + @Override + public void termination(PositionRegistrationOperatorDTO operatorDTO) { + Assert.notNull(operatorDTO.getId(), "id不能为空"); + + PositionRegistrationDTO positionRegistrationDTO = this.findById(operatorDTO.getId()); + Assert.notNull(positionRegistrationDTO, "未查询到数据"); + + PositionDTO positionDTO = positionService.findById(positionRegistrationDTO.getPositionId()); + if (Objects.isNull(positionDTO)) { + throw new BusinessException("未查询到岗位信息"); + } + + PositionRegistration positionRegistration = new PositionRegistration(); + positionRegistration.setId(operatorDTO.getId()); + positionRegistration.setStatus(PositionRegistrationStatusEnum.TERMINATION.getStatus()); + positionRegistration.setTerminationTime(new Date()); + positionRegistration.setUpdateBy(UserContextHolder.getLoginUserId()); + positionRegistrationMapper.updateStatus(positionRegistration, null); + } + + @Override + public void fulfillInterview(PositionRegistrationOperatorDTO operatorDTO) { + Assert.notNull(operatorDTO.getId(), "id不能为空"); + Assert.notNull(operatorDTO.getStatus(), "状态不能为空"); + if (!(PositionRegistrationStatusEnum.FAIL_THE_INTERVIEW.getStatus().equals(operatorDTO.getStatus()) || PositionRegistrationStatusEnum.TO_BE_HIRED.getStatus().equals(operatorDTO.getStatus()))) { + throw new BusinessException("请选择正确的面试结果"); + } + + PositionRegistrationDTO positionRegistrationDTO = this.findById(operatorDTO.getId()); + Assert.notNull(positionRegistrationDTO, "未查询到数据"); + + PositionDTO positionDTO = positionService.findById(positionRegistrationDTO.getPositionId()); + if (Objects.isNull(positionDTO)) { + throw new BusinessException("未查询到岗位信息"); + } + + PositionRegistration positionRegistration = new PositionRegistration(); + positionRegistration.setId(operatorDTO.getId()); + positionRegistration.setStatus(operatorDTO.getStatus()); + positionRegistration.setInductionTime(operatorDTO.getInductionTime()); + positionRegistration.setUpdateBy(UserContextHolder.getLoginUserId()); + positionRegistration.setRemark(operatorDTO.getRemark()); + long row = positionRegistrationMapper.updateStatus(positionRegistration, PositionRegistrationStatusEnum.WAIT_FOR_AN_INTERVIEW.getStatus()); + Assert.isTrue(row == 1, "完成面试失败,状态已被变更,请刷新页面重试"); + + ActionUtils.diff(operatorDTO.getId(), PositionRegistration.builder().status(PositionRegistrationStatusEnum.WAIT_FOR_AN_INTERVIEW.getStatus()).build() + , PositionRegistration.builder().status(operatorDTO.getStatus()).build()); + + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void onTheJob(OnTheJobDTO dto) { + for (OnTheJobDTO.OnTheJobDetailDTO detailDTO : dto.getDetailDTOS()) { + PositionRegistrationDTO positionRegistrationDTO = this.findById(detailDTO.getId()); + Assert.notNull(positionRegistrationDTO, "未查询到数据"); + + PositionDTO positionDTO = positionService.findById(positionRegistrationDTO.getPositionId()); + if (Objects.isNull(positionDTO)) { + throw new BusinessException("未查询到岗位信息"); + } + + + PositionRegistration positionRegistration = new PositionRegistration(); + positionRegistration.setId(detailDTO.getId()); + positionRegistration.setInductionTime(dto.getInductionTime()); + positionRegistration.setSalary(detailDTO.getSalary()); + positionRegistration.setStatus(PositionRegistrationStatusEnum.ON_THE_JOB.getStatus()); + positionRegistration.setUpdateBy(UserContextHolder.getLoginUserId()); + long row = positionRegistrationMapper.updateStatus(positionRegistration, PositionRegistrationStatusEnum.TO_BE_HIRED.getStatus()); + Assert.isTrue(row == 1, "入职失败,状态已被变更,请刷新页面重试"); + + ActionUtils.diff(detailDTO.getId(), PositionRegistration.builder().status(PositionRegistrationStatusEnum.TO_BE_HIRED.getStatus()).build() + , PositionRegistration.builder().status(PositionRegistrationStatusEnum.ON_THE_JOB.getStatus()).build()); + + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void resigned(ResignedDTO dto) { + for (Long id : dto.getIds()) { + PositionRegistrationDTO positionRegistrationDTO = this.findById(id); + Assert.notNull(positionRegistrationDTO, "未查询到数据"); + + PositionDTO positionDTO = positionService.findById(positionRegistrationDTO.getPositionId()); + if (Objects.isNull(positionDTO)) { + throw new BusinessException("未查询到岗位信息"); + } + + PositionRegistration positionRegistration = new PositionRegistration(); + positionRegistration.setId(id); + positionRegistration.setQuitTime(dto.getQuitTime()); + positionRegistration.setStatus(PositionRegistrationStatusEnum.RESIGNED.getStatus()); + positionRegistration.setUpdateBy(UserContextHolder.getLoginUserId()); + long row = positionRegistrationMapper.updateStatus(positionRegistration, PositionRegistrationStatusEnum.ON_THE_JOB.getStatus()); + Assert.isTrue(row == 1, "离职失败,状态已被变更,请刷新页面重试"); + + ActionUtils.diff(id, PositionRegistration.builder().status(PositionRegistrationStatusEnum.ON_THE_JOB.getStatus()).build() + , PositionRegistration.builder().status(PositionRegistrationStatusEnum.RESIGNED.getStatus()).build()); + + } + } + + @Override + public void export(PositionRegistrationPageQueryDTO queryDTO) { + boolean flag = true; + Integer pageNo = 1; + Integer pageSize = 100; + + List listAll = new ArrayList<>(); + + while (flag) { + queryDTO.setPageNo(pageNo); + queryDTO.setPageSize(pageSize); + List list = this.page(queryDTO); + if (org.springframework.util.CollectionUtils.isEmpty(list)) { + flag = false; + continue; + } + if (list.size() < pageSize) { + flag = false; + } + pageNo = pageNo + 1; + listAll.addAll(list); + } + List collect = listAll.stream().map(dto -> { + PositionRegistrationExportDTO exportDTO = new PositionRegistrationExportDTO(); + BeanUtils.copyProperties(dto, exportDTO); + exportDTO.setInterviewTime(DateUtil.format(dto.getInterviewTime(), "yyyy-MM-dd")); + exportDTO.setCreateTime(DateUtil.format(dto.getCreateTime(), "yyyy-MM-dd HH:mm:ss")); + exportDTO.setInductionTime(DateUtil.format(dto.getInductionTime(), "yyyy-MM-dd")); + exportDTO.setQuitTime(DateUtil.format(dto.getQuitTime(), "yyyy-MM-dd")); + exportDTO.setStatus(DictUtils.getCodeNameMap("position_registration_status").get(String.valueOf(dto.getStatus()))); + return exportDTO; + }).collect(Collectors.toList()); + + if (org.springframework.util.CollectionUtils.isEmpty(collect)) { + return; + } + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); + String fileName = "招聘明细导出" + "(" + formatter.format(LocalDateTime.now()) + ")"; + + ExportHeadInfoDTO infoDTO = ExportHeadInfoDTO.builder() + .fileName(fileName) + .build(); + List heads = infoDTO.getHeads(); + heads.add(ExportHeadDetailInfoDTO.builder().head("岗位名称").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("姓名").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("性别").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("年龄").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("手机号").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("身份证号").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("用工企业").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("招聘状态").build()); + + if (Boolean.TRUE.equals(queryDTO.getChildrenOrgAll())) { + heads.add(ExportHeadDetailInfoDTO.builder().head("发布机构").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("所属街镇").build()); + } + + List datas = Lists.newArrayList(); + + //全部 + if (CollectionUtils.isEmpty(queryDTO.getStatusList())) { + + heads.add(ExportHeadDetailInfoDTO.builder().head("面试时间").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("面试地点").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("入职薪资").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("报名时间").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("入职日期").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("最后工作日").build()); + for (PositionRegistrationExportDTO dto : collect) { + List objects = Lists.newArrayList(); + datas.add(objects); + objects.add(dto.getPositionName()); + objects.add(dto.getRealName()); + objects.add(dto.getGender()); + objects.add(dto.getAge()); + objects.add(dto.getPhone()); + objects.add(dto.getCardNo()); + objects.add(dto.getCompanyName()); + objects.add(dto.getStatus()); + if (Boolean.TRUE.equals(queryDTO.getChildrenOrgAll())) { + objects.add(dto.getPublishOrgName()); + objects.add(dto.getStreetName()); + } + objects.add(dto.getInterviewTime()); + objects.add(dto.getInterviewLocation()); + objects.add(dto.getSalary()); + objects.add(dto.getCreateTime()); + objects.add(dto.getInductionTime()); + objects.add(dto.getQuitTime()); + } + } else if (queryDTO.getStatusList().contains(PositionRegistrationStatusEnum.ALREADY_REGISTERED.getStatus())) { + heads.add(ExportHeadDetailInfoDTO.builder().head("报名时间").build()); + for (PositionRegistrationExportDTO dto : collect) { + List objects = Lists.newArrayList(); + datas.add(objects); + objects.add(dto.getPositionName()); + objects.add(dto.getRealName()); + objects.add(dto.getGender()); + objects.add(dto.getAge()); + objects.add(dto.getPhone()); + objects.add(dto.getCardNo()); + objects.add(dto.getCompanyName()); + objects.add(dto.getStatus()); + if (Boolean.TRUE.equals(queryDTO.getChildrenOrgAll())) { + objects.add(dto.getPublishOrgName()); + objects.add(dto.getStreetName()); + } + objects.add(dto.getCreateTime()); + } + } else if (queryDTO.getStatusList().containsAll(Arrays.asList( + PositionRegistrationStatusEnum.WAIT_FOR_AN_INTERVIEW.getStatus(), + PositionRegistrationStatusEnum.FAIL_THE_INTERVIEW.getStatus(), + PositionRegistrationStatusEnum.TO_BE_HIRED.getStatus() + ))) { + heads.add(ExportHeadDetailInfoDTO.builder().head("报名时间").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("面试时间").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("面试地点").build()); + + for (PositionRegistrationExportDTO dto : collect) { + List objects = Lists.newArrayList(); + datas.add(objects); + objects.add(dto.getPositionName()); + objects.add(dto.getRealName()); + objects.add(dto.getGender()); + objects.add(dto.getAge()); + objects.add(dto.getPhone()); + objects.add(dto.getCardNo()); + objects.add(dto.getCompanyName()); + objects.add(dto.getStatus()); + if (Boolean.TRUE.equals(queryDTO.getChildrenOrgAll())) { + objects.add(dto.getPublishOrgName()); + objects.add(dto.getStreetName()); + } + objects.add(dto.getCreateTime()); + objects.add(dto.getInterviewTime()); + objects.add(dto.getInterviewLocation()); + } + } else if (queryDTO.getStatusList().contains(PositionRegistrationStatusEnum.ON_THE_JOB.getStatus())) { + heads.add(ExportHeadDetailInfoDTO.builder().head("入职薪资").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("报名时间").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("面试时间").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("入职日期").build()); + for (PositionRegistrationExportDTO dto : collect) { + List objects = Lists.newArrayList(); + datas.add(objects); + objects.add(dto.getPositionName()); + objects.add(dto.getRealName()); + objects.add(dto.getGender()); + objects.add(dto.getAge()); + objects.add(dto.getPhone()); + objects.add(dto.getCardNo()); + objects.add(dto.getCompanyName()); + objects.add(dto.getStatus()); + if (Boolean.TRUE.equals(queryDTO.getChildrenOrgAll())) { + objects.add(dto.getPublishOrgName()); + objects.add(dto.getStreetName()); + } + objects.add(dto.getSalary()); + objects.add(dto.getCreateTime()); + objects.add(dto.getInterviewTime()); + objects.add(dto.getInductionTime()); + } + } + + infoDTO.setDatas(datas); + ExcelUtil.dynamicExportTemplate(infoDTO); + } + + @Override + public List userPage(UserPositionRegistrationPageQueryDTO queryDTO) { + queryDTO.setUserId(UserContextHolder.getExistLoginUserId()); + List list = positionRegistrationMapper.userPage(queryDTO); + for (UserPositionRegistrationResDTO userPositionRegistrationResDTO : list) { + userPositionRegistrationResDTO.setRecruitPositionTypeName(DictUtils.getCodeNameMap("recruit_position_type").get(userPositionRegistrationResDTO.getRecruitPositionType())); + } + return list; + } + + @Override + public void cancel(Long positionId) { + List userPositionRegistrationResDTOS = positionRegistrationMapper.userPage(UserPositionRegistrationPageQueryDTO.builder().positionId(positionId).userId(UserContextHolder.getExistLoginUserId()).build()); + if (CollectionUtils.isEmpty(userPositionRegistrationResDTOS)) { + throw new BusinessException("暂无可取消的报名记录"); + } + UserPositionRegistrationResDTO userPositionRegistrationResDTO = userPositionRegistrationResDTOS.get(0); + if (StringUtils.equals(PositionRegistrationStatusEnum.WAIT_FOR_AN_INTERVIEW.getStatus(), userPositionRegistrationResDTO.getStatus())) { + throw new BusinessException("您在该岗位处于【待面试】状态,无法取消报名。"); + } else if (StringUtils.equals(PositionRegistrationStatusEnum.TO_BE_HIRED.getStatus(), userPositionRegistrationResDTO.getStatus())) { + throw new BusinessException("您在该岗位处于【待入职】状态,无法取消报名。"); + } else if (StringUtils.equals(PositionRegistrationStatusEnum.ON_THE_JOB.getStatus(), userPositionRegistrationResDTO.getStatus())) { + throw new BusinessException("您在该岗位处于【已入职】状态,无法取消报名。"); + } + positionRegistrationMapper.updateStatus(PositionRegistration.builder().id(userPositionRegistrationResDTO.getId()).status(PositionRegistrationStatusEnum.CANCEL.getStatus()).build(), PositionRegistrationStatusEnum.ALREADY_REGISTERED.getStatus()); + } + + @Override + public void show(Long id) { + PositionRegistrationDTO positionRegistrationDTO = this.findById(id); + if (Objects.isNull(positionRegistrationDTO)) { + return; + } + if (Boolean.TRUE.equals(positionRegistrationDTO.getShow())) { + return; + } + PositionRegistration positionRegistration = new PositionRegistration(); + positionRegistration.setId(id); + positionRegistration.setShow(true); + positionRegistrationMapper.updateEntitySelective(positionRegistration); + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/service/impl/PositionServiceImpl.java b/src/main/java/com/newyetai/recruit/position/service/impl/PositionServiceImpl.java new file mode 100644 index 0000000..57bbdb4 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/service/impl/PositionServiceImpl.java @@ -0,0 +1,577 @@ +package com.newyetai.recruit.position.service.impl; + +import com.google.common.collect.Lists; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.RandomUtil; +import lombok.extern.slf4j.Slf4j; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.newyetai.common.AlitaResult; +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.dto.ExportHeadDetailInfoDTO; +import com.newyetai.common.dto.ExportHeadInfoDTO; +import com.newyetai.common.easyexcel.ExcelUtil; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.recruit.company.dto.HrCompanyDTO; +import com.newyetai.recruit.company.dto.HrCompanyPageQueryDTO; +import com.newyetai.recruit.company.enums.HrCompanyEnum; +import com.newyetai.recruit.company.service.IHrCompanyService; +import com.newyetai.component.dict.util.DictUtils; +import com.newyetai.recruit.position.convert.PositionConvert; +import com.newyetai.recruit.position.dao.PositionRegistrationMapper; +import com.newyetai.recruit.position.entity.Position; +import com.newyetai.recruit.position.dto.*; +import com.newyetai.recruit.position.dao.PositionMapper; +import com.newyetai.recruit.position.enums.PositionStatusEnum; +import com.newyetai.recruit.position.service.PositionFileService; +import com.newyetai.recruit.position.service.PositionService; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.recruit.user.dao.UserCollectionMapper; +import com.newyetai.recruit.user.dto.JobExpectDTO; +import com.newyetai.recruit.user.dto.JobExpectQueryDTO; +import com.newyetai.recruit.user.dto.ResumeDTO; +import com.newyetai.recruit.user.entity.UserCollection; +import com.newyetai.recruit.user.service.JobExpectService; +import com.newyetai.recruit.user.service.ResumeService; +import com.newyetai.sdk.tencent.map.TencentMapContext; +import com.newyetai.sdk.tencent.map.dto.TencentMapBaseResDTO; +import com.newyetai.sdk.tencent.map.dto.TencentWsDistanceV1MatrixElementsResDTO; +import com.newyetai.sdk.tencent.map.dto.TencentMapWsDistanceV1MatrixReqDTO; +import com.newyetai.sdk.tencent.map.dto.TencentWsDistanceV1MatrixResDTO; +import com.newyetai.sdk.tencent.map.dto.TencentWsDistanceV1MatrixElementsRowResDTO; +import com.newyetai.usercenter.org.dao.OrgMapper; +import com.newyetai.usercenter.org.entity.Org; +import com.newyetai.usercenter.org.enums.RecruitPositionTypeEnum; +import com.newyetai.usercenter.user.dto.UserDTO; +import com.newyetai.usercenter.user.service.UserService; +import com.spatial4j.core.context.SpatialContext; +import com.spatial4j.core.distance.DistanceUtils; +import com.spatial4j.core.shape.Rectangle; + +import javax.annotation.Resource; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.stream.Collectors; + +/** + * 岗位信息表;岗位信息表 + * + * @author guixinman + * @since 1.0.0 2024-04-11 + */ +@Slf4j +@Service +public class PositionServiceImpl implements PositionService { + + @Resource + private PositionMapper positionMapper; + + @Autowired + private IHrCompanyService hrCompanyService; + + @Autowired + private PositionFileService positionFileService; + + @Resource + private PositionRegistrationMapper positionRegistrationMapper; + + @Resource + private UserCollectionMapper userCollectionMapper; + + @Resource + private OrgMapper orgMapper; + + @Autowired + private JobExpectService jobExpectService; + + @Autowired + private UserService userService; + + @Autowired + private ResumeService resumeService; + + @Autowired + private TencentMapContext tencentMapContext; + + @Transactional(rollbackFor = Exception.class) + @Override + public PositionDTO create(PositionOperatorDTO operatorDto) { + Long orgId = UserContextHolder.getExistLoginOrgId(); + if (Objects.nonNull(operatorDto.getOrgId())) { + orgId = operatorDto.getOrgId(); + } + if (Objects.nonNull(operatorDto.getEndTime())) { + Assert.isTrue(! (DateUtil.endOfDay(operatorDto.getEndTime()).getTime() <= DateUtil.endOfDay(new Date()).getTime()),"岗位有效期不能小于等于当前日期"); + } + Org org = orgMapper.selectOne(new LambdaQueryWrapper().eq(Org::getDeleted, false).eq(Org::getId, orgId)); + if (Objects.isNull(org)) { + throw new BusinessException("未查询到数据"); + } + + //判断招聘岗位类型权限 + if (!org.getRecruitPositionType().equals(RecruitPositionTypeEnum.ODD_JOB_OR_GENERAL_WORKER.getType())) { + if (!StringUtils.equals(org.getRecruitPositionType(), operatorDto.getRecruitPositionType())) { + if (StringUtils.equals(org.getRecruitPositionType(), RecruitPositionTypeEnum.ODD_JOB.getType())) { + throw new BusinessException("当前企业仅支持维护零工性质岗位。"); + } + if (StringUtils.equals(org.getRecruitPositionType(), RecruitPositionTypeEnum.GENERAL_WORKER.getType())) { + throw new BusinessException("当前企业仅支持维护普工性质岗位。"); + } + } + } + + + //当前机构下,相同的用工企业,不能存在相同的岗位名称 + Assert.notNull(hrCompanyService.find(HrCompanyPageQueryDTO.builder().id(operatorDto.getCompanyId()).orgId(orgId).companyTypes(Arrays.asList(HrCompanyEnum.KH.getType(), HrCompanyEnum.SELF.getType())).build()), "未查询到用工企业"); + + List positions = positionMapper.selectList(new LambdaQueryWrapper() + .eq(Position::getCompanyId, operatorDto.getCompanyId()) + .eq(Position::getOrgId, orgId) + .eq(Position::getPositionName, operatorDto.getPositionName()) + ); + if (CollectionUtils.isNotEmpty(positions)) { + throw new BusinessException("该用工企业已存在相同的岗位名称,添加失败"); + } + + Position position = PositionConvert.INSTANCE.convert(operatorDto); + position.setOrgId(orgId); + if (Objects.isNull(operatorDto.getStatus())) { + position.setStatus(PositionStatusEnum.OPEN.getStatus()); + } + positionMapper.saveEntity(position); + return PositionConvert.INSTANCE.convert(position); + } + + @Override + public PositionDTO modify(PositionOperatorDTO operatorDto) { + Assert.notNull(operatorDto.getId(), "岗位id缺失"); + + Position positionDto = positionMapper.selectById(operatorDto.getId()); + if (Objects.isNull(positionDto)) { + throw new BusinessException("未查询到对应数据"); + } + if (Objects.nonNull(operatorDto.getEndTime())) { + Assert.isTrue(! (DateUtil.endOfDay(operatorDto.getEndTime()).getTime() <= DateUtil.endOfDay(new Date()).getTime()),"岗位有效期不能小于等于当前日期"); + } + Assert.notNull(hrCompanyService.find(HrCompanyPageQueryDTO.builder().id(operatorDto.getCompanyId()).companyTypes(Arrays.asList(HrCompanyEnum.KH.getType(), HrCompanyEnum.SELF.getType())).orgId(positionDto.getOrgId()).build()), "未查询到用工企业"); + List positions = positionMapper.selectList(new LambdaQueryWrapper() + .eq(Position::getCompanyId, operatorDto.getCompanyId()) + .eq(Position::getOrgId, positionDto.getOrgId()) + .eq(Position::getPositionName, operatorDto.getPositionName()) + .notIn(Position::getId, operatorDto.getId()) + ); + if (CollectionUtils.isNotEmpty(positions)) { + throw new BusinessException("该用工企业已存在相同的岗位名称,添加失败"); + } + + Position position = PositionConvert.INSTANCE.convert(operatorDto); + //不能修改 + position.setRecruitPositionType(positionDto.getRecruitPositionType()); + positionMapper.updateEntity(position); + return this.findById(operatorDto.getId()); + } + + @Override + public PositionDTO delete(Long id) { + PositionDTO positionDto = this.findById(id); + if (Objects.isNull(positionDto)) { + return null; + } + Position position = Position.builder().build(); + position.setId(id); + positionMapper.deleteEntity(position, UserContextHolder.getLoginUserId()); + return positionDto; + } + + @Override + public PositionDTO findById(Long id) { + Assert.notNull(id, "参数缺失"); + + PositionPageQueryDTO queryDTO = new PositionPageQueryDTO(); + queryDTO.disablePage(); + queryDTO.setId(id); + List list = this.page(queryDTO); + return CollectionUtils.isNotEmpty(list) ? list.get(0) : null; + } + + @Override + public PositionDTO userFindById(Long id) { + Assert.notNull(id, "id不能为空"); + + PositionPageQueryDTO queryDTO = new PositionPageQueryDTO(); + queryDTO.disablePage(); + queryDTO.setId(id); + queryDTO.setUseEndTime(false); + List list = this.userPage(queryDTO); + if (CollectionUtils.isNotEmpty(list)) { + PositionDTO positionDTO = list.get(0); + List positionFileDTOS = positionFileService.filePage(PositionFilePageQueryDTO.builder().positionId(positionDTO.getId()).build()); + positionDTO.setPositionFileDTOS(positionFileDTOS); + + if (Objects.nonNull(UserContextHolder.getLoginUserId())) { + List userPositionRegistrationResDTOS = positionRegistrationMapper.userPage(UserPositionRegistrationPageQueryDTO.builder().userId(UserContextHolder.getExistLoginUserId()).positionId(positionDTO.getId()).build()); + if (CollectionUtils.isNotEmpty(userPositionRegistrationResDTOS)) { + positionDTO.setPositionRegistrationStatus(userPositionRegistrationResDTOS.get(0).getStatus()); + positionDTO.setShow(userPositionRegistrationResDTOS.get(0).getShow()); + positionDTO.setPositionRegistrationCreateTime(userPositionRegistrationResDTOS.get(0).getCreateTime()); + positionDTO.setInterviewTime(userPositionRegistrationResDTOS.get(0).getInterviewTime()); + positionDTO.setInterviewLocation(userPositionRegistrationResDTOS.get(0).getInterviewLocation()); + positionDTO.setRemark(userPositionRegistrationResDTOS.get(0).getRemark()); + positionDTO.setInductionTime(userPositionRegistrationResDTOS.get(0).getInductionTime()); + positionDTO.setPositionRegistrationSalary(userPositionRegistrationResDTOS.get(0).getSalary()); + } + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(UserCollection::getUserId, UserContextHolder.getExistLoginUserId()); + queryWrapper.eq(UserCollection::getDeleted, false); + queryWrapper.eq(UserCollection::getPostId, positionDTO.getId()); + Integer count = userCollectionMapper.selectCount(queryWrapper); + positionDTO.setIsCollection(true); + if (count == 0) { + positionDTO.setIsCollection(false); + } + } + + return positionDTO; + } + + return null; + } + + @Override + public List list(PositionPageQueryDTO queryDTO) { + queryDTO.disablePage(); + return this.page(queryDTO); + } + + @Override + public List page(PositionPageQueryDTO queryDTO) { + if (!CommonConstants.PLATFORM_ORG_ID.equals(UserContextHolder.getExistLoginOrgId())) { + queryDTO.setOrgId(UserContextHolder.getExistLoginOrgId()); + } + List list = positionMapper.page(queryDTO); + for (PositionDTO positionDTO : list) { + positionDTO.setRecruitPositionTypeName(DictUtils.getCodeNameMap("recruit_position_type").get(positionDTO.getRecruitPositionType())); + } + return list; + } + + @Override + public List userPage(PositionPageQueryDTO queryDTO) { + List list = positionMapper.userPage(queryDTO); + for (PositionDTO positionDTO : list) { + positionDTO.setRecruitPositionTypeName(DictUtils.getCodeNameMap("recruit_position_type").get(positionDTO.getRecruitPositionType())); + } + return list; + } + + @Override + public List tencentMapUserPage(PositionPageQueryDTO queryDTO) { + if (Objects.nonNull(queryDTO.getLongitude()) && Objects.nonNull(queryDTO.getLatitude())) { + // 移动设备经纬度 + double lon = Double.parseDouble(String.valueOf(queryDTO.getLongitude())); + double lat = Double.parseDouble(String.valueOf(queryDTO.getLatitude())); + // 千米 + int radius = queryDTO.getRadius(); + try { + SpatialContext geo = SpatialContext.GEO; + Rectangle rectangle = geo.getDistCalc().calcBoxByDistFromPt( + geo.makePoint(lon, lat), radius * DistanceUtils.KM_TO_DEG, geo, null); + + queryDTO.setMinX(new BigDecimal(String.valueOf(rectangle.getMinX()))); + queryDTO.setMaxX(new BigDecimal(String.valueOf(rectangle.getMaxX()))); + queryDTO.setMinY(new BigDecimal(String.valueOf(rectangle.getMinY()))); + queryDTO.setMaxY(new BigDecimal(String.valueOf(rectangle.getMaxY()))); + }catch (Exception e) { + return new ArrayList<>(); + } + } + StringBuilder to = new StringBuilder(); + List list = positionMapper.userPage(queryDTO); + + //填充距离的对象集合 + List temp = new ArrayList<>(); + //岗位列表 + List positionDTOResultList = new ArrayList<>(); + + for (int i = 0; i < list.size(); i++) { + PositionDTO positionDTO = list.get(i); + positionDTO.setRecruitPositionTypeName(DictUtils.getCodeNameMap("recruit_position_type").get(positionDTO.getRecruitPositionType())); + if (Objects.nonNull(positionDTO.getLongitude()) && Objects.nonNull(positionDTO.getLatitude())) { + to.append(positionDTO.getLatitude().toPlainString() + "," + positionDTO.getLongitude().toPlainString()); + to.append(";"); + temp.add(positionDTO); + } + } + + if (Objects.nonNull(queryDTO.getLongitude()) && Objects.nonNull(queryDTO.getLatitude()) && temp.size() > 0) { + if (to.length() >= 2 && to.charAt(to.length() - 1) == ';') { + to.deleteCharAt(to.length() - 1); + } + AlitaResult walkingRes = tencentMapContext.wsDistanceV1MatrixReqDTO(TencentMapWsDistanceV1MatrixReqDTO.builder() + .from(queryDTO.getLatitude().toPlainString() + "," + queryDTO.getLongitude().toPlainString()) + .to(to.toString()) + .mode("walking") + .build()); + if (Boolean.TRUE.equals(walkingRes.getSuccess())) { + if (Objects.nonNull(walkingRes.getData())) { + TencentWsDistanceV1MatrixResDTO result = walkingRes.getData(); + List rows = result.getRows(); + List elements = rows.get(0).getElements(); + for (int i = 0; i < temp.size(); i++) { + PositionDTO positionDTOTemp = temp.get(i); + PositionDTO positionDTOFinal = list.stream().filter(positionDTO -> positionDTO.getId().longValue() == positionDTOTemp.getId().longValue()).findFirst().orElse(null); + positionDTOFinal.setDistance(elements.get(i).getDistance()); + if (positionDTOFinal.getDistance().longValue() <= Long.valueOf(queryDTO.getRadius()*1000).longValue()) { + positionDTOResultList.add(positionDTOFinal); + } + } + } + } + } + return positionDTOResultList.stream().sorted(Comparator.comparingLong(PositionDTO::getDistance)).collect(Collectors.toList()); + } + + @Override + public void export(PositionPageQueryDTO queryDTO) { + boolean flag = true; + Integer pageNo = 1; + Integer pageSize = 100; + + List listAll = new ArrayList<>(); + + while (flag) { + queryDTO.setPageNo(pageNo); + queryDTO.setPageSize(pageSize); + List list = this.page(queryDTO); + if (org.springframework.util.CollectionUtils.isEmpty(list)) { + flag = false; + continue; + } + if (list.size() < pageSize) { + flag = false; + } + pageNo = pageNo + 1; + listAll.addAll(list); + } + List collect = listAll.stream().map(dto -> { + PositionExportDTO exportDTO = new PositionExportDTO(); + BeanUtils.copyProperties(dto, exportDTO); + exportDTO.setCreateTime(DateUtil.format(dto.getCreateTime(), "yyyy-MM-dd HH:mm:ss")); + exportDTO.setStatus(DictUtils.getCodeNameMap("position_status").get(String.valueOf(dto.getStatus()))); + exportDTO.setSalary(dto.getSalaryStr()); + return exportDTO; + }).collect(Collectors.toList()); + + if (org.springframework.util.CollectionUtils.isEmpty(collect)) { + return; + } + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); + String fileName = "岗位明细导出" + "(" + formatter.format(LocalDateTime.now()) + ")"; + + ExportHeadInfoDTO infoDTO = ExportHeadInfoDTO.builder() + .fileName(fileName) + .build(); + List heads = infoDTO.getHeads(); + heads.add(ExportHeadDetailInfoDTO.builder().head("招聘岗位类型").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("岗位名称").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("用工企业").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("岗位状态").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("招聘人数").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("综合薪资").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("工作地址").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("创建时间").build()); + + List datas = Lists.newArrayList(); + for (PositionExportDTO dto : collect) { + List objects = Lists.newArrayList(); + datas.add(objects); + objects.add(dto.getRecruitPositionTypeName()); + objects.add(dto.getPositionName()); + objects.add(dto.getCompanyName()); + objects.add(dto.getStatus()); + objects.add(dto.getPositionNumber()); + objects.add(dto.getSalary()); + objects.add(dto.getPositionAddress()); + objects.add(dto.getCreateTime()); + } + infoDTO.setDatas(datas); + + ExcelUtil.dynamicExportTemplate(infoDTO); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void modifyStatus(PositionOperatorDTO dto) { + if (CollectionUtils.isEmpty(dto.getIds())) { + throw new BusinessException("请选择数据"); + } + Assert.notNull(dto.getStatus(), "请选择状态"); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper() + .in(Position::getId, dto.getIds()) + .eq(Position::getDeleted, false); + + if (!CommonConstants.PLATFORM_ORG_ID.equals(UserContextHolder.getExistLoginOrgId())) { + queryWrapper.eq(Position::getOrgId, UserContextHolder.getExistLoginOrgId()); + } + + Integer count = positionMapper.selectCount(queryWrapper); + Assert.isTrue(count == dto.getIds().size(), "网络异常,请刷新后再试"); + + List positions = new ArrayList<>(); + for (Long id : dto.getIds()) { + Position position = new Position(); + position.setId(id); + position.setStatus(dto.getStatus()); + positions.add(position); + } + positionMapper.updateEntitysSelective(positions, UserContextHolder.getExistLoginUserId()); + } + + @Override + public void template() { + ExportHeadInfoDTO infoDTO = ExportHeadInfoDTO.builder() + .fileName("岗位导入模板") + .build(); + List heads = infoDTO.getHeads(); + + List companyNameList = Optional.ofNullable(hrCompanyService.list(HrCompanyPageQueryDTO.builder().companyTypes(Arrays.asList(HrCompanyEnum.KH.getType(), HrCompanyEnum.SELF.getType())).build())) + .map(list -> list.stream().map(HrCompanyDTO::getCompanyName).collect(Collectors.toList())) + .orElse(new ArrayList<>()); + + heads.add(ExportHeadDetailInfoDTO.builder().head("用工企业(必填)").explicitList(companyNameList).build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("岗位名称(必填)").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("招聘标题(必填)").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("招聘人数").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("工作地址(必填)").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("工作性质(必填)").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("岗位类型").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("岗位标签").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("综合薪资(必填)").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("发薪日").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("性别(必填)").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("年龄(必填)").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("学历(必填)").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("经验(必填)").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("证件").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("其它").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("工作内容(必填)").build()); + + ExcelUtil.dynamicExportTemplate(infoDTO); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public Long copy(Long id) { + PositionDTO oldPositionDTO = this.findById(id); + if (Objects.isNull(oldPositionDTO)) { + throw new BusinessException("未查询到岗位信息"); + } + PositionOperatorDTO positionOperatorDTO = new PositionOperatorDTO(); + BeanUtils.copyProperties(oldPositionDTO, positionOperatorDTO); + positionOperatorDTO.setPositionName(String.format("%s复制%s", RandomUtil.randomString(3), StringUtils.substring(oldPositionDTO.getPositionName(), 0, 45))); + PositionDTO newPosition = ((PositionServiceImpl) AopContext.currentProxy()).create(positionOperatorDTO); + + List oldPositionFileDTOS = positionFileService.filePage(PositionFilePageQueryDTO.builder().positionId(id).build()); + for (PositionFileDTO oldPositionFileDTO : oldPositionFileDTOS) { + PositionFileDTO positionFileDTO = new PositionFileDTO(); + BeanUtils.copyProperties(oldPositionFileDTO, positionFileDTO); + positionFileDTO.setPositionId(newPosition.getId()); + positionFileService.create(positionFileDTO); + } + return newPosition.getId(); + } + + @Override + public List personPostMatching(Long id) { + JobExpectDTO jobExpectDTO = jobExpectService.find(JobExpectQueryDTO.builder().id(id).userId(UserContextHolder.getLoginUserId()).build()); + if (Objects.isNull(jobExpectDTO)) { + return new ArrayList<>(); + } + + UserDTO userDTO = userService.get(UserContextHolder.getExistLoginUserId()); + ResumeDTO resumeDTO = Optional.ofNullable(resumeService.userFind()).orElse(new ResumeDTO()); + + PersonPostMatchingQueryDTO queryDTO = new PersonPostMatchingQueryDTO(); + queryDTO.setPageNo(1); + queryDTO.setPageSize(100); + + queryDTO.setPositionNameLike(jobExpectDTO.getPositionName()); + queryDTO.setPositionType(jobExpectDTO.getTypeCode()); + queryDTO.setDetailAddressLike(jobExpectDTO.getExpectCityName()); + queryDTO.setSalary(jobExpectDTO.getExpectSalary()); + queryDTO.setSexRequire(Objects.isNull(userDTO.getGender()) ? null : String.valueOf(userDTO.getGender())); + queryDTO.setAge(Objects.isNull(userDTO.getBirthday()) ? null : DateUtil.ageOfNow(userDTO.getBirthday())); + queryDTO.setEducationRequire(resumeDTO.getEducation()); + List positionDTOS = positionMapper.personPostMatching(queryDTO); + + if (CollectionUtils.isEmpty(positionDTOS)) { + //岗位类型> 工作地 > 学历 / 年龄 / 薪酬 / 性别 / 经验 从右往左递减吧 + //岗位名称> 岗位类型> 工作地 > 学历 / 年龄 / 薪酬 / 性别 / 经验 + for (int i = 2; i <= 7; i++) { + if (i == 2) { + queryDTO.setSexRequire(null); + positionDTOS = positionMapper.personPostMatching(queryDTO); + if (CollectionUtils.isNotEmpty(positionDTOS)) { + break; + } + } else if (i == 3) { + queryDTO.setSalary(null); + positionDTOS = positionMapper.personPostMatching(queryDTO); + if (CollectionUtils.isNotEmpty(positionDTOS)) { + break; + } + } else if (i == 4) { + queryDTO.setAge(null); + positionDTOS = positionMapper.personPostMatching(queryDTO); + if (CollectionUtils.isNotEmpty(positionDTOS)) { + break; + } + } else if (i == 5) { + queryDTO.setEducationRequire(null); + positionDTOS = positionMapper.personPostMatching(queryDTO); + if (CollectionUtils.isNotEmpty(positionDTOS)) { + break; + } + } else if (i == 6) { + queryDTO.setDetailAddressLike(null); + positionDTOS = positionMapper.personPostMatching(queryDTO); + if (CollectionUtils.isNotEmpty(positionDTOS)) { + break; + } + } else if (i == 7) { + queryDTO.setPositionType(null); + positionDTOS = positionMapper.personPostMatching(queryDTO); + if (CollectionUtils.isNotEmpty(positionDTOS)) { + break; + } + } + } + } + + for (PositionDTO positionDTO : positionDTOS) { + positionDTO.setRecruitPositionTypeName(DictUtils.getCodeNameMap("recruit_position_type").get(positionDTO.getRecruitPositionType())); + } + return positionDTOS; + } + + @Override + public void positionExpiry() { + positionMapper.positionExpiry(); + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/position/service/impl/PositionTypeServiceImpl.java b/src/main/java/com/newyetai/recruit/position/service/impl/PositionTypeServiceImpl.java new file mode 100644 index 0000000..dd70102 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/position/service/impl/PositionTypeServiceImpl.java @@ -0,0 +1,90 @@ +package com.newyetai.recruit.position.service.impl; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + + +import com.newyetai.common.util.TreeHelper; +import com.newyetai.recruit.position.dao.PositionTypeMapper; +import com.newyetai.recruit.position.dto.PositionTypeDTO; +import com.newyetai.recruit.position.dto.PositionTypeQueryDTO; +import com.newyetai.recruit.position.service.PositionTypeService; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; + +import javax.annotation.Resource; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + + +@Slf4j +@Service +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class PositionTypeServiceImpl implements PositionTypeService { + + @Autowired + private RedisTemplate redisTemplate; + + @Resource + private PositionTypeMapper positionTypeMapper; + + private Long maxFirst = 1L; + private Map maxSecond = Maps.newConcurrentMap(); + private Map maxThree = Maps.newConcurrentMap(); + + @Override + public List batchCreate(List positionTypeDTOS) { +// List allCreateTypes = needCreate(positionTypeDTOS); +// //select db +// List currentTypes = Lists.newArrayList(); + + + return null; + } + + @Override + public List query(PositionTypeQueryDTO queryDTO) { + List types = positionTypeMapper.queryByDto(queryDTO); + List positionTypeDTOS = TreeHelper.buildTree(0L, types); + String nameLike = queryDTO.getNameLike(); + if (StrUtil.isNotEmpty(nameLike)) { + List typesTemp = Lists.newLinkedList(); + for (PositionTypeDTO type : positionTypeDTOS) { + if (handler(queryDTO, type)) { + typesTemp.add(type); + } + } + positionTypeDTOS = typesTemp; + } + return positionTypeDTOS; + } + + public Boolean handler(PositionTypeQueryDTO queryDTO, PositionTypeDTO type) { + Boolean contain = Boolean.FALSE; + String nameLike = queryDTO.getNameLike(); + if (StrUtil.containsIgnoreCase(type.getName(), nameLike)) { + contain = Boolean.TRUE; + } + List childrenSet = type.getChildrenSet(); + if (CollUtil.isNotEmpty(childrenSet)) { + List typesTemp = Lists.newLinkedList(); + for (PositionTypeDTO positionTypeDTO : childrenSet) { + Boolean handler = handler(queryDTO, positionTypeDTO); + contain |= handler; + if (handler) { + typesTemp.add(positionTypeDTO); + } + } + type.setChildrenSet(typesTemp); + } + return contain; + } +} diff --git a/src/main/java/com/newyetai/recruit/statistics/controller/OrgDailyStatisticController.java b/src/main/java/com/newyetai/recruit/statistics/controller/OrgDailyStatisticController.java new file mode 100644 index 0000000..3d142fb --- /dev/null +++ b/src/main/java/com/newyetai/recruit/statistics/controller/OrgDailyStatisticController.java @@ -0,0 +1,52 @@ +package com.newyetai.recruit.statistics.controller; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +import com.newyetai.common.AlitaResult; +import com.newyetai.recruit.statistics.dto.*; +import com.newyetai.recruit.statistics.service.OrgDailyStatisticService; + +import org.springframework.web.bind.annotation.*; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * 机构日统计信息 + * + * @author guixinman + * @since 1.0.0 2024-05-15 + */ +@Api(tags = "机构日统计信息") +@RestController +@RequestMapping("/org_daily_statistic") +public class OrgDailyStatisticController { + + @Autowired + private OrgDailyStatisticService orgDailyStatisticService; + + @PostMapping("/create") + @ApiOperation("机构日统计信息-创建") + public AlitaResult create(@RequestBody OrgDailyStatisticOperatorDTO operatorDTO) { + return AlitaResult.success(orgDailyStatisticService.create(operatorDTO)); + } + + @PutMapping("/modify") + @ApiOperation("机构日统计信息-修改") + public AlitaResult modify(@RequestBody OrgDailyStatisticOperatorDTO operatorDTO) { + return AlitaResult.success(orgDailyStatisticService.modify(operatorDTO)); + } + + @DeleteMapping("{id}") + @ApiOperation("机构日统计信息-删除") + public AlitaResult delete(@PathVariable("id") Long id) { + return AlitaResult.success(orgDailyStatisticService.delete(id)); + } + + @GetMapping("{id}") + @ApiOperation("机构日统计信息-查询单个") + public AlitaResult findById(@PathVariable("id") Long id) { + return AlitaResult.success(orgDailyStatisticService.findById(id)); + } + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/statistics/controller/StatisticsController.java b/src/main/java/com/newyetai/recruit/statistics/controller/StatisticsController.java new file mode 100644 index 0000000..abc5fd1 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/statistics/controller/StatisticsController.java @@ -0,0 +1,130 @@ +package com.newyetai.recruit.statistics.controller; + +import com.newyetai.common.AlitaResult; +import com.newyetai.recruit.position.dto.PositionDTO; +import com.newyetai.recruit.position.dto.PositionPageQueryDTO; +import com.newyetai.recruit.statistics.dto.HomeStatisticsDTO; +import com.newyetai.recruit.statistics.dto.JobSeekerInfoStatisticsDTO; +import com.newyetai.recruit.statistics.dto.OrgRegAndPositionStatisticsDTO; +import com.newyetai.recruit.statistics.dto.PositionMarkStatisticsDTO; +import com.newyetai.recruit.statistics.dto.PositionSupplyDemandStatisticsDTO; +import com.newyetai.recruit.statistics.dto.StatisticQueryDTO; +import com.newyetai.recruit.statistics.dto.StatisticsBaseDTO; +import com.newyetai.recruit.statistics.dto.UserOperationStatisticsDTO; +import com.newyetai.recruit.statistics.service.StatisticsService; +import com.newyetai.tkmybatis.pojo.Page; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +import io.swagger.annotations.ApiOperation; + +/** + * @description: + * @author: guixinman + * @create: 2024-05-13 15:55 + **/ +@RequestMapping("/statistics") +@RestController +public class StatisticsController { + + @Autowired + private StatisticsService statisticsService; + + /** + * 统计数据 + */ + @GetMapping("/getHomeStatistics") + public AlitaResult getHomeStatistics(){ + return AlitaResult.success(statisticsService.getHomeStatistics()); + } + + /** + * 求职者情况 + */ + @GetMapping("/getJobSeekerInfo") + public AlitaResult getJobSeekerInfo(){ + return AlitaResult.success(statisticsService.getJobSeekerInfo()); + } + + + /** + * 岗位供需 + */ + @GetMapping("/getPositionSupplyDemand") + public AlitaResult getPositionSupplyDemand(@RequestParam(required = false,value = "recruitPositionType") String recruitPositionType){ + return AlitaResult.success(statisticsService.getPositionSupplyDemand(recruitPositionType)); + } + + /** + * 招聘过程 + */ + @GetMapping("/getPositionRegistration") + public AlitaResult> getPositionRegistration(){ + return AlitaResult.success(statisticsService.getPositionRegistration()); + } + + /** + * 企业入驻与岗位发布 创建 + */ + @PostMapping("/saveOrgRegAndPosition") + public AlitaResult saveOrgRegAndPosition(@RequestParam("date") String date){ + statisticsService.saveOrgRegAndPosition(date); + return AlitaResult.success(); + } + + /** + * 企业入驻与岗位发布 + */ + @GetMapping("/getOrgRegAndPosition") + public AlitaResult> getOrgRegAndPosition(@Validated StatisticQueryDTO queryDTO){ + return AlitaResult.success(statisticsService.getOrgRegAndPosition(queryDTO)); + } + + /** + * 招聘岗位浏览、收藏、报名情况 创建 + */ + @PostMapping("/saveUserOperationStatisticsDTO") + public AlitaResult saveUserOperationStatisticsDTO(@RequestParam("date") String date){ + statisticsService.saveUserOperationStatisticsDTO(date); + return AlitaResult.success(); + } + + /** + * 招聘岗位浏览、收藏、报名情况 + */ + @GetMapping("/userOperationStatisticsDTO") + public AlitaResult> userOperationStatisticsDTO(@Validated StatisticQueryDTO queryDTO){ + return AlitaResult.success(statisticsService.userOperationStatisticsDTO(queryDTO)); + } + + /** + * 招聘岗位浏览量词云 查询 + */ + @GetMapping("/getWordCloud") + public AlitaResult> getWordCloud(){ + return AlitaResult.success(statisticsService.getWordCloud()); + } + + /** + * 岗位供需地理位置分析 查询 + */ + @GetMapping("/getPositionMark") + public AlitaResult> getPositionMark(){ + return AlitaResult.success(statisticsService.getPositionMark()); + } + + @GetMapping("/position/page") + @ApiOperation("岗位信息表;岗位信息表-分页查询") + public AlitaResult> positionPage(PositionPageQueryDTO queryDTO) { + statisticsService.positionPage(queryDTO); + return AlitaResult.success(queryDTO.getPageResult()); + } +} diff --git a/src/main/java/com/newyetai/recruit/statistics/convert/OrgDailyStatisticConvert.java b/src/main/java/com/newyetai/recruit/statistics/convert/OrgDailyStatisticConvert.java new file mode 100644 index 0000000..8fdb3dd --- /dev/null +++ b/src/main/java/com/newyetai/recruit/statistics/convert/OrgDailyStatisticConvert.java @@ -0,0 +1,28 @@ +package com.newyetai.recruit.statistics.convert; + +import com.newyetai.recruit.statistics.entity.OrgDailyStatistic; +import com.newyetai.recruit.statistics.dto.OrgDailyStatisticDTO; +import com.newyetai.recruit.statistics.dto.OrgDailyStatisticOperatorDTO; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 机构日统计信息 + * + * @author guixinman + * @since 1.0.0 2024-05-15 + */ +@Mapper +public interface OrgDailyStatisticConvert { + OrgDailyStatisticConvert INSTANCE = Mappers.getMapper(OrgDailyStatisticConvert.class); + + OrgDailyStatistic convert(OrgDailyStatisticDTO dto); + + OrgDailyStatisticDTO convert(OrgDailyStatistic entity); + + OrgDailyStatistic convert(OrgDailyStatisticOperatorDTO dto); + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/statistics/dao/OrgDailyStatisticMapper.java b/src/main/java/com/newyetai/recruit/statistics/dao/OrgDailyStatisticMapper.java new file mode 100644 index 0000000..b0e058d --- /dev/null +++ b/src/main/java/com/newyetai/recruit/statistics/dao/OrgDailyStatisticMapper.java @@ -0,0 +1,26 @@ +package com.newyetai.recruit.statistics.dao; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.recruit.statistics.entity.OrgDailyStatistic; +import com.newyetai.recruit.statistics.dto.OrgDailyStatisticDTO; +import com.newyetai.recruit.statistics.dto.OrgDailyStatisticQueryDTO; +import com.newyetai.recruit.statistics.dto.OrgDailyStatisticPageQueryDTO; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 机构日统计信息 + * + * @author guixinman + * @since 1.0.0 2024-05-15 + */ +@Mapper +public interface OrgDailyStatisticMapper extends MyMapper { + + List page(@Param("param") OrgDailyStatisticPageQueryDTO queryDTO); + + List list(@Param("param") OrgDailyStatisticQueryDTO queryDTO); +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/statistics/dao/StatisticsMapper.java b/src/main/java/com/newyetai/recruit/statistics/dao/StatisticsMapper.java new file mode 100644 index 0000000..6f3f893 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/statistics/dao/StatisticsMapper.java @@ -0,0 +1,13 @@ +package com.newyetai.recruit.statistics.dao; + +import com.newyetai.recruit.statistics.dto.StatisticsBaseDTO; + +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +@Mapper +public interface StatisticsMapper { + + List getWordCloud(); +} diff --git a/src/main/java/com/newyetai/recruit/statistics/dto/HomeStatisticsDTO.java b/src/main/java/com/newyetai/recruit/statistics/dto/HomeStatisticsDTO.java new file mode 100644 index 0000000..7d27417 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/statistics/dto/HomeStatisticsDTO.java @@ -0,0 +1,55 @@ +package com.newyetai.recruit.statistics.dto; + +import java.io.Serializable; +import java.math.BigDecimal; + +import lombok.Data; + +/** + * @description: 统计DTO + * @author: guixinman + * @create: 2024-05-13 15:57 + **/ +@Data +public class HomeStatisticsDTO implements Serializable { + + /** + * 入驻企业:平台的企业数量(用工机构+服务机构) + */ + private int orgCount; + + /** + * 入驻企业日环比 (日环比增长率 = (今日 - 昨日) / 昨日 × 100%) + */ + private BigDecimal orgDailyBasis; + + /** + * 招聘岗位:平台开启状态下的岗位数量 + */ + private int positionCount; + + /** + * 招聘岗位日环比 (日环比增长率 = (今日 - 昨日) / 昨日 × 100%) + */ + private BigDecimal positionDailyBasis; + + /** + * 求职者:平台个人用户人数 + */ + private int userCount; + + /** + * 求职者日环比 (日环比增长率 = (今日 - 昨日) / 昨日 × 100%) + */ + private BigDecimal userDailyBasis; + + /** + * 岗位报名:平台招聘记录数量(统计出招聘表中的记录数量) + */ + private int positionRegistrationCount; + + /** + * 岗位报名日环比 (日环比增长率 = (今日 - 昨日) / 昨日 × 100%) + */ + private BigDecimal positionRegistrationDailyBasis; +} diff --git a/src/main/java/com/newyetai/recruit/statistics/dto/JobSeekerInfoStatisticsDTO.java b/src/main/java/com/newyetai/recruit/statistics/dto/JobSeekerInfoStatisticsDTO.java new file mode 100644 index 0000000..a8499a8 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/statistics/dto/JobSeekerInfoStatisticsDTO.java @@ -0,0 +1,33 @@ +package com.newyetai.recruit.statistics.dto; + + + +import java.io.Serializable; +import java.util.List; + + +import lombok.Data; + +/** + * @description: 求职者情况DTO + * @author: guixinman + * @create: 2024-05-14 10:34 + **/ +@Data +public class JobSeekerInfoStatisticsDTO implements Serializable { + + /** + * 性别 + */ + private List genders; + + /** + * 年龄 + */ + private List ages; + + /** + * 学历 + */ + private List educations; +} diff --git a/src/main/java/com/newyetai/recruit/statistics/dto/OrgDailyStatisticDTO.java b/src/main/java/com/newyetai/recruit/statistics/dto/OrgDailyStatisticDTO.java new file mode 100644 index 0000000..ca83733 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/statistics/dto/OrgDailyStatisticDTO.java @@ -0,0 +1,45 @@ +package com.newyetai.recruit.statistics.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.newyetai.common.dto.BaseDTO; + +import org.springframework.format.annotation.DateTimeFormat; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.SuperBuilder; + +import java.util.Date; + +/** + * 机构日统计信息 + * + * @author guixinman + * @since 1.0.0 2024-05-15 + */ +@ApiModel("机构日统计信息") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class OrgDailyStatisticDTO extends BaseDTO { + private static final long serialVersionUID = 1L; + + @ApiModelProperty("机构id") + private Long orgId; + + @ApiModelProperty("业务类型") + private String bizType; + + @ApiModelProperty("业务时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date bizDate; + + @ApiModelProperty("数量") + private Integer count; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/statistics/dto/OrgDailyStatisticOperatorDTO.java b/src/main/java/com/newyetai/recruit/statistics/dto/OrgDailyStatisticOperatorDTO.java new file mode 100644 index 0000000..daabb64 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/statistics/dto/OrgDailyStatisticOperatorDTO.java @@ -0,0 +1,53 @@ +package com.newyetai.recruit.statistics.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.format.annotation.DateTimeFormat; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +import java.util.Date; + +/** + * 机构日统计信息 + * + * @author guixinman + * @since 1.0.0 2024-05-15 + */ +@ApiModel("机构日统计信息") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class OrgDailyStatisticOperatorDTO implements Serializable { + private static final long serialVersionUID = 1L; + + private Long id; + + @ApiModelProperty("机构id") + private Long orgId; + + @ApiModelProperty("业务类型") + private String bizType; + + @ApiModelProperty("业务时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date bizDate; + + @ApiModelProperty("数量") + private Integer count; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/statistics/dto/OrgDailyStatisticPageQueryDTO.java b/src/main/java/com/newyetai/recruit/statistics/dto/OrgDailyStatisticPageQueryDTO.java new file mode 100644 index 0000000..f2dbb0a --- /dev/null +++ b/src/main/java/com/newyetai/recruit/statistics/dto/OrgDailyStatisticPageQueryDTO.java @@ -0,0 +1,85 @@ +package com.newyetai.recruit.statistics.dto; + +import com.newyetai.common.dto.PageQueryDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import java.io.Serializable; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.format.annotation.DateTimeFormat; + + +import java.util.Date; +import java.util.List; + +/** + * 机构日统计信息 + * + * @author guixinman + * @since 1.0.0 2024-05-15 + */ + +@ApiModel("机构日统计信息") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class OrgDailyStatisticPageQueryDTO extends PageQueryDTO { + private static final long serialVersionUID = 1L; + + private Long id; + + @ApiModelProperty("机构id") + private Long orgId; + + @ApiModelProperty("业务类型") + private String bizType; + + private List bizTypes; + + @ApiModelProperty("业务时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date bizDate; + + + @ApiModelProperty("业务时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date bizDateStart; + + @ApiModelProperty("业务时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date bizDateEnd; + + @ApiModelProperty("数量") + private Integer count; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("更新时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeStart; + + @ApiModelProperty("更新时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeEnd; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/statistics/dto/OrgDailyStatisticQueryDTO.java b/src/main/java/com/newyetai/recruit/statistics/dto/OrgDailyStatisticQueryDTO.java new file mode 100644 index 0000000..0c9b4b9 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/statistics/dto/OrgDailyStatisticQueryDTO.java @@ -0,0 +1,85 @@ +package com.newyetai.recruit.statistics.dto; + +import com.newyetai.common.dto.BaseDTO; + +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; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; +import java.util.List; +import java.util.Set; + +/** + * 机构日统计信息 + * + * @author guixinman + * @since 1.0.0 2024-05-15 + */ +@ApiModel("机构日统计信息") +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class OrgDailyStatisticQueryDTO implements Serializable { + private static final long serialVersionUID = 1L; + + private Long id; + + @ApiModelProperty("机构id") + private Long orgId; + + @ApiModelProperty("业务类型") + private String bizType; + + private List bizTypes; + + @ApiModelProperty("业务时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date bizDate; + + @ApiModelProperty("业务时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date bizDateStart; + + @ApiModelProperty("业务时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date bizDateEnd; + + @ApiModelProperty("数量") + private Integer count; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("更新时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeStart; + + @ApiModelProperty("更新时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeEnd; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/statistics/dto/OrgRegAndPositionStatisticsDTO.java b/src/main/java/com/newyetai/recruit/statistics/dto/OrgRegAndPositionStatisticsDTO.java new file mode 100644 index 0000000..048e18b --- /dev/null +++ b/src/main/java/com/newyetai/recruit/statistics/dto/OrgRegAndPositionStatisticsDTO.java @@ -0,0 +1,27 @@ +package com.newyetai.recruit.statistics.dto; + +import java.io.Serializable; + +import lombok.Data; + +/** + * @description: 企业入驻与岗位发布 + * @author: guixinman + * @create: 2024-05-15 14:53 + **/ +@Data +public class OrgRegAndPositionStatisticsDTO implements Serializable { + + private String name; + + /** + * 入驻企业(用工机构+服务机构) + */ + private long orgCount; + + /** + * 岗位发布数量 + */ + private long positionCount; + +} diff --git a/src/main/java/com/newyetai/recruit/statistics/dto/PositionMarkStatisticsDTO.java b/src/main/java/com/newyetai/recruit/statistics/dto/PositionMarkStatisticsDTO.java new file mode 100644 index 0000000..3667eb9 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/statistics/dto/PositionMarkStatisticsDTO.java @@ -0,0 +1,29 @@ +package com.newyetai.recruit.statistics.dto; + +import java.io.Serializable; + +import lombok.Data; + +/** + * @description: 岗位供需地理位置分析DTO + * @author: guixinman + * @create: 2024-05-22 17:57 + **/ +@Data +public class PositionMarkStatisticsDTO implements Serializable { + + /** + * 城市编码 + */ + private String areaCode; + + /** + * 求职者期望数量 + */ + private long jobSeekerCount; + + /** + * 岗位数量 + */ + private long positionCount; +} diff --git a/src/main/java/com/newyetai/recruit/statistics/dto/PositionSupplyDemandStatisticsDTO.java b/src/main/java/com/newyetai/recruit/statistics/dto/PositionSupplyDemandStatisticsDTO.java new file mode 100644 index 0000000..ef6fed4 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/statistics/dto/PositionSupplyDemandStatisticsDTO.java @@ -0,0 +1,33 @@ +package com.newyetai.recruit.statistics.dto; + +import java.io.Serializable; +import java.util.List; + +import lombok.Data; + +/** + * @description: 岗位供需DTO + * @author: guixinman + * @create: 2024-05-14 14:06 + **/ +@Data +public class PositionSupplyDemandStatisticsDTO implements Serializable { + + private List positionSupplyDemands; + + @Data + public static class PositionSupplyDemandInfoDTO { + + private String name; + + /** + * 求职期望数量 + */ + private long jobExpectValue; + + /** + * 在招岗位类型数量 + */ + private long positionValue; + } +} diff --git a/src/main/java/com/newyetai/recruit/statistics/dto/StatisticQueryDTO.java b/src/main/java/com/newyetai/recruit/statistics/dto/StatisticQueryDTO.java new file mode 100644 index 0000000..11eb199 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/statistics/dto/StatisticQueryDTO.java @@ -0,0 +1,37 @@ +package com.newyetai.recruit.statistics.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.format.annotation.DateTimeFormat; + +import java.io.Serializable; +import java.util.Date; + +import javax.validation.constraints.NotNull; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author guixinman + * @since 1.0.0 2024-05-15 + */ +@Data +public class StatisticQueryDTO implements Serializable { + + /** + * 1.日 2.月 3年 + */ + @NotNull(message = "类型不能为空") + private Integer type; + + @NotNull(message = "请传入时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date bizDateStart; + + @NotNull(message = "请传入时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date bizDateEnd; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/statistics/dto/StatisticsBaseDTO.java b/src/main/java/com/newyetai/recruit/statistics/dto/StatisticsBaseDTO.java new file mode 100644 index 0000000..584c121 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/statistics/dto/StatisticsBaseDTO.java @@ -0,0 +1,18 @@ +package com.newyetai.recruit.statistics.dto; + +import java.io.Serializable; + +import lombok.Data; + +/** + * @description: 统计基础DTO + * @author: guixinman + * @create: 2024-05-14 16:18 + **/ +@Data +public class StatisticsBaseDTO implements Serializable { + + private String name; + + private long valueCount; +} diff --git a/src/main/java/com/newyetai/recruit/statistics/dto/UserOperationStatisticsDTO.java b/src/main/java/com/newyetai/recruit/statistics/dto/UserOperationStatisticsDTO.java new file mode 100644 index 0000000..c48044b --- /dev/null +++ b/src/main/java/com/newyetai/recruit/statistics/dto/UserOperationStatisticsDTO.java @@ -0,0 +1,36 @@ +package com.newyetai.recruit.statistics.dto; + +import java.io.Serializable; + +import lombok.Data; + +/** + * @description: 用户岗位浏览收藏报名DTO + * @author: guixinman + * @create: 2024-05-15 17:14 + **/ +@Data +public class UserOperationStatisticsDTO implements Serializable { + + /** + * 名称 + */ + private String name; + + /** + * 用户浏览 + */ + private long userPositionBrowseRecordCount; + + /** + * 用户收藏 + */ + private long userCollectionsCount; + + /** + * 岗位报名 + */ + private long positionRegistrationCount; + + +} diff --git a/src/main/java/com/newyetai/recruit/statistics/entity/OrgDailyStatistic.java b/src/main/java/com/newyetai/recruit/statistics/entity/OrgDailyStatistic.java new file mode 100644 index 0000000..06d6c66 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/statistics/entity/OrgDailyStatistic.java @@ -0,0 +1,43 @@ +package com.newyetai.recruit.statistics.entity; + +import lombok.*; + +import com.baomidou.mybatisplus.annotation.*; + +import java.util.Date; + +import com.newyetai.common.entity.BaseEntity; + +/** + * 机构日统计信息 + * + * @author guixinman + * @since 1.0.0 2024-05-15 + */ +@TableName(value = "uc_org_daily_statistic") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class OrgDailyStatistic extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * 机构id + */ + private Long orgId; + /** + * 业务类型 + */ + private String bizType; + /** + * 业务时间 + */ + private Date bizDate; + /** + * 数量 + */ + private Integer count; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/statistics/enums/OrgDailyStatisticTypeEnum.java b/src/main/java/com/newyetai/recruit/statistics/enums/OrgDailyStatisticTypeEnum.java new file mode 100644 index 0000000..3954095 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/statistics/enums/OrgDailyStatisticTypeEnum.java @@ -0,0 +1,30 @@ +package com.newyetai.recruit.statistics.enums; + +public enum OrgDailyStatisticTypeEnum { + ORG("1", "机构"), + POSITION("2", "岗位"), + USER_POSITION_BROWSE_RECORD("3","浏览"), + USER_COLLECTIONS("4","收藏"), + POSITION_REGISTRATION("5","报名"), + ; + + private String type; + /** + * 类型描述 + */ + private String desc; + + + OrgDailyStatisticTypeEnum(String type, String desc) { + this.type = type; + this.desc = desc; + } + + public String getType() { + return type; + } + + public String getDesc() { + return desc; + } +} diff --git a/src/main/java/com/newyetai/recruit/statistics/job/StatisticsJob.java b/src/main/java/com/newyetai/recruit/statistics/job/StatisticsJob.java new file mode 100644 index 0000000..9cc42df --- /dev/null +++ b/src/main/java/com/newyetai/recruit/statistics/job/StatisticsJob.java @@ -0,0 +1,49 @@ +package com.newyetai.recruit.statistics.job; + +import com.newyetai.common.annotation.AlitaStopWatch; +import com.newyetai.recruit.statistics.service.StatisticsService; +import com.newyetai.security.util.MockUtils; +import com.newyetai.usercenter.common.constant.XxlJobHandlerConstants; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.util.Date; +import java.util.List; + +import cn.hutool.core.date.DateUtil; +import lombok.extern.slf4j.Slf4j; + +/** + * @description: + * @author: guixinman + * @create: 2024-05-16 15:42 + **/ +@Slf4j +@Component +public class StatisticsJob { + + @Autowired + private StatisticsService statisticsService; + + @Scheduled(cron = "01 10 00 * * ?") + public void statistics() { + String date = DateUtil.format(DateUtil.yesterday(), "yyyy-MM-dd"); + log.info("统计 ======开始"); + MockUtils.mockPlatUser(); + try { + statisticsService.saveOrgRegAndPosition(date); + } catch (Exception e) { + log.error(e.getMessage()); + } + try { + statisticsService.saveUserOperationStatisticsDTO(date); + } catch (Exception e) { + log.error(e.getMessage()); + } + log.info("统计 ======结束"); + + } +} diff --git a/src/main/java/com/newyetai/recruit/statistics/mapper/OrgDailyStatisticMapper.xml b/src/main/java/com/newyetai/recruit/statistics/mapper/OrgDailyStatisticMapper.xml new file mode 100644 index 0000000..63f9f85 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/statistics/mapper/OrgDailyStatisticMapper.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + FROM + uc_org_daily_statistic t + WHERE t.deleted = 0 + + AND t.id = #{param.id} + + + AND t.org_id = #{param.orgId} + + + AND t.biz_type = #{param.bizType} + + + AND t.biz_type IN + + #{item} + + + + AND t.biz_date = #{param.bizDate} + + + AND t.biz_date >= #{param.bizDateStart} + + + AND t.biz_date <= #{param.bizDateEnd} + + + AND t.count = #{param.count} + + + AND t.create_time >= #{param.createTimeStart} + + + AND t.create_time <= #{param.createTimeEnd} + + + AND t.update_time >= #{param.updateTimeStart} + + + AND t.update_time <= #{param.updateTimeEnd} + + ORDER BY t.id DESC + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/statistics/mapper/StatisticMapper.xml b/src/main/java/com/newyetai/recruit/statistics/mapper/StatisticMapper.xml new file mode 100644 index 0000000..cf4a5f5 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/statistics/mapper/StatisticMapper.xml @@ -0,0 +1,30 @@ + + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/statistics/service/OrgDailyStatisticService.java b/src/main/java/com/newyetai/recruit/statistics/service/OrgDailyStatisticService.java new file mode 100644 index 0000000..b68a14a --- /dev/null +++ b/src/main/java/com/newyetai/recruit/statistics/service/OrgDailyStatisticService.java @@ -0,0 +1,68 @@ +package com.newyetai.recruit.statistics.service; + +import org.springframework.validation.annotation.Validated; + +import javax.validation.Valid; +import javax.validation.groups.Default; + +import java.util.List; + +import com.newyetai.recruit.statistics.dto.*; + +/** + * 机构日统计信息 + * + * @author guixinman + * @since 1.0.0 2024-05-15 + */ +@Validated(Default.class) +public interface OrgDailyStatisticService { + + /** + * 机构日统计信息 - 创建 + * + * @param operatorDto 操作dto + * @return {@link OrgDailyStatisticDTO} + */ + OrgDailyStatisticDTO create(@Valid OrgDailyStatisticOperatorDTO operatorDto); + + /** + * 机构日统计信息 - 修改 + * + * @param operatorDto 操作dto + * @return {@link OrgDailyStatisticDTO} + */ + OrgDailyStatisticDTO modify(@Valid OrgDailyStatisticOperatorDTO operatorDto); + + /** + * 机构日统计信息 - 删除 + * + * @param id id + * @return {@link OrgDailyStatisticDTO} + */ + OrgDailyStatisticDTO delete(Long id); + + /** + * 机构日统计信息 - 根据ID查询单个 + * + * @param id id + * @return {@link OrgDailyStatisticDTO} + */ + OrgDailyStatisticDTO findById(Long id); + + /** + * 机构日统计信息 - 列表查询 + * + * @param queryDTO 列表查询dto + * @return {@link List}<{@link OrgDailyStatisticDTO}> + */ + List list(OrgDailyStatisticQueryDTO queryDTO); + + /** + * 机构日统计信息 - 分页查询 + * + * @param queryDTO 分页查询dto + * @return {@link OrgDailyStatisticDTO} + */ + List page(OrgDailyStatisticPageQueryDTO queryDTO); +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/statistics/service/StatisticsService.java b/src/main/java/com/newyetai/recruit/statistics/service/StatisticsService.java new file mode 100644 index 0000000..b6b8ff4 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/statistics/service/StatisticsService.java @@ -0,0 +1,69 @@ +package com.newyetai.recruit.statistics.service; + +import com.newyetai.recruit.position.dto.PositionDTO; +import com.newyetai.recruit.position.dto.PositionPageQueryDTO; +import com.newyetai.recruit.statistics.dto.HomeStatisticsDTO; +import com.newyetai.recruit.statistics.dto.JobSeekerInfoStatisticsDTO; +import com.newyetai.recruit.statistics.dto.OrgRegAndPositionStatisticsDTO; +import com.newyetai.recruit.statistics.dto.PositionMarkStatisticsDTO; +import com.newyetai.recruit.statistics.dto.PositionSupplyDemandStatisticsDTO; +import com.newyetai.recruit.statistics.dto.StatisticQueryDTO; +import com.newyetai.recruit.statistics.dto.StatisticsBaseDTO; +import com.newyetai.recruit.statistics.dto.UserOperationStatisticsDTO; + +import java.util.List; + +public interface StatisticsService { + + /** + * 获取 统计数据 + */ + HomeStatisticsDTO getHomeStatistics(); + + /** + * 求职者情况 + */ + JobSeekerInfoStatisticsDTO getJobSeekerInfo(); + + /** + * 岗位供需情况 + */ + PositionSupplyDemandStatisticsDTO getPositionSupplyDemand(String recruitPositionType); + + /** + * 招聘过程 + */ + List getPositionRegistration(); + + /** + * 企业入驻与岗位发布保存 + */ + void saveOrgRegAndPosition(String date); + + /** + * 企业入驻与岗位发布查询 + */ + List getOrgRegAndPosition(StatisticQueryDTO queryDTO); + + /** + * 招聘岗位浏览、收藏、报名情况 保存 + */ + void saveUserOperationStatisticsDTO(String date); + + /** + * 招聘岗位浏览、收藏、报名情况 + */ + List userOperationStatisticsDTO(StatisticQueryDTO queryDTO); + + /** + * 招聘岗位浏览量词云 查询 + */ + List getWordCloud(); + + /** + * 岗位供需地理位置分析 查询 + */ + List getPositionMark(); + + List positionPage(PositionPageQueryDTO queryDTO); +} diff --git a/src/main/java/com/newyetai/recruit/statistics/service/impl/OrgDailyStatisticServiceImpl.java b/src/main/java/com/newyetai/recruit/statistics/service/impl/OrgDailyStatisticServiceImpl.java new file mode 100644 index 0000000..e8928fa --- /dev/null +++ b/src/main/java/com/newyetai/recruit/statistics/service/impl/OrgDailyStatisticServiceImpl.java @@ -0,0 +1,80 @@ +package com.newyetai.recruit.statistics.service.impl; + +import lombok.extern.slf4j.Slf4j; + +import com.newyetai.recruit.statistics.convert.OrgDailyStatisticConvert; +import com.newyetai.recruit.statistics.entity.OrgDailyStatistic; +import com.newyetai.recruit.statistics.dto.*; +import com.newyetai.recruit.statistics.dao.OrgDailyStatisticMapper; +import com.newyetai.recruit.statistics.service.OrgDailyStatisticService; + +import org.springframework.stereotype.Service; + +import com.newyetai.common.util.UserContextHolder; + +import javax.annotation.Resource; + +import java.util.*; + +/** + * 机构日统计信息 + * + * @author guixinman + * @since 1.0.0 2024-05-15 + */ +@Slf4j +@Service +public class OrgDailyStatisticServiceImpl implements OrgDailyStatisticService { + + @Resource + private OrgDailyStatisticMapper orgDailyStatisticMapper; + + @Override + public OrgDailyStatisticDTO create(OrgDailyStatisticOperatorDTO operatorDto) { + OrgDailyStatistic orgDailyStatistic = OrgDailyStatisticConvert.INSTANCE.convert(operatorDto); + orgDailyStatisticMapper.saveEntity(orgDailyStatistic); + return OrgDailyStatisticConvert.INSTANCE.convert(orgDailyStatistic); + } + + @Override + public OrgDailyStatisticDTO modify(OrgDailyStatisticOperatorDTO operatorDto) { + OrgDailyStatisticDTO orgDailyStatisticDto = this.findById(operatorDto.getId()); + if (Objects.isNull(orgDailyStatisticDto)) { + return null; + } + OrgDailyStatistic orgDailyStatistic = OrgDailyStatisticConvert.INSTANCE.convert(operatorDto); + orgDailyStatisticMapper.updateEntitySelective(orgDailyStatistic); + return this.findById(operatorDto.getId()); + } + + @Override + public OrgDailyStatisticDTO delete(Long id) { + OrgDailyStatisticDTO orgDailyStatisticDto = this.findById(id); + if (Objects.isNull(orgDailyStatisticDto)) { + return null; + } + OrgDailyStatistic orgDailyStatistic = OrgDailyStatistic.builder().build(); + orgDailyStatistic.setId(id); + orgDailyStatisticMapper.deleteEntity(orgDailyStatistic, UserContextHolder.getLoginUserId()); + return orgDailyStatisticDto; + } + + @Override + public OrgDailyStatisticDTO findById(Long id) { + OrgDailyStatistic orgDailyStatistic = orgDailyStatisticMapper.getById(id); + if (Objects.isNull(orgDailyStatistic)) { + return null; + } + return OrgDailyStatisticConvert.INSTANCE.convert(orgDailyStatistic); + } + + @Override + public List list(OrgDailyStatisticQueryDTO queryDTO) { + return orgDailyStatisticMapper.list(queryDTO); + } + + @Override + public List page(OrgDailyStatisticPageQueryDTO queryDTO) { + return orgDailyStatisticMapper.page(queryDTO); + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/statistics/service/impl/StatisticsServiceImpl.java b/src/main/java/com/newyetai/recruit/statistics/service/impl/StatisticsServiceImpl.java new file mode 100644 index 0000000..226d0ba --- /dev/null +++ b/src/main/java/com/newyetai/recruit/statistics/service/impl/StatisticsServiceImpl.java @@ -0,0 +1,618 @@ +package com.newyetai.recruit.statistics.service.impl; + + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.util.DateUtils; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.component.dict.dto.DictDetailDTO; +import com.newyetai.component.dict.util.DictUtils; +import com.newyetai.recruit.position.dao.PositionMapper; +import com.newyetai.recruit.position.dao.PositionRegistrationMapper; +import com.newyetai.recruit.position.dao.PositionTypeMapper; +import com.newyetai.recruit.position.dto.PositionDTO; +import com.newyetai.recruit.position.dto.PositionPageQueryDTO; +import com.newyetai.recruit.position.entity.Position; +import com.newyetai.recruit.position.entity.PositionRegistration; +import com.newyetai.recruit.position.entity.PositionType; +import com.newyetai.recruit.position.enums.PositionRegistrationStatusEnum; +import com.newyetai.recruit.position.enums.PositionStatusEnum; +import com.newyetai.recruit.statistics.dao.StatisticsMapper; +import com.newyetai.recruit.statistics.dto.HomeStatisticsDTO; +import com.newyetai.recruit.statistics.dto.JobSeekerInfoStatisticsDTO; +import com.newyetai.recruit.statistics.dto.OrgDailyStatisticDTO; +import com.newyetai.recruit.statistics.dto.OrgDailyStatisticOperatorDTO; +import com.newyetai.recruit.statistics.dto.OrgDailyStatisticQueryDTO; +import com.newyetai.recruit.statistics.dto.OrgRegAndPositionStatisticsDTO; +import com.newyetai.recruit.statistics.dto.PositionMarkStatisticsDTO; +import com.newyetai.recruit.statistics.dto.PositionSupplyDemandStatisticsDTO; +import com.newyetai.recruit.statistics.dto.StatisticQueryDTO; +import com.newyetai.recruit.statistics.dto.StatisticsBaseDTO; +import com.newyetai.recruit.statistics.dto.UserOperationStatisticsDTO; +import com.newyetai.recruit.statistics.enums.OrgDailyStatisticTypeEnum; +import com.newyetai.recruit.statistics.service.OrgDailyStatisticService; +import com.newyetai.recruit.statistics.service.StatisticsService; +import com.newyetai.recruit.user.dao.BrowseRecordMapper; +import com.newyetai.recruit.user.dao.JobExpectMapper; +import com.newyetai.recruit.user.dao.ResumeMapper; +import com.newyetai.recruit.user.dao.UserCollectionMapper; +import com.newyetai.recruit.user.entity.BrowseRecord; +import com.newyetai.recruit.user.entity.JobExpect; +import com.newyetai.recruit.user.entity.Resume; +import com.newyetai.recruit.user.entity.UserCollection; +import com.newyetai.usercenter.enums.OrgTypeEnum; +import com.newyetai.usercenter.org.dao.OrgMapper; +import com.newyetai.usercenter.org.entity.Org; +import com.newyetai.usercenter.user.constant.UserTypeEnum; +import com.newyetai.usercenter.user.dao.UserMapper; +import com.newyetai.usercenter.user.entity.User; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import javax.annotation.Resource; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; + +/** + * @description: 统计数据 + * @author: guixinman + * @create: 2024-05-13 16:10 + **/ +@Service +public class StatisticsServiceImpl implements StatisticsService { + + @Resource + private OrgMapper orgMapper; + + @Resource + private PositionMapper positionMapper; + + @Resource + private UserMapper userMapper; + + @Resource + private PositionRegistrationMapper positionRegistrationMapper; + + @Resource + private ResumeMapper resumeMapper; + + @Resource + private JobExpectMapper jobExpectMapper; + + @Resource + private PositionTypeMapper positionTypeMapper; + + @Autowired + private OrgDailyStatisticService orgDailyStatisticService; + + @Resource + private UserCollectionMapper userCollectionMapper; + + @Resource + private BrowseRecordMapper browseRecordMapper; + + @Resource + private StatisticsMapper statisticsMapper; + + @Override + public HomeStatisticsDTO getHomeStatistics() { + + DateTime yesterday = DateUtil.beginOfDay(DateUtil.yesterday()); + DateTime today = DateUtil.endOfDay(new Date()); + String yesterdayStr = DateUtil.format(yesterday, "yyyy-MM-dd"); + String todayStr = DateUtil.format(today, "yyyy-MM-dd"); + + + // ——入驻企业:平台的企业数量(用工机构+服务机构) + Integer orgCount = orgMapper.selectCount(new LambdaQueryWrapper() + .eq(Org::getDeleted, false) + .in(Org::getType, Arrays.asList(OrgTypeEnum.ORG_TYPE_SIMPLE.getType(), OrgTypeEnum.ORG_TYPE_HR.getType())) + ); + Map orgMap = orgMapper.selectList(new LambdaQueryWrapper() + .eq(Org::getDeleted, false) + .in(Org::getType, Arrays.asList(OrgTypeEnum.ORG_TYPE_SIMPLE.getType(), OrgTypeEnum.ORG_TYPE_HR.getType())) + .between(Org::getCreateTime, yesterday, today) + ).stream().collect(Collectors.groupingBy(org -> DateUtil.format(org.getCreateTime(), "yyyy-MM-dd"), Collectors.counting())); + + // ——招聘岗位:平台开启状态下的岗位数量 + Integer positionCount = positionMapper.selectCount(new LambdaQueryWrapper() + .eq(Position::getDeleted, false) + .eq(Position::getStatus, PositionStatusEnum.OPEN.getStatus()) + ); + Map positionMap = + positionMapper.selectList(new LambdaQueryWrapper() + .eq(Position::getDeleted, false) + .eq(Position::getStatus, PositionStatusEnum.OPEN.getStatus()) + .between(Position::getCreateTime, yesterday, today) + ) + .stream().collect(Collectors.groupingBy(position -> DateUtil.format(position.getCreateTime(), "yyyy-MM-dd"), Collectors.counting())); + + // ——求职者:平台个人用户人数 + Integer userCount = userMapper.selectCount( + new LambdaQueryWrapper() + .eq(User::getDeleted, false) + .eq(User::getType, UserTypeEnum.PERSON.getType()) + ); + Map userMap = + userMapper.selectList(new LambdaQueryWrapper() + .eq(User::getDeleted, false) + .eq(User::getType, UserTypeEnum.PERSON.getType()) + .between(User::getCreateTime, yesterday, today) + ) + .stream().collect(Collectors.groupingBy(user -> DateUtil.format(user.getCreateTime(), "yyyy-MM-dd"), Collectors.counting())); + + // ——岗位报名:平台招聘记录数量(统计出招聘表中的记录数量) + Integer positionRegistrationCount = positionRegistrationMapper.selectCount( + new LambdaQueryWrapper() + .eq(PositionRegistration::getDeleted, false) + ); + Map positionRegistrationMap = + positionRegistrationMapper.selectList(new LambdaQueryWrapper() + .eq(PositionRegistration::getDeleted, false) + .between(PositionRegistration::getCreateTime, yesterday, today) + ) + .stream().collect(Collectors.groupingBy(positionRegistration -> DateUtil.format(positionRegistration.getCreateTime(), "yyyy-MM-dd"), Collectors.counting())); + + HomeStatisticsDTO homeStatisticsDTO = new HomeStatisticsDTO(); + homeStatisticsDTO.setOrgCount(orgCount); + homeStatisticsDTO.setOrgDailyBasis(calculateDailyBasis(orgMap, yesterdayStr, todayStr)); + homeStatisticsDTO.setPositionCount(positionCount); + homeStatisticsDTO.setPositionDailyBasis(calculateDailyBasis(positionMap, yesterdayStr, todayStr)); + homeStatisticsDTO.setUserCount(userCount); + homeStatisticsDTO.setUserDailyBasis(calculateDailyBasis(userMap, yesterdayStr, todayStr)); + homeStatisticsDTO.setPositionRegistrationCount(positionRegistrationCount); + homeStatisticsDTO.setPositionRegistrationDailyBasis(calculateDailyBasis(positionRegistrationMap, yesterdayStr, todayStr)); + return homeStatisticsDTO; + } + + private BigDecimal calculateDailyBasis(Map map, String yesterdayStr, String todayStr) { + if (Objects.isNull(map) || StringUtils.isBlank(yesterdayStr) || StringUtils.isBlank(todayStr)) { + return null; + } + // 日环比增长率 = (今日 - 昨日) / 昨日 × 100% + Long yesterday = Objects.isNull(map.get(yesterdayStr)) ? 0l : map.get(yesterdayStr); + Long today = Objects.isNull(map.get(todayStr)) ? 0l : map.get(todayStr); + BigDecimal yesterdayCount = new BigDecimal(String.valueOf(yesterday)); + BigDecimal todayCount = new BigDecimal(String.valueOf(today)); + if (yesterdayCount.compareTo(BigDecimal.ZERO) == 0) { + return BigDecimal.ZERO; + } + return (todayCount.subtract(yesterdayCount)).divide(yesterdayCount, 2, BigDecimal.ROUND_HALF_UP); + } + + @Override + public JobSeekerInfoStatisticsDTO getJobSeekerInfo() { + //学历:小学、初中、中专/技校、高中、大专、本科、硕士、博士(按实际字典内容进行统计,图例是为了显示效果) + Map> resumeMap = resumeMapper.selectList(new LambdaQueryWrapper() + .eq(Resume::getDeleted, false)) + .stream().filter(resume -> StringUtils.isNotBlank(resume.getEducation())).collect(Collectors.groupingBy(Resume::getEducation)); + List educationList = DictUtils.getCacheTree("education"); + + List educations = new ArrayList<>(); + for (DictDetailDTO dictDetailDTO : educationList) { + int resumes = CollectionUtils.isEmpty(resumeMap.get(dictDetailDTO.getDictDetailCode())) ? 0 : resumeMap.get(dictDetailDTO.getDictDetailCode()).size(); + StatisticsBaseDTO statisticsBaseDTO = new StatisticsBaseDTO(); + statisticsBaseDTO.setName(dictDetailDTO.getDictDetailName()); + statisticsBaseDTO.setValueCount(resumes); + educations.add(statisticsBaseDTO); + } + + //用户性别 年龄 + List users = userMapper.selectList(new LambdaQueryWrapper() + .eq(User::getType, UserTypeEnum.PERSON.getType()) + .eq(User::getDeleted, false) + .ne(User::getCardNo, "") + .isNotNull(User::getCardNo) + ); + Map genderMap = users.stream().filter(user -> Objects.nonNull(user.getGender())).collect(Collectors.groupingBy(User::getGender, Collectors.counting())); + List genders = new ArrayList<>(); + List genderList = DictUtils.getCacheTree("gender"); + for (DictDetailDTO dictDetailDTO : genderList) { + long genderCount = Objects.isNull(genderMap.get(Integer.valueOf(dictDetailDTO.getDictDetailCode()))) ? 0 : genderMap.get(Integer.valueOf(dictDetailDTO.getDictDetailCode())); + StatisticsBaseDTO statisticsBaseDTO = new StatisticsBaseDTO(); + statisticsBaseDTO.setName(dictDetailDTO.getDictDetailName()); + statisticsBaseDTO.setValueCount(genderCount); + genders.add(statisticsBaseDTO); + } + + Map birthdayResultMap = new HashMap<>(); + birthdayResultMap.put("18-35岁", 0l); + birthdayResultMap.put("36-55岁", 0l); + birthdayResultMap.put("56岁以上", 0l); + + Map birthdayMap = users.stream().filter(user -> Objects.nonNull(user.getBirthday())).collect(Collectors.groupingBy(User::getBirthday, Collectors.counting())); + birthdayMap.forEach((k, v) -> { + + int age = DateUtil.ageOfNow(k); + if (age >= 18 && age <= 35) { + birthdayResultMap.put("18-35岁", birthdayResultMap.get("18-35岁") + v); + } else if (age >= 36 && age <= 55) { + birthdayResultMap.put("36-55岁", birthdayResultMap.get("36-55岁") + v); + } else if (age >= 56) { + birthdayResultMap.put("56岁以上", birthdayResultMap.get("56岁以上") + v); + } + }); + + List ages = new ArrayList<>(); + birthdayResultMap.forEach((k, v) -> { + StatisticsBaseDTO statisticsBaseDTO = new StatisticsBaseDTO(); + statisticsBaseDTO.setName(k); + statisticsBaseDTO.setValueCount(v); + ages.add(statisticsBaseDTO); + }); + + JobSeekerInfoStatisticsDTO jobSeekerInfoStatisticsDTO = new JobSeekerInfoStatisticsDTO(); + jobSeekerInfoStatisticsDTO.setEducations(educations); + jobSeekerInfoStatisticsDTO.setGenders(genders); + jobSeekerInfoStatisticsDTO.setAges(ages); + + return jobSeekerInfoStatisticsDTO; + } + + @Override + public PositionSupplyDemandStatisticsDTO getPositionSupplyDemand(String recruitPositionType) { + //期望岗位类型分组求数量 + Map jobExpectMap = jobExpectMapper.positionTypeCodeGroupMap(recruitPositionType) + .stream().collect(Collectors.toMap(StatisticsBaseDTO::getName, v -> v.getValueCount(), (v1, v2) -> v2)); + //岗位类型分组求数量 + Map positionMap = positionMapper.positionTypeGroupMap(recruitPositionType).stream().collect(Collectors.toMap(StatisticsBaseDTO::getName, v -> v.getValueCount(), (v1, v2) -> v2)); + + List positionTypes = positionTypeMapper.selectList( + new LambdaQueryWrapper() + .eq(PositionType::getDeleted, false) + .eq(StringUtils.isNotBlank(recruitPositionType),PositionType::getRecruitPositionType,recruitPositionType) + ); + Map positionTypeMap = new LinkedHashMap<>(); + for (PositionType positionType : positionTypes) { + positionTypeMap.putIfAbsent(positionType.getFullCode().split("@")[0], positionType.getFullName().split("@")[0]); + } + + List positionSupplyDemands = new ArrayList<>(); + + positionTypeMap.forEach((code, name) -> { + PositionSupplyDemandStatisticsDTO.PositionSupplyDemandInfoDTO positionSupplyDemandInfoDTO = new PositionSupplyDemandStatisticsDTO.PositionSupplyDemandInfoDTO(); + positionSupplyDemandInfoDTO.setName(name); + positionSupplyDemandInfoDTO.setJobExpectValue(Objects.isNull(jobExpectMap.get(code)) ? 0l : jobExpectMap.get(code)); + positionSupplyDemandInfoDTO.setPositionValue(Objects.isNull(positionMap.get(code)) ? 0l : positionMap.get(code)); + positionSupplyDemands.add(positionSupplyDemandInfoDTO); + }); + + PositionSupplyDemandStatisticsDTO positionSupplyDemandStatisticsDTO = new PositionSupplyDemandStatisticsDTO(); + positionSupplyDemandStatisticsDTO.setPositionSupplyDemands(positionSupplyDemands); + return positionSupplyDemandStatisticsDTO; + } + + @Override + public List getPositionRegistration() { + List list = new ArrayList<>(); + + List statusList = Arrays.asList(PositionRegistrationStatusEnum.ALREADY_REGISTERED.getStatus() + , PositionRegistrationStatusEnum.WAIT_FOR_AN_INTERVIEW.getStatus() + , PositionRegistrationStatusEnum.TO_BE_HIRED.getStatus() + , PositionRegistrationStatusEnum.ON_THE_JOB.getStatus() + , PositionRegistrationStatusEnum.RESIGNED.getStatus() + ); + Map positionRegistrationMap = positionRegistrationMapper.selectList( + new LambdaQueryWrapper() + .eq(PositionRegistration::getDeleted, false) + .in(PositionRegistration::getStatus, statusList) + ).stream().collect(Collectors.groupingBy(PositionRegistration::getStatus, Collectors.counting())); + + long alreadyRegisteredCount = Objects.isNull(positionRegistrationMap.get(statusList.get(0))) ? 0l : positionRegistrationMap.get(statusList.get(0)); + long waitForAnInterviewCount = Objects.isNull(positionRegistrationMap.get(statusList.get(1))) ? 0l : positionRegistrationMap.get(statusList.get(1)); + long toBeHiredCount = Objects.isNull(positionRegistrationMap.get(statusList.get(2))) ? 0l : positionRegistrationMap.get(statusList.get(2)); + long onTheJobCount = Objects.isNull(positionRegistrationMap.get(statusList.get(3))) ? 0l : positionRegistrationMap.get(statusList.get(3)); + long resignedCount = Objects.isNull(positionRegistrationMap.get(statusList.get(4))) ? 0l : positionRegistrationMap.get(statusList.get(4)); + + for (int i = 0; i < statusList.size(); i++) { + + StatisticsBaseDTO statisticsBaseDTO = new StatisticsBaseDTO(); + statisticsBaseDTO.setName(DictUtils.getCodeNameMap("position_registration_status").get(statusList.get(i))); + + if (i == 0) { + statisticsBaseDTO.setValueCount(alreadyRegisteredCount + waitForAnInterviewCount + toBeHiredCount + onTheJobCount + resignedCount); + } else if (i == 1) { + statisticsBaseDTO.setValueCount(waitForAnInterviewCount + toBeHiredCount + onTheJobCount + resignedCount); + } else if (i == 2) { + statisticsBaseDTO.setValueCount(toBeHiredCount + onTheJobCount + resignedCount); + } else if (i == 3) { + statisticsBaseDTO.setValueCount(onTheJobCount + resignedCount); + } else if (i == 4) { + statisticsBaseDTO.setValueCount(resignedCount); + } + + list.add(statisticsBaseDTO); + } + + + return list; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void saveOrgRegAndPosition(String date) { + if (StringUtils.isBlank(date)) { + return; + } + DateTime createTimeStart = DateUtil.beginOfDay(DateUtil.parseDate(date)); + DateTime createTimeEnd = DateUtil.endOfDay(DateUtil.parseDate(date)); + + // ——入驻企业:平台的企业数量(用工机构+服务机构) + List orgs = orgMapper.selectList(new LambdaQueryWrapper() + .eq(Org::getDeleted, false) + .in(Org::getType, Arrays.asList(OrgTypeEnum.ORG_TYPE_SIMPLE.getType(), OrgTypeEnum.ORG_TYPE_HR.getType())) + .between(Org::getCreateTime, createTimeStart, createTimeEnd)); + + List orgList = orgDailyStatisticService.list(OrgDailyStatisticQueryDTO.builder() + .orgId(CommonConstants.PLATFORM_ORG_ID) + .bizType(OrgDailyStatisticTypeEnum.ORG.getType()) + .bizDate(DateUtil.parseDate(date)) + .build()); + OrgDailyStatisticOperatorDTO orgOperatorDTO = new OrgDailyStatisticOperatorDTO(); + orgOperatorDTO.setOrgId(CommonConstants.PLATFORM_ORG_ID); + orgOperatorDTO.setBizType(OrgDailyStatisticTypeEnum.ORG.getType()); + orgOperatorDTO.setBizDate(DateUtil.parseDate(date)); + orgOperatorDTO.setCount(orgs.size()); + if (CollectionUtils.isEmpty(orgList)) { + orgDailyStatisticService.create(orgOperatorDTO); + } else { + orgOperatorDTO.setId(orgList.get(0).getId()); + orgDailyStatisticService.modify(orgOperatorDTO); + } + + // ——发布岗位 + List positions = positionMapper.selectList(new LambdaQueryWrapper() + .eq(Position::getDeleted, false) + .between(Position::getCreateTime, createTimeStart, createTimeEnd) + ); + List positionList = orgDailyStatisticService.list(OrgDailyStatisticQueryDTO.builder() + .orgId(CommonConstants.PLATFORM_ORG_ID) + .bizType(OrgDailyStatisticTypeEnum.POSITION.getType()) + .bizDate(DateUtil.parseDate(date)) + .build()); + OrgDailyStatisticOperatorDTO positionOperatorDTO = new OrgDailyStatisticOperatorDTO(); + positionOperatorDTO.setOrgId(CommonConstants.PLATFORM_ORG_ID); + positionOperatorDTO.setBizType(OrgDailyStatisticTypeEnum.POSITION.getType()); + positionOperatorDTO.setBizDate(DateUtil.parseDate(date)); + positionOperatorDTO.setCount(positions.size()); + if (CollectionUtils.isEmpty(positionList)) { + orgDailyStatisticService.create(positionOperatorDTO); + } else { + positionOperatorDTO.setId(positionList.get(0).getId()); + orgDailyStatisticService.modify(positionOperatorDTO); + } + + + } + + @Override + public List getOrgRegAndPosition(StatisticQueryDTO queryDTO) { + List orgDailyStatisticDTOList = orgDailyStatisticService.list(OrgDailyStatisticQueryDTO.builder() + .orgId(CommonConstants.PLATFORM_ORG_ID) + .bizTypes(Arrays.asList(OrgDailyStatisticTypeEnum.POSITION.getType(), OrgDailyStatisticTypeEnum.ORG.getType())) + .bizDateStart(queryDTO.getBizDateStart()) + .bizDateEnd(queryDTO.getBizDateEnd()) + .build()); + + Map orgMap = new HashMap<>(); + Map positionMap = new HashMap<>(); + + List list = new ArrayList<>(); + List betweenDate = new ArrayList<>(); + + if (queryDTO.getType() == 1) { + orgMap = orgDailyStatisticDTOList.stream().filter(orgDailyStatisticDTO -> orgDailyStatisticDTO.getBizType().equals(OrgDailyStatisticTypeEnum.ORG.getType())).collect(Collectors.groupingBy(orgDailyStatistic -> DateUtil.format(orgDailyStatistic.getBizDate(), "yyyy-MM-dd"), Collectors.summingInt(OrgDailyStatisticDTO::getCount))); + positionMap = orgDailyStatisticDTOList.stream().filter(orgDailyStatisticDTO -> orgDailyStatisticDTO.getBizType().equals(OrgDailyStatisticTypeEnum.POSITION.getType())).collect(Collectors.groupingBy(orgDailyStatistic -> DateUtil.format(orgDailyStatistic.getBizDate(), "yyyy-MM-dd"), Collectors.summingInt(OrgDailyStatisticDTO::getCount))); + betweenDate = DateUtils.getDateBetween(queryDTO.getBizDateStart(), queryDTO.getBizDateEnd(), DateUtils.YYYY_MM_DD); + + } else if (queryDTO.getType() == 2) { + orgMap = orgDailyStatisticDTOList.stream().filter(orgDailyStatisticDTO -> orgDailyStatisticDTO.getBizType().equals(OrgDailyStatisticTypeEnum.ORG.getType())).collect(Collectors.groupingBy(orgDailyStatistic -> DateUtil.format(orgDailyStatistic.getBizDate(), "yyyy-MM"), Collectors.summingInt(OrgDailyStatisticDTO::getCount))); + positionMap = orgDailyStatisticDTOList.stream().filter(orgDailyStatisticDTO -> orgDailyStatisticDTO.getBizType().equals(OrgDailyStatisticTypeEnum.POSITION.getType())).collect(Collectors.groupingBy(orgDailyStatistic -> DateUtil.format(orgDailyStatistic.getBizDate(), "yyyy-MM"), Collectors.summingInt(OrgDailyStatisticDTO::getCount))); + betweenDate = DateUtils.getDateBetween(queryDTO.getBizDateStart(), queryDTO.getBizDateEnd(), DateUtils.YYYY_MM); + + } else if (queryDTO.getType() == 3) { + orgMap = orgDailyStatisticDTOList.stream().filter(orgDailyStatisticDTO -> orgDailyStatisticDTO.getBizType().equals(OrgDailyStatisticTypeEnum.ORG.getType())).collect(Collectors.groupingBy(orgDailyStatistic -> DateUtil.format(orgDailyStatistic.getBizDate(), "yyyy"), Collectors.summingInt(OrgDailyStatisticDTO::getCount))); + positionMap = orgDailyStatisticDTOList.stream().filter(orgDailyStatisticDTO -> orgDailyStatisticDTO.getBizType().equals(OrgDailyStatisticTypeEnum.POSITION.getType())).collect(Collectors.groupingBy(orgDailyStatistic -> DateUtil.format(orgDailyStatistic.getBizDate(), "yyyy"), Collectors.summingInt(OrgDailyStatisticDTO::getCount))); + betweenDate = DateUtils.getDateBetween(queryDTO.getBizDateStart(), queryDTO.getBizDateEnd(), DateUtils.YYYY); + } + for (String dateStr : betweenDate) { + OrgRegAndPositionStatisticsDTO orgRegAndPositionStatisticsDTO = new OrgRegAndPositionStatisticsDTO(); + orgRegAndPositionStatisticsDTO.setName(dateStr); + orgRegAndPositionStatisticsDTO.setOrgCount(Objects.isNull(orgMap.get(dateStr)) ? 0l : orgMap.get(dateStr)); + orgRegAndPositionStatisticsDTO.setPositionCount(Objects.isNull(positionMap.get(dateStr)) ? 0l : positionMap.get(dateStr)); + list.add(orgRegAndPositionStatisticsDTO); + } + + return list; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void saveUserOperationStatisticsDTO(String date) { + + if (StringUtils.isBlank(date)) { + return; + } + DateTime createTimeStart = DateUtil.beginOfDay(DateUtil.parseDate(date)); + DateTime createTimeEnd = DateUtil.endOfDay(DateUtil.parseDate(date)); + + //浏览 + List browseRecords = browseRecordMapper.selectList( + new LambdaQueryWrapper() + .eq(BrowseRecord::getDeleted, false) + .between(BrowseRecord::getCreateTime, createTimeStart, createTimeEnd) + ); + List browseRecordList = orgDailyStatisticService.list(OrgDailyStatisticQueryDTO.builder() + .orgId(CommonConstants.PLATFORM_ORG_ID) + .bizType(OrgDailyStatisticTypeEnum.USER_POSITION_BROWSE_RECORD.getType()) + .bizDate(DateUtil.parseDate(date)) + .build()); + OrgDailyStatisticOperatorDTO browseRecordOperatorDTO = new OrgDailyStatisticOperatorDTO(); + browseRecordOperatorDTO.setOrgId(CommonConstants.PLATFORM_ORG_ID); + browseRecordOperatorDTO.setBizType(OrgDailyStatisticTypeEnum.USER_POSITION_BROWSE_RECORD.getType()); + browseRecordOperatorDTO.setBizDate(DateUtil.parseDate(date)); + browseRecordOperatorDTO.setCount(browseRecords.size()); + if (CollectionUtils.isEmpty(browseRecordList)) { + orgDailyStatisticService.create(browseRecordOperatorDTO); + } else { + browseRecordOperatorDTO.setId(browseRecordList.get(0).getId()); + orgDailyStatisticService.modify(browseRecordOperatorDTO); + } + + //收藏 + List userCollections = userCollectionMapper.selectList( + new LambdaQueryWrapper() + .eq(UserCollection::getDeleted, false) + .between(UserCollection::getCreateTime, createTimeStart, createTimeEnd) + ); + List userCollectionList = orgDailyStatisticService.list(OrgDailyStatisticQueryDTO.builder() + .orgId(CommonConstants.PLATFORM_ORG_ID) + .bizType(OrgDailyStatisticTypeEnum.USER_COLLECTIONS.getType()) + .bizDate(DateUtil.parseDate(date)) + .build()); + OrgDailyStatisticOperatorDTO userCollectionOperatorDTO = new OrgDailyStatisticOperatorDTO(); + userCollectionOperatorDTO.setOrgId(CommonConstants.PLATFORM_ORG_ID); + userCollectionOperatorDTO.setBizType(OrgDailyStatisticTypeEnum.USER_COLLECTIONS.getType()); + userCollectionOperatorDTO.setBizDate(DateUtil.parseDate(date)); + userCollectionOperatorDTO.setCount(userCollections.size()); + if (CollectionUtils.isEmpty(userCollectionList)) { + orgDailyStatisticService.create(userCollectionOperatorDTO); + } else { + userCollectionOperatorDTO.setId(userCollectionList.get(0).getId()); + orgDailyStatisticService.modify(userCollectionOperatorDTO); + } + + //岗位报名 + List positionRegistrations = positionRegistrationMapper.selectList( + new LambdaQueryWrapper() + .eq(PositionRegistration::getDeleted, false) + .between(PositionRegistration::getCreateTime, createTimeStart, createTimeEnd) + ); + + List positionRegistrationList = orgDailyStatisticService.list(OrgDailyStatisticQueryDTO.builder() + .orgId(CommonConstants.PLATFORM_ORG_ID) + .bizType(OrgDailyStatisticTypeEnum.POSITION_REGISTRATION.getType()) + .bizDate(DateUtil.parseDate(date)) + .build()); + OrgDailyStatisticOperatorDTO positionRegistrationOperatorDTO = new OrgDailyStatisticOperatorDTO(); + positionRegistrationOperatorDTO.setOrgId(CommonConstants.PLATFORM_ORG_ID); + positionRegistrationOperatorDTO.setBizType(OrgDailyStatisticTypeEnum.POSITION_REGISTRATION.getType()); + positionRegistrationOperatorDTO.setBizDate(DateUtil.parseDate(date)); + positionRegistrationOperatorDTO.setCount(positionRegistrations.size()); + if (CollectionUtils.isEmpty(positionRegistrationList)) { + orgDailyStatisticService.create(positionRegistrationOperatorDTO); + } else { + positionRegistrationOperatorDTO.setId(positionRegistrationList.get(0).getId()); + orgDailyStatisticService.modify(positionRegistrationOperatorDTO); + } + + } + + @Override + public List userOperationStatisticsDTO(StatisticQueryDTO queryDTO) { + List orgDailyStatisticDTOList = orgDailyStatisticService.list(OrgDailyStatisticQueryDTO.builder() + .orgId(CommonConstants.PLATFORM_ORG_ID) + .bizTypes(Arrays.asList(OrgDailyStatisticTypeEnum.USER_POSITION_BROWSE_RECORD.getType(), OrgDailyStatisticTypeEnum.USER_COLLECTIONS.getType(), OrgDailyStatisticTypeEnum.POSITION_REGISTRATION.getType())) + .bizDateStart(queryDTO.getBizDateStart()) + .bizDateEnd(queryDTO.getBizDateEnd()) + .build()); + + Map userPositionBrowseRecordMap = new HashMap<>(); + Map userCollectionsMap = new HashMap<>(); + Map positionRegistrationMap = new HashMap<>(); + + List list = new ArrayList<>(); + List betweenDate = new ArrayList<>(); + + if (queryDTO.getType() == 1) { + userPositionBrowseRecordMap = orgDailyStatisticDTOList.stream().filter(orgDailyStatisticDTO -> orgDailyStatisticDTO.getBizType().equals(OrgDailyStatisticTypeEnum.USER_POSITION_BROWSE_RECORD.getType())).collect(Collectors.groupingBy(orgDailyStatistic -> DateUtil.format(orgDailyStatistic.getBizDate(), "yyyy-MM-dd"), Collectors.summingInt(OrgDailyStatisticDTO::getCount))); + userCollectionsMap = orgDailyStatisticDTOList.stream().filter(orgDailyStatisticDTO -> orgDailyStatisticDTO.getBizType().equals(OrgDailyStatisticTypeEnum.USER_COLLECTIONS.getType())).collect(Collectors.groupingBy(orgDailyStatistic -> DateUtil.format(orgDailyStatistic.getBizDate(), "yyyy-MM-dd"), Collectors.summingInt(OrgDailyStatisticDTO::getCount))); + positionRegistrationMap = orgDailyStatisticDTOList.stream().filter(orgDailyStatisticDTO -> orgDailyStatisticDTO.getBizType().equals(OrgDailyStatisticTypeEnum.POSITION_REGISTRATION.getType())).collect(Collectors.groupingBy(orgDailyStatistic -> DateUtil.format(orgDailyStatistic.getBizDate(), "yyyy-MM-dd"), Collectors.summingInt(OrgDailyStatisticDTO::getCount))); + betweenDate = DateUtils.getDateBetween(queryDTO.getBizDateStart(), queryDTO.getBizDateEnd(), DateUtils.YYYY_MM_DD); + + } else if (queryDTO.getType() == 2) { + userPositionBrowseRecordMap = orgDailyStatisticDTOList.stream().filter(orgDailyStatisticDTO -> orgDailyStatisticDTO.getBizType().equals(OrgDailyStatisticTypeEnum.USER_POSITION_BROWSE_RECORD.getType())).collect(Collectors.groupingBy(orgDailyStatistic -> DateUtil.format(orgDailyStatistic.getBizDate(), "yyyy-MM"), Collectors.summingInt(OrgDailyStatisticDTO::getCount))); + userCollectionsMap = orgDailyStatisticDTOList.stream().filter(orgDailyStatisticDTO -> orgDailyStatisticDTO.getBizType().equals(OrgDailyStatisticTypeEnum.USER_COLLECTIONS.getType())).collect(Collectors.groupingBy(orgDailyStatistic -> DateUtil.format(orgDailyStatistic.getBizDate(), "yyyy-MM"), Collectors.summingInt(OrgDailyStatisticDTO::getCount))); + positionRegistrationMap = orgDailyStatisticDTOList.stream().filter(orgDailyStatisticDTO -> orgDailyStatisticDTO.getBizType().equals(OrgDailyStatisticTypeEnum.POSITION_REGISTRATION.getType())).collect(Collectors.groupingBy(orgDailyStatistic -> DateUtil.format(orgDailyStatistic.getBizDate(), "yyyy-MM"), Collectors.summingInt(OrgDailyStatisticDTO::getCount))); + betweenDate = DateUtils.getDateBetween(queryDTO.getBizDateStart(), queryDTO.getBizDateEnd(), DateUtils.YYYY_MM); + + } else if (queryDTO.getType() == 3) { + userPositionBrowseRecordMap = orgDailyStatisticDTOList.stream().filter(orgDailyStatisticDTO -> orgDailyStatisticDTO.getBizType().equals(OrgDailyStatisticTypeEnum.USER_POSITION_BROWSE_RECORD.getType())).collect(Collectors.groupingBy(orgDailyStatistic -> DateUtil.format(orgDailyStatistic.getBizDate(), "yyyy"), Collectors.summingInt(OrgDailyStatisticDTO::getCount))); + userCollectionsMap = orgDailyStatisticDTOList.stream().filter(orgDailyStatisticDTO -> orgDailyStatisticDTO.getBizType().equals(OrgDailyStatisticTypeEnum.USER_COLLECTIONS.getType())).collect(Collectors.groupingBy(orgDailyStatistic -> DateUtil.format(orgDailyStatistic.getBizDate(), "yyyy"), Collectors.summingInt(OrgDailyStatisticDTO::getCount))); + positionRegistrationMap = orgDailyStatisticDTOList.stream().filter(orgDailyStatisticDTO -> orgDailyStatisticDTO.getBizType().equals(OrgDailyStatisticTypeEnum.POSITION_REGISTRATION.getType())).collect(Collectors.groupingBy(orgDailyStatistic -> DateUtil.format(orgDailyStatistic.getBizDate(), "yyyy"), Collectors.summingInt(OrgDailyStatisticDTO::getCount))); + betweenDate = DateUtils.getDateBetween(queryDTO.getBizDateStart(), queryDTO.getBizDateEnd(), DateUtils.YYYY); + } + for (String dateStr : betweenDate) { + UserOperationStatisticsDTO userOperationStatisticsDTO = new UserOperationStatisticsDTO(); + userOperationStatisticsDTO.setName(dateStr); + userOperationStatisticsDTO.setUserPositionBrowseRecordCount(Objects.isNull(userPositionBrowseRecordMap.get(dateStr)) ? 0l : userPositionBrowseRecordMap.get(dateStr)); + userOperationStatisticsDTO.setUserCollectionsCount(Objects.isNull(userCollectionsMap.get(dateStr)) ? 0l : userCollectionsMap.get(dateStr)); + userOperationStatisticsDTO.setPositionRegistrationCount(Objects.isNull(positionRegistrationMap.get(dateStr)) ? 0l : positionRegistrationMap.get(dateStr)); + list.add(userOperationStatisticsDTO); + } + + return list; + } + + + @Override + public List getWordCloud() { + //name:客户名称,value:客户关联的岗位数量+ 客户关联的岗位浏览数量+ 客户关联的岗位收藏数量的总和 + return statisticsMapper.getWordCloud(); + } + + @Override + public List getPositionMark() { + //城市编码: + //求职者数量 + //在招岗位数量 + List jobExpects = jobExpectMapper.selectList(new LambdaQueryWrapper().eq(JobExpect::getDeleted, false)); + List positionDTOS = positionMapper.page(PositionPageQueryDTO.builder().build()).stream().filter(positionDTO -> Objects.nonNull(positionDTO.getAddressId())).collect(Collectors.toList()); + //统计存在的城市编码 去重 + Set areaCodeSet = new HashSet<>(); + areaCodeSet.addAll(jobExpects.stream().map(jobExpect -> jobExpect.getExpectCity()).collect(Collectors.toSet())); + areaCodeSet.addAll(positionDTOS.stream().map(positionDTO -> positionDTO.getDistrictCode()).collect(Collectors.toSet())); + + Map jobExpectMap = jobExpects.stream().collect(Collectors.groupingBy(jobExpect -> jobExpect.getExpectCity(), Collectors.counting())); + Map positionMap = positionDTOS.stream().collect(Collectors.groupingBy(positionDTO -> positionDTO.getDistrictCode(), Collectors.counting())); + + List list = new ArrayList<>(); + for (String areaCode : areaCodeSet) { + PositionMarkStatisticsDTO positionMarkStatisticsDTO = new PositionMarkStatisticsDTO(); + positionMarkStatisticsDTO.setAreaCode(areaCode); + positionMarkStatisticsDTO.setJobSeekerCount(Objects.isNull(jobExpectMap.get(areaCode)) ? 0 : jobExpectMap.get(areaCode)); + positionMarkStatisticsDTO.setPositionCount(Objects.isNull(positionMap.get(areaCode)) ? 0 : positionMap.get(areaCode)); + list.add(positionMarkStatisticsDTO); + } + return list; + } + + @Override + public List positionPage(PositionPageQueryDTO queryDTO) { + List list = positionMapper.page(queryDTO); + for (PositionDTO positionDTO : list) { + String recruitPositionTypeName = DictUtils.getCodeNameMap("recruit_position_type").get(positionDTO.getRecruitPositionType()); + positionDTO.setRecruitPositionTypeName(recruitPositionTypeName); + } + return list; + } +} diff --git a/src/main/java/com/newyetai/recruit/talent/controller/ImportDetailTalentController.java b/src/main/java/com/newyetai/recruit/talent/controller/ImportDetailTalentController.java new file mode 100644 index 0000000..9ce9fd4 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/talent/controller/ImportDetailTalentController.java @@ -0,0 +1,66 @@ +package com.newyetai.recruit.talent.controller; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +import com.newyetai.common.AlitaResult; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.recruit.talent.dto.*; +import com.newyetai.recruit.talent.service.ImportDetailTalentService; + +import org.springframework.web.bind.annotation.*; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; + +/** + * 人才库导入表 + * + * @author guixinman + * @since 1.0.0 2024-04-09 + */ +@Api(tags = "人才库导入表") +@RestController +@RequestMapping("/import_detail_talent") +public class ImportDetailTalentController { + + @Autowired + private ImportDetailTalentService importDetailTalentService; + + @PostMapping("/create") + @ApiOperation("人才库导入表-创建") + public AlitaResult create(@RequestBody ImportDetailTalentOperatorDTO operatorDTO) { + return AlitaResult.success(importDetailTalentService.create(operatorDTO)); + } + + @PutMapping("/modify") + @ApiOperation("人才库导入表-修改") + public AlitaResult modify(@RequestBody ImportDetailTalentOperatorDTO operatorDTO) { + return AlitaResult.success(importDetailTalentService.modify(operatorDTO)); + } + + @DeleteMapping("/{id}") + @ApiOperation("人才库导入表-删除") + public AlitaResult delete(@PathVariable("id") Long id) { + return AlitaResult.success(importDetailTalentService.delete(id)); + } + + @GetMapping("/{id}") + @ApiOperation("人才库导入表-查询单个") + public AlitaResult findById(@PathVariable("id") Long id) { + return AlitaResult.success(importDetailTalentService.findById(id)); + } + + @GetMapping("/list") + @ApiOperation("人才库导入表-列表查询") + public AlitaResult> list(ImportDetailTalentQueryDTO queryDTO) { + return AlitaResult.success(importDetailTalentService.list(queryDTO)); + } + + @GetMapping("/page") + @ApiOperation("人才库导入表-分页查询") + public AlitaResult> page(ImportDetailTalentPageQueryDTO queryDTO) { + importDetailTalentService.page(queryDTO); + return AlitaResult.success(queryDTO.getPageResult()); + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/talent/controller/TalentController.java b/src/main/java/com/newyetai/recruit/talent/controller/TalentController.java new file mode 100644 index 0000000..68746bd --- /dev/null +++ b/src/main/java/com/newyetai/recruit/talent/controller/TalentController.java @@ -0,0 +1,73 @@ +package com.newyetai.recruit.talent.controller; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +import com.newyetai.common.AlitaResult; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.recruit.talent.dto.*; +import com.newyetai.recruit.talent.service.TalentService; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; + +/** + * 人才库 + * + * @author guixinman + * @since 1.0.0 2024-04-09 + */ +@Api(tags = "人才库") +@RestController +@RequestMapping("/talent") +public class TalentController { + + @Autowired + private TalentService talentService; + + @PostMapping("/create") + @ApiOperation("人才库-创建") + public AlitaResult create(@RequestBody @Validated TalentOperatorDTO operatorDTO) { + return AlitaResult.success(talentService.create(operatorDTO)); + } + + @PutMapping("/modify") + @ApiOperation("人才库-修改") + public AlitaResult modify(@RequestBody @Validated TalentOperatorDTO operatorDTO) { + return AlitaResult.success(talentService.modify(operatorDTO)); + } + + @DeleteMapping("/{id}") + @ApiOperation("人才库-删除") + public AlitaResult delete(@PathVariable("id") Long id) { + return AlitaResult.success(talentService.delete(id)); + } + + @GetMapping("/{id}") + @ApiOperation("人才库-查询单个") + public AlitaResult findById(@PathVariable("id") Long id) { + return AlitaResult.success(talentService.findById(id)); + } + + @GetMapping("/list") + @ApiOperation("人才库-列表查询") + public AlitaResult> list(TalentPageQueryDTO queryDTO) { + return AlitaResult.success(talentService.list(queryDTO)); + } + + @GetMapping("/page") + @ApiOperation("人才库-分页查询") + public AlitaResult> page(TalentPageQueryDTO queryDTO) { + talentService.page(queryDTO); + return AlitaResult.success(queryDTO.getPageResult()); + } + + @GetMapping("/export") + @ApiOperation("人才库-导出") + public void export(TalentPageQueryDTO queryDTO) { + talentService.export(queryDTO); + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/talent/convert/ImportDetailTalentConvert.java b/src/main/java/com/newyetai/recruit/talent/convert/ImportDetailTalentConvert.java new file mode 100644 index 0000000..f5cba34 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/talent/convert/ImportDetailTalentConvert.java @@ -0,0 +1,26 @@ +package com.newyetai.recruit.talent.convert; + +import com.newyetai.recruit.talent.entity.ImportDetailTalent; +import com.newyetai.recruit.talent.dto.ImportDetailTalentDTO; +import com.newyetai.recruit.talent.dto.ImportDetailTalentOperatorDTO; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * 人才库导入表 + * + * @author guixinman + * @since 1.0.0 2024-04-09 + */ +@Mapper +public interface ImportDetailTalentConvert { + ImportDetailTalentConvert INSTANCE = Mappers.getMapper(ImportDetailTalentConvert.class); + + ImportDetailTalent convert(ImportDetailTalentDTO dto); + + ImportDetailTalentDTO convert(ImportDetailTalent entity); + + ImportDetailTalent convert(ImportDetailTalentOperatorDTO dto); + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/talent/convert/TalentConvert.java b/src/main/java/com/newyetai/recruit/talent/convert/TalentConvert.java new file mode 100644 index 0000000..0a6a451 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/talent/convert/TalentConvert.java @@ -0,0 +1,26 @@ +package com.newyetai.recruit.talent.convert; + +import com.newyetai.recruit.talent.entity.Talent; +import com.newyetai.recruit.talent.dto.TalentDTO; +import com.newyetai.recruit.talent.dto.TalentOperatorDTO; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * 人才库 + * + * @author guixinman + * @since 1.0.0 2024-04-09 + */ +@Mapper +public interface TalentConvert { + TalentConvert INSTANCE = Mappers.getMapper(TalentConvert.class); + + Talent convert(TalentDTO dto); + + TalentDTO convert(Talent entity); + + Talent convert(TalentOperatorDTO dto); + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/talent/dao/ImportDetailTalentMapper.java b/src/main/java/com/newyetai/recruit/talent/dao/ImportDetailTalentMapper.java new file mode 100644 index 0000000..ddbde2c --- /dev/null +++ b/src/main/java/com/newyetai/recruit/talent/dao/ImportDetailTalentMapper.java @@ -0,0 +1,26 @@ +package com.newyetai.recruit.talent.dao; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.recruit.talent.entity.ImportDetailTalent; +import com.newyetai.recruit.talent.dto.ImportDetailTalentDTO; +import com.newyetai.recruit.talent.dto.ImportDetailTalentQueryDTO; +import com.newyetai.recruit.talent.dto.ImportDetailTalentPageQueryDTO; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 人才库导入表 + * + * @author guixinman + * @since 1.0.0 2024-04-09 + */ +@Mapper +public interface ImportDetailTalentMapper extends MyMapper { + + List page(@Param("param") ImportDetailTalentPageQueryDTO queryDTO); + + List list(@Param("param") ImportDetailTalentQueryDTO queryDTO); +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/talent/dao/TalentMapper.java b/src/main/java/com/newyetai/recruit/talent/dao/TalentMapper.java new file mode 100644 index 0000000..86a75a0 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/talent/dao/TalentMapper.java @@ -0,0 +1,24 @@ +package com.newyetai.recruit.talent.dao; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.recruit.talent.entity.Talent; +import com.newyetai.recruit.talent.dto.TalentDTO; +import com.newyetai.recruit.talent.dto.TalentPageQueryDTO; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 人才库 + * + * @author guixinman + * @since 1.0.0 2024-04-09 + */ +@Mapper +public interface TalentMapper extends MyMapper { + + List page(@Param("param") TalentPageQueryDTO queryDTO); + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/talent/dto/ImportDetailTalentDTO.java b/src/main/java/com/newyetai/recruit/talent/dto/ImportDetailTalentDTO.java new file mode 100644 index 0000000..5966b65 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/talent/dto/ImportDetailTalentDTO.java @@ -0,0 +1,66 @@ +package com.newyetai.recruit.talent.dto; + +import com.newyetai.component.commonimport.dto.ImportDetailSuperDTO; + +import cn.hutool.core.util.StrUtil; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.SuperBuilder; + +/** + * 人才库导入表 + * + * @author guixinman + * @since 1.0.0 2024-04-09 + */ +@ApiModel("人才库导入表") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class ImportDetailTalentDTO extends ImportDetailSuperDTO { + private static final long serialVersionUID = 1L; + + @ApiModelProperty("导入任务ID") + private Long mainId; + + @ApiModelProperty("机构ID") + private Long orgId; + + @ApiModelProperty("模板全量数据") + private String dataJson; + + @ApiModelProperty("姓名") + private String realName; + + @ApiModelProperty("身份证号") + private String cardNo; + + @ApiModelProperty("联系方式") + private String contactWay; + + @ApiModelProperty("用户id") + private Long userId; + + @ApiModelProperty("明细状态") + private Integer detailStatus; + + @ApiModelProperty("失败原因") + private String failReason; + + @ApiModelProperty("备注") + private String remark; + + public void appendFailMsg(String msg) { + if (StrUtil.isEmpty(msg)) { + return; + } + if (StrUtil.isEmpty(getFailReason())) { + setFailReason(msg); + } else { + setFailReason(String.join(",", getFailReason(), msg)); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/talent/dto/ImportDetailTalentExecuteDTO.java b/src/main/java/com/newyetai/recruit/talent/dto/ImportDetailTalentExecuteDTO.java new file mode 100644 index 0000000..2bf3fca --- /dev/null +++ b/src/main/java/com/newyetai/recruit/talent/dto/ImportDetailTalentExecuteDTO.java @@ -0,0 +1,20 @@ +package com.newyetai.recruit.talent.dto; + +import com.newyetai.component.commonimport.dto.ImportExecuteSuperDTO; + +import lombok.Data; + +/** + * @description: 确定导入dto + * @author: guixinman + * @create: 2024-04-09 16:19 + **/ +@Data +public class ImportDetailTalentExecuteDTO extends ImportExecuteSuperDTO { + + /** + * 供应商id + */ + private Long companyId; + +} diff --git a/src/main/java/com/newyetai/recruit/talent/dto/ImportDetailTalentExportDTO.java b/src/main/java/com/newyetai/recruit/talent/dto/ImportDetailTalentExportDTO.java new file mode 100644 index 0000000..4089fa8 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/talent/dto/ImportDetailTalentExportDTO.java @@ -0,0 +1,36 @@ +package com.newyetai.recruit.talent.dto; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @description: + * @author: guixinman + * @create: 2024-06-12 14:34 + **/ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ImportDetailTalentExportDTO implements Serializable { + + @ApiModelProperty("姓名") + private String realName; + + @ApiModelProperty("身份证号") + private String cardNo; + + @ApiModelProperty("联系方式") + private String contactWay; + + @ApiModelProperty("失败原因") + private String failReason; + + @ApiModelProperty("备注") + private String remark; +} diff --git a/src/main/java/com/newyetai/recruit/talent/dto/ImportDetailTalentListenerDTO.java b/src/main/java/com/newyetai/recruit/talent/dto/ImportDetailTalentListenerDTO.java new file mode 100644 index 0000000..f469a03 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/talent/dto/ImportDetailTalentListenerDTO.java @@ -0,0 +1,27 @@ +package com.newyetai.recruit.talent.dto; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.newyetai.common.validation.annotation.IdCard; +import com.newyetai.component.commonimport.service.IImportDetailForm; +import javax.validation.groups.Default; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @description: 人才导入dto + * @author: guixinman + * @create: 2024-04-09 16:30 + **/ +@Data +public class ImportDetailTalentListenerDTO implements IImportDetailForm { + + @ApiModelProperty("姓名") + private String realName; + + @ApiModelProperty("身份证") + @IdCard(groups = Default.class) + private String cardNo; + + @ApiModelProperty("联系方式") + private String contactWay; +} diff --git a/src/main/java/com/newyetai/recruit/talent/dto/ImportDetailTalentOperatorDTO.java b/src/main/java/com/newyetai/recruit/talent/dto/ImportDetailTalentOperatorDTO.java new file mode 100644 index 0000000..756956a --- /dev/null +++ b/src/main/java/com/newyetai/recruit/talent/dto/ImportDetailTalentOperatorDTO.java @@ -0,0 +1,60 @@ +package com.newyetai.recruit.talent.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 guixinman + * @since 1.0.0 2024-04-09 + */ +@ApiModel("人才库导入表") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ImportDetailTalentOperatorDTO implements Serializable { + private static final long serialVersionUID = 1L; + + private Long id; + + @ApiModelProperty("导入任务ID") + private Long mainId; + + @ApiModelProperty("机构ID") + private Long orgId; + + @ApiModelProperty("模板全量数据") + private String dataJson; + + @ApiModelProperty("姓名") + private String realName; + + @ApiModelProperty("身份证号") + private String cardNo; + + @ApiModelProperty("联系方式") + private String contactWay; + + @ApiModelProperty("明细状态") + private Integer detailStatus; + + @ApiModelProperty("失败原因") + private String failReason; + + @ApiModelProperty("外部明细id") + private Long extraDetailId; + + @ApiModelProperty("备注") + private String remark; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/talent/dto/ImportDetailTalentPageQueryDTO.java b/src/main/java/com/newyetai/recruit/talent/dto/ImportDetailTalentPageQueryDTO.java new file mode 100644 index 0000000..dfcee20 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/talent/dto/ImportDetailTalentPageQueryDTO.java @@ -0,0 +1,82 @@ +package com.newyetai.recruit.talent.dto; + +import com.newyetai.common.dto.PageQueryDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.format.annotation.DateTimeFormat; + + +import java.util.Date; + +/** + * 人才库导入表 + * + * @author guixinman + * @since 1.0.0 2024-04-09 + */ + +@ApiModel("人才库导入表") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class ImportDetailTalentPageQueryDTO extends PageQueryDTO { + private static final long serialVersionUID = 1L; + + private Long id; + + @ApiModelProperty("导入任务ID") + private Long mainId; + + @ApiModelProperty("机构ID") + private Long orgId; + + @ApiModelProperty("模板全量数据") + private String dataJson; + + @ApiModelProperty("姓名 (模糊匹配)") + private String realNameLike; + + @ApiModelProperty("身份证号") + private String cardNo; + + @ApiModelProperty("联系方式") + private String contactWay; + + @ApiModelProperty("明细状态") + private Integer detailStatus; + + @ApiModelProperty("失败原因") + private String failReason; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("更新时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeStart; + + @ApiModelProperty("更新时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeEnd; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/talent/dto/ImportDetailTalentQueryDTO.java b/src/main/java/com/newyetai/recruit/talent/dto/ImportDetailTalentQueryDTO.java new file mode 100644 index 0000000..731f93c --- /dev/null +++ b/src/main/java/com/newyetai/recruit/talent/dto/ImportDetailTalentQueryDTO.java @@ -0,0 +1,82 @@ +package com.newyetai.recruit.talent.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; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +/** + * 人才库导入表 + * + * @author guixinman + * @since 1.0.0 2024-04-09 + */ +@ApiModel("人才库导入表") +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ImportDetailTalentQueryDTO implements Serializable { + private static final long serialVersionUID = 1L; + + private Long id; + + @ApiModelProperty("导入任务ID") + private Long mainId; + + @ApiModelProperty("机构ID") + private Long orgId; + + @ApiModelProperty("模板全量数据") + private String dataJson; + + @ApiModelProperty("姓名 (模糊匹配)") + private String realNameLike; + + @ApiModelProperty("身份证号") + private String cardNo; + + @ApiModelProperty("联系方式") + private String contactWay; + + @ApiModelProperty("明细状态") + private Integer detailStatus; + + @ApiModelProperty("失败原因") + private String failReason; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("更新时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeStart; + + @ApiModelProperty("更新时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeEnd; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/talent/dto/TalentDTO.java b/src/main/java/com/newyetai/recruit/talent/dto/TalentDTO.java new file mode 100644 index 0000000..4f41003 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/talent/dto/TalentDTO.java @@ -0,0 +1,56 @@ +package com.newyetai.recruit.talent.dto; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.common.util.IdcardUtils; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.SuperBuilder; + +/** + * 人才库 + * + * @author guixinman + * @since 1.0.0 2024-04-09 + */ +@ApiModel("人才库") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class TalentDTO extends BaseDTO { + private static final long serialVersionUID = 1L; + + private Long userId; + + @ApiModelProperty("姓名") + private String realName; + + @ApiModelProperty("年龄") + private Integer age; + + @ApiModelProperty("手机号") + private String phone; + + @ApiModelProperty("身份证号") + private String cardNo; + + @ApiModelProperty("联系方式") + private String contactWay; + + @ApiModelProperty("供应商") + private String companyName; + + private Long companyId; + + public void setCardNo(String cardNo) { + this.setAge(IdcardUtils.getAgeByIDNumber(cardNo)); + this.cardNo = cardNo; + } + + public String getCardNo() { + return cardNo; + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/talent/dto/TalentExportDTO.java b/src/main/java/com/newyetai/recruit/talent/dto/TalentExportDTO.java new file mode 100644 index 0000000..bcb3654 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/talent/dto/TalentExportDTO.java @@ -0,0 +1,53 @@ +package com.newyetai.recruit.talent.dto; + +import com.alibaba.excel.annotation.ExcelProperty; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @description: + * @author: guixinman + * @create: 2024-04-09 15:32 + **/ +@ApiModel("人才库导出") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class TalentExportDTO implements Serializable { + + @ExcelProperty("姓名") + @ApiModelProperty("姓名") + private String realName; + + @ExcelProperty("年龄") + @ApiModelProperty("年龄") + private Integer age; + + @ExcelProperty("手机号") + @ApiModelProperty("手机号") + private String phone; + + @ExcelProperty("身份证号") + @ApiModelProperty("身份证号") + private String cardNo; + + @ExcelProperty("联系方式") + @ApiModelProperty("联系方式") + private String contactWay; + + @ExcelProperty("供应商") + @ApiModelProperty("供应商") + private String companyName; + + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private String createTime; +} diff --git a/src/main/java/com/newyetai/recruit/talent/dto/TalentOperatorDTO.java b/src/main/java/com/newyetai/recruit/talent/dto/TalentOperatorDTO.java new file mode 100644 index 0000000..e5205b9 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/talent/dto/TalentOperatorDTO.java @@ -0,0 +1,56 @@ +package com.newyetai.recruit.talent.dto; + +import com.newyetai.common.annotation.trimAndUpper.TrimAndUpper; + +import org.hibernate.validator.constraints.Length; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +import java.io.Serializable; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + * 人才库 + * + * @author guixinman + * @since 1.0.0 2024-04-09 + */ +@ApiModel("人才库") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public class TalentOperatorDTO implements Serializable { + private static final long serialVersionUID = 1L; + + private Long id; + + @Length(max = 18,message = "身份证号超长") + @NotBlank(message = "身份证号不能为空") + @TrimAndUpper(value = TrimAndUpper.ExecuteType.ALL) + @ApiModelProperty("身份证号") + private String cardNo; + + @Length(max = 32,message = "姓名超长") + @NotBlank(message = "姓名不能为空") + @TrimAndUpper(value = TrimAndUpper.ExecuteType.ALL) + @ApiModelProperty("姓名") + private String realName; + + @Length(max = 50,message = "联系方式超长") + @ApiModelProperty("联系方式") + private String contactWay; + + @NotNull(message = "请选择供应商") + @ApiModelProperty("供应商id") + private Long companyId; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/talent/dto/TalentPageQueryDTO.java b/src/main/java/com/newyetai/recruit/talent/dto/TalentPageQueryDTO.java new file mode 100644 index 0000000..142f453 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/talent/dto/TalentPageQueryDTO.java @@ -0,0 +1,66 @@ +package com.newyetai.recruit.talent.dto; + +import com.newyetai.common.dto.PageQueryDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.format.annotation.DateTimeFormat; + + +import java.util.Date; +import java.util.Set; + +/** + * 人才库 + * + * @author guixinman + * @since 1.0.0 2024-04-09 + */ + +@ApiModel("人才库") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class TalentPageQueryDTO extends PageQueryDTO { + private static final long serialVersionUID = 1L; + + private Long id; + + @ApiModelProperty("机构id") + private Long orgId; + + @ApiModelProperty("姓名") + private String realNameLike; + + @ApiModelProperty("身份证号") + private String cardNoLike; + + @ApiModelProperty("身份证号") + private Set cardNos; + + @ApiModelProperty("手机号") + private String phoneLike; + + @ApiModelProperty("联系方式") + private String contactWayLike; + + @ApiModelProperty("供应商id") + private Long companyId; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/talent/dto/TalentQueryDTO.java b/src/main/java/com/newyetai/recruit/talent/dto/TalentQueryDTO.java new file mode 100644 index 0000000..e23a8e9 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/talent/dto/TalentQueryDTO.java @@ -0,0 +1,67 @@ +package com.newyetai.recruit.talent.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; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +/** + * 人才库 + * + * @author guixinman + * @since 1.0.0 2024-04-09 + */ +@ApiModel("人才库") +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class TalentQueryDTO implements Serializable { + private static final long serialVersionUID = 1L; + + private Long id; + + @ApiModelProperty("机构id") + private Long orgId; + + @ApiModelProperty("用户id") + private Long userId; + + @ApiModelProperty("联系方式") + private String contactWay; + + @ApiModelProperty("供应商id") + private Long companyId; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("更新时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeStart; + + @ApiModelProperty("更新时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeEnd; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/talent/entity/ImportDetailTalent.java b/src/main/java/com/newyetai/recruit/talent/entity/ImportDetailTalent.java new file mode 100644 index 0000000..9d95c56 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/talent/entity/ImportDetailTalent.java @@ -0,0 +1,68 @@ +package com.newyetai.recruit.talent.entity; + +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import com.baomidou.mybatisplus.annotation.*; +import com.newyetai.common.entity.BaseEntity; + +/** + * 人才库导入表 + * + * @author guixinman + * @since 1.0.0 2024-04-09 + */ +@TableName(value = "hr_import_detail_talent") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class ImportDetailTalent extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * 导入任务ID + */ + private Long mainId; + /** + * 机构ID + */ + private Long orgId; + /** + * 模板全量数据 + */ + private String dataJson; + /** + * 姓名 + */ + private String realName; + /** + * 身份证号 + */ + private String cardNo; + /** + * 联系方式 + */ + private String contactWay; + /** + * 明细状态 + */ + private Integer detailStatus; + /** + * 失败原因 + */ + private String failReason; + /** + * 外部明细id + */ + private Long extraDetailId; + /** + * 备注 + */ + private String remark; + + @ApiModelProperty("用户id") + private Long userId; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/talent/entity/Talent.java b/src/main/java/com/newyetai/recruit/talent/entity/Talent.java new file mode 100644 index 0000000..ca08be6 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/talent/entity/Talent.java @@ -0,0 +1,41 @@ +package com.newyetai.recruit.talent.entity; + + +import lombok.*; +import com.baomidou.mybatisplus.annotation.*; + +import com.newyetai.common.entity.BaseEntity; + +/** + * 人才库 + * + * @author guixinman + * @since 1.0.0 2024-04-09 + */ +@TableName(value = "hr_talent") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class Talent extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * 机构id + */ + private Long orgId; + /** + * 用户id + */ + private Long userId; + /** + * 联系方式 + */ + private String contactWay; + /** + * 供应商id + */ + private Long companyId; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/talent/mapper/ImportDetailTalentMapper.xml b/src/main/java/com/newyetai/recruit/talent/mapper/ImportDetailTalentMapper.xml new file mode 100644 index 0000000..f22b6f5 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/talent/mapper/ImportDetailTalentMapper.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + FROM + hr_import_detail_talent t + WHERE t.deleted = 0 + + AND t.id = #{param.id} + + + AND t.main_id = #{param.mainId} + + + AND t.org_id = #{param.orgId} + + + AND t.data_json = #{param.dataJson} + + + + AND t.real_name like #{realNameLike} + + + AND t.card_no = #{param.cardNo} + + + AND t.contact_way = #{param.contactWay} + + + AND t.detail_status = #{param.detailStatus} + + + AND t.fail_reason = #{param.failReason} + + + AND t.remark = #{param.remark} + + + AND t.create_time >= #{param.createTimeStart} + + + AND t.create_time <= #{param.createTimeEnd} + + + AND t.update_time >= #{param.updateTimeStart} + + + AND t.update_time <= #{param.updateTimeEnd} + + ORDER BY t.id DESC + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/talent/mapper/TalentMapper.xml b/src/main/java/com/newyetai/recruit/talent/mapper/TalentMapper.xml new file mode 100644 index 0000000..a379e26 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/talent/mapper/TalentMapper.xml @@ -0,0 +1,90 @@ + + + + + + + + + FROM + hr_talent t + WHERE t.deleted = 0 + + AND t.id = #{param.id} + + + AND t.org_id = #{param.orgId} + + + AND t.user_id = #{param.userId} + + + AND t.contact_way = #{param.contactWay} + + + AND t.company_id = #{param.companyId} + + + AND t.create_time >= #{param.createTimeStart} + + + AND t.create_time <= #{param.createTimeEnd} + + + AND t.update_time >= #{param.updateTimeStart} + + + AND t.update_time <= #{param.updateTimeEnd} + + ORDER BY t.id DESC + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/talent/service/ImportDetailTalentService.java b/src/main/java/com/newyetai/recruit/talent/service/ImportDetailTalentService.java new file mode 100644 index 0000000..b5e6395 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/talent/service/ImportDetailTalentService.java @@ -0,0 +1,71 @@ + +package com.newyetai.recruit.talent.service; + +import org.springframework.validation.annotation.Validated; + +import javax.validation.Valid; +import javax.validation.groups.Default; + +import java.util.List; + +import com.newyetai.recruit.talent.dto.*; + +/** + * 人才库导入表 + * + * @author guixinman + * @since 1.0.0 2024-04-09 + */ +@Validated(Default.class) +public interface ImportDetailTalentService { + + /** + * 人才库导入表 - 创建 + * + * @param operatorDto 操作dto + * @return {@link ImportDetailTalentDTO} + */ + ImportDetailTalentDTO create(@Valid ImportDetailTalentOperatorDTO operatorDto); + + /** + * 人才库导入表 - 修改 + * + * @param operatorDto 操作dto + * @return {@link ImportDetailTalentDTO} + */ + ImportDetailTalentDTO modify(@Valid ImportDetailTalentOperatorDTO operatorDto); + + /** + * 人才库导入表 - 删除 + * + * @param id id + * @return {@link ImportDetailTalentDTO} + */ + ImportDetailTalentDTO delete(Long id); + + /** + * 人才库导入表 - 根据ID查询单个 + * + * @param id id + * @return {@link ImportDetailTalentDTO} + */ + ImportDetailTalentDTO findById(Long id); + + /** + * 人才库导入表 - 列表查询 + * + * @param queryDTO 列表查询dto + * @return {@link List}<{@link ImportDetailTalentDTO}> + */ + List list(ImportDetailTalentQueryDTO queryDTO); + + /** + * 人才库导入表 - 分页查询 + * + * @param queryDTO 分页查询dto + * @return {@link ImportDetailTalentDTO} + */ + List page(ImportDetailTalentPageQueryDTO queryDTO); + + void batchCreate(List importDetailTalentDTOS); +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/talent/service/TalentService.java b/src/main/java/com/newyetai/recruit/talent/service/TalentService.java new file mode 100644 index 0000000..27eb9b6 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/talent/service/TalentService.java @@ -0,0 +1,81 @@ +package com.newyetai.recruit.talent.service; + +import org.springframework.validation.annotation.Validated; + +import javax.validation.Valid; +import javax.validation.groups.Default; + +import java.util.List; + +import com.newyetai.recruit.talent.dto.*; +import com.newyetai.recruit.talent.entity.Talent; + +/** + * 人才库 + * + * @author guixinman + * @since 1.0.0 2024-04-09 + */ +@Validated(Default.class) +public interface TalentService { + + /** + * 人才库 - 创建 + * + * @param operatorDto 操作dto + * @return {@link TalentDTO} + */ + TalentDTO create(@Valid TalentOperatorDTO operatorDto); + + /** + * 人才库 - 修改 + * + * @param operatorDto 操作dto + * @return {@link TalentDTO} + */ + TalentDTO modify(@Valid TalentOperatorDTO operatorDto); + + /** + * 人才库 - 删除 + * + * @param id id + * @return {@link TalentDTO} + */ + TalentDTO delete(Long id); + + /** + * 人才库 - 根据ID查询单个 + * + * @param id id + * @return {@link TalentDTO} + */ + TalentDTO findById(Long id); + + /** + * 人才库 - 列表查询 + * + * @param queryDTO 列表查询dto + * @return {@link List}<{@link TalentDTO}> + */ + List list(TalentPageQueryDTO queryDTO); + + /** + * 人才库 - 分页查询 + * + * @param queryDTO 分页查询dto + * @return {@link TalentDTO} + */ + List page(TalentPageQueryDTO queryDTO); + + void export(TalentPageQueryDTO queryDTO); + + /** + * @description: 确定导入用的创建 + * @return: id + * @author: guixinman + * @param: + */ + Long importCreate(Talent talent); + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/talent/service/impl/ImportDetailTalentProvider.java b/src/main/java/com/newyetai/recruit/talent/service/impl/ImportDetailTalentProvider.java new file mode 100644 index 0000000..a52130b --- /dev/null +++ b/src/main/java/com/newyetai/recruit/talent/service/impl/ImportDetailTalentProvider.java @@ -0,0 +1,325 @@ +package com.newyetai.recruit.talent.service.impl; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; + +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.read.builder.ExcelReaderBuilder; +import com.newyetai.common.dto.ExportHeadDetailInfoDTO; +import com.newyetai.common.dto.ExportHeadInfoDTO; +import com.newyetai.common.easyexcel.ExcelUtil; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.common.validation.util.ValidateUtils; +import com.newyetai.component.commonimport.constant.ImportDetailStatusEnum; +import com.newyetai.component.commonimport.constant.ImportStatusEnum; +import com.newyetai.component.commonimport.constant.ImportTypeEnum; +import com.newyetai.component.commonimport.dto.ImportDetailPageDTO; +import com.newyetai.component.commonimport.dto.ImportMainDTO; +import com.newyetai.component.commonimport.dto.ImportMainQueryDTO; +import com.newyetai.component.commonimport.dto.ImportMainUpdateDTO; +import com.newyetai.component.commonimport.service.ImportMainService; +import com.newyetai.component.commonimport.service.impl.AbstractCommonImportProvider; +import com.newyetai.component.dict.util.DictUtils; +import com.newyetai.component.file.entity.FileRecord; +import com.newyetai.component.file.service.FileRecordService; +import com.newyetai.recruit.position.dto.ImportDetailPositionExportDTO; +import com.newyetai.recruit.talent.dto.ImportDetailTalentDTO; +import com.newyetai.recruit.talent.dto.ImportDetailTalentExecuteDTO; +import com.newyetai.recruit.talent.dto.ImportDetailTalentExportDTO; +import com.newyetai.recruit.talent.dto.ImportDetailTalentListenerDTO; +import com.newyetai.recruit.talent.dto.ImportDetailTalentOperatorDTO; +import com.newyetai.recruit.talent.dto.ImportDetailTalentPageQueryDTO; +import com.newyetai.recruit.talent.dto.ImportDetailTalentQueryDTO; +import com.newyetai.recruit.talent.entity.Talent; +import com.newyetai.recruit.talent.service.ImportDetailTalentService; +import com.newyetai.recruit.talent.service.TalentService; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.user.dto.OrgUserOperateDTO; +import com.newyetai.usercenter.user.dto.SuperRealNameTwoAuthDTO; +import com.newyetai.usercenter.user.service.OrgUserService; +import com.newyetai.usercenter.user.service.UserRealNameTwoVerificationService; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.InputStream; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.stream.Collectors; + +import cn.hutool.json.JSONUtil; +import lombok.extern.slf4j.Slf4j; + +/** + * @description: + * @author: guixinman + * @create: 2024-04-09 16:18 + **/ +@Service +@Slf4j +public class ImportDetailTalentProvider extends AbstractCommonImportProvider { + + @Autowired + private ImportMainService importMainService; + + @Autowired + private FileRecordService fileRecordService; + + @Autowired + private ImportDetailTalentService importDetailTalentService; + + @Autowired + private UserRealNameTwoVerificationService userRealNameTwoVerificationService; + + @Autowired + private OrgUserService orgUserService; + + @Autowired + private TalentService talentService; + + public ImportDetailTalentProvider(ImportMainService imprImportMainService) { + super(imprImportMainService); + } + + @Override + public String getType() { + return ImportTypeEnum.TALENT.getType(); + } + + @Override + public Page pageDetail(ImportDetailPageDTO importDetailPageDTO) { + ImportDetailTalentPageQueryDTO queryDTO = new ImportDetailTalentPageQueryDTO(); + BeanUtils.copyProperties(importDetailPageDTO, queryDTO); + importDetailTalentService.page(queryDTO); + return queryDTO.getPageResult(); + } + + @Override + public void importDetailExport(ImportDetailPageDTO importDetailPageDTO) { + ImportDetailTalentPageQueryDTO queryDTO = new ImportDetailTalentPageQueryDTO(); + BeanUtils.copyProperties(importDetailPageDTO, queryDTO); + queryDTO.disablePage(); + List list = importDetailTalentService.page(queryDTO); + + List exportDTOList = list.stream().map(dto -> { + ImportDetailTalentExportDTO exportDTO = JsonUtils.toObject(dto.getDataJson(), ImportDetailTalentExportDTO.class); + exportDTO.setRemark(dto.getRemark()); + exportDTO.setFailReason(dto.getFailReason()); + return exportDTO; + }).collect(Collectors.toList()); + + if (org.springframework.util.CollectionUtils.isEmpty(exportDTOList)) { + return; + } + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); + String commonImportDetailStatus = DictUtils.getCodeNameMap("common_import_detail_status").get(String.valueOf(importDetailPageDTO.getDetailStatus())); + String fileName = "人才导入" + ( StringUtils.isNotBlank(commonImportDetailStatus) ? commonImportDetailStatus : "") + "明细导出" + "(" + formatter.format(LocalDateTime.now()) + ")"; + + ExportHeadInfoDTO infoDTO = ExportHeadInfoDTO.builder() + .fileName(fileName) + .build(); + List heads = infoDTO.getHeads(); + heads.add(ExportHeadDetailInfoDTO.builder().head("姓名").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("身份证号").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("联系方式").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("失败原因").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("备注").build()); + + List datas = Lists.newArrayList(); + for (ImportDetailTalentExportDTO dto : exportDTOList) { + List objects = Lists.newArrayList(); + datas.add(objects); + objects.add(dto.getRealName()); + objects.add(dto.getCardNo()); + objects.add(dto.getContactWay()); + objects.add(dto.getFailReason()); + objects.add(dto.getRemark()); + + } + infoDTO.setDatas(datas); + + ExcelUtil.dynamicExportTemplate(infoDTO); + + } + + @Override + public List analy(Long mainId) { + // 解析文件+明细 + ImportMainDTO importMainDTO = importMainService.find(ImportMainQueryDTO.builder().id(mainId).build()); + Assert.notNull(importMainDTO, "未查询到导入的数据"); + + FileRecord fileRecord; + try { + fileRecord = fileRecordService.find(FileRecord.builder().fileCode(importMainDTO.getFileCode()).build()); + } catch (Exception e) { + log.info("导入文件异常,", e); + fileRecord = null; + } + Assert.notNull(fileRecord, "上传文件不存在"); + try (InputStream is = fileRecordService.getFile(importMainDTO.getFileCode())) { + ImportTalentExcelListener listener = new ImportTalentExcelListener(); + ExcelReaderBuilder reader = EasyExcel.read(is, ImportDetailTalentListenerDTO.class, listener); + reader.sheet().doRead(); + List importDetailTalentListenerDTOS = listener.getImportDTOs(); + Assert.isTrue(!importDetailTalentListenerDTOS.isEmpty(), "导入文件无有效数据"); + return importDetailTalentListenerDTOS; + } catch (Exception e) { + throw new BusinessException(e.getMessage()); + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void checkAndSave(Long mainId, List detailCreateDtos) { + //更改状态为校验中 + ImportMainUpdateDTO updateDto = ImportMainUpdateDTO.builder().id(mainId) + .oldStatusSet(Sets.newHashSet(ImportStatusEnum.INIT.getStatus())) + .newStatus(ImportStatusEnum.CHECKING.getStatus()) + .build(); + importMainService.modify(updateDto); + + List importDetailTalentDTOS = new ArrayList<>(); + + //存储姓名+身份证号。用于校验 导入的数据中有没有重复的 + List realNameCardNos = new ArrayList<>(); + + for (ImportDetailTalentListenerDTO importDetailTalentListenerDTO : detailCreateDtos) { + importDetailTalentListenerDTO.setCardNo(StringUtils.upperCase(StringUtils.trim(importDetailTalentListenerDTO.getCardNo()))); + importDetailTalentListenerDTO.setRealName(StringUtils.trim(importDetailTalentListenerDTO.getRealName())); + + ImportDetailTalentDTO importDetailTalentDTO = new ImportDetailTalentDTO(); + + this.checkAndFill(importDetailTalentDTO, importDetailTalentListenerDTO); + + if (StringUtils.isBlank(importDetailTalentDTO.getFailReason())) { + if (realNameCardNos.contains(StringUtils.join(importDetailTalentListenerDTO.getRealName(), importDetailTalentListenerDTO.getCardNo()))) { + importDetailTalentDTO.appendFailMsg("姓名+身份证号出现多次"); + } + //存储姓名+身份证号 + realNameCardNos.add(StringUtils.join(importDetailTalentListenerDTO.getRealName(), importDetailTalentListenerDTO.getCardNo())); + } + + if (StringUtils.isNotBlank(importDetailTalentDTO.getFailReason())) { + importDetailTalentDTO.setDetailStatus(ImportDetailStatusEnum.CHECK_FAIL.getStatus()); + } else { + importDetailTalentDTO.setDetailStatus(ImportDetailStatusEnum.CHECK_SUCCESS.getStatus()); + } + importDetailTalentDTO.setMainId(mainId); + importDetailTalentDTO.setOrgId(UserContextHolder.getExistLoginOrgId()); + importDetailTalentDTOS.add(importDetailTalentDTO); + } + importDetailTalentService.batchCreate(importDetailTalentDTOS); + super.finishCheck(mainId, importDetailTalentDTOS); + } + + /** + * @param importDetailTalentDTO 插入导入表对象 + * @param importDetailTalentListenerDTO 解析导入明细对象 + * @description: 基础校验 -> 二要素认证 -> 创建个人用户 + * @return: + * @author: guixinman + */ + private void checkAndFill(ImportDetailTalentDTO importDetailTalentDTO, ImportDetailTalentListenerDTO importDetailTalentListenerDTO) { + LinkedHashMap dateJson = new LinkedHashMap(); + dateJson.put("realName", importDetailTalentListenerDTO.getRealName()); + dateJson.put("cardNo", importDetailTalentListenerDTO.getCardNo()); + dateJson.put("contactWay", importDetailTalentListenerDTO.getContactWay()); + + BeanUtils.copyProperties(importDetailTalentListenerDTO, importDetailTalentDTO); + importDetailTalentDTO.setDataJson(JSONUtil.toJsonStr(dateJson)); + + //必填项校验(姓名、身份证号)、基础格式校验(姓名/身份证/联系方式)、实名认证(二要素校验) + + //校验 姓名/身份证/联系方式 + if (StringUtils.isBlank(importDetailTalentListenerDTO.getRealName())) { + importDetailTalentDTO.appendFailMsg("姓名不能为空"); + } else if (importDetailTalentListenerDTO.getRealName().length() > 32) { + importDetailTalentDTO.appendFailMsg("姓名超过最大限制长度"); + importDetailTalentDTO.setRealName(null); + } else if (!ValidateUtils.checkRealName(importDetailTalentListenerDTO.getRealName())) { + importDetailTalentDTO.appendFailMsg("姓名格式不正确"); + } + + if (StringUtils.isBlank(importDetailTalentListenerDTO.getCardNo())) { + importDetailTalentDTO.appendFailMsg("身份证不能为空"); + } else if (importDetailTalentListenerDTO.getCardNo().length() > 18) { + importDetailTalentDTO.appendFailMsg("身份证号超过最大限制长度"); + importDetailTalentDTO.setCardNo(null); + } else if (!ValidateUtils.isIdCard(importDetailTalentListenerDTO.getCardNo())) { + importDetailTalentDTO.appendFailMsg("身份证格式不正确"); + } + + if (StringUtils.isNotBlank(importDetailTalentListenerDTO.getContactWay()) && importDetailTalentListenerDTO.getContactWay().length() > 50) { + importDetailTalentDTO.appendFailMsg("联系方式超过最大限制长度"); + importDetailTalentDTO.setContactWay(null); + } + + if (StringUtils.isBlank(importDetailTalentDTO.getFailReason())) { + + Long userId; + try { + // 直接认证,创建用户 + userId = userRealNameTwoVerificationService.superAuth( + SuperRealNameTwoAuthDTO.builder().realName(importDetailTalentDTO.getRealName()).cardNo(importDetailTalentDTO.getCardNo()).build()); + importDetailTalentDTO.setUserId(userId); + } catch (Exception e) { + importDetailTalentDTO.appendFailMsg("实名认证失败: " + e.getMessage()); + return; + } + + try { + //绑定机构 + orgUserService.create( + OrgUserOperateDTO.builder() + .orgId(UserContextHolder.getExistLoginOrgId()) + .userId(userId) + .build()); + } catch (Exception e) { + importDetailTalentDTO.appendFailMsg("个人用户绑定机构失败: " + e.getMessage()); + return; + } + } + + } + + @Transactional(rollbackFor = Exception.class) + @Override + public Long execute(ImportDetailTalentExecuteDTO executeDto) { + Long mainId = executeDto.getMainId(); + Assert.notNull(mainId, "参数异常"); + + ImportMainDTO importMainDTO = importMainService.find(ImportMainQueryDTO.builder().id(mainId).build()); + Assert.notNull(importMainDTO, "未查询到导入数据"); + + List importDetailTalentDTOS = importDetailTalentService.list(ImportDetailTalentQueryDTO.builder().mainId(mainId).detailStatus(ImportDetailStatusEnum.CHECK_SUCCESS.getStatus()).build()); + if (CollectionUtils.isEmpty(importDetailTalentDTOS)) { + throw new BusinessException("未查询到成功的明细数据"); + } + + for (ImportDetailTalentDTO importDetailTalentDTO : importDetailTalentDTOS) { + Talent talent = new Talent(); + talent.setContactWay(importDetailTalentDTO.getContactWay()); + talent.setCompanyId(executeDto.getCompanyId()); + talent.setUserId(importDetailTalentDTO.getUserId()); + talent.setOrgId(UserContextHolder.getExistLoginOrgId()); + Long talentId = talentService.importCreate(talent); + ImportDetailTalentOperatorDTO updateImportDetailTalentDTO = new ImportDetailTalentOperatorDTO(); + BeanUtils.copyProperties(importDetailTalentDTO, updateImportDetailTalentDTO); + updateImportDetailTalentDTO.setExtraDetailId(talentId); + importDetailTalentService.modify(updateImportDetailTalentDTO); + } + + return null; + } +} + diff --git a/src/main/java/com/newyetai/recruit/talent/service/impl/ImportDetailTalentServiceImpl.java b/src/main/java/com/newyetai/recruit/talent/service/impl/ImportDetailTalentServiceImpl.java new file mode 100644 index 0000000..2d6b76d --- /dev/null +++ b/src/main/java/com/newyetai/recruit/talent/service/impl/ImportDetailTalentServiceImpl.java @@ -0,0 +1,100 @@ +package com.newyetai.recruit.talent.service.impl; + +import lombok.extern.slf4j.Slf4j; + +import com.newyetai.recruit.talent.convert.ImportDetailTalentConvert; +import com.newyetai.recruit.talent.entity.ImportDetailTalent; +import com.newyetai.recruit.talent.dto.*; +import com.newyetai.recruit.talent.dao.ImportDetailTalentMapper; +import com.newyetai.recruit.talent.service.ImportDetailTalentService; + +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.common.util.UserContextHolder; + +import javax.annotation.Resource; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * 人才库导入表 + * + * @author guixinman + * @since 1.0.0 2024-04-09 + */ +@Slf4j +@Service +public class ImportDetailTalentServiceImpl implements ImportDetailTalentService { + + @Resource + private ImportDetailTalentMapper importDetailTalentMapper; + + @Override + public ImportDetailTalentDTO create(ImportDetailTalentOperatorDTO operatorDto) { + ImportDetailTalent importDetailTalent = ImportDetailTalentConvert.INSTANCE.convert(operatorDto); + importDetailTalentMapper.saveEntity(importDetailTalent); + return ImportDetailTalentConvert.INSTANCE.convert(importDetailTalent); + } + + @Override + public ImportDetailTalentDTO modify(ImportDetailTalentOperatorDTO operatorDto) { + ImportDetailTalentDTO importDetailTalentDto = this.findById(operatorDto.getId()); + if (Objects.isNull(importDetailTalentDto)) { + return null; + } + ImportDetailTalent importDetailTalent = ImportDetailTalentConvert.INSTANCE.convert(operatorDto); + importDetailTalentMapper.updateEntitySelective(importDetailTalent); + return this.findById(operatorDto.getId()); + } + + @Override + public ImportDetailTalentDTO delete(Long id) { + ImportDetailTalentDTO importDetailTalentDto = this.findById(id); + if (Objects.isNull(importDetailTalentDto)) { + return null; + } + ImportDetailTalent importDetailTalent = ImportDetailTalent.builder().build(); + importDetailTalent.setId(id); + importDetailTalentMapper.deleteEntity(importDetailTalent, UserContextHolder.getLoginUserId()); + return importDetailTalentDto; + } + + @Override + public ImportDetailTalentDTO findById(Long id) { + ImportDetailTalent importDetailTalent = importDetailTalentMapper.getById(id); + if (Objects.isNull(importDetailTalent)) { + return null; + } + return ImportDetailTalentConvert.INSTANCE.convert(importDetailTalent); + } + + @Override + public List list(ImportDetailTalentQueryDTO queryDTO) { + return importDetailTalentMapper.list(queryDTO); + } + + @Override + public List page(ImportDetailTalentPageQueryDTO queryDTO) { + return importDetailTalentMapper.page(queryDTO); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void batchCreate(List importDetailTalentDTOS) { + if (CollectionUtils.isEmpty(importDetailTalentDTOS)) { + return; + } + + List importDetailTalents = importDetailTalentDTOS.stream().map(dto -> { + ImportDetailTalent importDetailTalent = new ImportDetailTalent(); + BeanUtils.copyProperties(dto, importDetailTalent); + return importDetailTalent; + }).collect(Collectors.toList()); + + importDetailTalentMapper.saveEntites(importDetailTalents); + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/talent/service/impl/ImportTalentExcelListener.java b/src/main/java/com/newyetai/recruit/talent/service/impl/ImportTalentExcelListener.java new file mode 100644 index 0000000..bf4889c --- /dev/null +++ b/src/main/java/com/newyetai/recruit/talent/service/impl/ImportTalentExcelListener.java @@ -0,0 +1,55 @@ +package com.newyetai.recruit.talent.service.impl; + +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.event.AnalysisEventListener; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.recruit.talent.dto.ImportDetailTalentListenerDTO; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @description: 人才库导入 + * @author: guixinman + * @create: 2024-04-09 16:49 + **/ +public class ImportTalentExcelListener extends AnalysisEventListener{ + + private List dtos; + private Map headMap = new HashMap<>(); + public ImportTalentExcelListener() { + this.dtos = new ArrayList<>(); + } + + @Override + public void invoke(ImportDetailTalentListenerDTO data, AnalysisContext context) { + dtos.add(data); + } + + @Override + public void doAfterAllAnalysed(AnalysisContext context) { + + } + @Override + public void invokeHeadMap(Map headMap, AnalysisContext context) { + this.headMap = headMap; + if (headMap.isEmpty()) { + throw new BusinessException("导入模板表头有误"); + } + //姓名、身份证号、发放金额、备注 + if (headMap.size() != 3) { + throw new BusinessException("导入模板表头有误"); + } + Assert.isTrue(headMap.get(0).toString().contains("姓名"),"导入模板表头有误"); + Assert.isTrue(headMap.get(1).toString().contains("身份证"),"导入模板表头有误"); + Assert.isTrue(headMap.get(2).toString().contains("联系方式"),"导入模板表头有误"); + + } + + public List getImportDTOs(){ + return this.dtos; + } +} diff --git a/src/main/java/com/newyetai/recruit/talent/service/impl/TalentServiceImpl.java b/src/main/java/com/newyetai/recruit/talent/service/impl/TalentServiceImpl.java new file mode 100644 index 0000000..db3e3a2 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/talent/service/impl/TalentServiceImpl.java @@ -0,0 +1,285 @@ +package com.newyetai.recruit.talent.service.impl; + +import com.google.common.collect.Lists; + +import cn.hutool.core.date.DateUtil; +import lombok.extern.slf4j.Slf4j; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.dto.ExportHeadDetailInfoDTO; +import com.newyetai.common.dto.ExportHeadInfoDTO; +import com.newyetai.common.easyexcel.ExcelUtil; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.recruit.company.dto.HrCompanyDTO; +import com.newyetai.recruit.company.dto.HrCompanyPageQueryDTO; +import com.newyetai.recruit.company.enums.HrCompanyEnum; +import com.newyetai.recruit.company.service.IHrCompanyService; +import com.newyetai.frame.redis.aop.annotation.AutoUnLock; +import com.newyetai.frame.redis.dto.LockDTO; +import com.newyetai.frame.redis.redisson.RedissonUtils; +import com.newyetai.recruit.talent.convert.TalentConvert; +import com.newyetai.recruit.talent.entity.Talent; +import com.newyetai.recruit.talent.dto.*; +import com.newyetai.recruit.talent.dao.TalentMapper; +import com.newyetai.recruit.talent.service.TalentService; + +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.usercenter.user.dao.UserMapper; +import com.newyetai.usercenter.user.dto.SuperRealNameTwoAuthDTO; +import com.newyetai.usercenter.user.entity.User; +import com.newyetai.usercenter.user.service.UserRealNameTwoVerificationService; + +import javax.annotation.Resource; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.stream.Collectors; + +/** + * 人才库 + * + * @author guixinman + * @since 1.0.0 2024-04-09 + */ +@Slf4j +@Service +public class TalentServiceImpl implements TalentService { + + @Resource + private TalentMapper talentMapper; + + @Autowired + private UserRealNameTwoVerificationService userRealNameTwoVerificationService; + + @Resource + private UserMapper userMapper; + + @Autowired + private IHrCompanyService hrCompanyService; + + @Transactional(rollbackFor = Exception.class) + @AutoUnLock + @Override + public TalentDTO create(TalentOperatorDTO operatorDto) { + Assert.isTrue( + RedissonUtils.tryLockAutomatically( + LockDTO.builder() + .tryLockWaitTime(0L) + .lockTimeout(60 * 5L) + .methodName("talent:create") + .arg(operatorDto.getRealName()) + .arg(operatorDto.getCardNo()) + .arg(String.valueOf(UserContextHolder.getExistLoginOrgId())) + .build() + ), + "请稍后再试"); + + HrCompanyDTO hrCompanyDTO = hrCompanyService.find(HrCompanyPageQueryDTO.builder().id(operatorDto.getCompanyId()).companyType(HrCompanyEnum.GYS.getType()).build()); + Assert.notNull(hrCompanyDTO, "供应商不存在"); + + //姓名+身份证号进行实名,且在当前机构下唯一 + // 直接认证,创建用户 + Long userId = userRealNameTwoVerificationService.superAuth( + SuperRealNameTwoAuthDTO.builder().realName(operatorDto.getRealName()).cardNo(operatorDto.getCardNo()).build()); + + + Talent talent = TalentConvert.INSTANCE.convert(operatorDto); + talent.setUserId(userId); + talent.setOrgId(UserContextHolder.getExistLoginOrgId()); + + List talents = talentMapper.selectList( + new LambdaQueryWrapper() + .eq(Talent::getDeleted, false) + .eq(Talent::getOrgId, talent.getOrgId()) + .eq(Talent::getUserId, talent.getUserId()) + ); + if (CollectionUtils.isEmpty(talents)) { + talentMapper.saveEntity(talent); + } + + return TalentConvert.INSTANCE.convert(talentMapper.selectOne(new LambdaQueryWrapper() + .eq(Talent::getDeleted, false) + .eq(Talent::getOrgId, talent.getOrgId()) + .eq(Talent::getUserId, talent.getUserId()))); + } + + @Override + public TalentDTO modify(TalentOperatorDTO operatorDto) { + Assert.notNull(operatorDto.getId(), "参数缺失"); + + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper() + .eq(Talent::getDeleted, false) + .eq(Talent::getId, operatorDto.getId()); + + if (!CommonConstants.PLATFORM_ORG_ID.equals(UserContextHolder.getExistLoginOrgId())) { + queryWrapper.eq(Talent::getOrgId, UserContextHolder.getExistLoginOrgId()); + } + + Talent talent = talentMapper.selectOne(queryWrapper); + if (Objects.isNull(talent)) { + throw new BusinessException("未查询到数据"); + } + User user = userMapper.getById(talent.getUserId()); + Assert.notNull(user, "用户不存在"); + + HrCompanyDTO hrCompanyDTO = hrCompanyService.find(HrCompanyPageQueryDTO.builder().id(operatorDto.getCompanyId()).companyType(HrCompanyEnum.GYS.getType()).build()); + Assert.notNull(hrCompanyDTO, "供应商不存在"); + + Talent newTalent = new Talent(); + newTalent.setId(operatorDto.getId()); + newTalent.setContactWay(operatorDto.getContactWay()); + newTalent.setCompanyId(operatorDto.getCompanyId()); + newTalent.setUserId(user.getId()); + talentMapper.updateEntitySelective(newTalent); + return this.findById(operatorDto.getId()); + } + + @Override + public TalentDTO delete(Long id) { + TalentDTO talentDto = this.findById(id); + if (Objects.isNull(talentDto)) { + return null; + } + Talent talent = Talent.builder().build(); + talent.setId(id); + talentMapper.deleteEntity(talent, UserContextHolder.getLoginUserId()); + return talentDto; + } + + @Override + public TalentDTO findById(Long id) { + TalentPageQueryDTO queryDTO = new TalentPageQueryDTO(); + queryDTO.setId(id); + List list = this.page(queryDTO); + return org.apache.commons.collections.CollectionUtils.isEmpty(list) ? null : list.get(0); + } + + @Override + public List list(TalentPageQueryDTO queryDTO) { + queryDTO.disablePage(); + return this.page(queryDTO); + } + + @Override + public List page(TalentPageQueryDTO queryDTO) { + if (!CommonConstants.PLATFORM_ORG_ID.equals(UserContextHolder.getExistLoginOrgId())) { + queryDTO.setOrgId(UserContextHolder.getExistLoginOrgId()); + } + return talentMapper.page(queryDTO); + } + + @Override + public void export(TalentPageQueryDTO queryDTO) { + boolean flag = true; + Integer pageNo = 1; + Integer pageSize = 100; + + List listAll = new ArrayList<>(); + + while (flag) { + queryDTO.setPageNo(pageNo); + queryDTO.setPageSize(pageSize); + List list = this.page(queryDTO); + if (org.springframework.util.CollectionUtils.isEmpty(list)) { + flag = false; + continue; + } + if (list.size() < pageSize) { + flag = false; + } + pageNo = pageNo + 1; + listAll.addAll(list); + } + List collect = listAll.stream().map(dto -> { + TalentExportDTO talentExportDTO = new TalentExportDTO(); + BeanUtils.copyProperties(dto, talentExportDTO); + talentExportDTO.setCreateTime(DateUtil.format(dto.getCreateTime(), "yyyy-MM-dd HH:mm:ss")); + return talentExportDTO; + }).collect(Collectors.toList()); + + if (org.springframework.util.CollectionUtils.isEmpty(collect)) { + return; + } + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); + String fileName = "人才明细导出" + "(" + formatter.format(LocalDateTime.now()) + ")"; + + ExportHeadInfoDTO infoDTO = ExportHeadInfoDTO.builder() + .fileName(fileName) + .build(); + List heads = infoDTO.getHeads(); + heads.add(ExportHeadDetailInfoDTO.builder().head("姓名").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("年龄").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("手机号").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("身份证号").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("联系方式").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("供应商").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("创建时间").build()); + + List datas = Lists.newArrayList(); + for (TalentExportDTO dto : collect) { + List objects = Lists.newArrayList(); + datas.add(objects); + objects.add(dto.getRealName()); + objects.add(dto.getAge()); + objects.add(dto.getPhone()); + objects.add(dto.getCardNo()); + objects.add(dto.getContactWay()); + objects.add(dto.getCompanyName()); + objects.add(dto.getCreateTime()); + } + infoDTO.setDatas(datas); + + ExcelUtil.dynamicExportTemplate(infoDTO); + } + + @Transactional(rollbackFor = Exception.class) + @AutoUnLock + @Override + public Long importCreate(Talent talent) { + User user = userMapper.getById(talent.getUserId()); + Assert.notNull(user, "用户不存在"); + + Assert.isTrue( + RedissonUtils.tryLockAutomatically( + LockDTO.builder() + .tryLockWaitTime(0L) + .lockTimeout(60 * 5L) + .methodName("talent:create") + .arg(user.getRealName()) + .arg(user.getCardNo()) + .arg(String.valueOf(UserContextHolder.getExistLoginOrgId())) + .build() + ), + "该用户正在操作中,请检查"); + + List talents = talentMapper.selectList( + new LambdaQueryWrapper() + .eq(Talent::getDeleted, false) + .eq(Talent::getOrgId, talent.getOrgId()) + .eq(Talent::getUserId, talent.getUserId()) + ); + if (CollectionUtils.isEmpty(talents)) { + talentMapper.saveEntity(talent); + } else { + Long companyId = talents.get(0).getCompanyId(); + if (companyId.longValue() != talent.getCompanyId().longValue()) { + Talent updateTalent = new Talent(); + updateTalent.setId(talents.get(0).getId()); + updateTalent.setCompanyId(companyId); + talentMapper.updateEntitySelective(updateTalent); + } + } + return talent.getId(); + } + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/tencent/controller/TencentController.java b/src/main/java/com/newyetai/recruit/tencent/controller/TencentController.java new file mode 100644 index 0000000..fb589f5 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/tencent/controller/TencentController.java @@ -0,0 +1,42 @@ +package com.newyetai.recruit.tencent.controller; + +import com.newyetai.common.AlitaResult; +import com.newyetai.recruit.tencent.service.TencentService; +import com.newyetai.sdk.tencent.map.dto.TencentMapBaseResDTO; +import com.newyetai.sdk.tencent.map.dto.TencentMapLocationV1IpResDTO; +import com.newyetai.sdk.tencent.map.dto.TencentMapPlaceSearchReqDTO; +import com.newyetai.sdk.tencent.map.dto.TencentMapWsDistanceV1MatrixReqDTO; +import com.newyetai.sdk.tencent.map.dto.TencentWsDistanceV1MatrixResDTO; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @description: + * @author: guixinman + * @create: 2024-12-18 14:14 + **/ +@RestController +@RequestMapping("/tencent") +public class TencentController { + + @Autowired + private TencentService tencentService; + + @GetMapping("/ws/location/v1/ip") + public AlitaResult wsLocationV1Ip() { + return tencentService.wsLocationV1Ip(); + } + + @GetMapping("/ws/distance/v1/matrix") + public AlitaResult wsDistanceV1Matrix(TencentMapWsDistanceV1MatrixReqDTO reqDTO) { + return tencentService.wsDistanceV1Matrix(reqDTO); + } + + @GetMapping("/ws/place/v1/search") + public AlitaResult placeSearch(TencentMapPlaceSearchReqDTO reqDTO) { + return tencentService.placeSearch(reqDTO); + } +} diff --git a/src/main/java/com/newyetai/recruit/tencent/service/TencentService.java b/src/main/java/com/newyetai/recruit/tencent/service/TencentService.java new file mode 100644 index 0000000..1f2aa06 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/tencent/service/TencentService.java @@ -0,0 +1,17 @@ +package com.newyetai.recruit.tencent.service; + +import com.newyetai.common.AlitaResult; +import com.newyetai.sdk.tencent.map.dto.TencentMapBaseResDTO; +import com.newyetai.sdk.tencent.map.dto.TencentMapLocationV1IpResDTO; +import com.newyetai.sdk.tencent.map.dto.TencentMapPlaceSearchReqDTO; +import com.newyetai.sdk.tencent.map.dto.TencentMapWsDistanceV1MatrixReqDTO; +import com.newyetai.sdk.tencent.map.dto.TencentWsDistanceV1MatrixResDTO; + +public interface TencentService { + + AlitaResult wsLocationV1Ip(); + + AlitaResult wsDistanceV1Matrix(TencentMapWsDistanceV1MatrixReqDTO reqDTO); + + AlitaResult placeSearch(TencentMapPlaceSearchReqDTO reqDTO); +} diff --git a/src/main/java/com/newyetai/recruit/tencent/service/impl/TencentServiceImpl.java b/src/main/java/com/newyetai/recruit/tencent/service/impl/TencentServiceImpl.java new file mode 100644 index 0000000..cc68433 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/tencent/service/impl/TencentServiceImpl.java @@ -0,0 +1,44 @@ +package com.newyetai.recruit.tencent.service.impl; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.util.RequestUtils; +import com.newyetai.common.util.SpringContextHolder; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.recruit.tencent.service.TencentService; +import com.newyetai.sdk.tencent.map.TencentMapContext; +import com.newyetai.sdk.tencent.map.dto.TencentMapBaseResDTO; +import com.newyetai.sdk.tencent.map.dto.TencentMapLocationV1IpResDTO; +import com.newyetai.sdk.tencent.map.dto.TencentMapPlaceSearchReqDTO; +import com.newyetai.sdk.tencent.map.dto.TencentMapWsDistanceV1MatrixReqDTO; +import com.newyetai.sdk.tencent.map.dto.TencentMapWsLocationV1IpReqDTO; +import com.newyetai.sdk.tencent.map.dto.TencentWsDistanceV1MatrixResDTO; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * @description: + * @author: guixinman + * @create: 2024-12-18 14:14 + **/ +@Service +public class TencentServiceImpl implements TencentService { + + @Autowired + private TencentMapContext tencentMapContext; + + @Override + public AlitaResult wsLocationV1Ip() { + return tencentMapContext.webServiceWsLocationV1Ip(TencentMapWsLocationV1IpReqDTO.builder().ip(RequestUtils.getIpAddress(SpringContextHolder.getRequest())).build()); + } + + @Override + public AlitaResult wsDistanceV1Matrix(TencentMapWsDistanceV1MatrixReqDTO reqDTO) { + return tencentMapContext.wsDistanceV1MatrixReqDTO(reqDTO); + } + + @Override + public AlitaResult placeSearch(TencentMapPlaceSearchReqDTO reqDTO) { + return tencentMapContext.placeSearch(reqDTO); + } +} diff --git a/src/main/java/com/newyetai/recruit/user/controller/JobExpectController.java b/src/main/java/com/newyetai/recruit/user/controller/JobExpectController.java new file mode 100644 index 0000000..d700a84 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/controller/JobExpectController.java @@ -0,0 +1,84 @@ +package com.newyetai.recruit.user.controller; + + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.recruit.user.dto.JobExpectDTO; +import com.newyetai.recruit.user.dto.JobExpectOperateDTO; +import com.newyetai.recruit.user.dto.JobExpectQueryDTO; +import com.newyetai.recruit.user.service.JobExpectService; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +/** + * @author fzp on 2022-02-23 + */ +@RestController +@RequestMapping("job_expect") +@Api(tags = "求职期望表") +public class JobExpectController { + + @Autowired + private JobExpectService jobExpectService; + + @PostMapping("/create") + @ApiOperation("创建") + public AlitaResult create(@Validated(Create.class) @RequestBody JobExpectOperateDTO jobExpectOperateDTO){ + return AlitaResult.success(jobExpectService.create(jobExpectOperateDTO)); + } + + @PutMapping("/modify") + @ApiOperation("修改") + public AlitaResult modify(@Validated(Update.class) @RequestBody JobExpectOperateDTO jobExpectOperateDTO){ + jobExpectService.modify(jobExpectOperateDTO); + return AlitaResult.success(true); + } + + @PutMapping("/modify_job_status") + @ApiOperation("修改求职状态") + public AlitaResult modifyOnDuty(@RequestBody JobExpectOperateDTO jobExpectOperateDTO){ + jobExpectService.modifyOnDuty(jobExpectOperateDTO); + return AlitaResult.success(true); + } + + @DeleteMapping("/remove/{id}") + @ApiOperation("删除") + public AlitaResult remove(@PathVariable Long id){ + jobExpectService.remove(id); + return AlitaResult.success(true); + } + + @GetMapping("/page") + @ApiOperation("分页查询") + public AlitaResult> page(JobExpectQueryDTO jobExpectQueryDTO){ + jobExpectService.page(jobExpectQueryDTO); + return AlitaResult.success(jobExpectQueryDTO.getPageResult()); + } + + @GetMapping("/list") + @ApiOperation("列表查询") + public AlitaResult> list(JobExpectQueryDTO jobExpectQueryDTO){ + if(jobExpectQueryDTO.getUserId() == null){ + jobExpectQueryDTO.setUserId(UserContextHolder.getLoginUserId()); + } + return AlitaResult.success(jobExpectService.list(jobExpectQueryDTO)); + } + +} diff --git a/src/main/java/com/newyetai/recruit/user/controller/ResumeController.java b/src/main/java/com/newyetai/recruit/user/controller/ResumeController.java new file mode 100644 index 0000000..1e10484 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/controller/ResumeController.java @@ -0,0 +1,79 @@ +package com.newyetai.recruit.user.controller; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.recruit.user.dto.*; +import com.newyetai.recruit.user.service.ResumeService; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; + +/** + * 简历管理 + * + * @author guixinman + * @since 1.0.0 2024-04-19 + */ +@Api(tags = "简历管理") +@RestController +@RequestMapping("/resume") +public class ResumeController { + + @Autowired + private ResumeService resumeService; + + @PostMapping("/createOrModify") + @ApiOperation("简历管理-创建") + public AlitaResult createOrModify(@RequestBody ResumeOperatorDTO operatorDTO) { + resumeService.createOrModify(operatorDTO); + return AlitaResult.success(); + } + + @PutMapping("/modify") + @ApiOperation("简历管理-修改") + public AlitaResult modify(@RequestBody @Validated(Update.class) ResumeOperatorDTO operatorDTO) { + resumeService.modify(operatorDTO); + return AlitaResult.success(); + } + + @DeleteMapping("/delete") + @ApiOperation("简历管理-删除") + public AlitaResult delete() { + resumeService.delete(); + return AlitaResult.success(); + } + + @GetMapping("/{id}") + @ApiOperation("简历管理-查询单个") + public AlitaResult findById(@PathVariable("id") Long id) { + return AlitaResult.success(resumeService.findById(id)); + } + + @GetMapping("/list") + @ApiOperation("简历管理-列表查询") + public AlitaResult> list(ResumeQueryDTO queryDTO) { + return AlitaResult.success(resumeService.list(queryDTO)); + } + + @GetMapping("/page") + @ApiOperation("简历管理-分页查询") + public AlitaResult> page(ResumePageQueryDTO queryDTO) { + resumeService.page(queryDTO); + return AlitaResult.success(queryDTO.getPageResult()); + } + + + @GetMapping("/user_find") + @ApiOperation("简历管理-用户查询单个") + public AlitaResult userFind() { + return AlitaResult.success(resumeService.userFind()); + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/user/controller/UserCertificateController.java b/src/main/java/com/newyetai/recruit/user/controller/UserCertificateController.java new file mode 100644 index 0000000..c0048be --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/controller/UserCertificateController.java @@ -0,0 +1,85 @@ +package com.newyetai.recruit.user.controller; + + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.recruit.user.dto.UserCertificateCreateDTO; +import com.newyetai.recruit.user.dto.UserCertificateDTO; +import com.newyetai.recruit.user.dto.UserCertificateModifyDTO; +import com.newyetai.recruit.user.dto.UserCertificateQueryDTO; +import com.newyetai.recruit.user.service.UserCertificateService; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +/** + * @author fzp on 2022-02-23 + */ +@RestController +@RequestMapping("user_certificate") +@Api(tags = "用户证书表") +public class UserCertificateController { + + @Autowired + private UserCertificateService userCertificateService; + + @PostMapping("/create") + @ApiOperation("创建") + public AlitaResult create(@Validated @RequestBody List operateDTOs){ + userCertificateService.create(operateDTOs); + return AlitaResult.success(); + } + + @PutMapping("/modify") + @ApiOperation("修改") + public AlitaResult modify( + @Validated @RequestBody UserCertificateModifyDTO operateDTO) { + return AlitaResult.success(userCertificateService.modify(operateDTO)); + } + + @DeleteMapping("/{id}") + @ApiOperation("删除") + public AlitaResult delete(@PathVariable Long id){ + return AlitaResult.success(userCertificateService.delete(id)); + } + + @GetMapping("/{id}") + @ApiOperation("查询单个") + public AlitaResult findById(@PathVariable("id") Long id) { + return AlitaResult.success(userCertificateService.findById(id)); + } + + @GetMapping("/page") + @ApiOperation("分页查询") + public AlitaResult> page(UserCertificateQueryDTO queryDTO){ + if(queryDTO.getUserId() == null){ + queryDTO.setUserId(UserContextHolder.getLoginUserId()); + } + userCertificateService.page(queryDTO); + return AlitaResult.success(queryDTO.getPageResult()); + } + + @GetMapping("/list") + @ApiOperation("列表查询") + public AlitaResult> list(UserCertificateQueryDTO queryDTO){ + if(queryDTO.getUserId() == null){ + queryDTO.setUserId(UserContextHolder.getLoginUserId()); + } + return AlitaResult.success(userCertificateService.list(queryDTO)); + } + +} diff --git a/src/main/java/com/newyetai/recruit/user/controller/UserCollectionController.java b/src/main/java/com/newyetai/recruit/user/controller/UserCollectionController.java new file mode 100644 index 0000000..51686c8 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/controller/UserCollectionController.java @@ -0,0 +1,65 @@ +package com.newyetai.recruit.user.controller; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.validation.Create; +import com.newyetai.recruit.position.dto.PositionDTO; +import com.newyetai.recruit.position.dto.PositionPageQueryDTO; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.recruit.user.dto.UserCollectionCreateDTO; +import com.newyetai.recruit.user.service.UserCollectionService; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + + +/** + * 招聘系统 - 我的收藏 + * + * @author fzp + * @date 2021年10月22日11:17:24 + */ +@Api(tags = "招聘系统 - 用户职位") +@RestController +@RequestMapping("/user_collections") +public class UserCollectionController { + + @Autowired + private UserCollectionService userCollectionService; + + + @ApiOperation("查询收藏的职位列表") + @GetMapping("/page") + public AlitaResult> page(PositionPageQueryDTO queryDTO) { + userCollectionService.page(queryDTO); + return AlitaResult.success(queryDTO.getPageResult()); + } + + @ApiOperation("收藏职位") + @PostMapping("/create") + public AlitaResult create(@Validated(Create.class) @RequestBody UserCollectionCreateDTO dto) { + userCollectionService.create(dto); + return AlitaResult.success(); + } + + @ApiOperation("取消收藏") + @DeleteMapping("/delete/{id}") + public AlitaResult delete(@PathVariable("id") Long id) { + return AlitaResult.success(userCollectionService.delete(id)); + } + + @ApiOperation("收藏统计") + @GetMapping("/statistics") + public AlitaResult statistics(){ + return AlitaResult.success(userCollectionService.statistics()); + } +} diff --git a/src/main/java/com/newyetai/recruit/user/controller/UserPositionBrowseRecordController.java b/src/main/java/com/newyetai/recruit/user/controller/UserPositionBrowseRecordController.java new file mode 100644 index 0000000..d12fac0 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/controller/UserPositionBrowseRecordController.java @@ -0,0 +1,58 @@ +package com.newyetai.recruit.user.controller; + +import com.newyetai.common.AlitaResult; +import com.newyetai.recruit.user.dto.BrowseRecordUserPageQueryDTO; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.recruit.user.dto.BrowseRecordDTO; +import com.newyetai.recruit.user.dto.BrowseRecordPageQueryDTO; +import com.newyetai.recruit.user.service.BrowseRecordService; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.annotations.ApiOperation; + +/** + * @description: 用户浏览 + * @author: guixinman + * @create: 2024-04-18 17:15 + **/ +@RestController +@RequestMapping("/user_position_browse_record") +public class UserPositionBrowseRecordController { + + @Autowired + private BrowseRecordService browseRecordService; + + @PostMapping("/create") + @ApiOperation("新增岗位浏览记录") + public AlitaResult browseRecordCreate(@RequestBody @Validated BrowseRecordDTO recordDTO) { + browseRecordService.create(recordDTO); + return AlitaResult.success(); + } + + @GetMapping("/page") + @ApiOperation("分页查询岗位浏览记录") + public AlitaResult> browseRecordPage(BrowseRecordPageQueryDTO queryDTO) { + browseRecordService.pagePosition(queryDTO); + return AlitaResult.success(queryDTO.getPageResult()); + } + + @ApiOperation("浏览统计") + @GetMapping("/statistics") + public AlitaResult statistics(){ + return AlitaResult.success(browseRecordService.statistics()); + } + + @GetMapping("/user_page") + @ApiOperation("分页查询岗位浏览记录") + public AlitaResult> browseRecordUserPage(BrowseRecordUserPageQueryDTO queryDTO) { + browseRecordService.browseRecordUserPage(queryDTO); + return AlitaResult.success(queryDTO.getPageResult()); + } +} diff --git a/src/main/java/com/newyetai/recruit/user/convert/JobExpectMapMapper.java b/src/main/java/com/newyetai/recruit/user/convert/JobExpectMapMapper.java new file mode 100644 index 0000000..14babdc --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/convert/JobExpectMapMapper.java @@ -0,0 +1,37 @@ +package com.newyetai.recruit.user.convert; + +import com.newyetai.recruit.user.dto.JobExpectDTO; +import com.newyetai.recruit.user.dto.JobExpectOperateDTO; +import com.newyetai.recruit.user.entity.JobExpect; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * @author fzp on 2022-02-23 + */ +@Mapper +public interface JobExpectMapMapper { + + JobExpectMapMapper INSTANCE = + Mappers.getMapper(JobExpectMapMapper.class); + + /** + * dto to entity + * + * @param jobExpectDto + * @return + * @author fzp on 2022-02-23 + */ + JobExpect toEntity( + JobExpectDTO jobExpectDto); + + + /** + * @param jobExpectOperateDTO + * @return + * @author fzp on 2022-02-23 + */ + JobExpect toEntity(JobExpectOperateDTO jobExpectOperateDTO); + +} diff --git a/src/main/java/com/newyetai/recruit/user/convert/ResumeConvert.java b/src/main/java/com/newyetai/recruit/user/convert/ResumeConvert.java new file mode 100644 index 0000000..a90f7c2 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/convert/ResumeConvert.java @@ -0,0 +1,26 @@ +package com.newyetai.recruit.user.convert; + +import com.newyetai.recruit.user.entity.Resume; +import com.newyetai.recruit.user.dto.ResumeDTO; +import com.newyetai.recruit.user.dto.ResumeOperatorDTO; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * 简历管理 + * + * @author guixinman + * @since 1.0.0 2024-04-19 + */ +@Mapper +public interface ResumeConvert { + ResumeConvert INSTANCE = Mappers.getMapper(ResumeConvert.class); + + Resume convert(ResumeDTO dto); + + ResumeDTO convert(Resume entity); + + Resume convert(ResumeOperatorDTO dto); + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/user/convert/UserCertificateMapMapper.java b/src/main/java/com/newyetai/recruit/user/convert/UserCertificateMapMapper.java new file mode 100644 index 0000000..03df896 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/convert/UserCertificateMapMapper.java @@ -0,0 +1,27 @@ +package com.newyetai.recruit.user.convert; + +import com.newyetai.recruit.user.dto.UserCertificateCreateDTO; +import com.newyetai.recruit.user.dto.UserCertificateDTO; +import com.newyetai.recruit.user.dto.UserCertificateModifyDTO; +import com.newyetai.recruit.user.entity.UserCertificate; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * @author fzp on 2022-02-23 + */ +@Mapper +public interface UserCertificateMapMapper { + + UserCertificateMapMapper INSTANCE = + Mappers.getMapper(UserCertificateMapMapper.class); + + UserCertificate toEntity(UserCertificateModifyDTO jobExpectOperateDTO); + + List toEntitys(List jobExpectOperateDTOs); + + UserCertificateDTO toDTO(UserCertificate userCertificate); +} diff --git a/src/main/java/com/newyetai/recruit/user/dao/BrowseRecordMapper.java b/src/main/java/com/newyetai/recruit/user/dao/BrowseRecordMapper.java new file mode 100644 index 0000000..f38b93a --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/dao/BrowseRecordMapper.java @@ -0,0 +1,29 @@ +package com.newyetai.recruit.user.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.newyetai.recruit.user.dto.BrowseRecordDTO; +import com.newyetai.recruit.user.dto.BrowseRecordPageQueryDTO; +import com.newyetai.recruit.user.dto.BrowseRecordUserPageQueryDTO; +import com.newyetai.recruit.user.entity.BrowseRecord; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 用户岗位访问记录表 Mapper 接口 + *

+ * + * @author Carlye + * @since 2021-01-21 + */ +@Mapper +public interface BrowseRecordMapper extends BaseMapper { + + List pagePosition(BrowseRecordPageQueryDTO queryDTO); + List pageUserPosition(BrowseRecordUserPageQueryDTO queryDTO); + + int checkUserIdIsWechat(@Param("userId") Long userId); +} diff --git a/src/main/java/com/newyetai/recruit/user/dao/JobExpectMapper.java b/src/main/java/com/newyetai/recruit/user/dao/JobExpectMapper.java new file mode 100644 index 0000000..31d5d8a --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/dao/JobExpectMapper.java @@ -0,0 +1,40 @@ +package com.newyetai.recruit.user.dao; + + +import com.newyetai.recruit.statistics.dto.StatisticsBaseDTO; +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.recruit.user.dto.JobExpectDTO; +import com.newyetai.recruit.user.dto.JobExpectQueryDTO; +import com.newyetai.recruit.user.entity.JobExpect; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; +import java.util.Map; + +/** + * 求职期望表 + * + * @author fzp on 2022-02-23 + */ +@Mapper +public interface JobExpectMapper extends MyMapper { + + /** + * 查询 + * + * @param jobExpectQueryDTO + * @return + * @author fzp on 2022-02-23 + */ + List listJobExpectDTO(@Param("param") JobExpectQueryDTO jobExpectQueryDTO); + + long updateByUserId(@Param("param") JobExpect jobExpect); + + /** + * 期望岗位类型分组求数量 + */ + List positionTypeCodeGroupMap(@Param("recruitPositionType") String recruitPositionType); + +} diff --git a/src/main/java/com/newyetai/recruit/user/dao/ResumeMapper.java b/src/main/java/com/newyetai/recruit/user/dao/ResumeMapper.java new file mode 100644 index 0000000..18aaf4f --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/dao/ResumeMapper.java @@ -0,0 +1,28 @@ +package com.newyetai.recruit.user.dao; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.recruit.user.entity.Resume; +import com.newyetai.recruit.user.dto.ResumeDTO; +import com.newyetai.recruit.user.dto.ResumeQueryDTO; +import com.newyetai.recruit.user.dto.ResumePageQueryDTO; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 简历管理 + * + * @author guixinman + * @since 1.0.0 2024-04-19 + */ +@Mapper +public interface ResumeMapper extends MyMapper { + + List page(@Param("param") ResumePageQueryDTO queryDTO); + + List list(@Param("param") ResumeQueryDTO queryDTO); + + int updateByUserId(@Param("param") Resume resume); +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/user/dao/UserCertificateMapper.java b/src/main/java/com/newyetai/recruit/user/dao/UserCertificateMapper.java new file mode 100644 index 0000000..e1fbf26 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/dao/UserCertificateMapper.java @@ -0,0 +1,22 @@ +package com.newyetai.recruit.user.dao; + + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.recruit.user.dto.UserCertificateDTO; +import com.newyetai.recruit.user.dto.UserCertificateQueryDTO; +import com.newyetai.recruit.user.entity.UserCertificate; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; +@Mapper +public interface UserCertificateMapper extends MyMapper { + + /** + * 查询 + * + */ + List page(@Param("param") UserCertificateQueryDTO queryDTO); + +} diff --git a/src/main/java/com/newyetai/recruit/user/dao/UserCollectionMapper.java b/src/main/java/com/newyetai/recruit/user/dao/UserCollectionMapper.java new file mode 100644 index 0000000..2dc4a2d --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/dao/UserCollectionMapper.java @@ -0,0 +1,19 @@ +package com.newyetai.recruit.user.dao; + + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.recruit.user.entity.UserCollection; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +@Mapper +public interface UserCollectionMapper extends MyMapper { + + @Select("select post_id from hr_user_collection where deleted = 0 and user_id = #{userId} order by create_time desc limit #{startSize},#{endSize}") + List page(@Param("userId") Long userId, @Param("startSize") Integer startSize, @Param("endSize") Integer endSize); + +} diff --git a/src/main/java/com/newyetai/recruit/user/dto/BrowseRecordDTO.java b/src/main/java/com/newyetai/recruit/user/dto/BrowseRecordDTO.java new file mode 100644 index 0000000..bf4acad --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/dto/BrowseRecordDTO.java @@ -0,0 +1,49 @@ +package com.newyetai.recruit.user.dto; + +import com.newyetai.common.entity.BaseEntity; + +import javax.validation.constraints.NotNull; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +/** + *

+ * 用户岗位访问DTO + *

+ * + * @author Carlye + * @since 2021-01-21 + */ +@ApiModel("招聘用户岗位访问DTO") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +public class BrowseRecordDTO extends BaseEntity { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("用户ID") + private Long userId; + + @ApiModelProperty("岗位ID") + @NotNull(message = "岗位ID不能为空") + private Long positionId; + + @ApiModelProperty("访问记录数") + private Integer numberOfVisits; + + @ApiModelProperty("头像") + private String avatar; + + private String positionName; +} diff --git a/src/main/java/com/newyetai/recruit/user/dto/BrowseRecordPageQueryDTO.java b/src/main/java/com/newyetai/recruit/user/dto/BrowseRecordPageQueryDTO.java new file mode 100644 index 0000000..5d6c851 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/dto/BrowseRecordPageQueryDTO.java @@ -0,0 +1,38 @@ +package com.newyetai.recruit.user.dto; + +import com.newyetai.common.dto.PageQueryDTO; + +import javax.validation.constraints.NotNull; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +/** + *

+ * 用户岗位访问DTO + *

+ * + * @author Carlye + * @since 2021-01-21 + */ +@ApiModel("招聘用户岗位访问查询DTO") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +public class BrowseRecordPageQueryDTO extends PageQueryDTO { + + + private static final long serialVersionUID = -3261822980006851294L; + @ApiModelProperty("岗位ID") + @NotNull(message = "岗位ID不能为空") + private Long positionId; +} diff --git a/src/main/java/com/newyetai/recruit/user/dto/BrowseRecordUserPageQueryDTO.java b/src/main/java/com/newyetai/recruit/user/dto/BrowseRecordUserPageQueryDTO.java new file mode 100644 index 0000000..dee48ed --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/dto/BrowseRecordUserPageQueryDTO.java @@ -0,0 +1,14 @@ +package com.newyetai.recruit.user.dto; + +import com.newyetai.common.dto.PageQueryDTO; + +import lombok.Data; + +/** + * @description: + * @author: guixinman + * @create: 2024-05-07 10:03 + **/ +@Data +public class BrowseRecordUserPageQueryDTO extends PageQueryDTO { +} diff --git a/src/main/java/com/newyetai/recruit/user/dto/JobExpectDTO.java b/src/main/java/com/newyetai/recruit/user/dto/JobExpectDTO.java new file mode 100644 index 0000000..9f81402 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/dto/JobExpectDTO.java @@ -0,0 +1,47 @@ +package com.newyetai.recruit.user.dto; + +import com.newyetai.common.dto.BaseDTO; + +import java.math.BigDecimal; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author fzp on 2022-02-23 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@ApiModel(description = "求职期望表") +public class JobExpectDTO extends BaseDTO { + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("用户id") + private Long userId; + @ApiModelProperty("岗位类型编码") + private String typeCode; +// @ApiModelProperty("岗位类型名称") +// private String typeName; + @ApiModelProperty("期望城市") + private String expectCity; + @ApiModelProperty("期望城市名称") + private String expectCityName; + @ApiModelProperty("期望月薪") + private BigDecimal expectSalary; + @ApiModelProperty("是否在职 0否 1是") + private Boolean onDuty; + @ApiModelProperty("入职周期:1随时入职、2 2周内入职、3一个月内入职") + private Integer inductionCycle; + + private String positionName; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/user/dto/JobExpectOperateDTO.java b/src/main/java/com/newyetai/recruit/user/dto/JobExpectOperateDTO.java new file mode 100644 index 0000000..d90858e --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/dto/JobExpectOperateDTO.java @@ -0,0 +1,55 @@ +package com.newyetai.recruit.user.dto; + +import com.newyetai.common.dto.BaseOperateDTO; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; + +import java.io.Serializable; +import java.math.BigDecimal; + +import javax.validation.constraints.NotNull; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author fzp on 2022-02-23 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "求职期望表操作") +public class JobExpectOperateDTO extends BaseOperateDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @NotNull(message = "id不能为空", groups = {Update.class}) + private Long id; + + @ApiModelProperty("用户id") + private Long userId; + @ApiModelProperty("岗位类型编码") + @NotNull(message = "岗位类型不能为空", groups = {Update.class}) + private String typeCode; + @ApiModelProperty("期望城市") + @NotNull(message = "期望城市不能为空", groups = {Update.class, Create.class}) + private String expectCity; + @ApiModelProperty("期望月薪") + @NotNull(message = "期望月薪不能为空", groups = {Update.class}) + private BigDecimal expectSalary; + + @ApiModelProperty("是否在职 0否 1是") + private Boolean onDuty; + @ApiModelProperty("入职周期:1随时入职、2 2周内入职、3一个月内入职") + private Integer inductionCycle; + + @NotNull(message = "求职意向岗位不能为空", groups = {Create.class}) + private String positionName; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/user/dto/JobExpectQueryDTO.java b/src/main/java/com/newyetai/recruit/user/dto/JobExpectQueryDTO.java new file mode 100644 index 0000000..774bf57 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/dto/JobExpectQueryDTO.java @@ -0,0 +1,33 @@ +package com.newyetai.recruit.user.dto; + +import com.newyetai.common.dto.PageQueryDTO; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author fzp on 2022-02-23 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "求职期望表查询条件") +public class JobExpectQueryDTO extends PageQueryDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("用户id") + private Long userId; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/user/dto/ResumeDTO.java b/src/main/java/com/newyetai/recruit/user/dto/ResumeDTO.java new file mode 100644 index 0000000..a9616c7 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/dto/ResumeDTO.java @@ -0,0 +1,48 @@ +package com.newyetai.recruit.user.dto; + +import com.newyetai.common.dto.BaseDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.SuperBuilder; + +/** + * 简历管理 + * + * @author guixinman + * @since 1.0.0 2024-04-19 + */ +@ApiModel("简历管理") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class ResumeDTO extends BaseDTO { + private static final long serialVersionUID = 1L; + + @ApiModelProperty("用户id") + private Long userId; + + @ApiModelProperty("简历附件") + private String fileCode; + + private String fileName; + + @ApiModelProperty("所在城市") + private String cityCode; + + private String cityCodeName; + + @ApiModelProperty("学历") + private String education; + + @ApiModelProperty("个人评价") + private String selfEvaluation; + + @ApiModelProperty("备注") + private String remark; + + private String dataJson; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/user/dto/ResumeOperatorDTO.java b/src/main/java/com/newyetai/recruit/user/dto/ResumeOperatorDTO.java new file mode 100644 index 0000000..094def8 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/dto/ResumeOperatorDTO.java @@ -0,0 +1,63 @@ +package com.newyetai.recruit.user.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; + +import org.hibernate.validator.constraints.Length; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +import javax.validation.constraints.NotBlank; + +/** + * 简历管理 + * + * @author guixinman + * @since 1.0.0 2024-04-19 + */ +@ApiModel("简历管理") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ResumeOperatorDTO implements Serializable { + private static final long serialVersionUID = 1L; + + private Long id; + + @ApiModelProperty("用户id") + private Long userId; + + @Length(max = 32,message = "简历附件超长",groups = {Create.class, Update.class}) + @NotBlank(message = "简历附件不能为空",groups = {Create.class, Update.class}) + @ApiModelProperty("简历附件") + private String fileCode; + + @Length(max = 50,message = "所在城市长度超长",groups = {Create.class, Update.class}) + @NotBlank(message = "所在城市不能为空",groups = {Create.class, Update.class}) + @ApiModelProperty("所在城市") + private String cityCode; + + @Length(max = 32,message = "学历长度超长",groups = {Create.class, Update.class}) + @NotBlank(message = "学历不能为空",groups = {Create.class, Update.class}) + @ApiModelProperty("学历") + private String education; + + @Length(max = 255,message = "个人评价长度超长",groups = {Create.class, Update.class}) + @NotBlank(message = "个人评价不能为空",groups = {Create.class, Update.class}) + @ApiModelProperty("个人评价") + private String selfEvaluation; + + @ApiModelProperty("备注") + private String remark; + + private String dataJson; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/user/dto/ResumePageQueryDTO.java b/src/main/java/com/newyetai/recruit/user/dto/ResumePageQueryDTO.java new file mode 100644 index 0000000..ed0fe28 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/dto/ResumePageQueryDTO.java @@ -0,0 +1,73 @@ +package com.newyetai.recruit.user.dto; + +import com.newyetai.common.dto.PageQueryDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.format.annotation.DateTimeFormat; + + +import java.util.Date; + +/** + * 简历管理 + * + * @author guixinman + * @since 1.0.0 2024-04-19 + */ + +@ApiModel("简历管理") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class ResumePageQueryDTO extends PageQueryDTO { + private static final long serialVersionUID = 1L; + + private Long id; + + @ApiModelProperty("用户id") + private Long userId; + + @ApiModelProperty("简历附件") + private String fileCode; + + @ApiModelProperty("所在城市") + private String cityCode; + + @ApiModelProperty("学历") + private String education; + + @ApiModelProperty("个人评价") + private String selfEvaluation; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("更新时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeStart; + + @ApiModelProperty("更新时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeEnd; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/user/dto/ResumeQueryDTO.java b/src/main/java/com/newyetai/recruit/user/dto/ResumeQueryDTO.java new file mode 100644 index 0000000..d8059ae --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/dto/ResumeQueryDTO.java @@ -0,0 +1,73 @@ +package com.newyetai.recruit.user.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; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +/** + * 简历管理 + * + * @author guixinman + * @since 1.0.0 2024-04-19 + */ +@ApiModel("简历管理") +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ResumeQueryDTO implements Serializable { + private static final long serialVersionUID = 1L; + + private Long id; + + @ApiModelProperty("用户id") + private Long userId; + + @ApiModelProperty("简历附件") + private String fileCode; + + @ApiModelProperty("所在城市") + private String cityCode; + + @ApiModelProperty("学历") + private String education; + + @ApiModelProperty("个人评价") + private String selfEvaluation; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("更新时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeStart; + + @ApiModelProperty("更新时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeEnd; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/user/dto/UserCertificateCreateDTO.java b/src/main/java/com/newyetai/recruit/user/dto/UserCertificateCreateDTO.java new file mode 100644 index 0000000..05a70f9 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/dto/UserCertificateCreateDTO.java @@ -0,0 +1,44 @@ +package com.newyetai.recruit.user.dto; + +import com.newyetai.common.dto.BaseOperateDTO; + +import java.io.Serializable; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "用户证书创建") +public class UserCertificateCreateDTO extends BaseOperateDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("用户id") + private Long userId; + + @ApiModelProperty("证书Code") + @NotBlank(message = "证书code不能为空") + private String fileCode; + + @ApiModelProperty("证书名称") + private String fileName; + + @ApiModelProperty("证件类型") + @NotNull(message = "证件类型不能为空") + private Integer certType; + + @NotBlank(message = "证件名称不能为空") + @ApiModelProperty("证件名称") + private String name; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/user/dto/UserCertificateDTO.java b/src/main/java/com/newyetai/recruit/user/dto/UserCertificateDTO.java new file mode 100644 index 0000000..992bc05 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/dto/UserCertificateDTO.java @@ -0,0 +1,38 @@ +package com.newyetai.recruit.user.dto; + +import com.newyetai.common.dto.BaseDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@ApiModel(description = "用户证书") +public class UserCertificateDTO extends BaseDTO { + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("用户id") + private Long userId; + + @ApiModelProperty("证书Code") + private String fileCode; + + @ApiModelProperty("证书名称") + private String fileName; + + @ApiModelProperty("证件类型") + private Integer certType; + + @ApiModelProperty("证件名称") + private String name; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/user/dto/UserCertificateModifyDTO.java b/src/main/java/com/newyetai/recruit/user/dto/UserCertificateModifyDTO.java new file mode 100644 index 0000000..4a53553 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/dto/UserCertificateModifyDTO.java @@ -0,0 +1,41 @@ +package com.newyetai.recruit.user.dto; + +import com.newyetai.common.dto.BaseOperateDTO; + +import java.io.Serializable; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "用户证书操作") +public class UserCertificateModifyDTO extends BaseOperateDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @NotNull(message = "id不能为空") + private Long id; + + @ApiModelProperty("证书Code") + @NotBlank(message = "证书code不能为空") + private String fileCode; + + @ApiModelProperty("证书名称") + private String fileName; + + @NotBlank(message = "证件名称不能为空") + @ApiModelProperty("证件名称") + private String name; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/user/dto/UserCertificateQueryDTO.java b/src/main/java/com/newyetai/recruit/user/dto/UserCertificateQueryDTO.java new file mode 100644 index 0000000..a476749 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/dto/UserCertificateQueryDTO.java @@ -0,0 +1,33 @@ +package com.newyetai.recruit.user.dto; + +import com.newyetai.common.dto.PageQueryDTO; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author fzp on 2022-02-23 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "用户证书查询条件") +public class UserCertificateQueryDTO extends PageQueryDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("用户id") + private Long userId; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/user/dto/UserCollectionCreateDTO.java b/src/main/java/com/newyetai/recruit/user/dto/UserCollectionCreateDTO.java new file mode 100644 index 0000000..3426975 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/dto/UserCollectionCreateDTO.java @@ -0,0 +1,21 @@ +package com.newyetai.recruit.user.dto; + +import com.newyetai.common.validation.Create; + +import javax.validation.constraints.NotNull; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class UserCollectionCreateDTO { + + @ApiModelProperty("岗位id") + @NotNull(message = "岗位ID不能为空", groups = {Create.class}) + private Long positionId; + +} diff --git a/src/main/java/com/newyetai/recruit/user/entity/BrowseRecord.java b/src/main/java/com/newyetai/recruit/user/entity/BrowseRecord.java new file mode 100644 index 0000000..e83edb6 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/entity/BrowseRecord.java @@ -0,0 +1,42 @@ +package com.newyetai.recruit.user.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +/** + *

+ * 用户岗位访问记录表 + *

+ * + * @author Carlye + * @since 2021-01-21 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@TableName("hr_position_browse_record") +public class BrowseRecord extends BaseEntity { + + private static final long serialVersionUID = 5473693561130145709L; + + + /** + * 用户ID + */ + private Long userId; + + /** + * 岗位ID + */ + private Long positionId; +} diff --git a/src/main/java/com/newyetai/recruit/user/entity/JobExpect.java b/src/main/java/com/newyetai/recruit/user/entity/JobExpect.java new file mode 100644 index 0000000..f8c07a9 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/entity/JobExpect.java @@ -0,0 +1,60 @@ +package com.newyetai.recruit.user.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import java.math.BigDecimal; + + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 求职期望表 + * + * @author fzp on 2022-02-23 + */ +@TableName(value = "hr_job_expect") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +public class JobExpect extends BaseEntity { + + /** + * + **/ + private static final long serialVersionUID = 1L; + + /** + * 用户id + **/ + private Long userId; + /** + * 岗位类型编码 + **/ + private String typeCode; + /** + * 期望城市 + **/ + private String expectCity; + /** + * 期望月薪 + **/ + private BigDecimal expectSalary; + /** + * 是否在职 0否 1是 + **/ + private Boolean onDuty; + /** + * 入职周期:1随时入职、2 2周内入职、3一个月内入职 + **/ + private Integer inductionCycle; + + private String positionName; + +} diff --git a/src/main/java/com/newyetai/recruit/user/entity/Resume.java b/src/main/java/com/newyetai/recruit/user/entity/Resume.java new file mode 100644 index 0000000..cc7ec47 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/entity/Resume.java @@ -0,0 +1,51 @@ +package com.newyetai.recruit.user.entity; + + +import lombok.*; + +import com.baomidou.mybatisplus.annotation.*; +import com.newyetai.common.entity.BaseEntity; + +/** + * 简历管理 + * + * @author guixinman + * @since 1.0.0 2024-04-19 + */ +@TableName(value = "hr_resume") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class Resume extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * 用户id + */ + private Long userId; + /** + * 简历附件 + */ + private String fileCode; + /** + * 所在城市 + */ + private String cityCode; + /** + * 学历 + */ + private String education; + /** + * 个人评价 + */ + private String selfEvaluation; + /** + * 备注 + */ + private String remark; + + private String dataJson; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/user/entity/UserCertificate.java b/src/main/java/com/newyetai/recruit/user/entity/UserCertificate.java new file mode 100644 index 0000000..b9eb542 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/entity/UserCertificate.java @@ -0,0 +1,46 @@ +package com.newyetai.recruit.user.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author fzp + * @date 2022年6月8日09:29:20 + */ + +@TableName(value = "uc_user_certificate") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +public class UserCertificate extends BaseEntity { + + /** + * 用户Id + */ + private Long userId; + + /** + * 简历Code + */ + private String fileCode; + /** + * 简历名称 + */ + private String fileName; + + /** 证件类型 **/ + private Integer certType; + + @ApiModelProperty("证件名称") + private String name; +} diff --git a/src/main/java/com/newyetai/recruit/user/entity/UserCollection.java b/src/main/java/com/newyetai/recruit/user/entity/UserCollection.java new file mode 100644 index 0000000..75bf8cb --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/entity/UserCollection.java @@ -0,0 +1,41 @@ +package com.newyetai.recruit.user.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import java.io.Serializable; +import java.util.Date; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author fzp + * @date 2021年10月21日10:47:31 + */ +@TableName(value = "hr_user_collection") +@Data +@NoArgsConstructor +@AllArgsConstructor +public class UserCollection extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 用户ID + */ + private Long userId; + /** + * 收藏的岗位ID + */ + private Long postId; + + @Builder + public UserCollection(Long id, Boolean deleted, Long createBy, Date createTime, Long updateBy, Date updateTime, Long proxyBy, Long userId, Long postId) { + super(id, deleted, createBy, createTime, updateBy, updateTime, proxyBy); + this.userId = userId; + this.postId = postId; + } +} diff --git a/src/main/java/com/newyetai/recruit/user/enums/InductionCycleEnum.java b/src/main/java/com/newyetai/recruit/user/enums/InductionCycleEnum.java new file mode 100644 index 0000000..ab05be1 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/enums/InductionCycleEnum.java @@ -0,0 +1,47 @@ +package com.newyetai.recruit.user.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.newyetai.mybatis.handle.BaseEnum; + +/** + * 入职周期枚举 + */ +public enum InductionCycleEnum implements BaseEnum { + + ANY_TIME(1, "随时入职"), + TWO_WEEKS(2, "2周内入职"), + ONE_MONTH(3, "一个月内入职"); + + @EnumValue + private final Integer type; + + private final String desc; + + InductionCycleEnum(Integer type, String desc) { + this.type = type; + this.desc = desc; + } + + public Integer getType() { + return type; + } + + public String getDesc() { + return desc; + } + + @Override + public Integer getValue() { + return type; + } + + + public static Integer findTypeByDesc(String desc) { + for (InductionCycleEnum type : InductionCycleEnum.values()) { + if (type.getDesc().equals(desc)) { + return type.getType(); + } + } + return null; // 如果没有找到,返回null + } +} diff --git a/src/main/java/com/newyetai/recruit/user/mapper/BrowseRecordMapper.xml b/src/main/java/com/newyetai/recruit/user/mapper/BrowseRecordMapper.xml new file mode 100644 index 0000000..fbbb430 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/mapper/BrowseRecordMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + diff --git a/src/main/java/com/newyetai/recruit/user/mapper/JobExpectMapper.xml b/src/main/java/com/newyetai/recruit/user/mapper/JobExpectMapper.xml new file mode 100644 index 0000000..410975c --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/mapper/JobExpectMapper.xml @@ -0,0 +1,47 @@ + + + + + + update hr_job_expect + set type_code = #{param.typeCode}, + expect_city = #{param.expectCity}, + expect_salary = #{param.expectSalary}, + on_duty = #{param.onDuty}, + induction_cycle = #{param.inductionCycle}, + update_by = #{param.userId}, + update_time = now() + where user_id = #{param.userId} and deleted = 0 + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/user/mapper/ResumeMapper.xml b/src/main/java/com/newyetai/recruit/user/mapper/ResumeMapper.xml new file mode 100644 index 0000000..cf53641 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/mapper/ResumeMapper.xml @@ -0,0 +1,87 @@ + + + + + + + update hr_resume + set + update_by = #{param.userId}, + update_time = now() + + + ,file_code = #{param.fileCode} + + + ,city_code = #{param.cityCode} + + + ,education = #{param.education} + + + ,self_evaluation = #{param.selfEvaluation} + + + ,deleted = #{param.deleted} + + + ,data_json = #{param.dataJson} + + where user_id = #{param.userId} and deleted = 0 + + + + + + + + + FROM + hr_resume t + left join xs_district xd1 on t.city_code = xd1.code + left join xs_district xd2 on xd1.parent_id = xd2.id + left join xs_district xd3 on xd2.parent_id = xd3.id + WHERE t.deleted = 0 + + AND t.id = #{param.id} + + + AND t.user_id = #{param.userId} + + + AND t.file_code = #{param.fileCode} + + + AND t.city_code = #{param.cityCode} + + + AND t.education = #{param.education} + + + AND t.self_evaluation = #{param.selfEvaluation} + + + AND t.remark = #{param.remark} + + + AND t.create_time >= #{param.createTimeStart} + + + AND t.create_time <= #{param.createTimeEnd} + + + AND t.update_time >= #{param.updateTimeStart} + + + AND t.update_time <= #{param.updateTimeEnd} + + ORDER BY t.id DESC + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/user/mapper/UserCertificateMapper.xml b/src/main/java/com/newyetai/recruit/user/mapper/UserCertificateMapper.xml new file mode 100644 index 0000000..7171807 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/mapper/UserCertificateMapper.xml @@ -0,0 +1,19 @@ + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/user/service/BrowseRecordService.java b/src/main/java/com/newyetai/recruit/user/service/BrowseRecordService.java new file mode 100644 index 0000000..2cfdf16 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/service/BrowseRecordService.java @@ -0,0 +1,47 @@ +package com.newyetai.recruit.user.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.newyetai.recruit.user.dto.BrowseRecordDTO; +import com.newyetai.recruit.user.dto.BrowseRecordPageQueryDTO; +import com.newyetai.recruit.user.dto.BrowseRecordUserPageQueryDTO; +import com.newyetai.recruit.user.entity.BrowseRecord; + +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import javax.validation.Valid; +import javax.validation.groups.Default; + +/** + *

+ * 用户岗位访问记录表 服务类 + *

+ * + * @author Carlye + * @since 2021-01-21 + */ +@Validated(Default.class) +public interface BrowseRecordService extends IService { + + + /** + * 新增用户访问记录 + * + * @param recordDTO 记录dto + * @return {@link BrowseRecord} + */ + void create(BrowseRecordDTO recordDTO); + + /** + * 分页查询 + * + * @param queryDTO 查询dto + * @return {@link List< BrowseRecordDTO >} + */ + List pagePosition(@Valid BrowseRecordPageQueryDTO queryDTO); + + Integer statistics(); + + List browseRecordUserPage(BrowseRecordUserPageQueryDTO queryDTO); +} diff --git a/src/main/java/com/newyetai/recruit/user/service/JobExpectService.java b/src/main/java/com/newyetai/recruit/user/service/JobExpectService.java new file mode 100644 index 0000000..fa085ae --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/service/JobExpectService.java @@ -0,0 +1,76 @@ +package com.newyetai.recruit.user.service; + + +import com.newyetai.recruit.user.dto.JobExpectDTO; +import com.newyetai.recruit.user.dto.JobExpectOperateDTO; +import com.newyetai.recruit.user.dto.JobExpectQueryDTO; + +import java.util.List; + +/** + * 求职期望表 + * + * @author fzp on 2022-02-23 + */ +public interface JobExpectService { + + /** + * 新增 + * + * @param jobExpectOperateDTO + * @return + * @author fzp on 2022-02-23 + */ + Long create(JobExpectOperateDTO jobExpectOperateDTO); + + /** + * 修改 + * + * @param jobExpectOperateDTO + * @author fzp on 2022-02-23 + */ + void modify(JobExpectOperateDTO jobExpectOperateDTO); + + /** + * 更新求职状态 + * @param jobExpectOperateDTO + */ + void modifyOnDuty(JobExpectOperateDTO jobExpectOperateDTO); + + /** + * 删除 + * + * @param id + * @author fzp on 2022-02-23 + */ + void remove(Long id); + void removeByUserId(); + + /** + * 查询 + * + * @param jobExpectQueryDTO + * @return + * @author fzp on 2022-02-23 + */ + List list(JobExpectQueryDTO jobExpectQueryDTO); + + /** + * 分页查询 + * + * @param jobExpectQueryDTO + * @return + * @author fzp on 2022-02-23 + */ + void page(JobExpectQueryDTO jobExpectQueryDTO); + + /** + * 单个查询 + * + * @param jobExpectQueryDTO + * @return + * @author fzp on 2022-02-23 + */ + JobExpectDTO find(JobExpectQueryDTO jobExpectQueryDTO); + +} diff --git a/src/main/java/com/newyetai/recruit/user/service/ResumeService.java b/src/main/java/com/newyetai/recruit/user/service/ResumeService.java new file mode 100644 index 0000000..739c2b5 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/service/ResumeService.java @@ -0,0 +1,70 @@ +package com.newyetai.recruit.user.service; + +import org.springframework.validation.annotation.Validated; + +import javax.validation.Valid; +import javax.validation.groups.Default; + +import java.util.List; + +import com.newyetai.recruit.user.dto.*; + +/** + * 简历管理 + * + * @author guixinman + * @since 1.0.0 2024-04-19 + */ +@Validated(Default.class) +public interface ResumeService { + + /** + * 简历管理 - 创建 + * + * @param operatorDto 操作dto + * @return {@link ResumeDTO} + */ + void createOrModify(ResumeOperatorDTO operatorDto); + + /** + * 简历管理 - 修改 + * + * @param operatorDto 操作dto + * @return {@link ResumeDTO} + */ + void modify(@Valid ResumeOperatorDTO operatorDto); + + /** + * 简历管理 - 删除 + * + * @param id id + * @return {@link ResumeDTO} + */ + void delete(); + + /** + * 简历管理 - 根据ID查询单个 + * + * @param id id + * @return {@link ResumeDTO} + */ + ResumeDTO findById(Long id); + + /** + * 简历管理 - 列表查询 + * + * @param queryDTO 列表查询dto + * @return {@link List}<{@link ResumeDTO}> + */ + List list(ResumeQueryDTO queryDTO); + + /** + * 简历管理 - 分页查询 + * + * @param queryDTO 分页查询dto + * @return {@link ResumeDTO} + */ + List page(ResumePageQueryDTO queryDTO); + + ResumeDTO userFind(); +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/user/service/UserCertificateService.java b/src/main/java/com/newyetai/recruit/user/service/UserCertificateService.java new file mode 100644 index 0000000..2e5480e --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/service/UserCertificateService.java @@ -0,0 +1,26 @@ +package com.newyetai.recruit.user.service; + + + +import com.newyetai.recruit.user.dto.UserCertificateCreateDTO; +import com.newyetai.recruit.user.dto.UserCertificateDTO; +import com.newyetai.recruit.user.dto.UserCertificateModifyDTO; +import com.newyetai.recruit.user.dto.UserCertificateQueryDTO; + +import java.util.List; + +public interface UserCertificateService { + + void create(List operateDTOs); + + UserCertificateDTO modify(UserCertificateModifyDTO operateDTO); + + UserCertificateDTO delete(Long id); + + List list(UserCertificateQueryDTO queryDTO); + + List page(UserCertificateQueryDTO queryDTO); + + UserCertificateDTO findById(Long queryDTO); + +} diff --git a/src/main/java/com/newyetai/recruit/user/service/UserCollectionService.java b/src/main/java/com/newyetai/recruit/user/service/UserCollectionService.java new file mode 100644 index 0000000..66c78ee --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/service/UserCollectionService.java @@ -0,0 +1,23 @@ +package com.newyetai.recruit.user.service; + +import com.newyetai.recruit.position.dto.PositionDTO; +import com.newyetai.recruit.position.dto.PositionPageQueryDTO; +import com.newyetai.recruit.user.dto.UserCollectionCreateDTO; + +import java.util.List; + +/** + * @Author fzp + * @Date 2021年10月21日10:39:46 + * @Version 1.0 + */ +public interface UserCollectionService { + + List page(PositionPageQueryDTO queryDTO); + + void create(UserCollectionCreateDTO dto); + + int delete(Long id); + + Integer statistics(); +} diff --git a/src/main/java/com/newyetai/recruit/user/service/impl/BrowseRecordServiceImpl.java b/src/main/java/com/newyetai/recruit/user/service/impl/BrowseRecordServiceImpl.java new file mode 100644 index 0000000..cafe915 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/service/impl/BrowseRecordServiceImpl.java @@ -0,0 +1,65 @@ +package com.newyetai.recruit.user.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.recruit.user.dao.BrowseRecordMapper; +import com.newyetai.recruit.user.dto.BrowseRecordDTO; +import com.newyetai.recruit.user.dto.BrowseRecordPageQueryDTO; +import com.newyetai.recruit.user.dto.BrowseRecordUserPageQueryDTO; +import com.newyetai.recruit.user.entity.BrowseRecord; +import com.newyetai.recruit.user.service.BrowseRecordService; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Date; +import java.util.List; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + + +/** + *

+ * 用户岗位访问记录表 服务实现类 + *

+ * + * @author Carlye + * @since 2021-01-21 + */ +@Slf4j +@Service +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class BrowseRecordServiceImpl extends ServiceImpl implements BrowseRecordService { + + @Override + public void create(BrowseRecordDTO recordDTO) { + BrowseRecord browseRecord = new BrowseRecord(); + browseRecord.setPositionId(recordDTO.getPositionId()); + browseRecord.setUserId(UserContextHolder.getExistLoginUserId()); + browseRecord.setCreateBy(UserContextHolder.getExistLoginUserId()); + browseRecord.setCreateTime(new Date()); + Assert.isTrue(save(browseRecord), "新增浏览记录失败"); + } + + @Override + public List pagePosition(BrowseRecordPageQueryDTO queryDTO) { + return getBaseMapper().pagePosition(queryDTO); + } + + @Override + public Integer statistics() { + Integer count = getBaseMapper().selectCount(new LambdaQueryWrapper() + .eq(BrowseRecord::getDeleted, false) + .eq(BrowseRecord::getUserId, UserContextHolder.getExistLoginUserId()) + ); + return count; + } + + @Override + public List browseRecordUserPage(BrowseRecordUserPageQueryDTO queryDTO) { + return getBaseMapper().pageUserPosition(queryDTO); + } +} diff --git a/src/main/java/com/newyetai/recruit/user/service/impl/JobExpectServiceImpl.java b/src/main/java/com/newyetai/recruit/user/service/impl/JobExpectServiceImpl.java new file mode 100644 index 0000000..8ae0ae0 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/service/impl/JobExpectServiceImpl.java @@ -0,0 +1,110 @@ +package com.newyetai.recruit.user.service.impl; + + +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.ListUtil; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.recruit.user.convert.JobExpectMapMapper; +import com.newyetai.recruit.user.dao.JobExpectMapper; +import com.newyetai.recruit.user.dto.JobExpectDTO; +import com.newyetai.recruit.user.dto.JobExpectOperateDTO; +import com.newyetai.recruit.user.dto.JobExpectQueryDTO; +import com.newyetai.recruit.user.entity.JobExpect; +import com.newyetai.recruit.user.service.JobExpectService; + +import org.apache.commons.collections.CollectionUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.stream.Collectors; + + +/** + * @author fzp on 2022-02-23 + */ +@Service +public class JobExpectServiceImpl implements JobExpectService { + + @Autowired + private JobExpectMapper jobExpectMapper; + + @Override + @Transactional + public Long create(JobExpectOperateDTO jobExpectOperateDTO) { +// List jobExpectDTOS = this.list(JobExpectQueryDTO.builder().userId(UserContextHolder.getLoginUserId()).build()); +// if (jobExpectDTOS.size() >= 3) { +// throw new BusinessException("添加失败,求职期望数量最多3个"); +// } + this.removeByUserId(); + JobExpect jobExpect = JobExpectMapMapper.INSTANCE.toEntity(jobExpectOperateDTO); + jobExpect.setUserId(UserContextHolder.getLoginUserId()); + jobExpectMapper.saveEntity(jobExpect); + return jobExpect.getId(); + } + + @Override + @Transactional + public void modify(JobExpectOperateDTO jobExpectOperateDTO) { + JobExpect jobExpect = JobExpectMapMapper.INSTANCE.toEntity(jobExpectOperateDTO); + jobExpect.setUserId(UserContextHolder.getLoginUserId()); + jobExpectMapper.updateEntitySelective(jobExpect); + } + + @Override + @Transactional + public void modifyOnDuty(JobExpectOperateDTO jobExpectOperateDTO) { + JobExpect jobExpect = JobExpectMapMapper.INSTANCE.toEntity(jobExpectOperateDTO); + jobExpect.setUserId(UserContextHolder.getLoginUserId()); + // 批量更新未删除的求职状态 + jobExpectMapper.updateByUserId(jobExpect); + } + + @Override + @Transactional + public void remove(Long id) { + List list = this.list(JobExpectQueryDTO.builder().userId(UserContextHolder.getLoginUserId()).build()); + if (CollectionUtils.isEmpty(list)) { + return; + } + List jobExpectDTOList = list.stream() + .filter(jobExpectDTO -> jobExpectDTO.getUserId().equals(UserContextHolder.getExistLoginUserId()) && + jobExpectDTO.getId().equals(id) + ).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(jobExpectDTOList)) { + return; + } + + jobExpectMapper.deleteEntity(JobExpect.builder().id(id).build(), UserContextHolder.getLoginUserId()); + } + + @Transactional + @Override + public void removeByUserId() { + List list = this.list(JobExpectQueryDTO.builder().userId(UserContextHolder.getLoginUserId()).build()); + for (JobExpectDTO jobExpectDTO : list) { + jobExpectMapper.deleteEntity(JobExpect.builder().id(jobExpectDTO.getId()).build(), UserContextHolder.getLoginUserId()); + } + } + + @Override + public List list(JobExpectQueryDTO jobExpectQueryDTO) { + jobExpectQueryDTO.disablePage(); + return jobExpectMapper.listJobExpectDTO(jobExpectQueryDTO); + } + + @Override + public void page(JobExpectQueryDTO jobExpectQueryDTO) { + jobExpectQueryDTO.setUserId(UserContextHolder.getLoginUserId()); + jobExpectMapper.listJobExpectDTO(jobExpectQueryDTO); + } + + @Override + public JobExpectDTO find(JobExpectQueryDTO jobExpectQueryDTO) { + List jobExpectDTOs = this.list(jobExpectQueryDTO); + return jobExpectDTOs.isEmpty() ? null : ListUtil.first(jobExpectDTOs); + } + +} diff --git a/src/main/java/com/newyetai/recruit/user/service/impl/ResumeServiceImpl.java b/src/main/java/com/newyetai/recruit/user/service/impl/ResumeServiceImpl.java new file mode 100644 index 0000000..3c52d71 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/service/impl/ResumeServiceImpl.java @@ -0,0 +1,114 @@ +package com.newyetai.recruit.user.service.impl; + +import lombok.extern.slf4j.Slf4j; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.newyetai.component.file.entity.FileRecord; +import com.newyetai.component.file.service.FileRecordService; +import com.newyetai.recruit.user.convert.ResumeConvert; +import com.newyetai.recruit.user.dto.*; +import com.newyetai.recruit.user.dao.ResumeMapper; +import com.newyetai.recruit.user.entity.Resume; +import com.newyetai.recruit.user.service.ResumeService; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.newyetai.common.util.UserContextHolder; + +import javax.annotation.Resource; + +import java.util.*; + +/** + * 简历管理 + * + * @author guixinman + * @since 1.0.0 2024-04-19 + */ +@Slf4j +@Service +public class ResumeServiceImpl implements ResumeService { + + @Resource + private ResumeMapper resumeMapper; + + @Autowired + private FileRecordService fileRecordService; + + @Override + public void createOrModify(ResumeOperatorDTO operatorDto) { + Integer count = resumeMapper.selectCount(new LambdaQueryWrapper() + .eq(Resume::getUserId, UserContextHolder.getExistLoginUserId()) + .eq(Resume::getDeleted, false) + ); + if (count == 0) { + Resume resume = ResumeConvert.INSTANCE.convert(operatorDto); + resume.setUserId(UserContextHolder.getExistLoginUserId()); + resumeMapper.saveEntity(resume); + } else { + this.modify(operatorDto); + } + } + + @Override + public void modify(ResumeOperatorDTO operatorDto) { + Resume resume = ResumeConvert.INSTANCE.convert(operatorDto); + resume.setUserId(UserContextHolder.getExistLoginUserId()); + resumeMapper.updateByUserId(resume); + } + + @Override + public void delete() { + + Resume resume = Resume.builder().build(); + resume.setUserId(UserContextHolder.getExistLoginUserId()); + resume.setDeleted(true); + resumeMapper.updateByUserId(resume); + } + + @Override + public ResumeDTO findById(Long id) { + Resume resume = resumeMapper.getById(id); + if (Objects.isNull(resume)) { + return null; + } + return ResumeConvert.INSTANCE.convert(resume); + } + + @Override + public List list(ResumeQueryDTO queryDTO) { + return resumeMapper.list(queryDTO); + } + + @Override + public List page(ResumePageQueryDTO queryDTO) { + return resumeMapper.page(queryDTO); + } + + @Override + public ResumeDTO userFind() { + Resume resume = resumeMapper.selectOne(new LambdaQueryWrapper() + .eq(Resume::getDeleted, false) + .eq(Resume::getUserId, UserContextHolder.getExistLoginUserId()) + ); + if (Objects.isNull(resume)) { + return null; + } + + ResumeDTO resumeDTO = ResumeDTO.builder().build(); + if (StringUtils.isNotBlank(resume.getFileCode())) { + FileRecord fileRecord = fileRecordService.find(FileRecord.builder().fileCode(resume.getFileCode()).build()); + if (Objects.nonNull(fileRecord)) { + resumeDTO.setFileName(fileRecord.getFileName()); + } + } + resumeDTO.setFileCode(resume.getFileCode()); + resumeDTO.setSelfEvaluation(resume.getSelfEvaluation()); + resumeDTO.setEducation(resume.getEducation()); + resumeDTO.setCityCode(resume.getCityCode()); + resumeDTO.setDataJson(resume.getDataJson()); + return resumeDTO; + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/recruit/user/service/impl/UserCertificateServiceImpl.java b/src/main/java/com/newyetai/recruit/user/service/impl/UserCertificateServiceImpl.java new file mode 100644 index 0000000..373d6a1 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/service/impl/UserCertificateServiceImpl.java @@ -0,0 +1,81 @@ +package com.newyetai.recruit.user.service.impl; + + +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.frame.redis.aop.annotation.AutoUnLock; +import com.newyetai.recruit.user.convert.UserCertificateMapMapper; +import com.newyetai.recruit.user.dao.UserCertificateMapper; +import com.newyetai.recruit.user.dto.UserCertificateCreateDTO; +import com.newyetai.recruit.user.dto.UserCertificateDTO; +import com.newyetai.recruit.user.dto.UserCertificateModifyDTO; +import com.newyetai.recruit.user.dto.UserCertificateQueryDTO; +import com.newyetai.recruit.user.entity.UserCertificate; +import com.newyetai.recruit.user.service.UserCertificateService; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Objects; + +/** + * @author fzp on 2022年6月8日09:58:44 + */ +@Service +public class UserCertificateServiceImpl implements UserCertificateService { + + @Autowired + private UserCertificateMapper userCertificateMapper; + + @Override + @AutoUnLock + @Transactional(rollbackFor = Exception.class) + public void create(List operateDTOs) { + List userCertificates = UserCertificateMapMapper.INSTANCE.toEntitys(operateDTOs); + userCertificates.forEach(userCertificate -> { + userCertificate.setUserId(UserContextHolder.getLoginUserId()); + }); + userCertificateMapper.saveEntites(userCertificates, UserContextHolder.getExistLoginUserId()); + } + + @Override + public UserCertificateDTO modify(UserCertificateModifyDTO operateDTO) { + UserCertificate exchange = UserCertificateMapMapper.INSTANCE.toEntity(operateDTO); + userCertificateMapper.updateEntitySelective(exchange); + UserCertificate byId = userCertificateMapper.getById(exchange.getId()); + return UserCertificateMapMapper.INSTANCE.toDTO(byId); + } + + @Override + public UserCertificateDTO delete(Long id) { + UserCertificate userCertificate = userCertificateMapper.getById(id); + if (Objects.isNull(userCertificate)) { + return null; + } + UserCertificate param = new UserCertificate(); + param.setId(id); + userCertificateMapper.deleteEntity(param, UserContextHolder.getLoginUserId()); + return UserCertificateMapMapper.INSTANCE.toDTO(userCertificate); + } + + @Override + public UserCertificateDTO findById(Long id) { + UserCertificate byId = userCertificateMapper.getById(id); + if (Objects.isNull(byId)) { + return null; + } + return UserCertificateMapMapper.INSTANCE.toDTO(byId); + } + + @Override + public List page(UserCertificateQueryDTO queryDTO) { + return userCertificateMapper.page(queryDTO); + } + + @Override + public List list(UserCertificateQueryDTO queryDTO) { + queryDTO.disablePage(); + return userCertificateMapper.page(queryDTO); + } +} diff --git a/src/main/java/com/newyetai/recruit/user/service/impl/UserCollectionServiceImpl.java b/src/main/java/com/newyetai/recruit/user/service/impl/UserCollectionServiceImpl.java new file mode 100644 index 0000000..71dc5b7 --- /dev/null +++ b/src/main/java/com/newyetai/recruit/user/service/impl/UserCollectionServiceImpl.java @@ -0,0 +1,89 @@ +package com.newyetai.recruit.user.service.impl; + + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.recruit.position.dto.PositionDTO; +import com.newyetai.recruit.position.dto.PositionPageQueryDTO; +import com.newyetai.recruit.position.service.PositionService; +import com.newyetai.recruit.user.dao.UserCollectionMapper; +import com.newyetai.recruit.user.dto.UserCollectionCreateDTO; +import com.newyetai.recruit.user.entity.UserCollection; +import com.newyetai.recruit.user.service.UserCollectionService; + +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + +import javax.annotation.Resource; + +import cn.hutool.core.collection.CollectionUtil; +import lombok.extern.slf4j.Slf4j; + +/** + * @Author dylanyuan + * @Date 2021/1/16 3:44 下午 + * @Version 1.0 + */ +@Slf4j +@Service +public class UserCollectionServiceImpl implements UserCollectionService { + + + @Resource + private UserCollectionMapper userCollectionMapper; + + @Resource + private PositionService positionService; + + @Override + public List page(PositionPageQueryDTO queryDTO) { + int pageNo = queryDTO.getPageNo(); + int pageSize = queryDTO.getPageSize(); + // 收藏的岗位id + List ids = userCollectionMapper.page(UserContextHolder.getLoginUserId(), (pageNo - 1) * pageSize, pageSize); + queryDTO.setIds(ids); + return CollectionUtils.isEmpty(ids) ? new ArrayList<>() : positionService.userPage(queryDTO); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void create(UserCollectionCreateDTO dto) { + UserCollection userCollection = UserCollection.builder() + .userId(UserContextHolder.getExistLoginUserId()) + .postId(dto.getPositionId()) + .deleted(false).build(); + + if (CollectionUtil.isEmpty(userCollectionMapper.selectList(new LambdaQueryWrapper() + .eq(UserCollection::getUserId, UserContextHolder.getExistLoginUserId()) + .eq(UserCollection::getPostId, dto.getPositionId()) + .eq(UserCollection::getDeleted, false) + ))) { + userCollectionMapper.saveEntity(userCollection); + } + } + + @Override + public int delete(Long id) { + + List userCollection = userCollectionMapper.selectList(new LambdaQueryWrapper() + .eq(UserCollection::getUserId, UserContextHolder.getExistLoginUserId()) + .eq(UserCollection::getPostId, id) + .eq(UserCollection::getDeleted, false)); + if (!CollectionUtil.isEmpty(userCollection)) { + UserCollection entity = UserCollection.builder().id(userCollection.get(0).getId()) + .postId(id).build(); + return userCollectionMapper.deleteEntity(entity, UserContextHolder.getLoginUserId()); + } + return 0; + } + + @Override + public Integer statistics() { + return userCollectionMapper.selectCount(new LambdaQueryWrapper().eq(UserCollection::getDeleted, false).eq(UserCollection::getUserId, UserContextHolder.getExistLoginUserId())); + + } +} diff --git a/src/main/java/com/newyetai/sdk/bytedance/ByteDanceUtils.java b/src/main/java/com/newyetai/sdk/bytedance/ByteDanceUtils.java new file mode 100644 index 0000000..760dbfb --- /dev/null +++ b/src/main/java/com/newyetai/sdk/bytedance/ByteDanceUtils.java @@ -0,0 +1,30 @@ +package com.newyetai.sdk.bytedance; + +import com.newyetai.common.AlitaResult; +import com.newyetai.sdk.bytedance.constant.ByteDanceConstants; +import com.newyetai.sdk.bytedance.model.BaseByteDanceDTO; +import com.newyetai.sdk.common.constant.SdkConstants; +import com.newyetai.sdk.common.dto.ISdkRequest; +import com.newyetai.sdk.common.exception.SdkException; +import com.newyetai.sdk.common.util.HttpUtils; + +/** + * @author sr on 2021-11-25 + */ +public class ByteDanceUtils { + + public static AlitaResult execute(ISdkRequest> req) { + try { + BaseByteDanceDTO dto = HttpUtils.post(req); + Long errNo = dto.getErrNo(); + if (ByteDanceConstants.SUCCESS_CODE.equals(errNo)) { + return AlitaResult.success(dto.getData()); + } + return AlitaResult.error(SdkConstants.SDK_HTTP_INVOKE_RESPONSE_FAIL_CODE, + dto.getErrNo() + dto.getErrTips()); + } catch (SdkException e) { + return AlitaResult.error("字节接口调用失败:" + e.getMessage()); + } + } + +} diff --git a/src/main/java/com/newyetai/sdk/bytedance/constant/ByteDanceConstants.java b/src/main/java/com/newyetai/sdk/bytedance/constant/ByteDanceConstants.java new file mode 100644 index 0000000..b52b663 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/bytedance/constant/ByteDanceConstants.java @@ -0,0 +1,11 @@ +package com.newyetai.sdk.bytedance.constant; + +/** + * 字节常量 + * @author sr on 2021-11-25 + */ +public interface ByteDanceConstants { + + Long SUCCESS_CODE = 0L; + +} diff --git a/src/main/java/com/newyetai/sdk/bytedance/model/AccessTokenDataDTO.java b/src/main/java/com/newyetai/sdk/bytedance/model/AccessTokenDataDTO.java new file mode 100644 index 0000000..05f870b --- /dev/null +++ b/src/main/java/com/newyetai/sdk/bytedance/model/AccessTokenDataDTO.java @@ -0,0 +1,25 @@ +package com.newyetai.sdk.bytedance.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class AccessTokenDataDTO { + + /** **/ + private static final long serialVersionUID = 814049874223007628L; + + /** 接口调用凭证 **/ + @JsonProperty("access_token") + private String accessToken; + + /** access_token接口调用凭证超时时间,单位(秒) **/ + @JsonProperty("expires_in") + private String expiresIn; + +} diff --git a/src/main/java/com/newyetai/sdk/bytedance/model/AccessTokenReqDTO.java b/src/main/java/com/newyetai/sdk/bytedance/model/AccessTokenReqDTO.java new file mode 100644 index 0000000..d807559 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/bytedance/model/AccessTokenReqDTO.java @@ -0,0 +1,48 @@ +package com.newyetai.sdk.bytedance.model; + +import org.springframework.core.ParameterizedTypeReference; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.newyetai.common.annotation.Mask; +import com.newyetai.sdk.common.dto.ISdkRequest; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Builder.Default; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class AccessTokenReqDTO implements ISdkRequest>{ + + /** **/ + private static final long serialVersionUID = 197693764614332172L; + private static ParameterizedTypeReference> type = + new ParameterizedTypeReference>() {}; + + /** 第三方用户唯一凭证 **/ + @JsonProperty("appid") + private String appId; + @Mask + /** 第三方用户唯一凭证密钥,即appsecret **/ + private String secret; + @Default + @JsonProperty("grant_type") + private String grantType = "client_credential"; + + @Override + public String getUri() { + return "https://developer.toutiao.com/api/apps/v2/token"; + } + + @Override + public ParameterizedTypeReference> getResponseType() { + return type; + } + + + +} diff --git a/src/main/java/com/newyetai/sdk/bytedance/model/BaseByteDanceDTO.java b/src/main/java/com/newyetai/sdk/bytedance/model/BaseByteDanceDTO.java new file mode 100644 index 0000000..39e73c0 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/bytedance/model/BaseByteDanceDTO.java @@ -0,0 +1,23 @@ +package com.newyetai.sdk.bytedance.model; + +import lombok.Data; + +import java.io.Serializable; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.newyetai.sdk.common.dto.ISdkResponse; + +@Data +public class BaseByteDanceDTO implements ISdkResponse, Serializable { + + /** 错误编码 **/ + @JsonProperty("err_no") + private Long errNo; + + /** 错误信息 **/ + @JsonProperty("err_tips") + private String errTips; + + private T data; + +} diff --git a/src/main/java/com/newyetai/sdk/bytedance/model/Code2SessionDataDTO.java b/src/main/java/com/newyetai/sdk/bytedance/model/Code2SessionDataDTO.java new file mode 100644 index 0000000..14db37a --- /dev/null +++ b/src/main/java/com/newyetai/sdk/bytedance/model/Code2SessionDataDTO.java @@ -0,0 +1,40 @@ +package com.newyetai.sdk.bytedance.model; + +import java.io.Serializable; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2021-11-25 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class Code2SessionDataDTO implements Serializable { + + /** **/ + private static final long serialVersionUID = -5908915158294552716L; + + /** 会话密钥,如果请求时有 code 参数才会返回 **/ + @JsonProperty("session_key") + private String sessionKey; + + /** 用户在当前小程序的 ID,如果请求时有 code 参数才会返回 **/ + @JsonProperty("openid") + private String openId; + + /** 匿名用户在当前小程序的 ID,如果请求时有 anonymous_code 参数才会返回 **/ + @JsonProperty("anonymous_openid") + private String anonymousOpenId; + + + /** 用户在小程序平台的唯一标识符,请求时有 code 参数才会返回。如果开发者拥有多个小程序,可通过 unionid 来区分用户的唯一性 **/ + @JsonProperty("unionid") + private String unionId; + + +} diff --git a/src/main/java/com/newyetai/sdk/bytedance/model/Code2SessionReqDTO.java b/src/main/java/com/newyetai/sdk/bytedance/model/Code2SessionReqDTO.java new file mode 100644 index 0000000..3e53a61 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/bytedance/model/Code2SessionReqDTO.java @@ -0,0 +1,49 @@ +package com.newyetai.sdk.bytedance.model; + +import org.springframework.core.ParameterizedTypeReference; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.newyetai.common.annotation.Mask; +import com.newyetai.sdk.common.dto.ISdkRequest; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class Code2SessionReqDTO implements ISdkRequest> { + + /** **/ + private static final long serialVersionUID = 197693764614332172L; + private static ParameterizedTypeReference> type = + new ParameterizedTypeReference>() {}; + + /** 第三方用户唯一凭证 **/ + @JsonProperty("appid") + private String appId; + @Mask + /** 第三方用户唯一凭证密钥,即appsecret **/ + private String secret; + /** login 接口返回的登录凭证 **/ + private String code; + /** login 接口返回的匿名登录凭证 **/ + @JsonProperty("anonymous_code") + private String anonymousCode; + + @Override + public String getUri() { + return "https://developer.toutiao.com/api/apps/v2/jscode2session"; + } + + @Override + public ParameterizedTypeReference> getResponseType() { + return type; + } + + + +} diff --git a/src/main/java/com/newyetai/sdk/captcha/config/CaptchaConfiguration.java b/src/main/java/com/newyetai/sdk/captcha/config/CaptchaConfiguration.java new file mode 100644 index 0000000..eae9750 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/captcha/config/CaptchaConfiguration.java @@ -0,0 +1,39 @@ +package com.newyetai.sdk.captcha.config; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import com.newyetai.sdk.captcha.service.ITencentCaptchaService; +import com.newyetai.sdk.captcha.service.impl.LoginCaptchaAppProvider; +import com.newyetai.sdk.captcha.service.impl.TencentCaptchaServiceImpl; +import com.tencentcloudapi.common.Credential; + +/** + * 验证码配置类 + * + * @author sr on 2020-08-10 + */ +@Configuration +@EnableConfigurationProperties({CaptchaProperties.class}) +public class CaptchaConfiguration { + + @Bean + @ConditionalOnProperty(havingValue = "true", name = "captcha.tencent.enable") + public ITencentCaptchaService tencentCaptchaService(CaptchaProperties captchaProperties) { + Credential credential = new Credential(captchaProperties.getTencent().getSecretId(), + captchaProperties.getTencent().getSecretKey()); + return new TencentCaptchaServiceImpl(credential); + } + + + @Bean + @ConditionalOnBean(ITencentCaptchaService.class) + public LoginCaptchaAppProvider loginCaptchaAppProvider( + ITencentCaptchaService tencentCaptchaService, CaptchaProperties captchaProperties) { + return new LoginCaptchaAppProvider(tencentCaptchaService, captchaProperties); + } + +} diff --git a/src/main/java/com/newyetai/sdk/captcha/config/CaptchaProperties.java b/src/main/java/com/newyetai/sdk/captcha/config/CaptchaProperties.java new file mode 100644 index 0000000..e4670b9 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/captcha/config/CaptchaProperties.java @@ -0,0 +1,23 @@ +package com.newyetai.sdk.captcha.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 属性配置 + * + * @author sr on 2020-08-10 + */ +@ConfigurationProperties(prefix = CaptchaProperties.PREFIX) +@Data +@NoArgsConstructor +public class CaptchaProperties { + + public static final String PREFIX = "captcha"; + + /** 腾讯配置 **/ + private TencentProperties tencent; + +} diff --git a/src/main/java/com/newyetai/sdk/captcha/config/TencentAppProperties.java b/src/main/java/com/newyetai/sdk/captcha/config/TencentAppProperties.java new file mode 100644 index 0000000..9b8d4ff --- /dev/null +++ b/src/main/java/com/newyetai/sdk/captcha/config/TencentAppProperties.java @@ -0,0 +1,18 @@ +package com.newyetai.sdk.captcha.config; + +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 腾讯验证码应用配置 + * + * @author sr on 2020-08-11 + */ +@Data +@NoArgsConstructor +public class TencentAppProperties { + + private String appId; + private String appSecret; + +} diff --git a/src/main/java/com/newyetai/sdk/captcha/config/TencentProperties.java b/src/main/java/com/newyetai/sdk/captcha/config/TencentProperties.java new file mode 100644 index 0000000..2a69a3b --- /dev/null +++ b/src/main/java/com/newyetai/sdk/captcha/config/TencentProperties.java @@ -0,0 +1,24 @@ +package com.newyetai.sdk.captcha.config; + +import java.util.HashMap; +import java.util.Map; + +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 腾讯配置 + * + * @author sr on 2020-08-11 + */ +@Data +@NoArgsConstructor +public class TencentProperties { + + private Boolean enable; + private String secretId; + private String secretKey; + + private final Map app = new HashMap<>(); + +} diff --git a/src/main/java/com/newyetai/sdk/captcha/dto/TencentCaptchaDTO.java b/src/main/java/com/newyetai/sdk/captcha/dto/TencentCaptchaDTO.java new file mode 100644 index 0000000..ccf324b --- /dev/null +++ b/src/main/java/com/newyetai/sdk/captcha/dto/TencentCaptchaDTO.java @@ -0,0 +1,57 @@ +package com.newyetai.sdk.captcha.dto; + +import java.io.Serializable; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2020-08-10 + */ +@Data +@NoArgsConstructor +public class TencentCaptchaDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 2301105027025640174L; + + /** 前端回调函数返回的用户验证票据(必填) **/ + @JsonProperty("Ticket") + private String ticket; + /** 用户操作来源的外网 IP(可为空,前提是上下文request不为空) **/ + @JsonProperty("UserIp") + private String userIp; + /** 前端回调函数返回的随机字符串(必填) **/ + @JsonProperty("Randstr") + private String randstr; + /** 验证码应用ID;(可为空,配置文件获取) **/ + @JsonProperty("CaptchaAppId") + private Long captchaAppId; + /** 用于服务器端校验验证码票据的验证密钥;(可为空,配置文件获取) **/ + @JsonProperty("AppSecretKey") + private String appSecretKey; + /** 业务 ID,网站或应用在多个业务中使用此服务,通过此 ID 区分统计数据(可为空) **/ + @JsonProperty("BusinessId") + private Long businessId; + /** 场景 ID,网站或应用的业务下有多个场景使用此服务,通过此 ID 区分统计数据(可为空)**/ + @JsonProperty("SceneId") + private Long sceneId; + /** mac 地址或设备唯一标识(可为空) **/ + @JsonProperty("MacAddress") + private String macAddress; + /** 手机设备号(可为空) **/ + @JsonProperty("Imei") + private String imei; + /** 是否返回前端获取验证码时间,取值1:需要返回(可为空) **/ + @JsonProperty("NeedGetCaptchaTime") + private Long needGetCaptchaTime; + + public TencentCaptchaDTO(String ticket, String randstr) { + super(); + this.ticket = ticket; + this.randstr = randstr; + } + +} diff --git a/src/main/java/com/newyetai/sdk/captcha/mapstruct/CaptchaRequestMapMapper.java b/src/main/java/com/newyetai/sdk/captcha/mapstruct/CaptchaRequestMapMapper.java new file mode 100644 index 0000000..cf495db --- /dev/null +++ b/src/main/java/com/newyetai/sdk/captcha/mapstruct/CaptchaRequestMapMapper.java @@ -0,0 +1,29 @@ +package com.newyetai.sdk.captcha.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +import com.newyetai.sdk.captcha.dto.TencentCaptchaDTO; +import com.tencentcloudapi.captcha.v20190722.models.DescribeCaptchaResultRequest; + +/** + * @author sr on 2020-08-10 + */ +@Mapper +public interface CaptchaRequestMapMapper { + + CaptchaRequestMapMapper INSTANCE = Mappers.getMapper(CaptchaRequestMapMapper.class); + + /** + * @param dto + * @return + * @author sr on 2020-08-10 + */ + @Mappings({ + @Mapping(target = "captchaType", constant = "9") + }) + DescribeCaptchaResultRequest toRequest(TencentCaptchaDTO dto); + +} diff --git a/src/main/java/com/newyetai/sdk/captcha/service/AbstractTencentCaptchaAppProvider.java b/src/main/java/com/newyetai/sdk/captcha/service/AbstractTencentCaptchaAppProvider.java new file mode 100644 index 0000000..34f0312 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/captcha/service/AbstractTencentCaptchaAppProvider.java @@ -0,0 +1,78 @@ +package com.newyetai.sdk.captcha.service; + +import org.apache.commons.lang3.StringUtils; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.util.EnvironmentUtils; +import com.newyetai.common.util.RequestUtils; +import com.newyetai.common.util.SpringContextHolder; +import com.newyetai.sdk.captcha.config.CaptchaProperties; +import com.newyetai.sdk.captcha.dto.TencentCaptchaDTO; +import com.newyetai.sdk.captcha.mapstruct.CaptchaRequestMapMapper; +import com.tencentcloudapi.captcha.v20190722.models.DescribeCaptchaResultRequest; + +import lombok.extern.slf4j.Slf4j; + +/** + * @author sr on 2020-08-10 + */ +@Slf4j +public abstract class AbstractTencentCaptchaAppProvider implements ITencentCaptchaAppProvider { + + private static final String PARAM_NOT_ENOUTH = "参数缺失"; + private ITencentCaptchaService tencentCaptchaService; + private String appIdKey; + private String appSecretKey; + private CaptchaProperties captchaProperties; + + protected AbstractTencentCaptchaAppProvider(ITencentCaptchaService tencentCaptchaService, + CaptchaProperties captchaProperties) { + this.tencentCaptchaService = tencentCaptchaService; + this.captchaProperties = captchaProperties; + } + + private String getAppIdKey() { + if (appIdKey == null) { + appIdKey = captchaProperties.getTencent().getApp().get(getAppType()).getAppId(); + } + return appIdKey; + } + + private String getAppSecretKey() { + if (appSecretKey == null) { + appSecretKey = captchaProperties.getTencent().getApp().get(getAppType()).getAppSecret(); + } + return appSecretKey; + } + + @Override + public AlitaResult verify(TencentCaptchaDTO tencentCaptchaDTO) { + try { + if (StringUtils.isBlank(tencentCaptchaDTO.getTicket()) || StringUtils.isBlank(tencentCaptchaDTO.getRandstr())) { + return AlitaResult.bizError(PARAM_NOT_ENOUTH); + } + DescribeCaptchaResultRequest request = + CaptchaRequestMapMapper.INSTANCE.toRequest(tencentCaptchaDTO); + // 用户ip + if (StringUtils.isBlank(request.getUserIp())) { + request.setUserIp(RequestUtils.getIpAddress(SpringContextHolder.getRequest())); + } + // 应用id secret + if (request.getCaptchaAppId() == null) { + request.setCaptchaAppId(Long.valueOf(EnvironmentUtils.getProperty(getAppIdKey()))); + request.setAppSecretKey(EnvironmentUtils.getProperty(getAppSecretKey())); + } + return tencentCaptchaService.verify(request); + + } catch (Exception e) { + log.error("tencent captcha verify error", e); + return AlitaResult.bizError("验证失败:{}" + e.getMessage()); + } + } + + public AlitaResult verify(String ticket, String randstr) { + TencentCaptchaDTO tencentCaptchaDTO = new TencentCaptchaDTO(ticket, randstr); + return this.verify(tencentCaptchaDTO); + } + +} diff --git a/src/main/java/com/newyetai/sdk/captcha/service/ITencentCaptchaAppProvider.java b/src/main/java/com/newyetai/sdk/captcha/service/ITencentCaptchaAppProvider.java new file mode 100644 index 0000000..452e79e --- /dev/null +++ b/src/main/java/com/newyetai/sdk/captcha/service/ITencentCaptchaAppProvider.java @@ -0,0 +1,23 @@ +package com.newyetai.sdk.captcha.service; + +import com.newyetai.common.AlitaResult; +import com.newyetai.sdk.captcha.dto.TencentCaptchaDTO; + +/** + * @author sr on 2020-08-10 + */ +public interface ITencentCaptchaAppProvider { + + /** + * 验证应用类型; + * 同时确定应用id属性配置键 + * id键:captcha.tencent.${appType}.appId,secret键:id键:captcha.tencent.${appType}.appSecret + * + * @return + * @author sr on 2020-08-10 + */ + String getAppType(); + + AlitaResult verify(TencentCaptchaDTO tencentCaptchaDTO); + +} diff --git a/src/main/java/com/newyetai/sdk/captcha/service/ITencentCaptchaService.java b/src/main/java/com/newyetai/sdk/captcha/service/ITencentCaptchaService.java new file mode 100644 index 0000000..92311fd --- /dev/null +++ b/src/main/java/com/newyetai/sdk/captcha/service/ITencentCaptchaService.java @@ -0,0 +1,20 @@ +package com.newyetai.sdk.captcha.service; + +import com.newyetai.common.AlitaResult; +import com.tencentcloudapi.captcha.v20190722.models.DescribeCaptchaResultRequest; + +/** + * @author sr on 2020-08-10 + */ +public interface ITencentCaptchaService { + + /** + * 验证 + * + * @param request + * @return + * @author sr on 2020-08-10 + */ + AlitaResult verify(DescribeCaptchaResultRequest request); + +} diff --git a/src/main/java/com/newyetai/sdk/captcha/service/impl/LoginCaptchaAppProvider.java b/src/main/java/com/newyetai/sdk/captcha/service/impl/LoginCaptchaAppProvider.java new file mode 100644 index 0000000..3fbb141 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/captcha/service/impl/LoginCaptchaAppProvider.java @@ -0,0 +1,23 @@ +package com.newyetai.sdk.captcha.service.impl; + +import com.newyetai.sdk.captcha.config.CaptchaProperties; +import com.newyetai.sdk.captcha.service.AbstractTencentCaptchaAppProvider; +import com.newyetai.sdk.captcha.service.ITencentCaptchaService; + +/** + * 登录防水墙 + * + * @author sr on 2020-08-11 + */ +public class LoginCaptchaAppProvider extends AbstractTencentCaptchaAppProvider { + + public LoginCaptchaAppProvider(ITencentCaptchaService tencentCaptchaService, CaptchaProperties captchaProperties) { + super(tencentCaptchaService, captchaProperties); + } + + @Override + public String getAppType() { + return "login"; + } + +} diff --git a/src/main/java/com/newyetai/sdk/captcha/service/impl/TencentCaptchaServiceImpl.java b/src/main/java/com/newyetai/sdk/captcha/service/impl/TencentCaptchaServiceImpl.java new file mode 100644 index 0000000..6afe663 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/captcha/service/impl/TencentCaptchaServiceImpl.java @@ -0,0 +1,55 @@ +package com.newyetai.sdk.captcha.service.impl; + +import org.apache.commons.lang3.StringUtils; + +import com.newyetai.common.AlitaResult; +import com.newyetai.sdk.captcha.service.ITencentCaptchaService; +import com.tencentcloudapi.captcha.v20190722.CaptchaClient; +import com.tencentcloudapi.captcha.v20190722.models.DescribeCaptchaResultRequest; +import com.tencentcloudapi.captcha.v20190722.models.DescribeCaptchaResultResponse; +import com.tencentcloudapi.common.Credential; +import com.tencentcloudapi.common.exception.TencentCloudSDKException; +import com.tencentcloudapi.common.profile.ClientProfile; +import com.tencentcloudapi.common.profile.HttpProfile; + +import lombok.extern.slf4j.Slf4j; + +/** + * @author sr on 2020-08-10 + */ +@Slf4j +public class TencentCaptchaServiceImpl implements ITencentCaptchaService { + + private static final Long SUCCESS_CODE = 1L; + + private Credential defaultCredential; + + public TencentCaptchaServiceImpl(Credential defaultCredential) { + this.defaultCredential = defaultCredential; + } + + @Override + public AlitaResult verify(DescribeCaptchaResultRequest request) { + try { + Credential cred = defaultCredential; + HttpProfile httpProfile = new HttpProfile(); + ClientProfile clientProfile = new ClientProfile(); + clientProfile.setHttpProfile(httpProfile); + CaptchaClient client = new CaptchaClient(cred, "", clientProfile); + log.info("tencent captcha request:{}", request); + DescribeCaptchaResultResponse resp = client.DescribeCaptchaResult(request); + log.info("tencent captcha response:{}", resp); + Long captchaCode = resp.getCaptchaCode(); + if (SUCCESS_CODE.equals(captchaCode)) { + return AlitaResult.success(true); + } + String msg = resp.getCaptchaMsg(); + return AlitaResult.success(StringUtils.isBlank(msg) ? captchaCode.toString() : msg, false); + } catch (TencentCloudSDKException e) { + log.info("tencent captcha error", e); + return AlitaResult.bizError(e.getMessage()); + } + + } + +} diff --git a/src/main/java/com/newyetai/sdk/chuanglan/config/ChuangLanCommonProperties.java b/src/main/java/com/newyetai/sdk/chuanglan/config/ChuangLanCommonProperties.java new file mode 100644 index 0000000..7d1d6af --- /dev/null +++ b/src/main/java/com/newyetai/sdk/chuanglan/config/ChuangLanCommonProperties.java @@ -0,0 +1,21 @@ +package com.newyetai.sdk.chuanglan.config; + +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 接口链接地址映射 + * @author fzp on 2021年6月17日09:29:06 + */ +@Data +@NoArgsConstructor +public class ChuangLanCommonProperties { + + /** 是否启用 **/ + private Boolean enable = Boolean.FALSE; + /** 接口地址 **/ + private String url; + /** 次数限制 **/ + private Long numLimit; + +} diff --git a/src/main/java/com/newyetai/sdk/chuanglan/config/ChuangLanProperties.java b/src/main/java/com/newyetai/sdk/chuanglan/config/ChuangLanProperties.java new file mode 100644 index 0000000..c345a68 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/chuanglan/config/ChuangLanProperties.java @@ -0,0 +1,59 @@ +package com.newyetai.sdk.chuanglan.config; + +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * 创蓝配置 + * + * @author sr on 2020-04-09 + */ +@ConfigurationProperties(prefix = ChuangLanProperties.PREFIX) +@Data +@Component +@NoArgsConstructor +public class ChuangLanProperties { + + /** 创蓝配置前缀 */ + public static final String PREFIX = "chuanglan"; + /** 创蓝三要素配置前缀 */ + public static final String PHONE_THREE_PREFIX = PREFIX + ".phone3"; + /** 创蓝三要素配置前缀 */ + public static final String BANK_CARD_THREE_PREFIX = PREFIX + ".bankCard3"; + /** 创蓝四要素配置前缀 */ + public static final String BANK_CARD_FOUR_PREFIX = PREFIX + ".bankCard4"; + + /** 创蓝二要素实名认证配置前缀 */ + public static final String REAL_NAME_TWO_PREFIX = PREFIX + ".realName2"; + + /** 创蓝二要素实名认证配置前缀 */ + public static final String REAL_NAME_TWO_BASE_PREFIX = PREFIX + ".realName2Base"; + + /** 是否启用 **/ + private Boolean enable; + /** https://api.253.com */ + private String domain; + + /** 系统预留手机号 */ + private String phone; + + private String appId; + + private String appSecret; + + /** 手机号三要素配置 */ + private ChuangLanCommonProperties phone3; + + /** 银行卡三要素配置 */ + private ChuangLanCommonProperties bankCard3; + + /** 银行卡四要素配置 */ + private ChuangLanCommonProperties bankCard4; + /** 实名认证二要素配置 */ + private ChuangLanCommonProperties realName2; + + /** 实名认证二要素配置 (id-card-auth) */ + private ChuangLanCommonProperties realName2Base; +} diff --git a/src/main/java/com/newyetai/sdk/chuanglan/constant/BankCardVerifyStateEnum.java b/src/main/java/com/newyetai/sdk/chuanglan/constant/BankCardVerifyStateEnum.java new file mode 100644 index 0000000..d56dec2 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/chuanglan/constant/BankCardVerifyStateEnum.java @@ -0,0 +1,83 @@ +package com.newyetai.sdk.chuanglan.constant; + +import com.google.common.collect.Maps; +import com.newyetai.common.AlitaResult; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.sdk.chuanglan.dto.ChuangLanResponseDTO; +import com.newyetai.sdk.chuanglan.dto.ChuangLanResultDTO; +import java.util.Map; + +/** + * @author czy + * @date 2021-07-05 + */ + +public enum BankCardVerifyStateEnum { + + /** 认证一致 **/ + SUC("01", "认证一致", Boolean.TRUE), + /** 认证不一致 **/ + FAIL("02", "认证不一致", Boolean.FALSE), + /** 认证不确定 **/ + UNCERTAIN("03", "认证不确定", null), + /** 认证失败 **/ + EXCEPTION_FAIL("04", "认证失败", null), + /** 手机号码不匹配 **/ + MOBILE_ERROR("05", "手机号码不匹配", Boolean.FALSE), + /** 身份证号码不匹配 **/ + CARD_NO_ERROR("06", "身份证号码不匹配", Boolean.FALSE), + /** 姓名不匹配 **/ + NAME_ERROR("07", "姓名不匹配", Boolean.FALSE); + + private static Map stateMap; + /** 验证结果 **/ + private String state; + /** 说明 **/ + private String msg; + /** 认证结果 **/ + private Boolean result; + + + BankCardVerifyStateEnum(String state, String msg, Boolean result) { + this.state = state; + this.msg = msg; + this.result = result; + } + + static { + BankCardVerifyStateEnum[] array = BankCardVerifyStateEnum.values(); + stateMap = Maps.newHashMapWithExpectedSize(array.length); + for (BankCardVerifyStateEnum stateEnum : array) { + stateMap.put(stateEnum.getState(), stateEnum); + } + } + + public String getState() { + return state; + } + + public String getMsg() { + return msg; + } + + public Boolean getResult() { + return result; + } + + public static AlitaResult dealState(ChuangLanResponseDTO responseDto) { + ChuangLanResultDTO resultDTO = ChuangLanResultDTO.builder() + .jsonData(JsonUtils.toJsonString(responseDto)).build(); + String status = responseDto.getData().getResult(); + BankCardVerifyStateEnum stateEnum = stateMap.get(status); + if (stateEnum == null) { + return AlitaResult.success("state not available...", resultDTO); + } + if (stateEnum == SUC || stateEnum == FAIL || stateEnum == MOBILE_ERROR || stateEnum == CARD_NO_ERROR || stateEnum == NAME_ERROR) { + resultDTO.setStatus(stateEnum.getResult()); + return AlitaResult.success(stateEnum.getMsg(), resultDTO); + } + return AlitaResult.error(stateEnum.getMsg(), resultDTO); + } + + +} diff --git a/src/main/java/com/newyetai/sdk/chuanglan/constant/ChuangLanConstants.java b/src/main/java/com/newyetai/sdk/chuanglan/constant/ChuangLanConstants.java new file mode 100644 index 0000000..b4276cd --- /dev/null +++ b/src/main/java/com/newyetai/sdk/chuanglan/constant/ChuangLanConstants.java @@ -0,0 +1,22 @@ +package com.newyetai.sdk.chuanglan.constant; + +import com.newyetai.sdk.common.constant.SdkConstants; + +/** + * @author sr on 2020-04-10 + */ +public interface ChuangLanConstants { + + /** 创蓝接口调用,验证成功码 **/ + String IMPL_CODE = "01"; + + /** 成功码 **/ + String SUC_CODE = "200000"; + + /** ================ chuanglan 调起真实服务前异常msg ================= **/ + String PROPERTIES_NOT_SET = SdkConstants.CL_CODE + ":配置文件未配置"; + String ID_SECRET_NOT_ENOUGH = SdkConstants.CL_CODE + ":参数appId或appSecret缺失"; + /** ================ chuanglanW 调起真实服务前异常msq ================= **/ + + +} diff --git a/src/main/java/com/newyetai/sdk/chuanglan/constant/ChuangLanErrorCodeEnum.java b/src/main/java/com/newyetai/sdk/chuanglan/constant/ChuangLanErrorCodeEnum.java new file mode 100644 index 0000000..83c7c73 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/chuanglan/constant/ChuangLanErrorCodeEnum.java @@ -0,0 +1,33 @@ +package com.newyetai.sdk.chuanglan.constant; + +/** + * sdk创蓝错误码枚举;标识:创蓝(01) + * @author sr on 2020-05-22 + */ +public enum ChuangLanErrorCodeEnum { + + /** 创蓝调用返回错误码 **/ + INVOKE_RETURN_ERROR("060101", "创蓝接口调用失败,返回错误码"), + /** 创蓝调用成功,但信息不匹配 **/ + NOT_EQUAL("060102", "不匹配"); + + /** 错误码 **/ + private String code; + /** 错误信息 **/ + private String msg; + + ChuangLanErrorCodeEnum(String code, String msg){ + this.code = code; + this.msg = msg; + } + + public String getCode() { + return code; + } + + public String getMsg() { + return msg; + } + + +} diff --git a/src/main/java/com/newyetai/sdk/chuanglan/dto/BankCardFourRequestDTO.java b/src/main/java/com/newyetai/sdk/chuanglan/dto/BankCardFourRequestDTO.java new file mode 100644 index 0000000..266c003 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/chuanglan/dto/BankCardFourRequestDTO.java @@ -0,0 +1,35 @@ +package com.newyetai.sdk.chuanglan.dto; + +import lombok.*; + +import javax.validation.constraints.NotBlank; +import java.io.Serializable; + +/** + * 银行卡四要素请求 + * + * @author fzp 2021年6月15日15:11:31 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class BankCardFourRequestDTO extends ChuangLanRequestDTO implements Serializable { + + /** **/ + private static final long serialVersionUID = 3807618123977056991L; + + /** 姓名 **/ + @NotBlank(message = "姓名不能为空") + private String name; + /** 身份证号 **/ + @NotBlank(message = "身份证号不能为空") + private String idNum; + /** 银行卡号 **/ + @NotBlank(message = "银行卡号不能为空") + private String cardNo; + @NotBlank(message = "手机号码不能为空") + private String mobile; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/sdk/chuanglan/dto/BankCardThreeRequestDTO.java b/src/main/java/com/newyetai/sdk/chuanglan/dto/BankCardThreeRequestDTO.java new file mode 100644 index 0000000..a5caaa5 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/chuanglan/dto/BankCardThreeRequestDTO.java @@ -0,0 +1,33 @@ +package com.newyetai.sdk.chuanglan.dto; + +import lombok.*; + +import javax.validation.constraints.NotBlank; +import java.io.Serializable; + +/** + * 银行卡三要素请求 + * + * @author sr on 2020-04-09 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class BankCardThreeRequestDTO extends ChuangLanRequestDTO implements Serializable { + + /** **/ + private static final long serialVersionUID = -6539738426193243916L; + + /** 姓名 **/ + @NotBlank(message = "姓名不能为空") + private String name; + /** 身份证号 **/ + @NotBlank(message = "身份证号不能为空") + private String idNum; + /** 银行卡号 **/ + @NotBlank(message = "银行卡号不能为空") + private String cardNo; + +} diff --git a/src/main/java/com/newyetai/sdk/chuanglan/dto/ChuangLanRequestDTO.java b/src/main/java/com/newyetai/sdk/chuanglan/dto/ChuangLanRequestDTO.java new file mode 100644 index 0000000..1337ae1 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/chuanglan/dto/ChuangLanRequestDTO.java @@ -0,0 +1,27 @@ +package com.newyetai.sdk.chuanglan.dto; + +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 创蓝请求父类dto + * + * @author fzp on 2021年6月15日16:39:50 + */ +@Data +@NoArgsConstructor +public class ChuangLanRequestDTO implements Serializable { + + private static final long serialVersionUID = 3960499271644654446L; + /** + * id + **/ + private String appId; + /** + * secret + **/ + private String appKey; + +} diff --git a/src/main/java/com/newyetai/sdk/chuanglan/dto/ChuangLanResponseDTO.java b/src/main/java/com/newyetai/sdk/chuanglan/dto/ChuangLanResponseDTO.java new file mode 100644 index 0000000..0436a50 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/chuanglan/dto/ChuangLanResponseDTO.java @@ -0,0 +1,81 @@ +package com.newyetai.sdk.chuanglan.dto; + +import com.newyetai.common.AlitaResult; +import com.newyetai.sdk.fangxinqian.constant.FxqConstants; +import com.newyetai.sdk.fangxinqian.constant.FxqErrorCodeEnum; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.util.StringUtils; + +import java.io.Serializable; + +/** + * 创蓝返回 + * + * @param + * @author fzp on 2021年6月15日14:55:38 + */ +@Data +@NoArgsConstructor +public class ChuangLanResponseDTO implements Serializable { + + /** + * + **/ + private static final long serialVersionUID = -4576000729533850612L; + /** + * 错误码 + **/ + private String code; + /** + * 序列号(每次调用接口返回的唯一值,seqNo 如有接口问题,请提供此值) + **/ + private String seqNo; + /** + * 错误信息 1 + **/ + private String message; + + /** + * 错误信息 2 + */ + private String msg; + + /** + * 响应结果 + */ + private StatusDataDTO data; + + + public static ChuangLanResponseDTO buildCommonError() { + ChuangLanResponseDTO clResponseDTO = new ChuangLanResponseDTO(); + clResponseDTO.setCode("999"); + return clResponseDTO; + } + + /** + * 返回结果处理 + * + * @return + */ + public AlitaResult handleResult() { + if (FxqConstants.SUC_CODE.equals(this.getCode())) { + return AlitaResult.success(handleData()); + } else { + return AlitaResult.error(FxqErrorCodeEnum.INVOKE_RETURN_ERROR.getCode(), + StringUtils.isEmpty(this.getMsg()) ? + StringUtils.isEmpty(this.getMessage()) ? FxqErrorCodeEnum.INVOKE_RETURN_ERROR.getMsg() : this.getMessage() + : this.getMsg()); + } + } + + /** + * 子类DTO实现 转换为AlitaResult时 + * 通过 handleData()决定转换为AlitaResult的data返回什么 + * + * @return + */ + protected T handleData() { + return null; + } +} diff --git a/src/main/java/com/newyetai/sdk/chuanglan/dto/ChuangLanResultDTO.java b/src/main/java/com/newyetai/sdk/chuanglan/dto/ChuangLanResultDTO.java new file mode 100644 index 0000000..4498245 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/chuanglan/dto/ChuangLanResultDTO.java @@ -0,0 +1,23 @@ +package com.newyetai.sdk.chuanglan.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author czy + * @date 2021-07-05 + */ + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class ChuangLanResultDTO { + + private Boolean status; + + private String jsonData; + +} diff --git a/src/main/java/com/newyetai/sdk/chuanglan/dto/PhoneThreeRequestDTO.java b/src/main/java/com/newyetai/sdk/chuanglan/dto/PhoneThreeRequestDTO.java new file mode 100644 index 0000000..5013a73 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/chuanglan/dto/PhoneThreeRequestDTO.java @@ -0,0 +1,36 @@ +package com.newyetai.sdk.chuanglan.dto; + +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * 手机号三要素请求 + * + * @author sr on 2020-04-09 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class PhoneThreeRequestDTO extends ChuangLanRequestDTO implements Serializable { + + /** **/ + private static final long serialVersionUID = -6539738426193243916L; + + /** 姓名 **/ + @NotBlank(message = "姓名不能为空") + private String name; + /** 身份证号 **/ + @NotBlank(message = "身份证号不能为空") + private String idNum; + /** 银行卡号 **/ + @NotBlank(message = "手机号不能为空") + private String mobile; + +} diff --git a/src/main/java/com/newyetai/sdk/chuanglan/dto/RealNameTwoBaseRequestDTO.java b/src/main/java/com/newyetai/sdk/chuanglan/dto/RealNameTwoBaseRequestDTO.java new file mode 100644 index 0000000..b73983c --- /dev/null +++ b/src/main/java/com/newyetai/sdk/chuanglan/dto/RealNameTwoBaseRequestDTO.java @@ -0,0 +1,28 @@ +package com.newyetai.sdk.chuanglan.dto; + +import lombok.*; + +import javax.validation.constraints.NotBlank; +import java.io.Serializable; + +/** + * 实名认证(基础) + * + * @author fzp 2021年6月15日15:11:31 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class RealNameTwoBaseRequestDTO extends ChuangLanRequestDTO implements Serializable { + + private static final long serialVersionUID = -3985001434329229012L; + + /** 姓名 **/ + @NotBlank(message = "姓名不能为空") + private String name; + /** 身份证号 **/ + @NotBlank(message = "身份证号不能为空") + private String idNum; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/sdk/chuanglan/dto/RealNameTwoRequestDTO.java b/src/main/java/com/newyetai/sdk/chuanglan/dto/RealNameTwoRequestDTO.java new file mode 100644 index 0000000..f6d476f --- /dev/null +++ b/src/main/java/com/newyetai/sdk/chuanglan/dto/RealNameTwoRequestDTO.java @@ -0,0 +1,38 @@ +package com.newyetai.sdk.chuanglan.dto; + +import lombok.*; + +import javax.validation.constraints.NotBlank; +import java.io.Serializable; + +/** + * 实名认证 + * + * @author fzp 2021年6月15日15:11:31 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class RealNameTwoRequestDTO extends ChuangLanRequestDTO implements Serializable { + + /** **/ + private static final long serialVersionUID = 3807618123977056991L; + + /** 姓名 **/ + @NotBlank(message = "姓名不能为空") + private String name; + /** 身份证号 **/ + @NotBlank(message = "身份证号不能为空") + private String idNum; + + /** 身份证有效开始日期 **/ + @NotBlank(message = "startTime") + private String startTime; + + /** 身份证有效结束日期 **/ + @NotBlank(message = "startTime") + private String endTime; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/sdk/chuanglan/dto/StatusDataDTO.java b/src/main/java/com/newyetai/sdk/chuanglan/dto/StatusDataDTO.java new file mode 100644 index 0000000..c4d5feb --- /dev/null +++ b/src/main/java/com/newyetai/sdk/chuanglan/dto/StatusDataDTO.java @@ -0,0 +1,41 @@ +package com.newyetai.sdk.chuanglan.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author czy + * @date 2021-07-05 + */ + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class StatusDataDTO { + + @ApiModelProperty("业务唯一流水号") + private String orderNo; + + @ApiModelProperty("查询时间") + private String handleTime; + + @ApiModelProperty("认证结果代码") + private String result; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("银行卡所属银行") + private String bankName; + + @ApiModelProperty("银行卡类型") + private String cardType; + + @ApiModelProperty("银行卡类型") + private String cardCategory; + +} diff --git a/src/main/java/com/newyetai/sdk/chuanglan/service/ChuangLanService.java b/src/main/java/com/newyetai/sdk/chuanglan/service/ChuangLanService.java new file mode 100644 index 0000000..712aa0a --- /dev/null +++ b/src/main/java/com/newyetai/sdk/chuanglan/service/ChuangLanService.java @@ -0,0 +1,71 @@ +package com.newyetai.sdk.chuanglan.service; + +import com.newyetai.common.AlitaResult; +import com.newyetai.sdk.chuanglan.dto.*; +import org.springframework.validation.annotation.Validated; + +import javax.validation.Valid; +import javax.validation.constraints.NotNull; +import javax.validation.groups.Default; + +/** + * 创蓝 + * + * @author sr on 2020-04-09 + */ +@Validated(Default.class) +public interface ChuangLanService { + + String BEAN_ID = "sdk.chuangLanService"; + String MOCK_BEAN_ID = "mock.chuangLanService"; + + /** + * 二要素(基础) + * + * @param requestDTO 请求dto + * @return {@link AlitaResult}<{@link ChuangLanResultDTO}> + */ + AlitaResult checkRealNameTwoBase(RealNameTwoBaseRequestDTO requestDTO); + + /** + * 手机三要素 + * + * @param phoneThreeRequestDTO 电话请求dto + * @return {@link AlitaResult}<{@link ChuangLanResultDTO}> + */ + AlitaResult checkPhoneThree( + @NotNull @Valid PhoneThreeRequestDTO phoneThreeRequestDTO); + + /** + * 银行卡三要素 + * + * @param bankCardThreeRequestDto + * @return success-false真实调用第三方未成功,未拿到返回值; + * success-true获取到第三方返回,data-true校验成功,data-false校验不一致并返回失败原因(msg) + * @author sr on 2020-04-10 + */ + AlitaResult checkBankCardThree( + @NotNull @Valid BankCardThreeRequestDTO bankCardThreeRequestDto); + + /** + * 银行卡四要素 + * + * @param bankCardFourRequestDto + * @return success-false真实调用第三方未成功,未拿到返回值; + * success-true获取到第三方返回,data-true校验成功,data-false校验不一致并返回失败原因(msg) + * @author sr on 2020-05-22 + */ + AlitaResult checkBankCardFour( + @NotNull @Valid BankCardFourRequestDTO bankCardFourRequestDto); + + /** + * 二要素--实名认证 + * + * @param realNameTwoRequestDTO + * @return success-false真实调用第三方未成功,未拿到返回值; + * success-true获取到第三方返回,data-true校验成功,data-false校验不一致并返回失败原因(msg) + * @author sr on 2020-05-22 + */ + AlitaResult realNameTwoAuthentication( + @NotNull @Valid RealNameTwoRequestDTO realNameTwoRequestDTO); +} diff --git a/src/main/java/com/newyetai/sdk/chuanglan/service/impl/ChuangLanServiceImpl.java b/src/main/java/com/newyetai/sdk/chuanglan/service/impl/ChuangLanServiceImpl.java new file mode 100644 index 0000000..0e18224 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/chuanglan/service/impl/ChuangLanServiceImpl.java @@ -0,0 +1,98 @@ +package com.newyetai.sdk.chuanglan.service.impl; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.annotation.CheckAndMock; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.sdk.chuanglan.config.ChuangLanCommonProperties; +import com.newyetai.sdk.chuanglan.config.ChuangLanProperties; +import com.newyetai.sdk.chuanglan.constant.BankCardVerifyStateEnum; +import com.newyetai.sdk.chuanglan.constant.ChuangLanConstants; +import com.newyetai.sdk.chuanglan.dto.*; +import com.newyetai.sdk.chuanglan.service.ChuangLanService; +import com.newyetai.sdk.chuanglan.util.ChuangLanUtils; +import com.newyetai.sdk.chuanglan.util.HttpUtilCl; +import com.newyetai.sdk.common.constant.SdkConstants; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * @author fzp on 2021年6月15日16:46:26 + */ +@Slf4j +@Service(ChuangLanService.BEAN_ID) +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class ChuangLanServiceImpl implements ChuangLanService { + + private final ChuangLanProperties chuangLanProperties; + + @Override + @CheckAndMock(mockClass = MockChuangLanServiceImpl.class, + propertyPrefix = ChuangLanProperties.REAL_NAME_TWO_BASE_PREFIX) + public AlitaResult checkRealNameTwoBase(RealNameTwoBaseRequestDTO requestDTO) { + return this.check(requestDTO, chuangLanProperties.getRealName2Base()); + } + + @Override + @CheckAndMock(mockClass = MockChuangLanServiceImpl.class, + propertyPrefix = ChuangLanProperties.PHONE_THREE_PREFIX) + public AlitaResult checkPhoneThree(PhoneThreeRequestDTO requestDTO) { + return this.check(requestDTO, chuangLanProperties.getPhone3()); + } + + @Override + @CheckAndMock(mockClass = MockChuangLanServiceImpl.class, + propertyPrefix = ChuangLanProperties.BANK_CARD_THREE_PREFIX) + public AlitaResult checkBankCardThree(BankCardThreeRequestDTO bankCardThreeRequestDto) { + return this.check(bankCardThreeRequestDto, chuangLanProperties.getBankCard3()); + } + + @Override + @CheckAndMock(mockClass = MockChuangLanServiceImpl.class, + propertyPrefix = ChuangLanProperties.BANK_CARD_FOUR_PREFIX) + public AlitaResult checkBankCardFour(BankCardFourRequestDTO bankCardFourRequestDto) { + return this.check(bankCardFourRequestDto, chuangLanProperties.getBankCard4()); + } + + @Override + @CheckAndMock(mockClass = MockChuangLanServiceImpl.class, + propertyPrefix = ChuangLanProperties.REAL_NAME_TWO_PREFIX) + public AlitaResult realNameTwoAuthentication(RealNameTwoRequestDTO realNameTwoRequestDTO){ + return this.check(realNameTwoRequestDTO, chuangLanProperties.getRealName2()); + } + + /** + * 父类dto 添加请求父类,可以指定appId,appSecret调用接口 + * @param requestDto + * @param commonProperties + * @return + */ + private AlitaResult check(ChuangLanRequestDTO requestDto, ChuangLanCommonProperties commonProperties) { + // 校验部分 + if (commonProperties == null || chuangLanProperties == null) { + return AlitaResult.error(SdkConstants.SDK_INVOKE_NOT_REACH_CODE, + ChuangLanConstants.PROPERTIES_NOT_SET); + } + if (!Boolean.TRUE.equals(chuangLanProperties.getEnable())) { + return AlitaResult.error(SdkConstants.SDK_INVOKE_NOT_REACH_CODE, + "暂不支持要素认证"); + } + if (!ChuangLanUtils.dealAppIdAndSecret(commonProperties, requestDto, chuangLanProperties)) { + return AlitaResult.error(SdkConstants.SDK_INVOKE_NOT_REACH_CODE, + ChuangLanConstants.ID_SECRET_NOT_ENOUGH); + } + // 执行 + ChuangLanResponseDTO responseDto = HttpUtilCl.execute(chuangLanProperties.getDomain().concat(commonProperties.getUrl()), requestDto); + + // 返回结果校验 + if (!ChuangLanConstants.SUC_CODE.equals(responseDto.getCode())) { + // 返回结果验证错误 + return AlitaResult.error(SdkConstants.SDK_HTTP_INVOKE_RESPONSE_FAIL_CODE, responseDto.getMessage() ); + } + + return BankCardVerifyStateEnum.dealState(responseDto); + } + + +} diff --git a/src/main/java/com/newyetai/sdk/chuanglan/service/impl/MockChuangLanServiceImpl.java b/src/main/java/com/newyetai/sdk/chuanglan/service/impl/MockChuangLanServiceImpl.java new file mode 100644 index 0000000..f408153 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/chuanglan/service/impl/MockChuangLanServiceImpl.java @@ -0,0 +1,75 @@ +package com.newyetai.sdk.chuanglan.service.impl; + +import com.newyetai.common.AlitaResult; +import com.newyetai.sdk.chuanglan.config.ChuangLanProperties; +import com.newyetai.sdk.chuanglan.dto.*; +import com.newyetai.sdk.chuanglan.service.ChuangLanService; +import com.newyetai.sdk.common.constant.SdkConstants; + +import lombok.extern.slf4j.Slf4j; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.validation.Valid; +import javax.validation.constraints.NotNull; + +/** + * @author sr on 2020-04-09 + */ +@Service(ChuangLanService.MOCK_BEAN_ID) +@Slf4j +public class MockChuangLanServiceImpl implements ChuangLanService { + + private final static ChuangLanResultDTO result = + ChuangLanResultDTO.builder().status(Boolean.TRUE).build(); + + @Autowired + private ChuangLanProperties chuangLanProperties; + + private AlitaResult check() { + // 校验部分 + if (chuangLanProperties == null || !Boolean.TRUE.equals(chuangLanProperties.getEnable())) { + return AlitaResult.error(SdkConstants.SDK_INVOKE_NOT_REACH_CODE, + "暂不支持要素认证"); + } + return AlitaResult.success(result); + } + + @Override + public AlitaResult checkRealNameTwoBase( + RealNameTwoBaseRequestDTO requestDTO) { + log.info("chuanglan checkRealNameTwoBase mock..."); + return check(); + } + + @Override + public AlitaResult checkPhoneThree( + PhoneThreeRequestDTO phoneThreeRequestDTO) { + log.info("chuanglan checkPhoneThree mock..."); + return check(); + } + + @Override + public AlitaResult checkBankCardThree( + @NotNull @Valid BankCardThreeRequestDTO bankCardThreeRequestDto) { + log.info("chuanglan checkBankCardThree mock..."); + return check(); + } + + + @Override + public AlitaResult checkBankCardFour( + @NotNull @Valid BankCardFourRequestDTO bankCardFourRequestDto) { + log.info("chuanglan checkBankCardFour mock..."); + return check(); + } + + @Override + public AlitaResult realNameTwoAuthentication( + RealNameTwoRequestDTO realNameTwoRequestDTO) { + log.info("chuanglan checkRealNameTwo mock..."); + return check(); + } + +} diff --git a/src/main/java/com/newyetai/sdk/chuanglan/util/ChuangLanUtils.java b/src/main/java/com/newyetai/sdk/chuanglan/util/ChuangLanUtils.java new file mode 100644 index 0000000..07feba3 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/chuanglan/util/ChuangLanUtils.java @@ -0,0 +1,52 @@ +package com.newyetai.sdk.chuanglan.util; + +import com.newyetai.sdk.chuanglan.config.ChuangLanCommonProperties; +import com.newyetai.sdk.chuanglan.config.ChuangLanProperties; +import com.newyetai.sdk.chuanglan.dto.ChuangLanRequestDTO; +import org.apache.commons.lang3.StringUtils; + +/** + * 工具类 + * + * @author fzp on 2021年6月15日14:22:18 + */ +public final class ChuangLanUtils { + + /** + * 私有 + */ + private ChuangLanUtils() { + throw new IllegalStateException("Utility class"); + } + + /** + * 处理appId和appSecret参数 + * + * @param + * @param commonProperties + * @param requestDto + * @author fzp on 2021年6月15日16:20:49 + */ + public static boolean dealAppIdAndSecret(ChuangLanCommonProperties commonProperties, + T requestDto, ChuangLanProperties chuangLanProperties) { + + String appId = requestDto.getAppId(); + String appKey = requestDto.getAppKey(); + + // 如果appId为空,则从nacos配置文件读取 + if (StringUtils.isBlank(appId) && commonProperties.getEnable()) { + appId = chuangLanProperties.getAppId(); + } + if (StringUtils.isBlank(appKey) && commonProperties.getEnable()) { + appKey = chuangLanProperties.getAppSecret(); + } + if (StringUtils.isBlank(appId) || StringUtils.isBlank(appKey)) { + return false; + } + + requestDto.setAppId(appId); + requestDto.setAppKey(appKey); + return true; + } + +} diff --git a/src/main/java/com/newyetai/sdk/chuanglan/util/HttpUtilCl.java b/src/main/java/com/newyetai/sdk/chuanglan/util/HttpUtilCl.java new file mode 100644 index 0000000..8a7070e --- /dev/null +++ b/src/main/java/com/newyetai/sdk/chuanglan/util/HttpUtilCl.java @@ -0,0 +1,99 @@ +package com.newyetai.sdk.chuanglan.util; + +import com.newyetai.common.util.JsonUtils; +import com.newyetai.sdk.chuanglan.constant.ChuangLanConstants; +import com.newyetai.sdk.chuanglan.dto.ChuangLanResponseDTO; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Component; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.util.StopWatch; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestTemplate; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Objects; + +@Slf4j +@Component +public class HttpUtilCl { + + private static RestTemplate restTemplate; + + @Autowired + public HttpUtilCl() { + this.restTemplate = new RestTemplate(); + } + + /** + * Http 通用请求封装 + * + * @param url 请求地址 + * @param requestDto 请求实体 + * @param + * @param + * @return + */ + public static ChuangLanResponseDTO execute(String url, T requestDto) { + ChuangLanResponseDTO result; + + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + try { + String reqJson = JsonUtils.toJsonString(requestDto); + log.info("chuanglan request url :{}", url); + log.info("chuanglan request requestDto :{}", reqJson); + + MultiValueMap requestBody = new LinkedMultiValueMap(); + Map paramMap = JsonUtils.toMap(reqJson); + paramMap.forEach((k,v) -> { + if(Objects.nonNull(v)){ + requestBody.add(k,v); + } + }); + + // 设置请求头 + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + HttpEntity request = new HttpEntity(requestBody, headers); + String response = restTemplate.postForObject(url, request, String.class); + log.info("chuanglan 响应结果 :{}", response); + + result = formatDto(response); + + } catch (Exception e) { + log.error("chuanglan {} invoke error:{}", requestDto.getClass().getName(), e); + stopWatch.stop(); + return ChuangLanResponseDTO.buildCommonError(); + } + stopWatch.stop(); + log.info("chuanglan consuming {} s", stopWatch.getTotalTimeSeconds()); + + return result; + } + + private static ChuangLanResponseDTO formatDto(String json){ + if(StringUtils.isBlank(json)){ + return ChuangLanResponseDTO.buildCommonError(); + } + ChuangLanResponseDTO result = JsonUtils.toObject(json,ChuangLanResponseDTO.class); + Map map = JsonUtils.toMap(json); + if(map.get("data") != null){ + LinkedHashMap data = (LinkedHashMap) map.get("data"); + // 创蓝接口验证失败 + if(!ChuangLanConstants.IMPL_CODE.equals(data.get("result"))){ + result.setMsg(data.get("remark") + ""); + result.setMessage(data.get("remark") + ""); +// result.setCode(data.get("result") + ""); + } + } + return result; + } + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/sdk/common/config/ApiConfig.java b/src/main/java/com/newyetai/sdk/common/config/ApiConfig.java new file mode 100644 index 0000000..621add4 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/common/config/ApiConfig.java @@ -0,0 +1,73 @@ +package com.newyetai.sdk.common.config; + +import java.util.List; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.MediaType; +import org.springframework.http.client.ClientHttpRequestFactory; +import org.springframework.http.client.SimpleClientHttpRequestFactory; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.web.client.RestTemplate; + +import com.google.common.collect.Lists; + +/** + * @author sr on 2020-04-16 + */ +@Configuration +public class ApiConfig { + + /** + * 读取超时 + **/ + public static final int READ_TIME_OUT = 60000; + /** + * 连接超时 + **/ + public static final int CONNECT_TIME_OUT = 60000; + + @Bean + @ConditionalOnMissingBean + public RestTemplate restTemplate(ClientHttpRequestFactory factory) { + RestTemplate restTemplate = new RestTemplate(factory); + MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); + List mediaTypes = Lists.newArrayList(MediaType.APPLICATION_ATOM_XML, + MediaType.APPLICATION_FORM_URLENCODED, + MediaType.APPLICATION_JSON, + MediaType.APPLICATION_JSON_UTF8, + MediaType.APPLICATION_OCTET_STREAM, + MediaType.APPLICATION_PDF, + MediaType.APPLICATION_PROBLEM_JSON, + MediaType.APPLICATION_PROBLEM_JSON_UTF8, + MediaType.APPLICATION_PROBLEM_XML, + MediaType.APPLICATION_RSS_XML, + MediaType.APPLICATION_STREAM_JSON, + MediaType.APPLICATION_XHTML_XML, + MediaType.APPLICATION_XML, + MediaType.IMAGE_GIF, + MediaType.IMAGE_JPEG, + MediaType.IMAGE_PNG, + MediaType.MULTIPART_FORM_DATA, + MediaType.TEXT_EVENT_STREAM, + MediaType.TEXT_HTML, + MediaType.TEXT_MARKDOWN, + MediaType.TEXT_PLAIN, + MediaType.TEXT_XML); + converter.setSupportedMediaTypes(mediaTypes); + restTemplate.getMessageConverters().add(converter); + return restTemplate; + } + + @Bean + @ConditionalOnMissingBean + public ClientHttpRequestFactory simpleClientHttpRequestFactory() { + SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); + // 单位为ms + factory.setReadTimeout(READ_TIME_OUT); + factory.setConnectTimeout(CONNECT_TIME_OUT); + return factory; + } + +} diff --git a/src/main/java/com/newyetai/sdk/common/config/ValidConfig.java b/src/main/java/com/newyetai/sdk/common/config/ValidConfig.java new file mode 100644 index 0000000..424d7e6 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/common/config/ValidConfig.java @@ -0,0 +1,18 @@ +package com.newyetai.sdk.common.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.validation.beanvalidation.MethodValidationPostProcessor; + +import javax.validation.Validator; + +@Configuration +public class ValidConfig { + + public MethodValidationPostProcessor methodValidationPostProcessor(Validator validator) { + MethodValidationPostProcessor methodValidationPostProcessor = new MethodValidationPostProcessor(); + if (validator != null) { + methodValidationPostProcessor.setValidator(validator); + } + return methodValidationPostProcessor; + } +} diff --git a/src/main/java/com/newyetai/sdk/common/constant/SdkConstants.java b/src/main/java/com/newyetai/sdk/common/constant/SdkConstants.java new file mode 100644 index 0000000..8ca31a0 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/common/constant/SdkConstants.java @@ -0,0 +1,39 @@ +package com.newyetai.sdk.common.constant; + +/** + * @author sr on 2020-04-10 + */ +public interface SdkConstants { + + String INVOKE_FAIL = "第三方接口调用异常:"; + + /** ()代表错误码中间两位,如060101是放心签错误码 **/ + /** 标识:放心签(01) **/ + String FXQ_CODE = "fxq"; + /** 标识:短信(02) **/ + String SMS_CODE = "sms"; + /** 标识:支付宝(03) **/ + String ALIPAY_CODE = "alipay"; + /** 标识:微信(04) **/ + String WECHAT_CODE = "wechat"; + /** 标识:创蓝(05) **/ + String CL_CODE = "chuanglan"; + + + /** ================ sdk通用异常code ================= **/ + /** 调用异常,未调起第三方 **/ + String SDK_INVOKE_NOT_REACH_CODE = "060000"; + /** 调用异常,http调起第三方异常 **/ + String SDK_HTTP_INVOKE_ERROR_CODE = "060001"; + /** 调用失败,http调起第三方结果返回,非成功码 **/ + String SDK_HTTP_INVOKE_RESPONSE_FAIL_CODE = "060002"; + /** 调用失败(业务),http调起第三方结果返回成功,根据业务判断非成功状态 **/ + String SDK_HTTP_INVOKE_BUSINESS_FAIL_CODE = "060003"; + /** 请求参数异常 **/ + String SDK_REQUEST_PARAM_ERROR_CODE = "060004"; + /** 结果转换失败 **/ + String SDK_RESPONSE_CONVERT_ERROR_CODE = "060005"; + + /** ================ sdk通用异常code ================= **/ + +} diff --git a/src/main/java/com/newyetai/sdk/common/dto/AbstractSdkInvokeLogDTO.java b/src/main/java/com/newyetai/sdk/common/dto/AbstractSdkInvokeLogDTO.java new file mode 100644 index 0000000..9aab707 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/common/dto/AbstractSdkInvokeLogDTO.java @@ -0,0 +1,51 @@ +package com.newyetai.sdk.common.dto; + +import java.io.Serializable; +import java.util.Date; + +import com.newyetai.common.util.RandomUtils; + +import lombok.AllArgsConstructor; +import lombok.Builder.Default; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * sdk 调用日志对象 + * + * @author sr on 2021-01-27 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class AbstractSdkInvokeLogDTO implements Serializable { + + /** **/ + private static final long serialVersionUID = 4230907893212819576L; + + /** 请求对象 **/ + private Object requestData; + /** 结果对象 **/ + private Object responseData; + /** 请求时间 **/ + @Default + private Date requestDate = new Date(); + /** 请求标识 **/ + @Default + private String requestId = RandomUtils.generateUUID(); + /** 具体方法类型 **/ + private String methodType; + /** 调用耗时(单位毫秒) **/ + private Long useTime; + + public String getMethodType() { + if (methodType == null && requestData != null) { + methodType = requestData instanceof ISdkRequest ? ((ISdkRequest) requestData).getMethodName() + : requestData.getClass().getSimpleName(); + } + return methodType; + } + +} diff --git a/src/main/java/com/newyetai/sdk/common/dto/DefaultSdkInvokeLogDTO.java b/src/main/java/com/newyetai/sdk/common/dto/DefaultSdkInvokeLogDTO.java new file mode 100644 index 0000000..b3a8701 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/common/dto/DefaultSdkInvokeLogDTO.java @@ -0,0 +1,29 @@ +package com.newyetai.sdk.common.dto; + +import org.springframework.data.annotation.Transient; + +import lombok.AllArgsConstructor; +import lombok.Builder.Default; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 默认sdk调用日志对象 + * @author sr on 2021-03-18 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class DefaultSdkInvokeLogDTO extends AbstractSdkInvokeLogDTO{ + + /** **/ + private static final long serialVersionUID = -7870863791739331150L; + + /** 分类集合名称(mongo使用) **/ + @Transient + @Default + private String collectionName = "default_sdk_invoke_log"; + +} diff --git a/src/main/java/com/newyetai/sdk/common/dto/ISdkRequest.java b/src/main/java/com/newyetai/sdk/common/dto/ISdkRequest.java new file mode 100644 index 0000000..977d534 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/common/dto/ISdkRequest.java @@ -0,0 +1,55 @@ +package com.newyetai.sdk.common.dto; + +import java.io.Serializable; + +import org.springframework.core.ParameterizedTypeReference; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +/** + * 请求对象 + * @author sr on 2021-03-18 + */ +public interface ISdkRequest extends Serializable{ + + /** + * 方法名 + * @return + * @author sr on 2021-12-27 + */ + @JsonIgnore + default String getMethodName() { + return this.getClass().getSimpleName(); + } + + /** + * 调用uri + * @return + * @author sr on 2021-12-27 + */ + @JsonIgnore + default String getUri() { + return null; + } + + /** + * 结果集普通类型 + * @return + * @author sr on 2021-12-20 + */ + @JsonIgnore + default Class getResponseClass() { + return null; + } + + /** + * 结果集带范性类型 + * @return + * @author sr on 2021-12-20 + */ + @JsonIgnore + default ParameterizedTypeReference getResponseType() { + return null; + } + +} diff --git a/src/main/java/com/newyetai/sdk/common/dto/ISdkResponse.java b/src/main/java/com/newyetai/sdk/common/dto/ISdkResponse.java new file mode 100644 index 0000000..1c0a071 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/common/dto/ISdkResponse.java @@ -0,0 +1,11 @@ +package com.newyetai.sdk.common.dto; + +import java.io.Serializable; + +/** + * 结果 + * @author sr on 2021-11-24 + */ +public interface ISdkResponse extends Serializable{ + +} diff --git a/src/main/java/com/newyetai/sdk/common/dto/LiteUserPhoneDTO.java b/src/main/java/com/newyetai/sdk/common/dto/LiteUserPhoneDTO.java new file mode 100644 index 0000000..37e3050 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/common/dto/LiteUserPhoneDTO.java @@ -0,0 +1,32 @@ +package com.newyetai.sdk.common.dto; + +import java.io.Serializable; + +import com.newyetai.sdk.wechat.model.Watermark; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 小程序用户手机号信息 + * @author sr on 2021-11-25 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class LiteUserPhoneDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 4564606626820175506L; + + /** 用户绑定的手机号(国外手机号会有区号) **/ + private String phoneNumber; + /** 没有区号的手机号 **/ + private String purePhoneNumber; + /** 区号 **/ + private String countryCode; + /** 数据水印 **/ + private Watermark watermark; + +} diff --git a/src/main/java/com/newyetai/sdk/common/exception/SdkException.java b/src/main/java/com/newyetai/sdk/common/exception/SdkException.java new file mode 100644 index 0000000..61ffe16 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/common/exception/SdkException.java @@ -0,0 +1,34 @@ +package com.newyetai.sdk.common.exception; + +/** + * @author sr on 2020-04-09 + */ +public class SdkException extends RuntimeException { + + /** **/ + private static final long serialVersionUID = 1139970958567895252L; + + public SdkException() { + super(); + } + + public SdkException(String message, Throwable cause, boolean enableSuppression, + boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } + + public SdkException(String message, Throwable cause) { + super(message, cause); + } + + public SdkException(String message) { + super(message); + } + + public SdkException(Throwable cause) { + super(cause); + } + + + +} diff --git a/src/main/java/com/newyetai/sdk/common/util/HttpUtils.java b/src/main/java/com/newyetai/sdk/common/util/HttpUtils.java new file mode 100644 index 0000000..db771d1 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/common/util/HttpUtils.java @@ -0,0 +1,97 @@ +package com.newyetai.sdk.common.util; + +import java.util.List; + +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.util.StopWatch; +import org.springframework.web.client.RestTemplate; + +import com.google.common.collect.Lists; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.sdk.common.dto.DefaultSdkInvokeLogDTO; +import com.newyetai.sdk.common.dto.ISdkRequest; +import com.newyetai.sdk.common.dto.ISdkResponse; +import com.newyetai.sdk.common.exception.SdkException; + +import lombok.extern.slf4j.Slf4j; + + +/** + * sdk,http调用工具类 + * @author sr on 2022-07-26 + */ +@Slf4j +public class HttpUtils { + + public static RestTemplate restTemplate = new RestTemplate(); + static { + MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); + List mediaTypes = Lists.newArrayList(MediaType.APPLICATION_ATOM_XML, + MediaType.APPLICATION_FORM_URLENCODED, + MediaType.APPLICATION_JSON, + MediaType.APPLICATION_JSON_UTF8, + MediaType.APPLICATION_OCTET_STREAM, + MediaType.APPLICATION_PDF, + MediaType.APPLICATION_PROBLEM_JSON, + MediaType.APPLICATION_PROBLEM_JSON_UTF8, + MediaType.APPLICATION_PROBLEM_XML, + MediaType.APPLICATION_RSS_XML, + MediaType.APPLICATION_STREAM_JSON, + MediaType.APPLICATION_XHTML_XML, + MediaType.APPLICATION_XML, + MediaType.IMAGE_GIF, + MediaType.IMAGE_JPEG, + MediaType.IMAGE_PNG, + MediaType.MULTIPART_FORM_DATA, + MediaType.TEXT_EVENT_STREAM, + MediaType.TEXT_HTML, + MediaType.TEXT_MARKDOWN, + MediaType.TEXT_PLAIN, + MediaType.TEXT_XML); + converter.setSupportedMediaTypes(mediaTypes); + restTemplate.getMessageConverters().add(converter); + } + + public static RES post(ISdkRequest req) throws SdkException { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + HttpEntity httpEntity = new HttpEntity<>(req, headers); + return exchange(req, req.getUri(), httpEntity, HttpMethod.POST); + } + + public static RES exchange(ISdkRequest req, String url, HttpEntity httpEntity, + HttpMethod method) throws SdkException { + Class responseClass = req.getResponseClass(); + ParameterizedTypeReference responseType = req.getResponseType(); + Object requestData = httpEntity.getBody(); + try { + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + ResponseEntity response = null; + if (responseClass != null) { + response = restTemplate.exchange(url, method, httpEntity, responseClass); + } else { + response = + restTemplate.exchange(url, method, httpEntity, + responseType); + } + Object body = response.getBody(); + stopWatch.stop(); + log.info("req:{} invoke:{}, ", req.getClass(), JsonUtils + .toJsonString(DefaultSdkInvokeLogDTO.builder().requestData(requestData).responseData(body) + .useTime(stopWatch.getTotalTimeMillis()) + .methodType(req.getMethodName()) + .build())); + return (RES) body; + } catch (Exception e) { + log.error("req:{}, :{},{}", req.getClass(), JsonUtils.toJsonString(requestData), e); + throw new SdkException(e); + } + } +} diff --git a/src/main/java/com/newyetai/sdk/common/util/LiteEncryptor.java b/src/main/java/com/newyetai/sdk/common/util/LiteEncryptor.java new file mode 100644 index 0000000..fe7aa7e --- /dev/null +++ b/src/main/java/com/newyetai/sdk/common/util/LiteEncryptor.java @@ -0,0 +1,46 @@ +package com.newyetai.sdk.common.util; + +import java.nio.charset.StandardCharsets; +import java.security.AlgorithmParameters; +import java.util.Base64; + +import javax.crypto.Cipher; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.util.JsonUtils; + +import lombok.extern.slf4j.Slf4j; + +/** + * 加密器 + * @author sr on 2021-11-23 + */ +@Slf4j +public class LiteEncryptor { + + public static T decrypt(String encryptData, String iv, String sessionKey, Class clazz) { + String decryptStr ; + try { + AlgorithmParameters algorithmParameters = AlgorithmParameters.getInstance("AES"); + algorithmParameters.init(new IvParameterSpec(Base64.getDecoder().decode(iv))); + Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); + cipher.init(Cipher.DECRYPT_MODE, + new SecretKeySpec(Base64.getDecoder().decode(sessionKey), "AES"), algorithmParameters); + byte[] decode = PKCS7Encoder.decode(cipher.doFinal(Base64.getDecoder().decode(encryptData))); + decryptStr = new String(decode, StandardCharsets.US_ASCII); + } catch (Exception e) { + log.error("微信解密失败:", e); + throw new BusinessException("微信解密失败"); + } + try { + return JsonUtils.toObject(decryptStr, clazz); + } catch (Exception e) { + log.debug(decryptStr); + throw new BusinessException("微信解密失败(可能小程序session_key过期)"); + } + + } + +} diff --git a/src/main/java/com/newyetai/sdk/common/util/PKCS7Encoder.java b/src/main/java/com/newyetai/sdk/common/util/PKCS7Encoder.java new file mode 100644 index 0000000..9b12011 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/common/util/PKCS7Encoder.java @@ -0,0 +1,67 @@ +/** + * 对企业微信发送给企业后台的消息加解密示例代码. + * + * @copyright Copyright (c) 1998-2014 Tencent Inc. + */ + +// ------------------------------------------------------------------------ + +package com.newyetai.sdk.common.util; + +import java.nio.charset.Charset; +import java.util.Arrays; + +/** + * 提供基于PKCS7算法的加解密接口. + */ +class PKCS7Encoder { + static Charset CHARSET = Charset.forName("utf-8"); + static int BLOCK_SIZE = 32; + + /** + * 获得对明文进行补位填充的字节. + * + * @param count 需要进行填充补位操作的明文字节个数 + * @return 补齐用的字节数组 + */ + static byte[] encode(int count) { + // 计算需要填充的位数 + int amountToPad = BLOCK_SIZE - (count % BLOCK_SIZE); + if (amountToPad == 0) { + amountToPad = BLOCK_SIZE; + } + // 获得补位所用的字符 + char padChr = chr(amountToPad); + String tmp = new String(); + for (int index = 0; index < amountToPad; index++) { + tmp += padChr; + } + return tmp.getBytes(CHARSET); + } + + /** + * 删除解密后明文的补位字符 + * + * @param decrypted 解密后的明文 + * @return 删除补位字符后的明文 + */ + static byte[] decode(byte[] decrypted) { + int pad = (int) decrypted[decrypted.length - 1]; + if (pad < 1 || pad > 32) { + pad = 0; + } + return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad); + } + + /** + * 将数字转化成ASCII码对应的字符,用于对明文进行补码 + * + * @param a 需要转化的数字 + * @return 转化得到的字符 + */ + static char chr(int a) { + byte target = (byte) (a & 0xFF); + return (char) target; + } + +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/config/FxqCommonProperties.java b/src/main/java/com/newyetai/sdk/fangxinqian/config/FxqCommonProperties.java new file mode 100644 index 0000000..26b9d87 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/config/FxqCommonProperties.java @@ -0,0 +1,24 @@ +package com.newyetai.sdk.fangxinqian.config; + +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2020-04-09 + */ +@Data +@NoArgsConstructor +public class FxqCommonProperties{ + + /** 是否启用 **/ + private Boolean enable = Boolean.FALSE; + /** id **/ + private String appId; + /** secret **/ + private String appSecret; + /** 接口地址 **/ + private String url; + /** 次数限制 **/ + private Long numLimit; + +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/config/FxqContractExtensionProperties.java b/src/main/java/com/newyetai/sdk/fangxinqian/config/FxqContractExtensionProperties.java new file mode 100644 index 0000000..4b77cf5 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/config/FxqContractExtensionProperties.java @@ -0,0 +1,24 @@ +package com.newyetai.sdk.fangxinqian.config; + +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 合同相关配置 + */ +@Data +@NoArgsConstructor +public class FxqContractExtensionProperties { + /** + * 是否启用 + **/ + private Boolean enable = Boolean.FALSE; + /** + * 接口地址 + **/ + private String url; + /** + * 次数限制 + **/ + private Long numLimit; +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/config/FxqContractProperties.java b/src/main/java/com/newyetai/sdk/fangxinqian/config/FxqContractProperties.java new file mode 100644 index 0000000..e75e678 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/config/FxqContractProperties.java @@ -0,0 +1,39 @@ +package com.newyetai.sdk.fangxinqian.config; + +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 合同相关配置 + */ +@Data +@NoArgsConstructor +public class FxqContractProperties extends FxqCommonProperties { + + /** + * 普通签署 + */ + private FxqContractExtensionProperties commonSign; + /** + * 关键字签署 + */ + private FxqContractExtensionProperties keySign; + /** + * 存证 + */ + private FxqContractExtensionProperties evidenceSave; + /** + * 出证 + */ + private FxqContractExtensionProperties evidenceGet; + + public FxqCommonProperties build(FxqContractExtensionProperties properties) { + FxqCommonProperties result = new FxqCommonProperties(); + result.setAppId(this.getAppId()); + result.setAppSecret(this.getAppSecret()); + result.setEnable(properties.getEnable()); + result.setNumLimit(properties.getNumLimit()); + result.setUrl(properties.getUrl()); + return result; + } +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/config/FxqProperties.java b/src/main/java/com/newyetai/sdk/fangxinqian/config/FxqProperties.java new file mode 100644 index 0000000..9f5d354 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/config/FxqProperties.java @@ -0,0 +1,112 @@ +package com.newyetai.sdk.fangxinqian.config; + +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * 放心签配置 + * + * @author sr on 2020-04-09 + */ +@ConfigurationProperties(prefix = FxqProperties.PREFIX, ignoreUnknownFields = false) +@Data +@Component +@NoArgsConstructor +public class FxqProperties { + + /** + * 放心签配置前缀 + **/ + public static final String PREFIX = "fangxinqian"; + /** + * 放心签三要素配置前缀 + **/ + public static final String BANK_CARD_THREE_PREFIX = PREFIX + ".bankCard3"; + /** + * 放心签四要素配置前缀 + **/ + public static final String BANK_CARD_FOUR_PREFIX = PREFIX + ".bankCard4"; + + /** + * 实名认证配置前缀 + */ + public static final String REALNAME_AUTH_PREFIX = PREFIX + ".realname"; + + /** + * 工商核验 + */ + public static final String GOVERNMENT_AUTH_PREFIX = PREFIX + ".government"; + + /** + * 普通签署 + */ + public static final String COMMON_SIGN_PREFIX = PREFIX + ".contract.commonSign"; + + /** + * 关键字签署 + */ + public static final String KEY_SIGN_PREFIX = PREFIX + ".contract.keySign"; + /** + * 存证 + */ + public static final String EVIDENCE_SAVE_PREFIX = PREFIX + ".contract.evidenceSave"; + + /** + * 出证 + */ + public static final String EVIDENCE_GET_PREFIX = PREFIX + ".contract.evidenceGet"; + + + /** + * https://api.fangxinqian.cn + */ + private String domain; + + /** + * 系统预留手机号 + */ + private String phone; + + /** + * 公章uri + */ + private String officialSealUri; + + /** + * 个人章uri + */ + private String personalSealUri; + + /** + * 合同关键字替换 + */ + private String textReplaceUri; + + /** + * 银行卡三要素配置 + **/ + private FxqCommonProperties bankCard3; + + /** + * 银行卡四要素配置 + **/ + private FxqCommonProperties bankCard4; + + /** + * 实名认证配置 + */ + private FxqCommonProperties realName; + + /** + * 工商信息核验配置 + */ + private FxqCommonProperties government; + + /** + * 合同 + */ + private FxqContractProperties contract; + +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/constant/BankCardFourStateEnum.java b/src/main/java/com/newyetai/sdk/fangxinqian/constant/BankCardFourStateEnum.java new file mode 100644 index 0000000..c869607 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/constant/BankCardFourStateEnum.java @@ -0,0 +1,66 @@ +package com.newyetai.sdk.fangxinqian.constant; + +import java.util.Map; + +import com.google.common.collect.Maps; +import com.newyetai.common.AlitaResult; + +/** + * 银行三要素验证结果枚举 + * + * @author sr on 2020-04-10 + */ +public enum BankCardFourStateEnum { + /** 验证一致 **/ + SUC("1", "验证一致"), + /** 验证不一致 **/ + FAIL("2", "验证不一致"); + + private static Map stateMap; + /** 验证结果 **/ + private String state; + /** 说明 **/ + private String msg; + + + BankCardFourStateEnum(String state, String msg) { + this.state = state; + this.msg = msg; + } + + static { + BankCardFourStateEnum[] array = BankCardFourStateEnum.values(); + stateMap = Maps.newHashMapWithExpectedSize(array.length); + for (BankCardFourStateEnum stateEnum : array) { + stateMap.put(stateEnum.getState(), stateEnum); + } + } + + public String getState() { + return state; + } + + public String getMsg() { + return msg; + } + + /** + * 处理验证结果 + * + * @param state + * @return + * @author sr on 2020-04-10 + */ + public static AlitaResult dealState(String state) { + BankCardFourStateEnum stateEnum = stateMap.get(state); + if (stateEnum == null) { + return AlitaResult.success("state not available...", false); + } + if (stateEnum == SUC) { + return AlitaResult.success(true); + } + return AlitaResult.success(stateEnum.getMsg(), false); + } + + +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/constant/BankCardThreeStateEnum.java b/src/main/java/com/newyetai/sdk/fangxinqian/constant/BankCardThreeStateEnum.java new file mode 100644 index 0000000..ea7c259 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/constant/BankCardThreeStateEnum.java @@ -0,0 +1,68 @@ +package com.newyetai.sdk.fangxinqian.constant; + +import java.util.Map; + +import com.google.common.collect.Maps; +import com.newyetai.common.AlitaResult; + +/** + * 银行三要素验证结果枚举 + * + * @author sr on 2020-04-10 + */ +public enum BankCardThreeStateEnum { + /** 验证一致 **/ + SUC("1", "验证一致"), + /** 验证不一致 **/ + FAIL("2", "验证不一致"), + /** 异常情况 **/ + UNKNOWN("3", "异常情况"); + + private static Map stateMap; + /** 验证结果 **/ + private String state; + /** 说明 **/ + private String msg; + + + BankCardThreeStateEnum(String state, String msg) { + this.state = state; + this.msg = msg; + } + + static { + BankCardThreeStateEnum[] array = BankCardThreeStateEnum.values(); + stateMap = Maps.newHashMapWithExpectedSize(array.length); + for (BankCardThreeStateEnum stateEnum : array) { + stateMap.put(stateEnum.getState(), stateEnum); + } + } + + public String getState() { + return state; + } + + public String getMsg() { + return msg; + } + + /** + * 处理验证结果 + * + * @param state + * @return + * @author sr on 2020-04-10 + */ + public static AlitaResult dealState(String state) { + BankCardThreeStateEnum stateEnum = stateMap.get(state); + if (stateEnum == null) { + return AlitaResult.success("state not available...", false); + } + if (stateEnum == SUC) { + return AlitaResult.success(true); + } + return AlitaResult.success(stateEnum.getMsg(), false); + } + + +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/constant/FxqConstants.java b/src/main/java/com/newyetai/sdk/fangxinqian/constant/FxqConstants.java new file mode 100644 index 0000000..ca63dee --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/constant/FxqConstants.java @@ -0,0 +1,19 @@ +package com.newyetai.sdk.fangxinqian.constant; + +import com.newyetai.sdk.common.constant.SdkConstants; + +/** + * @author sr on 2020-04-10 + */ +public interface FxqConstants { + + /** 成功码 **/ + String SUC_CODE = "10000"; + + /** ================ fxq 调起真实服务前异常msg ================= **/ + String PROPERTIES_NOT_SET = SdkConstants.FXQ_CODE + ":配置文件未配置"; + String ID_SECRET_NOT_ENOUGH = SdkConstants.FXQ_CODE + ":参数appId或appSecret缺失"; + /** ================ fxq 调起真实服务前异常msq ================= **/ + + +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/constant/FxqErrorCodeEnum.java b/src/main/java/com/newyetai/sdk/fangxinqian/constant/FxqErrorCodeEnum.java new file mode 100644 index 0000000..a431fcf --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/constant/FxqErrorCodeEnum.java @@ -0,0 +1,33 @@ +package com.newyetai.sdk.fangxinqian.constant; + +/** + * sdk放心签错误码枚举;标识:放心签(01) + * @author sr on 2020-05-22 + */ +public enum FxqErrorCodeEnum { + + /** 放心签调用返回错误码 **/ + INVOKE_RETURN_ERROR("060101", "放心签接口调用失败,返回错误码"), + /** 放心签调用成功,但信息不匹配 **/ + NOT_EQUAL("060102", "不匹配"); + + /** 错误码 **/ + private String code; + /** 错误信息 **/ + private String msg; + + FxqErrorCodeEnum(String code, String msg){ + this.code = code; + this.msg = msg; + } + + public String getCode() { + return code; + } + + public String getMsg() { + return msg; + } + + +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/dto/BankCardFourRequestDTO.java b/src/main/java/com/newyetai/sdk/fangxinqian/dto/BankCardFourRequestDTO.java new file mode 100644 index 0000000..07e2e2d --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/dto/BankCardFourRequestDTO.java @@ -0,0 +1,40 @@ +package com.newyetai.sdk.fangxinqian.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotBlank; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * 银行卡四要素请求 + * + * @author sr on 2020-04-09 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class BankCardFourRequestDTO extends FxqRequestDTO implements Serializable { + + /** **/ + private static final long serialVersionUID = 3807618123977056991L; + + /** 姓名 **/ + @NotBlank(message = "姓名不能为空") + private String name; + /** 身份证号 **/ + @NotBlank(message = "身份证号不能为空") + private String identityCode; + /** 银行卡号 **/ + @NotBlank(message = "银行卡号不能为空") + private String bankcardNumber; + @NotBlank(message = "手机号码不能为空") + private String phoneNumber; + +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/dto/BankCardFourResponseDTO.java b/src/main/java/com/newyetai/sdk/fangxinqian/dto/BankCardFourResponseDTO.java new file mode 100644 index 0000000..9fe991b --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/dto/BankCardFourResponseDTO.java @@ -0,0 +1,29 @@ +package com.newyetai.sdk.fangxinqian.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.ToString; + +/** + * 银行卡四要素请求 + * + * @author sr on 2020-04-09 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ToString(callSuper = true) +public class BankCardFourResponseDTO extends FxqResponseDTO { + + /** **/ + private static final long serialVersionUID = 3188936116187424875L; + + /** 结果data **/ + private StateDataDTO data; + +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/dto/BankCardThreeRequestDTO.java b/src/main/java/com/newyetai/sdk/fangxinqian/dto/BankCardThreeRequestDTO.java new file mode 100644 index 0000000..363006f --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/dto/BankCardThreeRequestDTO.java @@ -0,0 +1,38 @@ +package com.newyetai.sdk.fangxinqian.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotBlank; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * 银行卡三要素请求 + * + * @author sr on 2020-04-09 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class BankCardThreeRequestDTO extends FxqRequestDTO implements Serializable { + + /** **/ + private static final long serialVersionUID = -6539738426193243916L; + + /** 姓名 **/ + @NotBlank(message = "姓名不能为空") + private String name; + /** 身份证号 **/ + @NotBlank(message = "身份证号不能为空") + private String identityCode; + /** 银行卡号 **/ + @NotBlank(message = "银行卡号不能为空") + private String bankcardNumber; + +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/dto/BankCardThreeResponseDTO.java b/src/main/java/com/newyetai/sdk/fangxinqian/dto/BankCardThreeResponseDTO.java new file mode 100644 index 0000000..4facd04 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/dto/BankCardThreeResponseDTO.java @@ -0,0 +1,29 @@ +package com.newyetai.sdk.fangxinqian.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.ToString; + +/** + * 银行卡三要素请求 + * + * @author sr on 2020-04-09 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ToString(callSuper = true) +public class BankCardThreeResponseDTO extends FxqResponseDTO { + + /** **/ + private static final long serialVersionUID = 3188936116187424875L; + + /** 结果data **/ + private StateDataDTO data; + +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/dto/ContractRequestDTO.java b/src/main/java/com/newyetai/sdk/fangxinqian/dto/ContractRequestDTO.java new file mode 100644 index 0000000..671e5fe --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/dto/ContractRequestDTO.java @@ -0,0 +1,113 @@ +package com.newyetai.sdk.fangxinqian.dto; + +import lombok.*; + +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * 合同签署请求DTO + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class ContractRequestDTO extends FxqRequestDTO { + private static final long serialVersionUID = 7354207669664708465L; + + /** + * 合同⽂件(base64/云存储⽂件链接) + */ + @NotBlank(message = "合同⽂件不能为空") + private String contract; + + /** + * 合同文件名 + */ + @NotBlank(message = "合同⽂件名不能为空") + private String title; + + /** + * 0.返回签署完成的base64 1.返回云存储⽂件链接 不填默认 0 + */ + private String returnType; + + /** + * 签署⼈信息 + */ + @Valid + @NotNull(message = "签署⼈信息不能为空") + private List signers; + + /** + * 签署人信息 + */ + @Data + @NoArgsConstructor + @AllArgsConstructor + @Builder + public static class CommonSignSigner { + /** + * 真实姓名/公司名称 + */ + @NotBlank(message = "签署人名称不能为空") + private String name; + + /** + * 身份证号码/统⼀信⽤代码 + */ + @NotBlank(message = "签署人证件信息不能为空") + private String idcard; + + /** + * 签章图⽚⽂件 + */ + @NotBlank(message = "签章图⽚⽂件信息不能为空") + private String img; + + /** + * 个⼈传⼿机号码,企业传法⼈⼿机号码/公司简称的拼⾳⾸字⺟ 如葫芦娃:hlw + */ + @NotBlank(message = "手机号不能为空") + private String phone; + + /** + * 该值控制骑缝章位置 ⼤于100 表示需要签署骑缝章 双⽅骑缝章 位置间隔建议⼤于100 最⼤不能超过650 + */ + private Integer gapMargin; + + /** + * 签署区域 (普通签署方式) + */ + private List areas; + + /** + * 签署关键字 (关键字签署方式) + */ + private String key; + /** + * 签章签署在距离关键字距离 正数(往右)负数(往左) (关键字签署方式) + */ + private Integer marginLeft; + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + @Builder + public static class Area { + @NotNull(message = "签署区域左下⻆点X坐标不能为空") + private Integer x1; + @NotNull(message = "签署区域左下⻆点Y坐标不能为空") + private Integer y1; + @NotNull(message = "签署区域右上⻆点X坐标不能为空") + private Integer x2; + @NotNull(message = "签署区域右上⻆点Y坐标不能为空") + private Integer y2; + @NotNull(message = "签署⻚数不能为空") + private Integer page; + } +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/dto/ContractResponseDTO.java b/src/main/java/com/newyetai/sdk/fangxinqian/dto/ContractResponseDTO.java new file mode 100644 index 0000000..5d96225 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/dto/ContractResponseDTO.java @@ -0,0 +1,17 @@ +package com.newyetai.sdk.fangxinqian.dto; + +import lombok.Data; + +@Data +public class ContractResponseDTO extends FxqResponseDTO { + + /** + * 文件base64或云链接 + */ + private String data; + + @Override + protected String handleData() { + return this.data; + } +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/dto/EvidenceGetRequestDTO.java b/src/main/java/com/newyetai/sdk/fangxinqian/dto/EvidenceGetRequestDTO.java new file mode 100644 index 0000000..80c7d0b --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/dto/EvidenceGetRequestDTO.java @@ -0,0 +1,23 @@ +package com.newyetai.sdk.fangxinqian.dto; + +import lombok.*; + +import javax.validation.constraints.NotNull; + +/** + * 区块链出证请求DTO + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class EvidenceGetRequestDTO extends FxqRequestDTO { + private static final long serialVersionUID = 7354207669664708465L; + + /** + * 合同区块链存证时的回执 + */ + @NotNull(message = "回执不能为空") + private String evidenceID; +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/dto/EvidenceGetResponseDTO.java b/src/main/java/com/newyetai/sdk/fangxinqian/dto/EvidenceGetResponseDTO.java new file mode 100644 index 0000000..72ee44e --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/dto/EvidenceGetResponseDTO.java @@ -0,0 +1,17 @@ +package com.newyetai.sdk.fangxinqian.dto; + +import lombok.Data; + +@Data +public class EvidenceGetResponseDTO extends FxqResponseDTO { + + /** + * 证据链上地址 + */ + private String data; + + @Override + protected String handleData() { + return this.data; + } +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/dto/EvidenceSaveRequestDTO.java b/src/main/java/com/newyetai/sdk/fangxinqian/dto/EvidenceSaveRequestDTO.java new file mode 100644 index 0000000..298ac2c --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/dto/EvidenceSaveRequestDTO.java @@ -0,0 +1,96 @@ +package com.newyetai.sdk.fangxinqian.dto; + +import lombok.*; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * 区块链存证请求DTO + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class EvidenceSaveRequestDTO extends FxqRequestDTO { + private static final long serialVersionUID = 7354207669664708465L; + + /** + * 合同⽂件(base64/云存储⽂件链接) + */ + @NotBlank(message = "合同⽂件不能为空") + private String contract; + + /** + * 合同名称 + */ + @NotBlank(message = "合同名称不能为空") + private String title; + + /** + * ⾏业类型 + * 1 政务⺠⽣ + * 2 保险 + * 3 银⾏ + * 4 消费⾦融-资产 + * 5 消费⾦融-资⾦ + * 6 持牌⼩贷 + * 7 医疗 + * 8 教育 + * 9 出⾏与交通 + * 10 ⽣活服务 + * 11 通信与运营商 + * 12 旅游与酒店 + * 13 快递与邮政 + * 99 其他 + */ + @NotBlank(message = "⾏业类型不能为空") + private String industry; + + /** + * 签署⼈信息 + */ + @NotNull(message = "签署⼈列表") + private List userInfos; + + /** + * 合同签署⼈列表 + */ + @Data + @NoArgsConstructor + @AllArgsConstructor + @Builder + public static class UserInfo { + /** + * 真实姓名/公司名称 + */ + @NotBlank(message = "签署人姓名不能为空") + private String userName; + + /** + * ⽤户类型 0.个⼈ 1.企业 + */ + @NotBlank(message = "⽤户类型不能为空") + private String customerType; + + /** + * 证件类型 具体参考类型列表 + * 0 居⺠身份证 + * 1 护照 + * 3 ⼯商登记证 + * C 台湾居⺠来往⼤陆通⾏证 + * P 外国⼈永久居留证 + * Z 其它 + */ + @NotBlank(message = "证件类型不能为空") + private String identificationType; + + /** + * 证件号码 + */ + @NotBlank(message = "证件号码不能为空") + private String identificationNo; + } +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/dto/EvidenceSaveResponseDTO.java b/src/main/java/com/newyetai/sdk/fangxinqian/dto/EvidenceSaveResponseDTO.java new file mode 100644 index 0000000..21b3c09 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/dto/EvidenceSaveResponseDTO.java @@ -0,0 +1,17 @@ +package com.newyetai.sdk.fangxinqian.dto; + +import lombok.Data; + +@Data +public class EvidenceSaveResponseDTO extends FxqResponseDTO { + + /** + * 区块链存证业务回执 这个需要⾃⾏保存 出证需要⽤到 + */ + private String data; + + @Override + protected String handleData() { + return this.data; + } +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/dto/FxqRequestDTO.java b/src/main/java/com/newyetai/sdk/fangxinqian/dto/FxqRequestDTO.java new file mode 100644 index 0000000..6ef9b7c --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/dto/FxqRequestDTO.java @@ -0,0 +1,27 @@ +package com.newyetai.sdk.fangxinqian.dto; + +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 放心签请求父类dto + * + * @author sr on 2020-04-09 + */ +@Data +@NoArgsConstructor +public class FxqRequestDTO implements Serializable { + + private static final long serialVersionUID = 3960499271644654446L; + /** + * id + **/ + private String appId; + /** + * secret + **/ + private String appSecret; + +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/dto/FxqResponseDTO.java b/src/main/java/com/newyetai/sdk/fangxinqian/dto/FxqResponseDTO.java new file mode 100644 index 0000000..7c31828 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/dto/FxqResponseDTO.java @@ -0,0 +1,76 @@ +package com.newyetai.sdk.fangxinqian.dto; + +import com.newyetai.common.AlitaResult; +import com.newyetai.sdk.fangxinqian.constant.FxqConstants; +import com.newyetai.sdk.fangxinqian.constant.FxqErrorCodeEnum; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.util.StringUtils; + +import java.io.Serializable; + +/** + * 放心签返回 + * + * @param + * @author sr on 2020-04-09 + */ +@Data +@NoArgsConstructor +public class FxqResponseDTO implements Serializable { + + /** + * + **/ + private static final long serialVersionUID = -4576000729533850612L; + /** + * 错误码 + **/ + private String code; + /** + * 序列号(每次调用接口返回的唯一值,seqNo 如有接口问题,请提供此值) + **/ + private String seqNo; + /** + * 错误信息 1 + **/ + private String message; + + /** + * 错误信息 2 + */ + private String msg; + + + public static FxqResponseDTO buildCommonError() { + FxqResponseDTO fxqResponseDTO = new FxqResponseDTO(); + fxqResponseDTO.setCode("999"); + return fxqResponseDTO; + } + + /** + * 返回结果处理 + * + * @return + */ + public AlitaResult handleResult() { + if (FxqConstants.SUC_CODE.equals(this.getCode())) { + return AlitaResult.success(handleData()); + } else { + return AlitaResult.error(FxqErrorCodeEnum.INVOKE_RETURN_ERROR.getCode(), + StringUtils.isEmpty(this.getMsg()) ? + StringUtils.isEmpty(this.getMessage()) ? FxqErrorCodeEnum.INVOKE_RETURN_ERROR.getMsg() : this.getMessage() + : this.getMsg()); + } + } + + /** + * 子类DTO实现 转换为AlitaResult时 + * 通过 handleData()决定转换为AlitaResult的data返回什么 + * + * @return + */ + protected T handleData() { + return null; + } +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/dto/GovernmentAuthRequestDTO.java b/src/main/java/com/newyetai/sdk/fangxinqian/dto/GovernmentAuthRequestDTO.java new file mode 100644 index 0000000..f732ada --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/dto/GovernmentAuthRequestDTO.java @@ -0,0 +1,34 @@ +package com.newyetai.sdk.fangxinqian.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; + +/** + * @author chenyun + * @description [ 放心签 ] 公章生成请求DTO + * @date 2020/8/14 11:33 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class GovernmentAuthRequestDTO extends FxqRequestDTO { + + private static final long serialVersionUID = -5777141264861824696L; + + /** + * 企业名称 + */ + @NotNull(message = "企业名称不能为空") + private String companyName; + + /** + * 企业类型 0.企业 1.个体⼯商户 + */ + @NotNull(message = "企业类型不能为空") + private String companyType; +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/dto/GovernmentAuthResponseDTO.java b/src/main/java/com/newyetai/sdk/fangxinqian/dto/GovernmentAuthResponseDTO.java new file mode 100644 index 0000000..72d0790 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/dto/GovernmentAuthResponseDTO.java @@ -0,0 +1,123 @@ +package com.newyetai.sdk.fangxinqian.dto; + +import lombok.Data; + +import java.io.Serializable; +import java.util.Map; +import java.util.Optional; + +@Data +public class GovernmentAuthResponseDTO extends FxqResponseDTO { + + private String status; + + /** + * 返回实体 + */ + private Map data; + + @Override + protected GovernmentAuthResponseDataDTO handleData() { + return Optional.ofNullable(this.getData()) + .map(result -> Optional.ofNullable(result.get("basic")).orElse(null)) + .orElse(null); + } + + @Data + public static class GovernmentAuthResponseDataDTO implements Serializable { + private static final long serialVersionUID = -3235649555399151281L; + private String esdate; + /** + * 原注册号 + */ + private String regno; + /** + * 统一信用代码 + */ + private String creditcode; + /** + * 地址 + */ + private String dom; + /** + * 经营业务范围 + */ + private String zsopscope; + /** + * 实收资本 + */ + private String reccap; + /** + * 原注册号 + */ + private String oriregno; + /** + * 企业英文名 + */ + private String entnameeng; + /** + * 企业类型 + */ + private String enttype; + /** + * 最后年检度 + */ + private String ancheyear; + /** + * 经营期限至 + */ + private String opto; + /** + * 经营企业自 + */ + private String opfrom; + /** + * 注册资本币种 + */ + private String regcapcur; + /** + * 组织机构代码 + */ + private String orgcodes; + /** + * 注销日期 + */ + private String candate; + /** + * 企业名称 + */ + private String entname; + /** + * 实收资本 + */ + private String regcap; + /** + * 登记机关 + */ + private String regorg; + /** + * 吊销日期 + */ + private String revdate; + /** + * 经营状态 + */ + private String entstatus; + /** + * 许可经营项目 + */ + private String abuitem; + /** + * 注册地址编码 + */ + private String regorgcode; + /** + * 法人姓名 + */ + private String frname; + /** + * + */ + private String apprdate; + } +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/dto/OfficialSealGenerateRequestDTO.java b/src/main/java/com/newyetai/sdk/fangxinqian/dto/OfficialSealGenerateRequestDTO.java new file mode 100644 index 0000000..bc00ed3 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/dto/OfficialSealGenerateRequestDTO.java @@ -0,0 +1,60 @@ +package com.newyetai.sdk.fangxinqian.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +/** + * @author chenyun + * @description [ 放心签 ] 公章生成请求DTO + * @date 2020/8/14 11:33 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class OfficialSealGenerateRequestDTO implements Serializable { + + private static final long serialVersionUID = -4020535227323920801L; + + /** + * 系统预留⼿机号 + */ + private String phone; + + /** + * 公司名称 + */ + @NotNull(message = "公司名称不能为空") + private String companyName; + + /** + * 公章类型 默认圆形 0:圆形 ,1:椭圆形 + */ + @NotNull(message = "公章类型不能为空") + private String serviceType; + + /** + * 公章颜⾊ , 默认红⾊ ,0:红⾊ ,1:蓝⾊ ,2:⿊⾊ + */ + private String color; + + /** + * 公章字体 , 默认宋体 ,0:宋体 ,1:楷体 ,2:正⽅⿊体 + */ + private String font; + + /** + * 公章下弦⽂ + */ + private String serNo; + + /** + * 公章副标题 + */ + private String title; +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/dto/PersonalSealGenerateRequestDTO.java b/src/main/java/com/newyetai/sdk/fangxinqian/dto/PersonalSealGenerateRequestDTO.java new file mode 100644 index 0000000..e6442cf --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/dto/PersonalSealGenerateRequestDTO.java @@ -0,0 +1,49 @@ +package com.newyetai.sdk.fangxinqian.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +/** + * @author chenyun + * @description [ 放心签 ] 个人章生成请求DTO + * @date 2020/8/17 10:41 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PersonalSealGenerateRequestDTO implements Serializable { + + private static final long serialVersionUID = -4020535227323920801L; + + /** + * 系统预留⼿机号 + */ + private String phone; + + /** + * 个⼈签章名称 + */ + @NotNull(message = "个⼈签章名称不能为空") + private String fontText; + + /** + * 签章颜⾊ , 默认红⾊ ,1: 红⾊ ,2: ⿊⾊ ,3: 蓝⾊ + */ + private Integer colorTag; + + /** + * 签章字体 , 默认⽅正⿊体 ,1: ⽅正⿊体 ,2: 仿宋 ,3: 楷体 + */ + private Integer fontFamilyTag; + + /** + * 签章类型 , 默认⻓⽅形 ; 1: ⻓⽅形 , 2 正⽅形 + */ + private Integer shape; +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/dto/PersonalSealGenerateResponseDTO.java b/src/main/java/com/newyetai/sdk/fangxinqian/dto/PersonalSealGenerateResponseDTO.java new file mode 100644 index 0000000..21aa025 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/dto/PersonalSealGenerateResponseDTO.java @@ -0,0 +1,19 @@ +package com.newyetai.sdk.fangxinqian.dto; + +import com.newyetai.common.annotation.Mask; +import lombok.Data; + +@Data +public class PersonalSealGenerateResponseDTO extends FxqResponseDTO { + + /** + * 公章/个人章 图片 base64 + */ + @Mask + private String data; + + @Override + protected String handleData() { + return this.data; + } +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/dto/RealnameAuthRequestDTO.java b/src/main/java/com/newyetai/sdk/fangxinqian/dto/RealnameAuthRequestDTO.java new file mode 100644 index 0000000..b2b5a49 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/dto/RealnameAuthRequestDTO.java @@ -0,0 +1,34 @@ +package com.newyetai.sdk.fangxinqian.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; + +/** + * @author chenyun + * @description [ 放心签 ] 公章生成请求DTO + * @date 2020/8/14 11:33 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class RealnameAuthRequestDTO extends FxqRequestDTO { + + private static final long serialVersionUID = -5777141264861824696L; + + /** + * 系统预留⼿机号 + */ + @NotNull(message = "姓名不能为空") + private String name; + + /** + * 公司名称 + */ + @NotNull(message = "身份证号码不能为空") + private String identityNumber; +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/dto/RealnameAuthResponseDTO.java b/src/main/java/com/newyetai/sdk/fangxinqian/dto/RealnameAuthResponseDTO.java new file mode 100644 index 0000000..4272749 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/dto/RealnameAuthResponseDTO.java @@ -0,0 +1,31 @@ +package com.newyetai.sdk.fangxinqian.dto; + +import com.newyetai.sdk.fangxinqian.enums.RealnameResultEnum; +import lombok.Data; + +import java.io.Serializable; +import java.util.Optional; + +@Data +public class RealnameAuthResponseDTO extends FxqResponseDTO { + + private String status; + + /** + * 实名认证结果 1:实名通过 2:实名不通过 + */ + private RealnameAuthResponseDataDTO data; + + @Override + protected Boolean handleData() { + return Optional.ofNullable(this.getData()) + .map(result -> Optional.ofNullable(result.getResult()).orElse("").equals(RealnameResultEnum.SUC.getResult())) + .orElse(false); + } + + @Data + public static class RealnameAuthResponseDataDTO implements Serializable { + private static final long serialVersionUID = -3235649555399151281L; + private String result; + } +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/dto/SealGenerateResponseDTO.java b/src/main/java/com/newyetai/sdk/fangxinqian/dto/SealGenerateResponseDTO.java new file mode 100644 index 0000000..b7926fa --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/dto/SealGenerateResponseDTO.java @@ -0,0 +1,17 @@ +package com.newyetai.sdk.fangxinqian.dto; + +import lombok.Data; + +@Data +public class SealGenerateResponseDTO extends FxqResponseDTO { + + /** + * 公章/个人章 图片 base64 + */ + private String baseStr; + + @Override + protected String handleData() { + return this.baseStr; + } +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/dto/StateDataDTO.java b/src/main/java/com/newyetai/sdk/fangxinqian/dto/StateDataDTO.java new file mode 100644 index 0000000..f0b1699 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/dto/StateDataDTO.java @@ -0,0 +1,21 @@ +package com.newyetai.sdk.fangxinqian.dto; + +import java.io.Serializable; + +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2020-04-09 + */ +@Data +@NoArgsConstructor +public class StateDataDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = -4608569342053995450L; + + /** 状态 **/ + private String state; + +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/dto/TextReplaceRequestDTO.java b/src/main/java/com/newyetai/sdk/fangxinqian/dto/TextReplaceRequestDTO.java new file mode 100644 index 0000000..229a269 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/dto/TextReplaceRequestDTO.java @@ -0,0 +1,64 @@ +package com.newyetai.sdk.fangxinqian.dto; + +import com.newyetai.common.annotation.Mask; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.List; + +/** + * @author chenyun + * @description [ 放心签 ] 合同替换关键字请求DTO + * @date 2020/8/17 11:15 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class TextReplaceRequestDTO implements Serializable { + + private static final long serialVersionUID = -4020535227323920801L; + + /** + * 系统预留⼿机号 + */ + private String phone; + + /** + * 待替换的 base64 ⽂档 + */ + @Mask + @NotNull(message = "个⼈签章名称不能为空") + private String fileBase64; + + /** + * ⽂件类型暂时只⽀持以下三种 + * 1:pdf 2:doc 3.docx + * 不传默认1 + */ + private String fileType; + + /** 待替换内容集合 **/ + private List keyValues; + + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class KeyValueBO { + /** + * 关键字key + */ + private String oldText; + + /** + * 关键字value + */ + private String newText; + } +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/dto/TextReplaceResponseDTO.java b/src/main/java/com/newyetai/sdk/fangxinqian/dto/TextReplaceResponseDTO.java new file mode 100644 index 0000000..12622c6 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/dto/TextReplaceResponseDTO.java @@ -0,0 +1,19 @@ +package com.newyetai.sdk.fangxinqian.dto; + +import com.newyetai.common.annotation.Mask; +import lombok.Data; + +@Data +public class TextReplaceResponseDTO extends FxqResponseDTO { + + /** + * 文档 base64 + */ + @Mask + private String data; + + @Override + protected String handleData() { + return this.data; + } +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/enums/RealnameResultEnum.java b/src/main/java/com/newyetai/sdk/fangxinqian/enums/RealnameResultEnum.java new file mode 100644 index 0000000..cf4240d --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/enums/RealnameResultEnum.java @@ -0,0 +1,26 @@ +package com.newyetai.sdk.fangxinqian.enums; + +/** + * 实名认证状态枚举类 + */ +public enum RealnameResultEnum { + + SUC("1", "实名通过"), + FAIL("2", "实名不通过"); + + private String result; + private String message; + + RealnameResultEnum(String result, String message) { + this.result = result; + this.message = message; + } + + public String getResult() { + return result; + } + + public String getMessage() { + return message; + } +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/service/FangXinQianService.java b/src/main/java/com/newyetai/sdk/fangxinqian/service/FangXinQianService.java new file mode 100644 index 0000000..39abb01 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/service/FangXinQianService.java @@ -0,0 +1,116 @@ +package com.newyetai.sdk.fangxinqian.service; + +import com.newyetai.common.AlitaResult; +import com.newyetai.sdk.fangxinqian.dto.*; +import org.springframework.validation.annotation.Validated; + +import javax.validation.Valid; +import javax.validation.constraints.NotNull; +import javax.validation.groups.Default; + +/** + * 放心签 + * + * @author sr on 2020-04-09 + */ +@Validated(Default.class) +public interface FangXinQianService { + + String BEAN_ID = "sdk.fangXinQianService"; + String MOCK_BEAN_ID = "mock.fangXinQianService"; + + /** + * 银行卡三要素 + * + * @param bankCardThreeRequestDto + * @return success-false真实调用第三方未成功,未拿到返回值; + * success-true获取到第三方返回,data-true校验成功,data-false校验不一致并返回失败原因(msg) + * @author sr on 2020-04-10 + */ + AlitaResult checkBankCardThree(@NotNull @Valid BankCardThreeRequestDTO bankCardThreeRequestDto); + + /** + * 银行卡四要素 + * + * @param bankCardFourRequestDto + * @return success-false真实调用第三方未成功,未拿到返回值; + * success-true获取到第三方返回,data-true校验成功,data-false校验不一致并返回失败原因(msg) + * @author sr on 2020-05-22 + */ + AlitaResult checkBankCardFour(@NotNull @Valid BankCardFourRequestDTO bankCardFourRequestDto); + + /** + * 公章生成 + * + * @param officialSealGenerateRequestDTO + * @return base64 + */ + AlitaResult generateOfficialSeal(@NotNull @Valid OfficialSealGenerateRequestDTO officialSealGenerateRequestDTO); + + /** + * 个人章生成 + * + * @param personalSealGenerateRequestDTO + * @return + */ + AlitaResult generatePersonalSeal(@NotNull @Valid PersonalSealGenerateRequestDTO personalSealGenerateRequestDTO); + + + /** + * 文档关键字替换 + * + * @param textReplaceRequestDTO + * @return + */ + AlitaResult textReplace(@NotNull @Valid TextReplaceRequestDTO textReplaceRequestDTO); + + /** + * 实名认证 + * + * @param realnameAuthRequestDTO + * @return + */ + AlitaResult realnameAuth(@NotNull @Valid RealnameAuthRequestDTO realnameAuthRequestDTO); + + /** + * 工商信息核验 + * + * @param governmentAuthRequestDTO + * @return + */ + AlitaResult governmentAuth(@NotNull @Valid GovernmentAuthRequestDTO governmentAuthRequestDTO); + + /** + * 合同签署 (普通签署) + * + * @param contractRequestDTO + * @return + */ + AlitaResult contractCommonSign(@NotNull @Valid ContractRequestDTO contractRequestDTO); + + /** + * 合同签署 (关键字签署) + * + * @param contractRequestDTO + * @return + */ + AlitaResult contractKeySign(@NotNull @Valid ContractRequestDTO contractRequestDTO); + + + /** + * 存证接⼝ + * 存证成功的合同默认30s以后才能出证,如果太早出证会提示证据不存在 + * + * @param evidenceSaveRequestDTO + * @return + */ + AlitaResult evidenceSave(@NotNull @Valid EvidenceSaveRequestDTO evidenceSaveRequestDTO); + + /** + * 出证接口 + * + * @param evidenceGetRequestDTO + * @return + */ + AlitaResult evidenceGet(@NotNull @Valid EvidenceGetRequestDTO evidenceGetRequestDTO); +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/service/impl/FangXinQianServiceImpl.java b/src/main/java/com/newyetai/sdk/fangxinqian/service/impl/FangXinQianServiceImpl.java new file mode 100644 index 0000000..3dc8fa6 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/service/impl/FangXinQianServiceImpl.java @@ -0,0 +1,247 @@ +package com.newyetai.sdk.fangxinqian.service.impl; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.annotation.CheckAndMock; +import com.newyetai.sdk.common.constant.SdkConstants; +import com.newyetai.sdk.fangxinqian.config.FxqCommonProperties; +import com.newyetai.sdk.fangxinqian.config.FxqContractProperties; +import com.newyetai.sdk.fangxinqian.config.FxqProperties; +import com.newyetai.sdk.fangxinqian.constant.BankCardFourStateEnum; +import com.newyetai.sdk.fangxinqian.constant.BankCardThreeStateEnum; +import com.newyetai.sdk.fangxinqian.constant.FxqConstants; +import com.newyetai.sdk.fangxinqian.constant.FxqErrorCodeEnum; +import com.newyetai.sdk.fangxinqian.dto.*; +import com.newyetai.sdk.fangxinqian.service.FangXinQianService; +import com.newyetai.sdk.fangxinqian.util.FxqUtils; +import com.newyetai.sdk.fangxinqian.util.HttpUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * @author sr on 2020-04-09 + */ +@Slf4j +@Service(FangXinQianService.BEAN_ID) +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class FangXinQianServiceImpl implements FangXinQianService { + + private final FxqProperties fxqProperties; + + @Override + public AlitaResult generateOfficialSeal(OfficialSealGenerateRequestDTO officialSealGenerateRequestDTO) { + if (StringUtils.isEmpty(officialSealGenerateRequestDTO.getPhone())) { + officialSealGenerateRequestDTO.setPhone(fxqProperties.getPhone()); + } + return HttpUtil + .execute(fxqProperties.getDomain().concat(fxqProperties.getOfficialSealUri()), + officialSealGenerateRequestDTO, SealGenerateResponseDTO.class) + .handleResult(); + } + + @Override + public AlitaResult generatePersonalSeal(PersonalSealGenerateRequestDTO personalSealGenerateRequestDTO) { + if (StringUtils.isEmpty(personalSealGenerateRequestDTO.getPhone())) { + personalSealGenerateRequestDTO.setPhone(fxqProperties.getPhone()); + } + return HttpUtil + .execute(fxqProperties.getDomain().concat(fxqProperties.getPersonalSealUri()), + personalSealGenerateRequestDTO, PersonalSealGenerateResponseDTO.class) + .handleResult(); + } + + @Override + public AlitaResult textReplace(TextReplaceRequestDTO textReplaceRequestDTO) { + if (StringUtils.isEmpty(textReplaceRequestDTO.getPhone())) { + textReplaceRequestDTO.setPhone(fxqProperties.getPhone()); + } + return HttpUtil + .execute(fxqProperties.getDomain().concat(fxqProperties.getTextReplaceUri()), + textReplaceRequestDTO, TextReplaceResponseDTO.class) + .handleResult(); + } + + @Override + @CheckAndMock(mockClass = MockFangXinQianServiceImpl.class, + propertyPrefix = FxqProperties.REALNAME_AUTH_PREFIX) + public AlitaResult realnameAuth(RealnameAuthRequestDTO realnameAuthRequestDTO) { + FxqCommonProperties fxqCommonProperties = fxqProperties.getRealName(); + // 校验部分 + if (fxqCommonProperties == null) { + return AlitaResult.error(SdkConstants.SDK_INVOKE_NOT_REACH_CODE, + FxqConstants.PROPERTIES_NOT_SET); + } + if (!FxqUtils.dealAppIdAndSecret(fxqCommonProperties, realnameAuthRequestDTO)) { + return AlitaResult.error(SdkConstants.SDK_INVOKE_NOT_REACH_CODE, + FxqConstants.ID_SECRET_NOT_ENOUGH); + } + //执行 + return HttpUtil + .execute(fxqProperties.getDomain().concat(fxqCommonProperties.getUrl()), + realnameAuthRequestDTO, RealnameAuthResponseDTO.class) + .handleResult(); + } + + @Override + @CheckAndMock(mockClass = MockFangXinQianServiceImpl.class, + propertyPrefix = FxqProperties.GOVERNMENT_AUTH_PREFIX) + public AlitaResult governmentAuth(GovernmentAuthRequestDTO governmentAuthRequestDTO) { + FxqCommonProperties fxqCommonProperties = fxqProperties.getGovernment(); + // 校验部分 + if (fxqCommonProperties == null) { + return AlitaResult.error(SdkConstants.SDK_INVOKE_NOT_REACH_CODE, + FxqConstants.PROPERTIES_NOT_SET); + } + if (!FxqUtils.dealAppIdAndSecret(fxqCommonProperties, governmentAuthRequestDTO)) { + return AlitaResult.error(SdkConstants.SDK_INVOKE_NOT_REACH_CODE, + FxqConstants.ID_SECRET_NOT_ENOUGH); + } + //执行 + return HttpUtil + .execute(fxqProperties.getDomain().concat(fxqCommonProperties.getUrl()), + governmentAuthRequestDTO, GovernmentAuthResponseDTO.class) + .handleResult(); + } + + @Override + @CheckAndMock(mockClass = MockFangXinQianServiceImpl.class, + propertyPrefix = FxqProperties.COMMON_SIGN_PREFIX) + public AlitaResult contractCommonSign(ContractRequestDTO contractRequestDTO) { + FxqContractProperties contract = fxqProperties.getContract(); + FxqCommonProperties fxqCommonProperties = contract.build(contract.getCommonSign()); + // 校验部分 + if (fxqCommonProperties == null) { + return AlitaResult.error( + SdkConstants.SDK_INVOKE_NOT_REACH_CODE, FxqConstants.PROPERTIES_NOT_SET); + } + if (!FxqUtils.dealAppIdAndSecret(fxqCommonProperties, contractRequestDTO)) { + return AlitaResult.error( + SdkConstants.SDK_INVOKE_NOT_REACH_CODE, FxqConstants.ID_SECRET_NOT_ENOUGH); + } + // 执行 + return HttpUtil + .execute(fxqProperties.getDomain().concat(fxqCommonProperties.getUrl()), + contractRequestDTO, ContractResponseDTO.class) + .handleResult(); + } + + @Override + @CheckAndMock(mockClass = MockFangXinQianServiceImpl.class, + propertyPrefix = FxqProperties.KEY_SIGN_PREFIX) + public AlitaResult contractKeySign(ContractRequestDTO contractRequestDTO) { + FxqContractProperties contract = fxqProperties.getContract(); + FxqCommonProperties fxqCommonProperties = contract.build(contract.getKeySign()); + // 校验部分 + if (fxqCommonProperties == null) { + return AlitaResult.error( + SdkConstants.SDK_INVOKE_NOT_REACH_CODE, FxqConstants.PROPERTIES_NOT_SET); + } + if (!FxqUtils.dealAppIdAndSecret(fxqCommonProperties, contractRequestDTO)) { + return AlitaResult.error( + SdkConstants.SDK_INVOKE_NOT_REACH_CODE, FxqConstants.ID_SECRET_NOT_ENOUGH); + } + // 执行 + return HttpUtil + .execute( + fxqProperties.getDomain().concat(fxqCommonProperties.getUrl()), + contractRequestDTO, ContractResponseDTO.class) + .handleResult(); + } + + @Override + @CheckAndMock(mockClass = MockFangXinQianServiceImpl.class, + propertyPrefix = FxqProperties.EVIDENCE_SAVE_PREFIX) + public AlitaResult evidenceSave(EvidenceSaveRequestDTO evidenceSaveRequestDTO) { + FxqContractProperties contract = fxqProperties.getContract(); + FxqCommonProperties fxqCommonProperties = contract.build(contract.getEvidenceSave()); + // 校验部分 + if (fxqCommonProperties == null) { + return AlitaResult.error( + SdkConstants.SDK_INVOKE_NOT_REACH_CODE, FxqConstants.PROPERTIES_NOT_SET); + } + if (!FxqUtils.dealAppIdAndSecret(fxqCommonProperties, evidenceSaveRequestDTO)) { + return AlitaResult.error( + SdkConstants.SDK_INVOKE_NOT_REACH_CODE, FxqConstants.ID_SECRET_NOT_ENOUGH); + } + // 执行 + return HttpUtil + .execute( + fxqProperties.getDomain().concat(fxqCommonProperties.getUrl()), + evidenceSaveRequestDTO, ContractResponseDTO.class) + .handleResult(); + } + + @Override + @CheckAndMock(mockClass = MockFangXinQianServiceImpl.class, + propertyPrefix = FxqProperties.EVIDENCE_GET_PREFIX) + public AlitaResult evidenceGet(EvidenceGetRequestDTO evidenceGetRequestDTO) { + FxqContractProperties contract = fxqProperties.getContract(); + FxqCommonProperties fxqCommonProperties = contract.build(contract.getEvidenceGet()); + // 校验部分 + if (fxqCommonProperties == null) { + return AlitaResult.error( + SdkConstants.SDK_INVOKE_NOT_REACH_CODE, FxqConstants.PROPERTIES_NOT_SET); + } + if (!FxqUtils.dealAppIdAndSecret(fxqCommonProperties, evidenceGetRequestDTO)) { + return AlitaResult.error( + SdkConstants.SDK_INVOKE_NOT_REACH_CODE, FxqConstants.ID_SECRET_NOT_ENOUGH); + } + // 执行 + return HttpUtil + .execute( + fxqProperties.getDomain().concat(fxqCommonProperties.getUrl()), + evidenceGetRequestDTO, ContractResponseDTO.class) + .handleResult(); + } + + @Override + @CheckAndMock(mockClass = MockFangXinQianServiceImpl.class, + propertyPrefix = FxqProperties.BANK_CARD_THREE_PREFIX) + public AlitaResult checkBankCardThree(BankCardThreeRequestDTO bankCardThreeRequestDto) { + return this.check(bankCardThreeRequestDto, fxqProperties.getBankCard3(), + BankCardThreeResponseDTO.class); + } + + @Override + @CheckAndMock(mockClass = MockFangXinQianServiceImpl.class, + propertyPrefix = FxqProperties.BANK_CARD_FOUR_PREFIX) + public AlitaResult checkBankCardFour(BankCardFourRequestDTO bankCardFourRequestDto) { + return this.check(bankCardFourRequestDto, fxqProperties.getBankCard4(), + BankCardFourResponseDTO.class); + } + + + private AlitaResult check(FxqRequestDTO fxqRequestDto, + FxqCommonProperties fxqCommonProperties, + Class responseClazz) { + // 校验部分 + if (fxqCommonProperties == null) { + return AlitaResult.error(SdkConstants.SDK_INVOKE_NOT_REACH_CODE, + FxqConstants.PROPERTIES_NOT_SET); + } + if (!FxqUtils.dealAppIdAndSecret(fxqCommonProperties, fxqRequestDto)) { + return AlitaResult.error(SdkConstants.SDK_INVOKE_NOT_REACH_CODE, + FxqConstants.ID_SECRET_NOT_ENOUGH); + } + // 执行 + FxqResponseDTO responseDto = HttpUtil.execute(fxqProperties.getDomain().concat(fxqCommonProperties.getUrl()), + fxqRequestDto, responseClazz); + + // 返回结果校验 + if (!FxqConstants.SUC_CODE.equals(responseDto.getCode())) { + return AlitaResult.success(StringUtils.join(FxqErrorCodeEnum.INVOKE_RETURN_ERROR.getMsg(), + responseDto.getMessage()), false); + } + if (responseClazz == BankCardThreeResponseDTO.class) { + String state = ((BankCardThreeResponseDTO) responseDto).getData().getState(); + return BankCardThreeStateEnum.dealState(state); + } + + // 处理验证结果 + return BankCardFourStateEnum.dealState(((BankCardFourResponseDTO) responseDto).getData().getState()); + } + + +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/service/impl/MockFangXinQianServiceImpl.java b/src/main/java/com/newyetai/sdk/fangxinqian/service/impl/MockFangXinQianServiceImpl.java new file mode 100644 index 0000000..f49d5de --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/service/impl/MockFangXinQianServiceImpl.java @@ -0,0 +1,86 @@ +package com.newyetai.sdk.fangxinqian.service.impl; + +import com.newyetai.common.AlitaResult; +import com.newyetai.sdk.fangxinqian.dto.*; +import com.newyetai.sdk.fangxinqian.service.FangXinQianService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import javax.validation.Valid; +import javax.validation.constraints.NotNull; + +/** + * @author sr on 2020-04-09 + */ +@Service(FangXinQianService.MOCK_BEAN_ID) +@Slf4j +public class MockFangXinQianServiceImpl implements FangXinQianService { + + @Override + public AlitaResult checkBankCardThree( + @NotNull @Valid BankCardThreeRequestDTO bankCardThreeRequestDto) { + log.info("fxq checkBankCardThree mock..."); + return AlitaResult.success(true); + } + + + @Override + public AlitaResult checkBankCardFour(@NotNull @Valid BankCardFourRequestDTO bankCardFourRequestDto) { + log.info("fxq checkBankCardFour mock..."); + return AlitaResult.success(true); + } + + @Override + public AlitaResult generateOfficialSeal(@NotNull @Valid OfficialSealGenerateRequestDTO officialSealGenerateRequestDTO) { + log.info("fxq generateOfficialSeal mock..."); + return AlitaResult.success(""); + } + + @Override + public AlitaResult generatePersonalSeal(@NotNull @Valid PersonalSealGenerateRequestDTO personalSealGenerateRequestDTO) { + log.info("fxq generatePersonalSeal mock..."); + return AlitaResult.success(""); + } + + @Override + public AlitaResult textReplace(@NotNull @Valid TextReplaceRequestDTO textReplaceRequestDTO) { + log.info("fxq textReplace mock..."); + return AlitaResult.success(""); + } + + @Override + public AlitaResult realnameAuth(@NotNull @Valid RealnameAuthRequestDTO realnameAuthRequestDTO) { + log.info("fxq realnameAuth mock..."); + return AlitaResult.success(true); + } + + @Override + public AlitaResult governmentAuth(@NotNull @Valid GovernmentAuthRequestDTO governmentAuthRequestDTO) { + log.info("fxq governmentAuth mock..."); + return AlitaResult.success(new GovernmentAuthResponseDTO.GovernmentAuthResponseDataDTO()); + } + + @Override + public AlitaResult contractCommonSign(@NotNull @Valid ContractRequestDTO contractRequestDTO) { + log.info("fxq contractCommonSign mock..."); + return AlitaResult.success("https://huluwa-ec.oss-accelerate.aliyuncs.com/20200825/20200825174051_2913.pdf?Expires=4751948451&OSSAccessKeyId=HLUmOSIDpYentPOt&Signature=RB%2FFQgM7dJyBac4DMSG0YZYz3ao%3D"); + } + + @Override + public AlitaResult contractKeySign(@NotNull @Valid ContractRequestDTO contractRequestDTO) { + log.info("fxq contractKeySign mock..."); + return AlitaResult.success("https://huluwa-ec.oss-accelerate.aliyuncs.com/20200825/20200825174051_2913.pdf?Expires=4751948451&OSSAccessKeyId=HLUmOSIDpYentPOt&Signature=RB%2FFQgM7dJyBac4DMSG0YZYz3ao%3D"); + } + + @Override + public AlitaResult evidenceSave(@NotNull @Valid EvidenceSaveRequestDTO evidenceSaveRequestDTO) { + log.info("fxq evidenceSave mock..."); + return AlitaResult.success(""); + } + + @Override + public AlitaResult evidenceGet(@NotNull @Valid EvidenceGetRequestDTO evidenceGetRequestDTO) { + log.info("fxq evidenceGet mock..."); + return AlitaResult.success(""); + } +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/util/FxqUtils.java b/src/main/java/com/newyetai/sdk/fangxinqian/util/FxqUtils.java new file mode 100644 index 0000000..0aad8f0 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/util/FxqUtils.java @@ -0,0 +1,62 @@ +package com.newyetai.sdk.fangxinqian.util; + +import org.apache.commons.lang3.StringUtils; + +import com.newyetai.sdk.fangxinqian.config.FxqCommonProperties; +import com.newyetai.sdk.fangxinqian.dto.FxqRequestDTO; + +/** + * 工具类 + * + * @author sr on 2020-04-09 + */ +public final class FxqUtils { + + /** + * 私有 + */ + private FxqUtils() { + throw new IllegalStateException("Utility class"); + } + + /** + * 处理appId和appSecret参数 + * + * @param + * @param fxqCommonProperties + * @param fxqRequestDto + * @author sr on 2020-04-09 + */ + public static boolean dealAppIdAndSecret(FxqCommonProperties fxqCommonProperties, + T fxqRequestDto) { + + String appId = fxqRequestDto.getAppId(); + String appSecret = fxqRequestDto.getAppSecret(); + boolean enable = enableFxq(fxqCommonProperties); + if (StringUtils.isBlank(appId) && enable) { + appId = fxqCommonProperties.getAppId(); + } + if (StringUtils.isBlank(appSecret) && enable) { + appSecret = fxqCommonProperties.getAppSecret(); + } + if (StringUtils.isBlank(appId) || StringUtils.isBlank(appSecret)) { + return false; + } + + fxqRequestDto.setAppId(appId); + fxqRequestDto.setAppSecret(appSecret); + return true; + } + + /** + * 是否开启放心签接口 + * + * @param fxqCommonProperties + * @return + * @author sr on 2020-04-21 + */ + public static boolean enableFxq(FxqCommonProperties fxqCommonProperties) { + return fxqCommonProperties != null && fxqCommonProperties.getEnable(); + } + +} diff --git a/src/main/java/com/newyetai/sdk/fangxinqian/util/HttpUtil.java b/src/main/java/com/newyetai/sdk/fangxinqian/util/HttpUtil.java new file mode 100644 index 0000000..3e8b632 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/fangxinqian/util/HttpUtil.java @@ -0,0 +1,58 @@ +package com.newyetai.sdk.fangxinqian.util; + +import com.newyetai.common.util.JsonUtils; +import com.newyetai.sdk.fangxinqian.dto.FxqResponseDTO; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; +import org.springframework.util.StopWatch; +import org.springframework.web.client.RestTemplate; + +@Slf4j +@Component +public class HttpUtil { + + private static RestTemplate restTemplate; + + @Autowired + public HttpUtil(RestTemplate restTemplate) { + this.restTemplate = restTemplate; + } + + /** + * Http 通用请求封装 + * + * @param url 请求地址 + * @param requestDto 请求实体 + * @param responseClazz 返回实体Class + * @param + * @param + * @return + */ + public static FxqResponseDTO execute(String url, T requestDto, Class responseClazz) { + ResponseEntity response; + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + try { + log.debug("fangxinqian request url :{}", url); + log.info("fangxinqian request requestDto :{}", JsonUtils.toJsonString(requestDto)); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + HttpEntity request = new HttpEntity<>(requestDto, headers); + response = restTemplate.postForEntity(url, request, responseClazz); + log.info("fangxinqian {}:{}", responseClazz.getName(), JsonUtils.toJsonString(response)); + } catch (Exception e) { + log.error("fangxinqian {} invoke error:{}", requestDto.getClass().getName(), + e); + stopWatch.stop(); + return FxqResponseDTO.buildCommonError(); + } + stopWatch.stop(); + log.info("fangxinqian consuming {} s", stopWatch.getTotalTimeSeconds()); + return JsonUtils.objToClassObj(response.getBody(), responseClazz); + } +} diff --git a/src/main/java/com/newyetai/sdk/mbti/config/MbtiProperties.java b/src/main/java/com/newyetai/sdk/mbti/config/MbtiProperties.java new file mode 100644 index 0000000..eaf9704 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/mbti/config/MbtiProperties.java @@ -0,0 +1,25 @@ +package com.newyetai.sdk.mbti.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@ConfigurationProperties(prefix = MbtiProperties.PREFIX) +@Data +@Component +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class MbtiProperties { + + public static final String PREFIX = "mbti"; + + private String urlPrefix; + private String appId; + private String appKey; + +} diff --git a/src/main/java/com/newyetai/sdk/mbti/mobel/AnswerReq.java b/src/main/java/com/newyetai/sdk/mbti/mobel/AnswerReq.java new file mode 100644 index 0000000..ad82b2a --- /dev/null +++ b/src/main/java/com/newyetai/sdk/mbti/mobel/AnswerReq.java @@ -0,0 +1,39 @@ +package com.newyetai.sdk.mbti.mobel; + +import org.springframework.core.ParameterizedTypeReference; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class AnswerReq extends MbtiTokenReq>{ + + /** **/ + private static final long serialVersionUID = 1L; + + private static ParameterizedTypeReference> type = + new ParameterizedTypeReference>() {}; + + private String liangbiaoId; + private String userName; + private String userEmail; + private AnswerReqDTO answerData; + + @Override + public String getUri() { + return "submit"; + } + + @Override + public ParameterizedTypeReference> getResponseType() { + return type; + } + + + +} diff --git a/src/main/java/com/newyetai/sdk/mbti/mobel/AnswerReqDTO.java b/src/main/java/com/newyetai/sdk/mbti/mobel/AnswerReqDTO.java new file mode 100644 index 0000000..faead9b --- /dev/null +++ b/src/main/java/com/newyetai/sdk/mbti/mobel/AnswerReqDTO.java @@ -0,0 +1,32 @@ +package com.newyetai.sdk.mbti.mobel; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.io.Serializable; +import java.util.Map; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Builder.Default; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class AnswerReqDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + @Default + private String liangbiaoId = "MBTI-STEP-II"; + @JsonProperty(value="Answers") + private Map Answers; + @Default + private String checkcode = "I194H5LAHLJR2DIJ"; + + private String test_name; + + private String test_email; +} diff --git a/src/main/java/com/newyetai/sdk/mbti/mobel/AnswerRes.java b/src/main/java/com/newyetai/sdk/mbti/mobel/AnswerRes.java new file mode 100644 index 0000000..31175b6 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/mbti/mobel/AnswerRes.java @@ -0,0 +1,21 @@ +package com.newyetai.sdk.mbti.mobel; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class AnswerRes implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + private String liangbiaoId; + private String orderId; +} diff --git a/src/main/java/com/newyetai/sdk/mbti/mobel/AnwserDTO.java b/src/main/java/com/newyetai/sdk/mbti/mobel/AnwserDTO.java new file mode 100644 index 0000000..7f795c7 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/mbti/mobel/AnwserDTO.java @@ -0,0 +1,27 @@ +package com.newyetai.sdk.mbti.mobel; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class AnwserDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + public String code; + public String content; + public String createTime; + public String deleteFlag; + public String id; + public String liangbiaoId; + public String questionId; + public String updateTime; + +} diff --git a/src/main/java/com/newyetai/sdk/mbti/mobel/MbtiRes.java b/src/main/java/com/newyetai/sdk/mbti/mobel/MbtiRes.java new file mode 100644 index 0000000..c75e998 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/mbti/mobel/MbtiRes.java @@ -0,0 +1,23 @@ +package com.newyetai.sdk.mbti.mobel; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class MbtiRes implements Serializable{ + + public static final String SUC_STATUS = "success"; + + private T data; + private String message; + private String redirect; + private String status; + +} diff --git a/src/main/java/com/newyetai/sdk/mbti/mobel/MbtiTokenReq.java b/src/main/java/com/newyetai/sdk/mbti/mobel/MbtiTokenReq.java new file mode 100644 index 0000000..6ab6ba8 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/mbti/mobel/MbtiTokenReq.java @@ -0,0 +1,18 @@ +package com.newyetai.sdk.mbti.mobel; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.newyetai.sdk.common.dto.ISdkRequest; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public abstract class MbtiTokenReq implements ISdkRequest{ + + @JsonIgnore + private String token; + +} diff --git a/src/main/java/com/newyetai/sdk/mbti/mobel/OrderQueryReq.java b/src/main/java/com/newyetai/sdk/mbti/mobel/OrderQueryReq.java new file mode 100644 index 0000000..ee026cc --- /dev/null +++ b/src/main/java/com/newyetai/sdk/mbti/mobel/OrderQueryReq.java @@ -0,0 +1,37 @@ +package com.newyetai.sdk.mbti.mobel; + +import org.springframework.core.ParameterizedTypeReference; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class OrderQueryReq extends MbtiTokenReq>{ + + /** **/ + private static final long serialVersionUID = 1L; + + private static ParameterizedTypeReference> type = + new ParameterizedTypeReference>() {}; + + private String liangbiaoId; + private String orderId; + + @Override + public String getUri() { + return "query"; + } + + @Override + public ParameterizedTypeReference> getResponseType() { + return type; + } + + + +} diff --git a/src/main/java/com/newyetai/sdk/mbti/mobel/OrderQueryRes.java b/src/main/java/com/newyetai/sdk/mbti/mobel/OrderQueryRes.java new file mode 100644 index 0000000..c6b50db --- /dev/null +++ b/src/main/java/com/newyetai/sdk/mbti/mobel/OrderQueryRes.java @@ -0,0 +1,21 @@ +package com.newyetai.sdk.mbti.mobel; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class OrderQueryRes implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + private String reportId; + private String orderId; +} diff --git a/src/main/java/com/newyetai/sdk/mbti/mobel/QuestionReq.java b/src/main/java/com/newyetai/sdk/mbti/mobel/QuestionReq.java new file mode 100644 index 0000000..64572c7 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/mbti/mobel/QuestionReq.java @@ -0,0 +1,38 @@ +package com.newyetai.sdk.mbti.mobel; + +import java.util.List; + +import org.springframework.core.ParameterizedTypeReference; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class QuestionReq extends MbtiTokenReq>>{ + + /** **/ + private static final long serialVersionUID = 1L; + + private static ParameterizedTypeReference>> type = + new ParameterizedTypeReference>>() {}; + + private String liangbiaoId; + + @Override + public String getUri() { + return "getQuestions"; + } + + @Override + public ParameterizedTypeReference>> getResponseType() { + return type; + } + + + +} diff --git a/src/main/java/com/newyetai/sdk/mbti/mobel/QuestionRes.java b/src/main/java/com/newyetai/sdk/mbti/mobel/QuestionRes.java new file mode 100644 index 0000000..8c04eb4 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/mbti/mobel/QuestionRes.java @@ -0,0 +1,25 @@ +package com.newyetai.sdk.mbti.mobel; + +import java.io.Serializable; +import java.util.List; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class QuestionRes implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + private String anwType; + private List anwserList; + private String id; + private String liangbiaoId; + private String part; + private String title; +} diff --git a/src/main/java/com/newyetai/sdk/mbti/mobel/ReportReq.java b/src/main/java/com/newyetai/sdk/mbti/mobel/ReportReq.java new file mode 100644 index 0000000..8432d3d --- /dev/null +++ b/src/main/java/com/newyetai/sdk/mbti/mobel/ReportReq.java @@ -0,0 +1,37 @@ +package com.newyetai.sdk.mbti.mobel; + +import org.springframework.core.ParameterizedTypeReference; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class ReportReq extends MbtiTokenReq>{ + + /** **/ + private static final long serialVersionUID = 1L; + + private static ParameterizedTypeReference> type = + new ParameterizedTypeReference>() {}; + + private String liangbiaoId; + private String reportId; + + @Override + public String getUri() { + return "getReport"; + } + + @Override + public ParameterizedTypeReference> getResponseType() { + return type; + } + + + +} diff --git a/src/main/java/com/newyetai/sdk/mbti/mobel/ReportRes.java b/src/main/java/com/newyetai/sdk/mbti/mobel/ReportRes.java new file mode 100644 index 0000000..3d114a7 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/mbti/mobel/ReportRes.java @@ -0,0 +1,22 @@ +package com.newyetai.sdk.mbti.mobel; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class ReportRes implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + private String liangbiaoId; + private String reportId; + private String content; +} diff --git a/src/main/java/com/newyetai/sdk/mbti/mobel/TokenReq.java b/src/main/java/com/newyetai/sdk/mbti/mobel/TokenReq.java new file mode 100644 index 0000000..fb8b78e --- /dev/null +++ b/src/main/java/com/newyetai/sdk/mbti/mobel/TokenReq.java @@ -0,0 +1,39 @@ +package com.newyetai.sdk.mbti.mobel; + +import org.springframework.core.ParameterizedTypeReference; + +import com.newyetai.sdk.common.dto.ISdkRequest; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class TokenReq implements ISdkRequest>{ + + /** **/ + private static final long serialVersionUID = 1L; + + private static ParameterizedTypeReference> type = + new ParameterizedTypeReference>() {}; + + private String appId; + private String appKey; + + @Override + public String getUri() { + return "getToken"; + } + + @Override + public ParameterizedTypeReference> getResponseType() { + return type; + } + + + +} diff --git a/src/main/java/com/newyetai/sdk/mbti/mobel/TokenRes.java b/src/main/java/com/newyetai/sdk/mbti/mobel/TokenRes.java new file mode 100644 index 0000000..2f450c5 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/mbti/mobel/TokenRes.java @@ -0,0 +1,22 @@ +package com.newyetai.sdk.mbti.mobel; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class TokenRes implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + private String expiresIn; + private String appId; + private String token; +} diff --git a/src/main/java/com/newyetai/sdk/mbti/service/MbtiProvider.java b/src/main/java/com/newyetai/sdk/mbti/service/MbtiProvider.java new file mode 100644 index 0000000..bdc0b10 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/mbti/service/MbtiProvider.java @@ -0,0 +1,80 @@ +package com.newyetai.sdk.mbti.service; + +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.sdk.common.constant.SdkConstants; +import com.newyetai.sdk.common.dto.DefaultSdkInvokeLogDTO; +import com.newyetai.sdk.common.dto.ISdkRequest; +import com.newyetai.sdk.common.util.HttpUtils; +import com.newyetai.sdk.mbti.config.MbtiProperties; +import com.newyetai.sdk.mbti.mobel.MbtiRes; +import com.newyetai.sdk.mbti.mobel.MbtiTokenReq; +import com.newyetai.sdk.mbti.mobel.TokenReq; +import com.newyetai.sdk.mbti.mobel.TokenRes; + +import io.jsonwebtoken.lang.Assert; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class MbtiProvider { + + private static MbtiProperties mbtiProperties; + + private MbtiProvider(MbtiProperties mbtiProperties) { + MbtiProvider.mbtiProperties = mbtiProperties; + } + + public static String getToken() { + AlitaResult res = http(TokenReq.builder().appId(mbtiProperties.getAppId()).appKey(mbtiProperties.getAppKey()).build()); + Assert.isTrue(res.getSuccess(), res.getMsg()); + return res.getData().getToken(); + } + + + public static AlitaResult http(ISdkRequest> req) { + MbtiRes res = null; + try { + try { + HttpHeaders header = new HttpHeaders(); + if (req instanceof MbtiTokenReq) { + header.add("Authentication", getToken()); + header.add("appId", mbtiProperties.getAppId()); + } + // 发送请求 + HttpEntity requestEntity = new HttpEntity(req, header); + ResponseEntity> response = HttpUtils.restTemplate.exchange(mbtiProperties.getUrlPrefix() + req.getUri(), + HttpMethod.POST, requestEntity, req.getResponseType()); + res = response.getBody(); + } catch (Exception e) { + log.error("mbti http error:{}", e.getMessage()); + return AlitaResult.error(SdkConstants.SDK_HTTP_INVOKE_ERROR_CODE, e.getMessage()); + } + try { + if (MbtiRes.SUC_STATUS.equals(res.getStatus())) { + return AlitaResult.success(res.getData()); + } + return AlitaResult.error(SdkConstants.SDK_HTTP_INVOKE_RESPONSE_FAIL_CODE, + res.getMessage()); + } catch (Exception e) { + return AlitaResult.error(SdkConstants.SDK_RESPONSE_CONVERT_ERROR_CODE, + e.getMessage()); + } + + } finally { + log.info("mbti invoke:{}", + JsonUtils + .toJsonString( + DefaultSdkInvokeLogDTO.builder().requestData(req).responseData(res) + .build())); + } + } + + +} diff --git a/src/main/java/com/newyetai/sdk/robot/constant/DingTalkMsgTypeEnum.java b/src/main/java/com/newyetai/sdk/robot/constant/DingTalkMsgTypeEnum.java new file mode 100644 index 0000000..e64373e --- /dev/null +++ b/src/main/java/com/newyetai/sdk/robot/constant/DingTalkMsgTypeEnum.java @@ -0,0 +1,28 @@ +package com.newyetai.sdk.robot.constant; + +/** + * @author sr on 2020-09-30 + */ +public enum DingTalkMsgTypeEnum { + /** **/ + TEXT("text"), + /** **/ + LINK("link"), + /** **/ + MARKDOWN("markdown"), + /** **/ + ACTIONCARD("actionCard"), + /** **/ + FEEDCARD("feedCard") + ; + + private String msgType; + + DingTalkMsgTypeEnum(String msgType){ + this.msgType = msgType; + } + + public String getMsgType() { + return this.msgType; + } +} diff --git a/src/main/java/com/newyetai/sdk/robot/constant/RobotTypeEnum.java b/src/main/java/com/newyetai/sdk/robot/constant/RobotTypeEnum.java new file mode 100644 index 0000000..d00e47b --- /dev/null +++ b/src/main/java/com/newyetai/sdk/robot/constant/RobotTypeEnum.java @@ -0,0 +1,13 @@ +package com.newyetai.sdk.robot.constant; + +/** + * @author sr on 2020-09-30 + */ +public enum RobotTypeEnum { + + /** 企业微信 **/ + WORK_WECHAT, + /** 钉钉 **/ + DING_TALK; + +} diff --git a/src/main/java/com/newyetai/sdk/robot/constant/WorkWechatMsgTypeEnum.java b/src/main/java/com/newyetai/sdk/robot/constant/WorkWechatMsgTypeEnum.java new file mode 100644 index 0000000..cda557d --- /dev/null +++ b/src/main/java/com/newyetai/sdk/robot/constant/WorkWechatMsgTypeEnum.java @@ -0,0 +1,26 @@ +package com.newyetai.sdk.robot.constant; + +/** + * @author sr on 2020-09-30 + */ +public enum WorkWechatMsgTypeEnum { + /** **/ + TEXT("text"), + /** **/ + MARKDOWN("markdown"), + /** **/ + NEWS("news"), + /** **/ + IMAGE("image"); + + private String type; + + WorkWechatMsgTypeEnum(String msgType){ + this.type = msgType; + } + + public String getType() { + return this.type; + } + +} diff --git a/src/main/java/com/newyetai/sdk/robot/model/IDingTalkMsg.java b/src/main/java/com/newyetai/sdk/robot/model/IDingTalkMsg.java new file mode 100644 index 0000000..8e2f769 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/robot/model/IDingTalkMsg.java @@ -0,0 +1,19 @@ +package com.newyetai.sdk.robot.model; + +import com.newyetai.sdk.robot.constant.RobotTypeEnum; + +import lombok.Data; + +/** + * @author sr on 2020-07-06 + */ +@Data +public abstract class IDingTalkMsg implements IMsg{ + + private String robotKey; + + public RobotTypeEnum getRobotType() { + return RobotTypeEnum.DING_TALK; + } + +} diff --git a/src/main/java/com/newyetai/sdk/robot/model/IMsg.java b/src/main/java/com/newyetai/sdk/robot/model/IMsg.java new file mode 100644 index 0000000..ecb02cb --- /dev/null +++ b/src/main/java/com/newyetai/sdk/robot/model/IMsg.java @@ -0,0 +1,35 @@ +package com.newyetai.sdk.robot.model; + +import com.newyetai.sdk.robot.constant.RobotTypeEnum; + +/** + * @author sr on 2020-09-30 + */ +public interface IMsg { + + /** + * 机器人类型 + * + * @return + * @author sr on 2020-09-30 + */ + RobotTypeEnum getRobotType(); + + /** + * 机器人标识 + * + * @return + * @author sr on 2020-09-30 + */ + String getRobotKey(); + + /** + * 消息类型 + * @return + * @author sr on 2020-09-30 + */ + String getMsgType(); + + + +} diff --git a/src/main/java/com/newyetai/sdk/robot/model/IRobot.java b/src/main/java/com/newyetai/sdk/robot/model/IRobot.java new file mode 100644 index 0000000..c5fb924 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/robot/model/IRobot.java @@ -0,0 +1,26 @@ +package com.newyetai.sdk.robot.model; + +import com.newyetai.sdk.robot.constant.RobotTypeEnum; + +/** + * @author sr on 2020-09-30 + */ +public interface IRobot { + + /** + * 机器人标识 + * + * @return + * @author sr on 2020-09-30 + */ + String getRobotKey(); + + /** + * 机器人类型 + * + * @return + * @author sr on 2020-09-30 + */ + RobotTypeEnum getRobotType(); + +} diff --git a/src/main/java/com/newyetai/sdk/robot/model/IWorkWechatMsg.java b/src/main/java/com/newyetai/sdk/robot/model/IWorkWechatMsg.java new file mode 100644 index 0000000..f8265b9 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/robot/model/IWorkWechatMsg.java @@ -0,0 +1,19 @@ +package com.newyetai.sdk.robot.model; + +import com.newyetai.sdk.robot.constant.RobotTypeEnum; + +import lombok.Data; + +/** + * @author sr on 2020-07-06 + */ +@Data +public abstract class IWorkWechatMsg implements IMsg{ + + private String robotKey; + + public RobotTypeEnum getRobotType() { + return RobotTypeEnum.WORK_WECHAT; + } + +} diff --git a/src/main/java/com/newyetai/sdk/robot/model/MarkdownMsg.java b/src/main/java/com/newyetai/sdk/robot/model/MarkdownMsg.java new file mode 100644 index 0000000..336bfe0 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/robot/model/MarkdownMsg.java @@ -0,0 +1,51 @@ +package com.newyetai.sdk.robot.model; + +import com.google.common.collect.Lists; +import com.newyetai.sdk.robot.constant.DingTalkMsgTypeEnum; +import com.newyetai.sdk.robot.constant.RobotTypeEnum; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Builder.Default; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; + + +/** + * markdown类型 消息 + * + * @author Carlye + * @date 2021/10/08 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class MarkdownMsg implements Serializable, IMsg{ + + /** **/ + private String title; + /** 消息内容 **/ + private String text; + + /** @ 手机号列表 **/ + @Default + private List atMobiles = Lists.newArrayList(); + + /** 是否@全部 **/ + private boolean atAll; + + @Default + private RobotTypeEnum robotType = RobotTypeEnum.DING_TALK; + + private String robotKey; + + @Override + public String getMsgType() { + return DingTalkMsgTypeEnum.MARKDOWN.getMsgType(); + } + + +} diff --git a/src/main/java/com/newyetai/sdk/robot/model/TextMsg.java b/src/main/java/com/newyetai/sdk/robot/model/TextMsg.java new file mode 100644 index 0000000..4076c90 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/robot/model/TextMsg.java @@ -0,0 +1,50 @@ +package com.newyetai.sdk.robot.model; + +import java.io.Serializable; +import java.util.List; + +import com.google.common.collect.Lists; +import com.newyetai.sdk.robot.constant.DingTalkMsgTypeEnum; +import com.newyetai.sdk.robot.constant.RobotTypeEnum; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Builder.Default; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 机器人消息 + * @author sr on 2020-09-30 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class TextMsg implements Serializable, IMsg{ + + /** **/ + private static final long serialVersionUID = -947405425579179554L; + + /** 消息内容 **/ + private String content; + + /** @ 手机号列表 **/ + @Default + private List atMobiles = Lists.newArrayList(); + + /** 是否@全部 **/ + private boolean atAll; + + @Default + private RobotTypeEnum robotType = RobotTypeEnum.DING_TALK; + + private String robotKey; + + @Override + public String getMsgType() { + return DingTalkMsgTypeEnum.TEXT.getMsgType(); + } + + +} diff --git a/src/main/java/com/newyetai/sdk/robot/service/IRobotService.java b/src/main/java/com/newyetai/sdk/robot/service/IRobotService.java new file mode 100644 index 0000000..b926b4f --- /dev/null +++ b/src/main/java/com/newyetai/sdk/robot/service/IRobotService.java @@ -0,0 +1,41 @@ +package com.newyetai.sdk.robot.service; + +import com.newyetai.sdk.robot.model.IDingTalkMsg; +import com.newyetai.sdk.robot.model.IWorkWechatMsg; +import com.newyetai.sdk.robot.model.MarkdownMsg; +import com.newyetai.sdk.robot.model.TextMsg; + +/** + * @author sr on 2020-09-30 + */ +public interface IRobotService { + + /** + * @param msg + * @return + * @author sr on 2020-10-09 + */ + boolean sendWorkWechat(IWorkWechatMsg msg); + + /** + * @param msg + * @return + * @author sr on 2020-10-09 + */ + boolean sendDingTalk(IDingTalkMsg msg); + + /** + * @param msg + * @return + * @author sr on 2020-10-09 + */ + boolean sendText(TextMsg msg); + + /** + * 发送 markdown 消息 + * + * @param msg 味精 + * @return boolean + */ + boolean sendMarkdown(MarkdownMsg msg); +} diff --git a/src/main/java/com/newyetai/sdk/robot/service/impl/RobotDevopsProvider.java b/src/main/java/com/newyetai/sdk/robot/service/impl/RobotDevopsProvider.java new file mode 100644 index 0000000..5acb7eb --- /dev/null +++ b/src/main/java/com/newyetai/sdk/robot/service/impl/RobotDevopsProvider.java @@ -0,0 +1,20 @@ +package com.newyetai.sdk.robot.service.impl; + +import org.springframework.stereotype.Service; + +import com.newyetai.common.exception.IDevopsProvider; +import com.newyetai.sdk.robot.util.RobotUtils; + +/** + * 机器人运维工具类 + * @author sr on 2022-03-01 + */ +@Service +public class RobotDevopsProvider implements IDevopsProvider{ + + @Override + public void deal(String msg) { + RobotUtils.sendDevops(msg); + } + +} diff --git a/src/main/java/com/newyetai/sdk/robot/service/impl/RobotServiceImpl.java b/src/main/java/com/newyetai/sdk/robot/service/impl/RobotServiceImpl.java new file mode 100644 index 0000000..e5ea60a --- /dev/null +++ b/src/main/java/com/newyetai/sdk/robot/service/impl/RobotServiceImpl.java @@ -0,0 +1,117 @@ +package com.newyetai.sdk.robot.service.impl; + +import com.newyetai.sdk.robot.model.MarkdownMsg; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import com.dingtalk.api.DefaultDingTalkClient; +import com.dingtalk.api.DingTalkClient; +import com.dingtalk.api.request.OapiRobotSendRequest; +import com.dingtalk.api.response.OapiRobotSendResponse; +import com.newyetai.sdk.robot.constant.RobotTypeEnum; +import com.newyetai.sdk.robot.model.IDingTalkMsg; +import com.newyetai.sdk.robot.model.IWorkWechatMsg; +import com.newyetai.sdk.robot.model.TextMsg; +import com.newyetai.sdk.robot.service.IRobotService; +import com.newyetai.sdk.workwechat.constant.WorkWechatConstants; +import com.newyetai.sdk.workwechat.model.WwrTextMsg; +import com.newyetai.sdk.workwechat.util.WorkWechatUtils; +import com.taobao.api.ApiException; + +import lombok.extern.slf4j.Slf4j; + +/** + * @author sr on 2020-09-30 + */ +@Service +@Slf4j +public class RobotServiceImpl implements IRobotService { + + private static final String WORK_WECHAT_URL_PREFIX = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key="; + private static final String DING_TALK_URL_PREFIX = "https://oapi.dingtalk.com/robot/send?access_token="; + + private static final Long DING_TALK_SUC_CODE = 0L; + + @Autowired + private RestTemplate restTemplate; + + @Override + public boolean sendMarkdown(MarkdownMsg msg) { + if (msg.getRobotType() == RobotTypeEnum.DING_TALK) { + OapiRobotSendRequest request = new OapiRobotSendRequest(); + request.setMsgtype(msg.getMsgType()); + + OapiRobotSendRequest.Markdown markdown = new OapiRobotSendRequest.Markdown(); + markdown.setText(msg.getText()); + markdown.setTitle(msg.getTitle()); + request.setMarkdown(markdown); + + OapiRobotSendRequest.At at = new OapiRobotSendRequest.At(); + at.setAtMobiles(msg.getAtMobiles()); + // isAtAll类型如果不为Boolean,请升级至最新SDK + at.setIsAtAll(msg.isAtAll()); + request.setAt(at); + this.sendDingTalk(msg.getRobotKey(), request); + } + return false; + } + + @Override + public boolean sendText(TextMsg msg) { + if (msg.getRobotType() == RobotTypeEnum.DING_TALK) { + OapiRobotSendRequest request = new OapiRobotSendRequest(); + request.setMsgtype(msg.getMsgType()); + OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text(); + text.setContent(msg.getContent()); + request.setText(text); + OapiRobotSendRequest.At at = new OapiRobotSendRequest.At(); + at.setAtMobiles(msg.getAtMobiles()); + // isAtAll类型如果不为Boolean,请升级至最新SDK + at.setIsAtAll(msg.isAtAll()); + request.setAt(at); + this.sendDingTalk(msg.getRobotKey(), request); + } else { + WwrTextMsg wwrMsg = WwrTextMsg.builder().content(msg.getContent()) + .mentionedMobileList(msg.getAtMobiles()).build(); + wwrMsg.setRobotKey(msg.getRobotKey()); + if (msg.isAtAll()) { + wwrMsg.getMentionedMobileList().add(WorkWechatConstants.AT_ALL); + } + return this.sendWorkWechat(wwrMsg); + } + return false; + } + + @Override + public boolean sendWorkWechat(IWorkWechatMsg msg) { + try { + restTemplate.postForEntity(WORK_WECHAT_URL_PREFIX + msg.getRobotKey(), WorkWechatUtils.parsePostData(msg), + Object.class); + return true; + } catch (Exception e) { + log.info("WorkWechatRobot send error:{}", e.getMessage(), e); + return false; + } + } + + @Override + public boolean sendDingTalk(IDingTalkMsg msg) { + // TODO 待实现其他类型 + return false; + } + + private boolean sendDingTalk(String robotKey, OapiRobotSendRequest request) { + DingTalkClient client = + new DefaultDingTalkClient(DING_TALK_URL_PREFIX + robotKey); + try { + OapiRobotSendResponse response = client.execute(request); + log.info("DingTalkRobot response,code:{},msg:{}", response.getErrcode(), response.getErrmsg()); + return DING_TALK_SUC_CODE.equals(response.getErrcode()); + } catch (ApiException e) { + log.info("DingTalkRobot send error:{}", e.getMessage()); + return false; + } + } + +} diff --git a/src/main/java/com/newyetai/sdk/robot/util/MarkdownMsgUtils.java b/src/main/java/com/newyetai/sdk/robot/util/MarkdownMsgUtils.java new file mode 100644 index 0000000..1e98c9b --- /dev/null +++ b/src/main/java/com/newyetai/sdk/robot/util/MarkdownMsgUtils.java @@ -0,0 +1,87 @@ +package com.newyetai.sdk.robot.util; + +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.sdk.robot.constant.RobotTypeEnum; +import com.newyetai.sdk.robot.model.MarkdownMsg; +import org.apache.commons.lang3.StringUtils; + +import java.util.Arrays; +import java.util.List; + + +/** + * Markdown + * + * @author Carlye + * @date 2021/10/08 + */ +public class MarkdownMsgUtils { + + public static MarkdownMsg build(String robotKey, String title, String msg) { + return MarkdownMsg.builder().robotKey(robotKey).title(title).text(msg).build(); + } + + public static MarkdownMsg setAtMobiles(MarkdownMsg markdownMsg, List atMobileList) { + if (markdownMsg == null) { + return markdownMsg; + } + markdownMsg.setAtMobiles(atMobileList); + return markdownMsg; + } + + + /** + * 根据传入类型创建文本消息 + * + * @param robotTypeKey 机器人类型关键 + * @param title 标题 + * @param msg 味精 + * @return {@link MarkdownMsg} + */ + public static MarkdownMsg createMsg(String robotTypeKey, String title, String msg) { + String[] typeKey = robotTypeKey.split(CommonConstants.COLON); + RobotTypeEnum robotType = RobotTypeEnum.valueOf(typeKey[0]); + String robotKey = typeKey[1]; + MarkdownMsg markdownMsg = null; + if (robotType == RobotTypeEnum.WORK_WECHAT) { +// markdownMsg = build(robotKey, title, msg); +// markdownMsg.setRobotType(RobotTypeEnum.WORK_WECHAT); + } else if (robotType == RobotTypeEnum.DING_TALK) { + markdownMsg = build(robotKey, title, msg); + } + return markdownMsg; + } + + + /** + * 根据传入类型创建文本消息 + * + * @param robotTypeKey 机器人类型关键 + * @param atMobiles 在手机 + * @param title 标题 + * @param msg 味精 + * @return {@link MarkdownMsg} + */ + public static MarkdownMsg createMsg(String robotTypeKey, String atMobiles, String title, String msg) { + List atMobileList = + StringUtils.isNotBlank(atMobiles) ? Arrays.asList(atMobiles.split(",")) : null; + return createMsg(robotTypeKey, atMobileList, title, msg); + } + + + /** + * 根据传入类型创建文本消息 + * + * @param robotTypeKey 机器人类型关键 + * @param atMobileList 在移动列表 + * @param title 标题 + * @param msg 味精 + * @return {@link MarkdownMsg} + */ + public static MarkdownMsg createMsg(String robotTypeKey, List atMobileList, String title, String msg) { + MarkdownMsg markdownMsg = createMsg(robotTypeKey, title, msg); + return setAtMobiles(markdownMsg, atMobileList); + } + + +} diff --git a/src/main/java/com/newyetai/sdk/robot/util/RobotUtils.java b/src/main/java/com/newyetai/sdk/robot/util/RobotUtils.java new file mode 100644 index 0000000..fc266e6 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/robot/util/RobotUtils.java @@ -0,0 +1,168 @@ +package com.newyetai.sdk.robot.util; + +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.util.EnvironmentUtils; +import com.newyetai.sdk.robot.model.MarkdownMsg; +import com.newyetai.sdk.robot.model.TextMsg; +import com.newyetai.sdk.robot.service.IRobotService; + +import lombok.extern.slf4j.Slf4j; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * @author sr on 2020-10-12 + */ +@Component +@Slf4j +public class RobotUtils { + + private static IRobotService robotService; + + /** + * 运维机器人配置键 + **/ + public static final String DEVOPS_KEY = "robot.devops.typeKey"; + + @Autowired + public void setRobotService(IRobotService robotService) { + RobotUtils.robotService = robotService; + } + + + /** + * 发送文本消息,@指定手机号 + * + * @param robotTypeKey 机器人类型关键 + * @param atMobiles 在手机 + * @param title 标题 + * @param msg 味精 + */ + public static void sendMarkdownMsg(String robotTypeKey, String atMobiles, String title, + String msg) { + try { + MarkdownMsg markdownMsg = MarkdownMsgUtils.createMsg(robotTypeKey, atMobiles, title, msg); + robotService.sendMarkdown(markdownMsg); + } catch (BusinessException be) { + log.info("执行失败:{}", be.getMessage()); + } catch (Exception e) { + log.info("robot error", e); + } + } + + /** + * 发送文本消息,@指定手机号 + * + * @param robotTypeKey 机器人类型关键 + * @param atMobileList 在移动列表 + * @param title 标题 + * @param msg 味精 + */ + public static void sendMarkdownMsg(String robotTypeKey, List atMobileList, String title, + String msg) { + try { + MarkdownMsg markdownMsg = MarkdownMsgUtils.createMsg(robotTypeKey, atMobileList, title, msg); + robotService.sendMarkdown(markdownMsg); + } catch (BusinessException be) { + log.info("执行失败:{}", be.getMessage()); + } catch (Exception e) { + log.info("robot error", e); + } + } + + + /** + * 发送文本消息,@所有人 + * + * @param robotTypeKey 机器人类型关键 + * @param title 标题 + * @param msg 味精 + */ + public static void sendMarkdownMsgAtAll(String robotTypeKey, String title, String msg) { + try { + MarkdownMsg markdownMsg = MarkdownMsgUtils.createMsg(robotTypeKey, title, msg); + markdownMsg.setAtAll(true); + robotService.sendMarkdown(markdownMsg); + } catch (BusinessException be) { + log.info("执行失败:{}", be.getMessage()); + } catch (Exception e) { + log.info("robot error", e); + } + } + + /** + * 发送文本消息,@指定手机号 + * + * @param robotTypeKey + * @param atMobiles 手机号逗号拼接 + * @param msg + * @author sr on 2020-10-12 + */ + public static void sendTextMsg(String robotTypeKey, String atMobiles, String msg) { + try { + TextMsg textMsg = TextMsgUtils.createMsg(robotTypeKey, atMobiles, msg); + robotService.sendText(textMsg); + } catch (BusinessException be) { + log.info("执行失败:{}", be.getMessage()); + } catch (Exception e) { + log.info("robot error", e); + } + } + + /** + * 发送文本消息,@指定手机号 + * + * @param robotTypeKey + * @param atMobileList 手机号集合 + * @param msg + * @author sr on 2020-10-12 + */ + public static void sendTextMsg(String robotTypeKey, List atMobileList, String msg) { + try { + TextMsg textMsg = TextMsgUtils.createMsg(robotTypeKey, atMobileList, msg); + robotService.sendText(textMsg); + } catch (BusinessException be) { + log.info("执行失败:{}", be.getMessage()); + }catch (Exception e) { + log.info("robot error", e); + } + } + + /** + * 发送文本消息,@所有人 + * + * @param robotTypeKey + * @param msg + * @author sr on 2020-10-12 + */ + public static void sendTextMsgAtAll(String robotTypeKey, String msg) { + try { + TextMsg textMsg = TextMsgUtils.createMsg(robotTypeKey, msg); + textMsg.setAtAll(true); + robotService.sendText(textMsg); + } catch (BusinessException be) { + log.info("执行失败:{}", be.getMessage()); + } catch (Exception e) { + log.info("robot error", e); + } + } + + + + /** + * 发送运维人员消息 + * + * @param msg 消息体 + * @author sr on 2021-04-13 + */ + public static void sendDevops(String msg) { + try { + sendTextMsgAtAll(EnvironmentUtils.getProperty(DEVOPS_KEY), msg); + } catch (Exception e) { + log.info("robot error", e); + } + } +} diff --git a/src/main/java/com/newyetai/sdk/robot/util/TextMsgUtils.java b/src/main/java/com/newyetai/sdk/robot/util/TextMsgUtils.java new file mode 100644 index 0000000..90423ca --- /dev/null +++ b/src/main/java/com/newyetai/sdk/robot/util/TextMsgUtils.java @@ -0,0 +1,86 @@ +package com.newyetai.sdk.robot.util; + +import java.util.Arrays; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; + +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.sdk.robot.constant.RobotTypeEnum; +import com.newyetai.sdk.robot.model.TextMsg; + +/** + * @author sr on 2020-10-12 + */ +public class TextMsgUtils { + + public static TextMsg build(String robotKey, String msg){ + return TextMsg.builder().robotKey(robotKey).content(msg).build(); + } + + public static TextMsg setAtMobiles(TextMsg textMsg, List atMobileList) { + if (textMsg == null) { + return textMsg; + } + textMsg.setAtMobiles(atMobileList); + return textMsg; + } + + /** + * 根据传入类型创建文本消息 + * + * @param robotTypeKey + * @param msg + * @return + * @author sr on 2020-10-12 + */ + public static TextMsg createMsg(String robotTypeKey, String msg) { + Assert.isTrue( + StringUtils.isNotBlank(robotTypeKey) && robotTypeKey.contains(CommonConstants.COLON), + "机器人类型有误:" + robotTypeKey); + String[] typeKey = robotTypeKey.split(CommonConstants.COLON); + String robotTypeStr = typeKey[0]; + RobotTypeEnum robotType = RobotTypeEnum.valueOf(robotTypeStr); + String robotKey = typeKey[1]; + TextMsg textMsg = null; + if (robotType == RobotTypeEnum.WORK_WECHAT) { + textMsg = build(robotKey, msg); + textMsg.setRobotType(RobotTypeEnum.WORK_WECHAT); + } else if (robotType == RobotTypeEnum.DING_TALK) { + textMsg = build(robotKey, msg); + } + return textMsg; + } + + /** + * 根据传入类型创建文本消息 + * + * @param robotTypeKey 机器人类型和标识,type:key + * @param atMobiles + * @param msg + * @return + * @author sr on 2020-10-12 + */ + public static TextMsg createMsg(String robotTypeKey, String atMobiles, String msg) { + List atMobileList = + StringUtils.isNotBlank(atMobiles) ? Arrays.asList(atMobiles.split(",")) : null; + return createMsg(robotTypeKey, atMobileList, msg); + } + + /** + * 根据传入类型创建文本消息 + * + * @param robotTypeKey + * @param atMobileList + * @param msg + * @return + * @author sr on 2020-10-12 + */ + public static TextMsg createMsg(String robotTypeKey, List atMobileList, String msg) { + TextMsg textMsg = createMsg(robotTypeKey, msg); + return setAtMobiles(textMsg, atMobileList); + } + + +} diff --git a/src/main/java/com/newyetai/sdk/sms/config/SmsConfig.java b/src/main/java/com/newyetai/sdk/sms/config/SmsConfig.java new file mode 100644 index 0000000..ad3c6c9 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/config/SmsConfig.java @@ -0,0 +1,49 @@ +package com.newyetai.sdk.sms.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.stereotype.Component; + +import com.aliyuncs.DefaultAcsClient; +import com.aliyuncs.IAcsClient; +import com.aliyuncs.profile.DefaultProfile; + +import lombok.Data; + +/** + * 短信sms配置 + * + * @author on 2019-11-05 + */ +@ConfigurationProperties(prefix = SmsConfig.PREFIX) +@Data +@Component +public class SmsConfig { + + public static final String PREFIX = "sms"; + + private Boolean enable; + + /** 次数限制 **/ + private Long numLimit; + + private String domain; + + private String accessKeyId; + + private String accessSecret; + + private String regionId; + + private String version; + + /** 签名 **/ + private String signName; + + + @Bean + public IAcsClient defaultProfile() { + DefaultProfile defaultProfile = DefaultProfile.getProfile(regionId, accessKeyId, accessSecret); + return new DefaultAcsClient(defaultProfile); + } +} diff --git a/src/main/java/com/newyetai/sdk/sms/constant/AliSmsActionEnum.java b/src/main/java/com/newyetai/sdk/sms/constant/AliSmsActionEnum.java new file mode 100644 index 0000000..4419002 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/constant/AliSmsActionEnum.java @@ -0,0 +1,44 @@ +package com.newyetai.sdk.sms.constant; + +/** + * 阿里云action + * + * @author sr on 2020-07-03 + */ +public enum AliSmsActionEnum { + + /** 发送短信 **/ + SEND_SMS("SendSms"), + /** 批量发送短信 **/ + SEND_BATCH_SMS("SendBatchSms"), + /** 查询短信发送的状态 **/ + QUERY_SEND_DETAILS("QuerySendDetails"), + /** 申请短信签名 **/ + ADD_SMS_SIGN("AddSmsSign"), + /** 删除短信签名 **/ + DELETE_SMS_SIGN("DeleteSmsSign"), + /** 查询短信签名申请状态 **/ + QUERY_SMS_SIGN("QuerySmsSign"), + /** 修改未审核通过的短信签名,并重新提交审核 **/ + MODIFY_SMS_SIGN("ModifySmsSign"), + /** 修改未通过审核的短信模板 **/ + MODIFY_SMS_TEMPLATE("ModifySmsTemplate"), + /** 查询短信模板的审核状态 **/ + QUERY_SMS_TEMPLATE("QuerySmsTemplate"), + /** 申请短信模板 **/ + ADD_SMS_TEMPLATE("AddSmsTemplate"), + /** 删除短信模板 **/ + DELETE_SMS_TEMPLATE("DeleteSmsTemplate"); + + private String value; + + private AliSmsActionEnum(String value) { + this.value = value; + } + + public String getValue() { + return this.value; + } + + +} diff --git a/src/main/java/com/newyetai/sdk/sms/constant/SmsConstants.java b/src/main/java/com/newyetai/sdk/sms/constant/SmsConstants.java new file mode 100644 index 0000000..7e97599 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/constant/SmsConstants.java @@ -0,0 +1,18 @@ +package com.newyetai.sdk.sms.constant; + +/** + * 短信常量类 + * + * @author sr on 2019-09-16 + */ +public interface SmsConstants { + + /** 成功码 **/ + String SUCCESS_CODE = "OK"; + + /** ================ sms 调起真实服务前异常msg ================= **/ + String TEMPLATE_CODE_KEY_EMPTY = "sms短信模版配置健为空"; + String TEMPLATE_CODE_EMPTY = "sms短信模版为空"; + /** ================ sms 调起真实服务前异常msg ================= **/ + +} diff --git a/src/main/java/com/newyetai/sdk/sms/constant/SmsProviderEnum.java b/src/main/java/com/newyetai/sdk/sms/constant/SmsProviderEnum.java new file mode 100644 index 0000000..ab7f433 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/constant/SmsProviderEnum.java @@ -0,0 +1,22 @@ +package com.newyetai.sdk.sms.constant; + +/** + * 短信服务提供者 + * @author sr on 2020-07-03 + */ +public enum SmsProviderEnum { + + /** 阿里云 **/ + ALIYAN("aliyun"); + + private String providerName; + + SmsProviderEnum(String providerName){ + this.providerName = providerName; + } + + public String getProviderName() { + return this.providerName; + } + +} diff --git a/src/main/java/com/newyetai/sdk/sms/dto/ISendDTO.java b/src/main/java/com/newyetai/sdk/sms/dto/ISendDTO.java new file mode 100644 index 0000000..1ea39e7 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/dto/ISendDTO.java @@ -0,0 +1,64 @@ +package com.newyetai.sdk.sms.dto; + +import com.newyetai.sdk.sms.constant.SmsProviderEnum; + +/** + * 发送短信对象接口 + * + * @author sr on 2020-07-02 + * @param + */ +public interface ISendDTO { + + /** + * 短信服务商提供者,默认阿里云 + * + * @return + * @author sr on 2020-07-03 + */ + default SmsProviderEnum getSmsProvider() { + return SmsProviderEnum.ALIYAN; + } + + /** + * 短信模版配置key,获取配置时内部会自动加上(sms)前缀, 如配置文件中添加sms.someTemplateCode,此处配置someTemplateCode + * + * @return + * @author sr on 2020-07-02 + */ + String getTemplateCodeKey(); + + /** + * 阿里云模版code,如SMS_19522**** + * + * @return + * @author sr on 2020-07-03 + */ + default String getTemplateCode() { + return null; + } + + /** + * 手机号 + * + * @return + * @author sr on 2020-07-02 + */ + String getPhone(); + + /** + * 短信模版参数 + * + * @return + * @author sr on 2020-07-02 + */ + T getParameters(); + + /** + * 获取签名 + * + * @return + */ + String getSignName(); + +} diff --git a/src/main/java/com/newyetai/sdk/sms/dto/ITemplateCode.java b/src/main/java/com/newyetai/sdk/sms/dto/ITemplateCode.java new file mode 100644 index 0000000..ce488e3 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/dto/ITemplateCode.java @@ -0,0 +1,18 @@ +package com.newyetai.sdk.sms.dto; + +/** + * 短信模版对象 + * + * @author sr on 2020-07-03 + */ +public interface ITemplateCode { + + /** + * 模版属性配置键,不带sms.前缀 + * + * @return + * @author sr on 2020-07-03 + */ + String getTemplateCodeKey(); + +} diff --git a/src/main/java/com/newyetai/sdk/sms/dto/SimpleSendDTO.java b/src/main/java/com/newyetai/sdk/sms/dto/SimpleSendDTO.java new file mode 100644 index 0000000..73dcb4f --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/dto/SimpleSendDTO.java @@ -0,0 +1,31 @@ +package com.newyetai.sdk.sms.dto; + +import java.util.Map; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 发送sms对象,模版参数对象为map + * + * @author sr on 2020-07-02 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class SimpleSendDTO implements ISendDTO> { + + private String templateCodeKey; + + private String templateCode; + + private String phone; + + private Map parameters; + + private String signName; + +} diff --git a/src/main/java/com/newyetai/sdk/sms/dto/VerificationCodeParamDTO.java b/src/main/java/com/newyetai/sdk/sms/dto/VerificationCodeParamDTO.java new file mode 100644 index 0000000..9ffe8f7 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/dto/VerificationCodeParamDTO.java @@ -0,0 +1,26 @@ +package com.newyetai.sdk.sms.dto; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 验证码短信参数对象 + * + * @author sr on 2020-07-02 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class VerificationCodeParamDTO implements Serializable { + + /** **/ + private static final long serialVersionUID = 2431795846055282684L; + + private String code; + +} diff --git a/src/main/java/com/newyetai/sdk/sms/dto/VerificationCodeSendDTO.java b/src/main/java/com/newyetai/sdk/sms/dto/VerificationCodeSendDTO.java new file mode 100644 index 0000000..526ce9d --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/dto/VerificationCodeSendDTO.java @@ -0,0 +1,54 @@ +package com.newyetai.sdk.sms.dto; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 发送验证码sms对象 + * + * @author sr on 2020-07-02 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class VerificationCodeSendDTO implements ISendDTO { + + /** 短信模版配置key **/ + private String templateCodeKey; + + /** 短信模版号 **/ + private String templateCode; + + /** 手机号 **/ + private String phone; + + /** 验证码参数 **/ + private VerificationCodeParamDTO parameters; + + private String signName; + + /** 验证码 **/ + @JsonIgnore + private String code; + + @Override + public String getSignName() { + return signName; + } + + public VerificationCodeParamDTO getParameters() { + if (parameters != null) { + return parameters; + } + if (code != null) { + parameters = VerificationCodeParamDTO.builder().code(code).build(); + } + return parameters; + } + +} diff --git a/src/main/java/com/newyetai/sdk/sms/model/AddSmsSign.java b/src/main/java/com/newyetai/sdk/sms/model/AddSmsSign.java new file mode 100644 index 0000000..ba555f4 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/model/AddSmsSign.java @@ -0,0 +1,62 @@ +package com.newyetai.sdk.sms.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; + + +/** + * 短信签名 + * + * @author Rey(leijiaping@newyetai.com) {@link undefined} + */ +public class AddSmsSign implements Serializable { + + /** + * + */ + private static final long serialVersionUID = -5401737524288272902L; + + /** + * 是否必填:是
+ * 事例:阿里云
+ * 描述:签名名称。 **说明** + * 签名必须符合[个人用户签名规范](https://help.aliyun.com/document_detail/108076.html)或[企业用户签名规范](https://help.aliyun.com/document_detail/108254.html)。
+ */ + @JsonProperty("SignName") + private String signName; + + /** + * 是否必填:是
+ * 事例:1
+ * 描述:签名来源。其中: - 0:企事业单位的全称或简称。 - 1:工信部备案网站的全称或简称。 - 2:APP 应用的全称或简称。 - 3:公众号或小程序的全称或简称。 - + * 4:电商平台店铺名的全称或简称。 - 5:商标名的全称或简称 说明** 签名来源为 1 时,请在申请说明中添加网站域名,加快审核速度。
+ */ + @JsonProperty("SignSource") + private Integer signSource; + + /** + * 是否必填:是
+ * 事例:当前的短信签名应用于双 11 大促推广营销
+ * 描述:短信签名申请说明。请在申请说明中详细描述您的业务使用场景,申请工信部备案网站的全称或简称请在此处填写域名,长度不超过 200 个字符。
+ */ + @JsonProperty("Remark") + private String remark; + + /** + * 是否必填:否
+ * 事例:jpg
+ * 描述:签名的证明文件格式,支持上传多张图片。当前支持 jpg、png、gif 或 jpeg + * 格式的图片。个别场景下,申请签名需要上传证明文件。详细说明请参考[个人用户签名规范](https://help.aliyun.com/document_detail/108076.html)和[企业用户签名规范](https://help.aliyun.com/document_detail/108254.html)。
+ */ + @JsonProperty("SignFileList.N.FileSuffix") + private String fileSuffix; + + /** + * 是否必填:否
+ * 事例:R0lGODlhHAAmAKIHAKqqqsvLy0hISObm5vf394uLiwAA
+ * 描述:签名的资质证明文件经 base64 编码后的字符串。图片不超过 2 + * MB。个别场景下,申请签名需要上传证明文件。详细说明请参考[个人用户签名规范](https://help.aliyun.com/document_detail/108076.html)和[企业用户签名规范](https://help.aliyun.com/document_detail/108254.html)。
+ */ + @JsonProperty("SignFileList.N.FileContents") + private String fileContents; +} diff --git a/src/main/java/com/newyetai/sdk/sms/model/AddSmsSignResponse.java b/src/main/java/com/newyetai/sdk/sms/model/AddSmsSignResponse.java new file mode 100644 index 0000000..3119052 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/model/AddSmsSignResponse.java @@ -0,0 +1,46 @@ +package com.newyetai.sdk.sms.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; + +/** + * 短信签名 + * + * @author Rey(leijiaping@newyetai.com) + */ +public class AddSmsSignResponse implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 4121769016752821993L; + + /** + * 事例:阿里云
+ * 描述:签名名称。
+ */ + @JsonProperty("SignName") + private String signName; + + /** + * 事例:OK
+ * 描述:状态码的描述。
+ */ + @JsonProperty("Message") + private String message; + + /** + * 事例:F655A8D5-B967-440B-8683-DAD6FF8DE990
+ * 描述:请求 ID。
+ */ + @JsonProperty("RequestId") + private String requestId; + + /** + * 事例:OK
+ * 描述:请求状态码。 - 返回 OK 代表请求成功。 - + * 其他错误码详见[错误码列表](https://help.aliyun.com/document_detail/101346.html)。
+ */ + @JsonProperty("Code") + private String code; +} diff --git a/src/main/java/com/newyetai/sdk/sms/model/AddSmsTemplate.java b/src/main/java/com/newyetai/sdk/sms/model/AddSmsTemplate.java new file mode 100644 index 0000000..ddd97e1 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/model/AddSmsTemplate.java @@ -0,0 +1,51 @@ +package com.newyetai.sdk.sms.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; + +/** + * 短信模板 + * + * @author Rey(leijiaping@newyetai.com) + */ +public class AddSmsTemplate implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 5868722985393802890L; + + /** + * 是否必填:是
+ * 事例:1
+ * 描述:短信类型。其中: - 0:验证码。 - 1:短信通知。 - 2:推广短信。 - 3:国际 / 港澳台消息。
+ */ + @JsonProperty("TemplateType") + private Integer templateType; + + /** + * 是否必填:是
+ * 事例:阿里云短信测试模板
+ * 描述:模板名称,长度为 1~30 个字符。
+ */ + @JsonProperty("TemplateName") + private String templateName; + + /** + * 是否必填:是
+ * 事例:您正在申请手机注册,验证码为:${code},5 分钟内有效!
+ * 描述:模板内容,长度为 1~500 + * 个字符。模板内容需要符合[文本短信模板规范](https://help.aliyun.com/document_detail/108253.html)或[国际 / + * 港澳台短信模板规范](https://help.aliyun.com/document_detail/108254.html)。
+ */ + @JsonProperty("TemplateContent") + private String templateContent; + + /** + * 是否必填:是
+ * 事例:当前的短信模板应用于双 11 大促推广营销
+ * 描述:短信模板申请说明。请在申请说明中描述您的业务使用场景,长度为 1~100 个字符。
+ */ + @JsonProperty("Remark") + private String remark; +} diff --git a/src/main/java/com/newyetai/sdk/sms/model/DeleteSmsSign.java b/src/main/java/com/newyetai/sdk/sms/model/DeleteSmsSign.java new file mode 100644 index 0000000..151704a --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/model/DeleteSmsSign.java @@ -0,0 +1,25 @@ +package com.newyetai.sdk.sms.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; + +/** + * 短信签名 + * + * @author Rey(leijiaping@newyetai.com) {@link undefined} + */ +public class DeleteSmsSign implements Serializable { + + /** + * + */ + private static final long serialVersionUID = -6841147861661592533L; + + /** + * 是否必填:是
+ * 事例:阿里云
+ * 描述:短信签名。 **说明** 必须是本账号已申请的短信签名。
+ */ + @JsonProperty("SignName") + private String signName; +} diff --git a/src/main/java/com/newyetai/sdk/sms/model/DeleteSmsSignResponse.java b/src/main/java/com/newyetai/sdk/sms/model/DeleteSmsSignResponse.java new file mode 100644 index 0000000..8270de4 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/model/DeleteSmsSignResponse.java @@ -0,0 +1,47 @@ +package com.newyetai.sdk.sms.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; + +/** + * 短信签名 + * + * @author Rey(leijiaping@newyetai.com) + * + */ +public class DeleteSmsSignResponse implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 8836559705606969786L; + + /** + * 事例:OK
+ * 描述:请求状态码。 - 返回 OK 代表请求成功。 - + * 其他错误码详见[错误码列表](https://help.aliyun.com/document_detail/101346.html)。
+ */ + @JsonProperty("Code") + private String code; + + /** + * 事例:OK
+ * 描述:状态码的描述。
+ */ + @JsonProperty("Message") + private String message; + + /** + * 事例:F655A8D5-B967-440B-8683-DAD6FF8DE990
+ * 描述:请求 ID。
+ */ + @JsonProperty("RequestId") + private String requestId; + + /** + * 事例:阿里云
+ * 描述:签名名称。
+ */ + @JsonProperty("SignName") + private String signName; +} diff --git a/src/main/java/com/newyetai/sdk/sms/model/DeleteSmsTemplate.java b/src/main/java/com/newyetai/sdk/sms/model/DeleteSmsTemplate.java new file mode 100644 index 0000000..97563dd --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/model/DeleteSmsTemplate.java @@ -0,0 +1,25 @@ +package com.newyetai.sdk.sms.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; + +/** + * 短信模板 + * + * @author Rey(leijiaping@newyetai.com) + */ +public class DeleteSmsTemplate implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 3423181148483950846L; + + /** + * 是否必填:是
+ * 事例:SMS\_152550005
+ * 描述:短信模板 CODE。您可以在控制台 **模板管理** 页面或 API 接口 ** AddSmsTemplate** 的返回参数中获取短信模板 CODE。
+ */ + @JsonProperty("TemplateCode") + private String templateCode; +} diff --git a/src/main/java/com/newyetai/sdk/sms/model/ModifySmsSign.java b/src/main/java/com/newyetai/sdk/sms/model/ModifySmsSign.java new file mode 100644 index 0000000..10b1ef5 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/model/ModifySmsSign.java @@ -0,0 +1,61 @@ +package com.newyetai.sdk.sms.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; + +/** + * 短信签名 + * + * @author Rey(leijiaping@newyetai.com) + */ +public class ModifySmsSign implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 7033519742117645850L; + + /** + * 是否必填:是
+ * 事例:阿里云
+ * 描述:签名内容。 **说明** + * 签名内容必须符合[个人用户签名规范](https://help.aliyun.com/document_detail/108076.html)或[企业用户签名规范](https://help.aliyun.com/document_detail/108254.html)。
+ */ + @JsonProperty("SignName") + private String signName; + + /** + * 是否必填:是
+ * 事例:1
+ * 描述:签名来源。其中: - 0:企事业单位的全称或简称。 - 1:工信部备案网站的全称或简称。 - 2:APP 应用的全称或简称。 - 3:公众号或小程序的全称或简称。 - + * 4:电商平台店铺名的全称或简称。 - 5:商标名的全称或简称 说明** 签名来源为 1 时,请在申请说明中添加网站域名,加快审核速度。
+ */ + @JsonProperty("SignSource") + private Integer signSource; + + /** + * 是否必填:是
+ * 事例:当前的短信签名应用于双 11 大促推广营销
+ * 描述:短信签名申请说明。请在申请说明中详细描述您的业务使用场景,申请工信部备案网站的全称或简称请在此处填写域名,长度不超过 200 个字符。
+ */ + @JsonProperty("Remark") + private String remark; + + /** + * 是否必填:否
+ * 事例:jpg
+ * 描述:签名的证明文件格式,支持上传多张图片。当前支持 jpg、png、gif 或 jpeg + * 格式的图片。个别场景下,申请签名需要上传证明文件。详细说明请参考[个人用户签名规范](https://help.aliyun.com/document_detail/108076.html)和[企业用户签名规范](https://help.aliyun.com/document_detail/108254.html)。
+ */ + @JsonProperty("SignFileList.N.FileSuffix") + private String fileSuffix; + + /** + * 是否必填:否
+ * 事例:R0lGODlhHAAmAKIHAKqqqsvLy0hISObm5vf394uLiwAA
+ * 描述:签名的质证明文件经 base64 编码后的字符串。图片不超过 2 + * MB。个别场景下,申请签名需要上传证明文件。详细说明请参考[个人用户签名规范](https://help.aliyun.com/document_detail/108076.html)和[企业用户签名规范](https://help.aliyun.com/document_detail/108254.html)。
+ */ + @JsonProperty("SignFileList.N.FileContents") + private String fileContents; +} diff --git a/src/main/java/com/newyetai/sdk/sms/model/ModifySmsSignResponse.java b/src/main/java/com/newyetai/sdk/sms/model/ModifySmsSignResponse.java new file mode 100644 index 0000000..34454d9 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/model/ModifySmsSignResponse.java @@ -0,0 +1,46 @@ +package com.newyetai.sdk.sms.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; + +/** + * 短信签名 + * + * @author Rey(leijiaping@newyetai.com) + */ +public class ModifySmsSignResponse implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 2556874115950958951L; + + /** + * 事例:OK
+ * 描述:请求状态码。 - 返回 OK 代表请求成功。 - + * 其他错误码详见[错误码列表](https://help.aliyun.com/document_detail/101346.html)。
+ */ + @JsonProperty("Code") + private String code; + + /** + * 事例:OK
+ * 描述:状态码的描述。
+ */ + @JsonProperty("Message") + private String message; + + /** + * 事例:F655A8D5-B967-440B-8683-DAD6FF8DE990
+ * 描述:请求 ID。
+ */ + @JsonProperty("RequestId") + private String requestId; + + /** + * 事例:阿里云
+ * 描述:签名名称。
+ */ + @JsonProperty("SignName") + private String signName; +} diff --git a/src/main/java/com/newyetai/sdk/sms/model/ModifySmsTemplate.java b/src/main/java/com/newyetai/sdk/sms/model/ModifySmsTemplate.java new file mode 100644 index 0000000..3d0af5a --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/model/ModifySmsTemplate.java @@ -0,0 +1,60 @@ +package com.newyetai.sdk.sms.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; + +/** + * 短信模板 + * + * @author Rey(leijiaping@newyetai.com) + */ +public class ModifySmsTemplate implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 4824423254878168505L; + + /** + * 是否必填:是
+ * 事例:1
+ * 描述:短信类型。其中: - 0 表示验证码。 - 1 表示短信通知。 - 2 表示推广短信。 - 3 国际 / 港澳台消息。
+ */ + @JsonProperty("TemplateType") + private Integer templateType; + + /** + * 是否必填:是
+ * 事例:阿里云短信测试模板
+ * 描述:模板名称,长度为 1~30 个字符。
+ */ + @JsonProperty("TemplateName") + private String templateName; + + /** + * 是否必填:是
+ * 事例:您正在申请手机注册,验证码为:${code},5 分钟内有效!
+ * 描述:模板内容,长度为 1~500 + * 个字符。模板内容需要符合[文本短信模板规范](https://help.aliyun.com/document_detail/108253.html)或[国际 / + * 港澳台短信模板规范](https://help.aliyun.com/document_detail/108254.html)。 **说明** + * 修改模板时,请针对审核意见合理设计模板内容。
+ */ + @JsonProperty("TemplateContent") + private String templateContent; + + /** + * 是否必填:是
+ * 事例:当前的短信模板应用于双 11 大促推广营销
+ * 描述:短信模板申请说明。请在申请说明中描述您的业务使用场景,长度为 1~100 个字符。
+ */ + @JsonProperty("Remark") + private String remark; + + /** + * 是否必填:是
+ * 事例:SMS\_152550005
+ * 描述:短信模板 CODE。您可以在控制台 **模板管理** 页面或 API 接口 ** AddSmsTemplate** 的返回参数中获取短信模板 CODE。
+ */ + @JsonProperty("TemplateCode") + private String templateCode; +} diff --git a/src/main/java/com/newyetai/sdk/sms/model/QuerySendDetails.java b/src/main/java/com/newyetai/sdk/sms/model/QuerySendDetails.java new file mode 100644 index 0000000..4b1609c --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/model/QuerySendDetails.java @@ -0,0 +1,57 @@ +package com.newyetai.sdk.sms.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; + +/** + * 查询发送记录 + * + * @author Rey(leijiaping@newyetai.com) + */ +public class QuerySendDetails implements Serializable { + + /** + * + */ + private static final long serialVersionUID = -6796100129790552341L; + + /** + * 是否必填:是
+ * 事例:1
+ * 描述:分页查看发送记录,指定发送记录的的当前页码。
+ */ + @JsonProperty("CurrentPage") + private Long currentPage; + + /** + * 是否必填:是
+ * 事例:10
+ * 描述:分页查看发送记录,指定每页显示的短信记录数量。取值范围为 1~50。
+ */ + @JsonProperty("PageSize") + private Long pageSize; + + /** + * 是否必填:是
+ * 事例:15900000000
+ * 描述:接收短信的手机号码。格式: - 国内短信:11 位手机号码,例如 15900000000。 - 国际 / 港澳台消息:国际区号 + 号码,例如 85200000000。
+ */ + @JsonProperty("PhoneNumber") + private String phoneNumber; + + /** + * 是否必填:是
+ * 事例:20181228
+ * 描述:短信发送日期,支持查询最近 30 天的记录。格式为 yyyyMMdd,例如 20181225。
+ */ + @JsonProperty("SendDate") + private String sendDate; + + /** + * 是否必填:否
+ * 事例:134523^4351232
+ * 描述:发送回执 ID,即发送流水号。调用发送接口 SendSms 或 SendBatchSms 发送短信时,返回值中的 BizId 字段。
+ */ + @JsonProperty("BizId") + private String bizId; +} diff --git a/src/main/java/com/newyetai/sdk/sms/model/QuerySmsSign.java b/src/main/java/com/newyetai/sdk/sms/model/QuerySmsSign.java new file mode 100644 index 0000000..fe3cad2 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/model/QuerySmsSign.java @@ -0,0 +1,26 @@ +package com.newyetai.sdk.sms.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; + +/** + * 短信签名 + * + * @author Rey(leijiaping@newyetai.com) + */ +public class QuerySmsSign implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 7244896668246210132L; + + /** + * 是否必填:是
+ * 事例:阿里云
+ * 描述:签名名称。
+ */ + @JsonProperty("SignName") + private String signName; + +} diff --git a/src/main/java/com/newyetai/sdk/sms/model/QuerySmsSignResponse.java b/src/main/java/com/newyetai/sdk/sms/model/QuerySmsSignResponse.java new file mode 100644 index 0000000..b3b8a4d --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/model/QuerySmsSignResponse.java @@ -0,0 +1,68 @@ +package com.newyetai.sdk.sms.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; + +/** + * 短信签名 + * + * @author Rey(leijiaping@newyetai.com) + */ +public class QuerySmsSignResponse implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 3695802019215175700L; + + /** + * 事例:OK
+ * 描述:请求状态码。 - 返回 OK 代表请求成功。 - + * 其他错误码详见[错误码列表](https://help.aliyun.com/document_detail/101346.html)。
+ */ + @JsonProperty("Code") + private String code; + + /** + * 事例:2019-01-08 16:44:13
+ * 描述:短信签名的创建日期和时间。
+ */ + @JsonProperty("CreateDate") + private String createDate; + + /** + * 事例:OK
+ * 描述:状态码描述。
+ */ + @JsonProperty("Message") + private String message; + + /** + * 事例:文件不能证明信息真实性,请重新上传
+ * 描述:审核备注。 - 如果审核状态为 **审核通过** 或 **审核中** ,参数 Reason 显示为 "无审核备注"。 - 如果审核状态为 **审核未通过** ,参数 + * Reason 显示审核的具体原因。
+ */ + @JsonProperty("Reason") + private String reason; + + /** + * 事例:CC89A90C-978F-46AC-B80D-54738371E7CA
+ * 描述:请求 ID。
+ */ + @JsonProperty("RequestId") + private String requestId; + + /** + * 事例:阿里云
+ * 描述:短信签名。
+ */ + @JsonProperty("SignName") + private String signName; + + /** + * 事例:1
+ * 描述:签名审核状态。其中: - 0:审核中。 - 1:审核通过。 - 2:审核失败,请在返回参数 Reason 中查看审核失败原因。
+ */ + @JsonProperty("SignStatus") + private Integer signStatus; +} diff --git a/src/main/java/com/newyetai/sdk/sms/model/QuerySmsTemplate.java b/src/main/java/com/newyetai/sdk/sms/model/QuerySmsTemplate.java new file mode 100644 index 0000000..8e39c5e --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/model/QuerySmsTemplate.java @@ -0,0 +1,26 @@ +package com.newyetai.sdk.sms.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; + +/** + * 短信模板 + * + * @author Rey(leijiaping@newyetai.com) + */ +public class QuerySmsTemplate implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 7787624013394982501L; + + /** + * 是否必填:是
+ * 事例:SMS\_152550005
+ * 描述:短信模板 CODE。您可以在控制台 **模板管理** 页面或 API 接口 ** AddSmsTemplate** 的返回参数中获取短信模板 CODE。
+ */ + @JsonProperty("TemplateCode") + private String templateCode; + +} diff --git a/src/main/java/com/newyetai/sdk/sms/model/QuerySmsTemplateResponse.java b/src/main/java/com/newyetai/sdk/sms/model/QuerySmsTemplateResponse.java new file mode 100644 index 0000000..434982a --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/model/QuerySmsTemplateResponse.java @@ -0,0 +1,64 @@ +package com.newyetai.sdk.sms.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * 查询查询短信模板的审核状态响应体 + * + * @author Rey(leijiaping@newyetai.com) {@link undefined} + */ +public class QuerySmsTemplateResponse extends SmsResponse { + + /** **/ + private static final long serialVersionUID = 4855274472484572364L; + + /** + * 事例:2019-06-04 11:42:17
+ * 描述:短信模板的创建日期和时间。
+ */ + @JsonProperty("CreateDate") + private String createDate; + + /** + * 事例:非验证码类型短信,请选择短信通知类型为推广短信。
+ * 描述:审核备注。 - 如果审核状态为 **审核通过** 或 **审核中** ,参数 Reason 显示为 "无审核备注"。 - 如果审核状态为 **审核未通过** ,参数 + * Reason 显示审核的具体原因。
+ */ + @JsonProperty("Reason") + private String reason; + + /** + * 事例:SMS\_167035184
+ * 描述:短信模板 CODE。
+ */ + @JsonProperty("TemplateCode") + private String templateCode; + + /** + * 事例:亲爱的会员!阿里云短信服务祝您新年快乐!
+ * 描述:模板内容。
+ */ + @JsonProperty("TemplateContent") + private String templateContent; + + /** + * 事例:阿里云短信测试模板
+ * 描述:模板名称。
+ */ + @JsonProperty("TemplateName") + private String templateName; + + /** + * 事例:1
+ * 描述:模板审核状态。其中: - 0:审核中。 - 1:审核通过。 - 2:审核失败,请在返回参数 Reason 中查看审核失败原因。
+ */ + @JsonProperty("TemplateStatus") + private Integer templateStatus; + + /** + * 事例:1
+ * 描述:短信类型。其中: - 0:验证码。 - 1:短信通知。 - 2:推广短信。 - 3:国际 / 港澳台消息。
+ */ + @JsonProperty("TemplateType") + private Integer templateType; +} diff --git a/src/main/java/com/newyetai/sdk/sms/model/SendBatchSms.java b/src/main/java/com/newyetai/sdk/sms/model/SendBatchSms.java new file mode 100644 index 0000000..592f956 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/model/SendBatchSms.java @@ -0,0 +1,70 @@ +package com.newyetai.sdk.sms.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 发送短信 + * + * @author Rey(leijiaping@newyetai.com) + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class SendBatchSms implements Serializable { + + /** + * + */ + private static final long serialVersionUID = -721415853051957784L; + + /** + * 是否必填:是
+ * 事例:["15900000000","13500000000"]
+ * 描述:接收短信的手机号码,JSON 数组格式。手机号码格式: - 国内短信:11 位手机号码,例如 15900000000。 - 国际 / 港澳台消息:国际区号 + 号码,例如 + * 85200000000。 说明** 验证码类型短信,建议使用接口 SendSms 单独发送。
+ */ + @JsonProperty("PhoneNumberJson") + private String phoneNumberJson; + + /** + * 是否必填:是
+ * 事例:["阿里云","阿里巴巴"]
+ * 描述:短信签名名称,JSON 数组格式。请在控制台 **签名管理** 页面 **签名名称** 一列查看。 **说明** + * 必须是已添加、并通过审核的短信签名;且短信签名的个数必须与手机号码的个数相同、内容一一对应。
+ */ + @JsonProperty("SignNameJson") + private String signNameJson; + + /** + * 是否必填:是
+ * 事例:SMS\_152550005
+ * 描述:短信模板 CODE。请在控制台 **模板管理** 页面 **模板 CODE** 一列查看。 **说明** 必须是已添加、并通过审核的模板 CODE;且发送国际 / + * 港澳台消息时,请使用国际 / 港澳台短信模版。
+ */ + @JsonProperty("TemplateCode") + private String templateCode; + + /** + * 是否必填:否
+ * 事例:["90999","90998"]
+ * 描述:上行短信扩展码,JSON 数组格式。无特殊需要此字段的用户请忽略此字段。
+ */ + @JsonProperty("SmsUpExtendCodeJson") + private String smsUpExtendCodeJson; + + /** + * 是否必填:否
+ * 事例:[{"name":"TemplateParamJson"},{"name":"TemplateParamJson"}]
+ * 描述:短信模板变量对应的实际值,JSON 格式。 **说明** 如果 JSON 中需要带换行符,请参照标准的 JSON + * 协议处理;且模板变量值的个数必须与手机号码、签名的个数相同、内容一一对应,表示向指定手机号码中发对应签名的短信,且短信模板中的变量参数替换为对应的值。
+ */ + @JsonProperty("TemplateParamJson") + private String templateParamJson; +} diff --git a/src/main/java/com/newyetai/sdk/sms/model/SendSms.java b/src/main/java/com/newyetai/sdk/sms/model/SendSms.java new file mode 100644 index 0000000..5087ffb --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/model/SendSms.java @@ -0,0 +1,77 @@ +package com.newyetai.sdk.sms.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 发送短信 + * + * @author Rey(leijiaping@newyetai.com) + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class SendSms implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 4127513146153674808L; + + /** + * 是否必填:是
+ * 事例:15900000000
+ * 描述:接收短信的手机号码。格式: - 国内短信:11 位手机号码,例如 15951955195。 - 国际 / 港澳台消息:国际区号 + 号码,例如 85200000000。 + * 支持对多个手机号码发送短信,手机号码之间以英文逗号(,)分隔。上限为 1000 个手机号码。批量调用相对于单条调用及时性稍有延迟。 **说明** + * 验证码类型短信,建议使用单独发送的方式。
+ */ + @JsonProperty("PhoneNumbers") + private String phoneNumbers; + + /** + * 是否必填:是
+ * 事例:阿里云
+ * 描述:短信签名名称。请在控制台 **签名管理** 页面 **签名名称** 一列查看。 **说明** 必须是已添加、并通过审核的短信签名。
+ */ + @JsonProperty("SignName") + private String signName; + + /** + * 是否必填:是
+ * 事例:SMS\_153055065
+ * 描述:短信模板 ID。请在控制台 **模板管理** 页面 **模板 CODE** 一列查看。 **说明** 必须是已添加、并通过审核的短信签名;且发送国际 / 港澳台消息时,请使用国际 / + * 港澳台短信模版。
+ */ + @JsonProperty("TemplateCode") + private String templateCode; + + /** + * 是否必填:否
+ * 事例:abcdefgh
+ * 描述:外部流水扩展字段。
+ */ + @JsonProperty("OutId") + private String outId; + + /** + * 是否必填:否
+ * 事例:90999
+ * 描述:上行短信扩展码,无特殊需要此字段的用户请忽略此字段。
+ */ + @JsonProperty("SmsUpExtendCode") + private String smsUpExtendCode; + + /** + * 是否必填:否
+ * 事例:{"code":"1111"}
+ * 描述:短信模板变量对应的实际值,JSON 格式。 **说明** 如果 JSON 中需要带换行符,请参照标准的 JSON 协议处理。
+ */ + @JsonProperty("TemplateParam") + private String templateParam; +} diff --git a/src/main/java/com/newyetai/sdk/sms/model/SendSmsResponse.java b/src/main/java/com/newyetai/sdk/sms/model/SendSmsResponse.java new file mode 100644 index 0000000..cb5b927 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/model/SendSmsResponse.java @@ -0,0 +1,16 @@ +package com.newyetai.sdk.sms.model; + +import lombok.NoArgsConstructor; + +/** + * 发送短信(单个/批量)响应体 + * + * @author Rey(leijiaping@newyetai.com) {@link undefined} + */ +@NoArgsConstructor +public class SendSmsResponse extends SmsResponse { + + /** **/ + private static final long serialVersionUID = -1884360556092571210L; + +} diff --git a/src/main/java/com/newyetai/sdk/sms/model/SmsResponse.java b/src/main/java/com/newyetai/sdk/sms/model/SmsResponse.java new file mode 100644 index 0000000..a0b9527 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/model/SmsResponse.java @@ -0,0 +1,40 @@ +package com.newyetai.sdk.sms.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.Data; + +import java.io.Serializable; + + +/** + * 短信响应体 + * + * @author Rey(leijiaping@newyetai.com) {@link undefined} + */ +@SuppressWarnings("serial") +@Data +public class SmsResponse implements Serializable{ + + /** + * 事例:OK
+ * 描述:请求状态码。 - 返回 OK 代表请求成功。 - + * 其他错误码详见[错误码列表](https://help.aliyun.com/document_detail/101346.html)。
+ */ + @JsonProperty("Code") + private String code; + + /** + * 事例:OK
+ * 描述:状态码的描述。
+ */ + @JsonProperty("Message") + private String message; + + /** + * 事例:F655A8D5-B967-440B-8683-DAD6FF8DE990
+ * 描述:请求 ID。
+ */ + @JsonProperty("RequestId") + private String requestId; +} diff --git a/src/main/java/com/newyetai/sdk/sms/model/SmsSendDetailResponse.java b/src/main/java/com/newyetai/sdk/sms/model/SmsSendDetailResponse.java new file mode 100644 index 0000000..02f973c --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/model/SmsSendDetailResponse.java @@ -0,0 +1,74 @@ +package com.newyetai.sdk.sms.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; + +/** + * 短信发送明细 + * + * @author Rey(leijiaping@newyetai.com) {@link undefined} + */ +public class SmsSendDetailResponse implements Serializable { + + /** + * + */ + private static final long serialVersionUID = -4473285026346918644L; + + /** + * 事例:【阿里云】验证码为:123,您正在登录,若非本人操作,请勿泄露
+ * 描述:短信内容。
+ */ + @JsonProperty("Content") + private String content; + + /** + * 事例:DELIVRD
+ * 描述:运营商短信状态码。 - 短信发送成功:DELIVRD。 - + * 短信发送失败:失败错误码请参考[错误码文档](https://help.aliyun.com/document_detail/101347.html)。
+ */ + @JsonProperty("ErrCode") + private String errCode; + + /** + * 事例:123
+ * 描述:外部流水扩展字段。
+ */ + @JsonProperty("OutId") + private String outId; + + /** + * 事例:15200000000
+ * 描述:接收短信的手机号码。
+ */ + @JsonProperty("PhoneNum") + private String phoneNum; + + /** + * 事例:2019-01-08 16:44:13
+ * 描述:短信接收日期和时间。
+ */ + @JsonProperty("ReceiveDate") + private String receiveDate; + + /** + * 事例:2019-01-08 16:44:10
+ * 描述:短信发送日期和时间。
+ */ + @JsonProperty("SendDate") + private String sendDate; + + /** + * 事例:3
+ * 描述:短信发送状态,包括: - 1:等待回执。 - 2:发送失败。 - 3:发送成功。
+ */ + @JsonProperty("SendStatus") + private Long sendStatus; + + /** + * 事例:SMS\_122310183
+ * 描述:短信模板 ID。
+ */ + @JsonProperty("TemplateCode") + private String templateCode; +} diff --git a/src/main/java/com/newyetai/sdk/sms/model/SmsTemplateResponse.java b/src/main/java/com/newyetai/sdk/sms/model/SmsTemplateResponse.java new file mode 100644 index 0000000..b78b66a --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/model/SmsTemplateResponse.java @@ -0,0 +1,20 @@ +package com.newyetai.sdk.sms.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * 短信模板响应体 + * @author Rey(leijiaping@newyetai.com) + *{@link undefined} + */ + public class SmsTemplateResponse extends SmsResponse{ + + /** **/ + private static final long serialVersionUID = -8499116525368789422L; + /** + * 事例:SMS\_152550005
+ * 描述:短信模板 CODE。您可以使用模板 CODE 通过 API 接口 ** QuerySmsTemplate** 或在控制台查看模板申请状态和结果。
+ */ + @JsonProperty("TemplateCode") + private String templateCode; + } \ No newline at end of file diff --git a/src/main/java/com/newyetai/sdk/sms/service/SdkSmsProvider.java b/src/main/java/com/newyetai/sdk/sms/service/SdkSmsProvider.java new file mode 100644 index 0000000..15701f7 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/service/SdkSmsProvider.java @@ -0,0 +1,32 @@ +package com.newyetai.sdk.sms.service; + +import com.newyetai.common.AlitaResult; +import com.newyetai.sdk.sms.constant.SmsProviderEnum; +import com.newyetai.sdk.sms.dto.ISendDTO; + +/** + * 短信服务提供者 + * + * @author sr on 2020-07-03 + */ +public interface SdkSmsProvider { + + /** + * 提供者类型 + * + * @return + * @author sr on 2020-07-03 + */ + SmsProviderEnum getType(); + + /** + * 发送短信 + * + * @param + * @param iSendDTO + * @return + * @author sr on 2020-07-03 + */ + AlitaResult send(ISendDTO iSendDTO); + +} diff --git a/src/main/java/com/newyetai/sdk/sms/service/SdkSmsService.java b/src/main/java/com/newyetai/sdk/sms/service/SdkSmsService.java new file mode 100644 index 0000000..2583479 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/service/SdkSmsService.java @@ -0,0 +1,90 @@ +package com.newyetai.sdk.sms.service; + +import com.newyetai.common.AlitaResult; +import com.newyetai.sdk.sms.dto.ISendDTO; +import com.newyetai.sdk.sms.dto.ITemplateCode; + +import java.util.Map; + +/** + * 短信 + * + * @author sr on 2020-07-02 + */ +public interface SdkSmsService { + + /** + * 发送短信(使用配置文件配置) + * + * @param + * @param iSendDTO 发送对象 + * @return success-false真实调用第三方未成功,未拿到返回值; + * success-true获取到第三方返回,data-true发送成功,data-false发送失败并返回失败原因(msg) + * @author sr on 2020-07-02 + */ + AlitaResult send(ISendDTO iSendDTO); + + /** + * 发送短信验证码 + * + * @param + * @param iTemplateCode 获取templateCodeKey 短信模版配置key,获取配置时内部会自动加上(sms)前缀;如配置文件中添加sms.someTemplate,此处配置someTemplate + * @param phone + * @param code 验证码 + * @return success-false真实调用第三方未成功,未拿到返回值; + * success-true获取到第三方返回,data-true发送成功,data-false发送失败并返回失败原因(msg) + * @author sr on 2020-07-02 + */ + AlitaResult sendVerificationCode(ITemplateCode iTemplateCode, String phone, String code); + + /** + * 发送短信验证码 + * + * @param + * @param iTemplateCode 获取templateCodeKey 短信模版配置key,获取配置时内部会自动加上(sms)前缀;如配置文件中添加sms.someTemplate,此处配置someTemplate + * @param phone + * @param code 验证码 + * @param signName 验证码签名 + * @return success-false真实调用第三方未成功,未拿到返回值; + * success-true获取到第三方返回,data-true发送成功,data-false发送失败并返回失败原因(msg) + * @author sr on 2020-07-02 + */ + AlitaResult sendVerificationCode(ITemplateCode iTemplateCode, String phone, String code, String signName); + + /** + * 发送短信验证码 + * + * @param + * @param templateCode 模版code + * @param phone + * @param code 验证码 + * @return success-false真实调用第三方未成功,未拿到返回值; + * success-true获取到第三方返回,data-true发送成功,data-false发送失败并返回失败原因(msg) + * @author sr on 2020-07-02 + */ + AlitaResult sendVerificationCode(String templateCode, String phone, String code); + + /** + * 发送短信 + * @param iTemplateCode 短信模版配置key,获取配置时内部会自动加上(sms)前缀;如配置文件中添加sms.someTemplate,此处配置someTemplate + * @param phone + * @param params + * @return success-false真实调用第三方未成功,未拿到返回值; + * success-true获取到第三方返回,data-true发送成功,data-false发送失败并返回失败原因(msg) + * @author sr on 2020-07-02 + */ + AlitaResult sendSimple(ITemplateCode iTemplateCode, String phone, Map params); + + /** + * 发送短信 + * @param templateCode 模版code + * @param phone + * @param params + * @return success-false真实调用第三方未成功,未拿到返回值; + * success-true获取到第三方返回,data-true发送成功,data-false发送失败并返回失败原因(msg) + * @author sr on 2020-07-02 + */ + AlitaResult sendSimple(String templateCode, String phone, Map params); + + +} diff --git a/src/main/java/com/newyetai/sdk/sms/service/impl/SdkSmsServiceImpl.java b/src/main/java/com/newyetai/sdk/sms/service/impl/SdkSmsServiceImpl.java new file mode 100644 index 0000000..19675d8 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/service/impl/SdkSmsServiceImpl.java @@ -0,0 +1,88 @@ +package com.newyetai.sdk.sms.service.impl; + +import com.google.common.collect.Maps; +import com.newyetai.common.AlitaResult; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.sdk.sms.config.SmsConfig; +import com.newyetai.sdk.sms.constant.SmsProviderEnum; +import com.newyetai.sdk.sms.dto.*; +import com.newyetai.sdk.sms.service.SdkSmsProvider; +import com.newyetai.sdk.sms.service.SdkSmsService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; + +/** + * @author sr on 2020-07-02 + */ +@Service +public class SdkSmsServiceImpl implements SdkSmsService { + @Autowired + private SmsConfig smsConfig; + + private final Map smsProviders = Maps.newHashMap(); + + @Autowired + SdkSmsServiceImpl(List providers) { + providers.forEach(provider -> smsProviders.put(provider.getType(), provider)); + } + + + @Override + public AlitaResult send(ISendDTO iSendDTO) { + Assert.isTrue(Boolean.TRUE.equals(smsConfig.getEnable()), "暂不支持短信功能"); + SdkSmsProvider sdkSmsProvider = smsProviders.get(iSendDTO.getSmsProvider()); + // 默认阿里云 + if (sdkSmsProvider == null) { + sdkSmsProvider = smsProviders.get(SmsProviderEnum.ALIYAN); + } + + return sdkSmsProvider.send(iSendDTO); + } + + @Override + public AlitaResult sendVerificationCode(ITemplateCode iTemplateCode, String phone, + String code) { + return this.sendVerificationCode(iTemplateCode, phone, code, null); + } + + @Override + public AlitaResult sendVerificationCode(ITemplateCode iTemplateCode, String phone, String code, String signName) { + VerificationCodeSendDTO sendDto = VerificationCodeSendDTO.builder().phone(phone) + .templateCodeKey(iTemplateCode.getTemplateCodeKey()) + .parameters(new VerificationCodeParamDTO(code)) + .signName(signName) + .build(); + return this.send(sendDto); + } + + @Override + public AlitaResult sendSimple(ITemplateCode iTemplateCode, String phone, + Map params) { + SimpleSendDTO sendDto = + SimpleSendDTO.builder().templateCodeKey(iTemplateCode.getTemplateCodeKey()).phone(phone) + .parameters(params).build(); + return this.send(sendDto); + } + + @Override + public AlitaResult sendVerificationCode(String templateCode, String phone, + String code) { + VerificationCodeSendDTO sendDto = VerificationCodeSendDTO.builder().phone(phone) + .templateCode(templateCode).parameters(new VerificationCodeParamDTO(code)) + .build(); + return this.send(sendDto); + } + + @Override + public AlitaResult sendSimple(String templateCode, String phone, + Map params) { + SimpleSendDTO sendDto = SimpleSendDTO.builder().templateCode(templateCode).phone(phone) + .parameters(params).build(); + return this.send(sendDto); + } + + +} diff --git a/src/main/java/com/newyetai/sdk/sms/service/provider/AliyunSmsInvoker.java b/src/main/java/com/newyetai/sdk/sms/service/provider/AliyunSmsInvoker.java new file mode 100644 index 0000000..9f13acd --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/service/provider/AliyunSmsInvoker.java @@ -0,0 +1,67 @@ +package com.newyetai.sdk.sms.service.provider; + +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.aliyuncs.CommonRequest; +import com.aliyuncs.CommonResponse; +import com.aliyuncs.IAcsClient; +import com.aliyuncs.exceptions.ClientException; +import com.aliyuncs.http.MethodType; +import com.newyetai.common.AlitaResult; +import com.newyetai.common.annotation.CheckAndMock; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.sdk.common.constant.SdkConstants; +import com.newyetai.sdk.sms.config.SmsConfig; +import com.newyetai.sdk.sms.constant.AliSmsActionEnum; + +import lombok.extern.slf4j.Slf4j; + +/** + * 短信sms调用 + * + * @author on 2019-11-05 + */ +@Service +@Slf4j +public class AliyunSmsInvoker { + + @Autowired + private IAcsClient client; + + @SuppressWarnings("unchecked") + @CheckAndMock(mockClass = MockAliyunSmsInvoker.class, propertyPrefix = "sms") + public AlitaResult invoke(SmsConfig smsConfig, AliSmsActionEnum action, Object params, + Class responseClazz) { + + CommonRequest request = new CommonRequest(); + request.setMethod(MethodType.POST); + request.setDomain(smsConfig.getDomain()); + request.setVersion(smsConfig.getVersion()); + request.setAction(action.getValue()); + + if (params instanceof Map) { + ((Map) params).forEach(request::putQueryParameter); + } else { + Map paramMap = JsonUtils.objToClassObj(params, Map.class); + paramMap.forEach(request::putQueryParameter); + + } + try { + log.info("sendSms request:{}", params); + CommonResponse response = client.getCommonResponse(request); + String data = response.getData(); + log.info("sendSms reponse:{}", data); + return AlitaResult.success(JsonUtils.toObject(data, responseClazz)); + } catch (ClientException e) { + return AlitaResult.error(SdkConstants.SDK_INVOKE_NOT_REACH_CODE, e.getMessage()); + } catch (Exception e) { + return AlitaResult.error(SdkConstants.SDK_HTTP_INVOKE_ERROR_CODE, + StringUtils.join(SdkConstants.SMS_CODE, SdkConstants.INVOKE_FAIL, e.getMessage())); + } + } + +} diff --git a/src/main/java/com/newyetai/sdk/sms/service/provider/AliyunSmsProvider.java b/src/main/java/com/newyetai/sdk/sms/service/provider/AliyunSmsProvider.java new file mode 100644 index 0000000..e62a815 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/service/provider/AliyunSmsProvider.java @@ -0,0 +1,91 @@ +package com.newyetai.sdk.sms.service.provider; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.util.EnvironmentUtils; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.sdk.common.constant.SdkConstants; +import com.newyetai.sdk.sms.config.SmsConfig; +import com.newyetai.sdk.sms.constant.AliSmsActionEnum; +import com.newyetai.sdk.sms.constant.SmsConstants; +import com.newyetai.sdk.sms.constant.SmsProviderEnum; +import com.newyetai.sdk.sms.dto.ISendDTO; +import com.newyetai.sdk.sms.model.SendSms; +import com.newyetai.sdk.sms.model.SendSmsResponse; +import com.newyetai.sdk.sms.service.SdkSmsProvider; +import com.newyetai.sdk.sms.util.SmsUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * 阿里云服务商提供者 + * + * @author sr on 2020-07-03 + */ +@Service +public class AliyunSmsProvider implements SdkSmsProvider { + + @Autowired + private SmsConfig smsConfig; + + @Autowired + private AliyunSmsInvoker aliyunSmsInvoker; + + @Override + public SmsProviderEnum getType() { + return SmsProviderEnum.ALIYAN; + } + + @Override + public AlitaResult send(ISendDTO iSendDTO) { + // 处理模版 + String templateCode = this.dealTemplateCode(iSendDTO); + if (templateCode == null) { + return AlitaResult.error(SdkConstants.SDK_INVOKE_NOT_REACH_CODE, + SmsConstants.TEMPLATE_CODE_EMPTY); + } + SendSms sendSms = + SendSms.builder().phoneNumbers(iSendDTO.getPhone()).templateCode(templateCode) + .templateParam(JsonUtils.toJsonString(iSendDTO.getParameters())) + .signName(StringUtils.isEmpty(iSendDTO.getSignName()) ? smsConfig.getSignName() + : iSendDTO.getSignName()) + .build(); + + AlitaResult result = + aliyunSmsInvoker.invoke(smsConfig, AliSmsActionEnum.SEND_SMS, sendSms, + SendSmsResponse.class); + // 失败,success-false + if (!result.getSuccess()) { + return AlitaResult.error(result.getCode(), result.getMsg()); + } + SendSmsResponse responseData = result.getData(); + // sms状态码成功,success-true,data-true + if (SmsConstants.SUCCESS_CODE.equals(responseData.getCode())) { + return AlitaResult.success(Boolean.TRUE); + } + // sms状态码失败,success-true,data-false + return AlitaResult.success(responseData.getMessage(), Boolean.FALSE); + } + + /** + * 处理短信发送模版 + * @param iSendDTO + * @return + * @author sr on 2021-06-16 + */ + private String dealTemplateCode(ISendDTO iSendDTO) { + String templateCode = iSendDTO.getTemplateCode(); + String templateCodeKey = iSendDTO.getTemplateCodeKey(); + // 模版为空 且 模版属性键不为空,去环境配置中获取模版 + if (StringUtils.isBlank(templateCode) && StringUtils.isNotBlank(templateCodeKey)) { + templateCode = EnvironmentUtils + .getProperty(String.join(CommonConstants.POINT, SmsConfig.PREFIX, templateCodeKey)); + } + if (StringUtils.isBlank(templateCode)) { + return null; + } + return templateCode; + } + +} diff --git a/src/main/java/com/newyetai/sdk/sms/service/provider/MockAliyunSmsInvoker.java b/src/main/java/com/newyetai/sdk/sms/service/provider/MockAliyunSmsInvoker.java new file mode 100644 index 0000000..e5a72de --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/service/provider/MockAliyunSmsInvoker.java @@ -0,0 +1,34 @@ +package com.newyetai.sdk.sms.service.provider; + +import org.springframework.stereotype.Service; + +import com.newyetai.common.AlitaResult; +import com.newyetai.sdk.sms.config.SmsConfig; +import com.newyetai.sdk.sms.constant.AliSmsActionEnum; +import com.newyetai.sdk.sms.constant.SmsConstants; +import com.newyetai.sdk.sms.model.SendSmsResponse; + +import lombok.extern.slf4j.Slf4j; + +/** + * 模拟短信调用 + * + * @author sr on 2020-05-28 + */ +@Service +@Slf4j +public class MockAliyunSmsInvoker { + + @SuppressWarnings("unchecked") + public AlitaResult invoke(SmsConfig smsConfig, AliSmsActionEnum action, Object params, + Class responseClazz) { + log.info("mock sms params:{}", params); + if (action == AliSmsActionEnum.SEND_SMS) { + SendSmsResponse response = new SendSmsResponse(); + response.setCode(SmsConstants.SUCCESS_CODE); + return (AlitaResult) AlitaResult.success(response); + } + return null; + } + +} diff --git a/src/main/java/com/newyetai/sdk/sms/util/SmsUtils.java b/src/main/java/com/newyetai/sdk/sms/util/SmsUtils.java new file mode 100644 index 0000000..e2f572f --- /dev/null +++ b/src/main/java/com/newyetai/sdk/sms/util/SmsUtils.java @@ -0,0 +1,26 @@ +package com.newyetai.sdk.sms.util; + +import org.springframework.stereotype.Component; + +import com.newyetai.sdk.sms.service.SdkSmsService; + +/** + * sms工具类 + * + * @author sr on 2020-07-03 + */ +@Component +public class SmsUtils { + + private static SdkSmsService sdkSmsService; + + private SmsUtils(SdkSmsService sdkSmsService) { + SmsUtils.sdkSmsService = sdkSmsService; + } + + public static SdkSmsService getService() { + return sdkSmsService; + } + + +} diff --git a/src/main/java/com/newyetai/sdk/ssb/SsbProperties.java b/src/main/java/com/newyetai/sdk/ssb/SsbProperties.java new file mode 100644 index 0000000..9ebac56 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/ssb/SsbProperties.java @@ -0,0 +1,87 @@ +package com.newyetai.sdk.ssb; + +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.security.NoSuchAlgorithmException; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import com.newyetai.common.exception.BusinessException; +import com.newyetai.sdk.ssb.util.AESEncryption; +import com.newyetai.sdk.ssb.util.SsbRsaUtils; + +/** + * 随申办配置 + * + */ +@ConfigurationProperties(prefix = SsbProperties.PREFIX) +@Data +@Component +@NoArgsConstructor +public class SsbProperties { + + /** + * 随申办配置前缀 + **/ + public static final String PREFIX = "ssb"; + + /** 开发商标识(在区运营服务平台注册开发商后获得) **/ + private String clientId; + private String clientSecret; + /** 接口标识(申请调用 API 后获得) **/ + private String apiId; + /** AES 密钥(使用 RSA 公钥加密) **/ + private String aesKey; + /** AES 偏移量(使用 RSA 公钥加密) **/ + private String aesIv; + /** 公钥 **/ + private String pubKey; + /** 网关地址 **/ + private String gatewayUrl; + /** sm2公钥 **/ + private String sm2PublicKey; + /** sm2私钥 **/ + private String sm2PrivateKey; + private String appKey; + private String appSecret; + + public static AESEncryption aESEncryption = null; + public static String enAesKey = null; + public static String enAesIv = null; + + public AESEncryption getAESEncryption() { + if (aESEncryption == null) { + try { + aESEncryption = new AESEncryption(this.getAesKey(), this.getAesIv()); + } catch (NoSuchAlgorithmException e) { + throw new BusinessException("随申办aes配置错误:" + e.getMessage()); + } + } + return aESEncryption; + } + + public String getEnAesKey() { + if (enAesKey == null) { + try { + enAesKey = SsbRsaUtils.encryptByPublicKey(this.getPubKey(), this.getAesKey()); + } catch (Exception e) { + throw new BusinessException("随申办aesKey配置错误:" + e.getMessage()); + } + } + return enAesKey; + } + + public String getEnAesIv() { + if (enAesIv == null) { + try { + enAesIv = SsbRsaUtils.encryptByPublicKey(this.getPubKey(), this.getAesIv()); + } catch (Exception e) { + throw new BusinessException("随申办aesIv配置错误:" + e.getMessage()); + } + } + return enAesIv; + } + +} diff --git a/src/main/java/com/newyetai/sdk/ssb/constant/SsbConstants.java b/src/main/java/com/newyetai/sdk/ssb/constant/SsbConstants.java new file mode 100644 index 0000000..9fc0a30 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/ssb/constant/SsbConstants.java @@ -0,0 +1,11 @@ +package com.newyetai.sdk.ssb.constant; + +public interface SsbConstants { + + /** 成功编码 **/ + Integer SUC_CODE = 200; + + /** 用户类型:身份证 **/ + Integer CERT_TYPE_ID_CARD = 1; + +} diff --git a/src/main/java/com/newyetai/sdk/ssb/constant/SsbPlatformEnum.java b/src/main/java/com/newyetai/sdk/ssb/constant/SsbPlatformEnum.java new file mode 100644 index 0000000..a0e4677 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/ssb/constant/SsbPlatformEnum.java @@ -0,0 +1,24 @@ +package com.newyetai.sdk.ssb.constant; + +public enum SsbPlatformEnum{ + /** 随申办APP **/ + ESHIMIN("eshimin") , + /** 微信小程序 **/ + WEIXINMINI("weixinmini"), + /** 微信公众号 **/ + WEIXINMP("weixinmp"), + /** 支付宝小程序 **/ + ALIPAYMINI("alipaymini"), + /** 支付宝生活号 **/ + ALIPAYFUWU("alipayfuwu"), + ; + + SsbPlatformEnum(String type){ + this.type = type; + } + private String type; + + public String getType() { + return type; + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/sdk/ssb/dto/SsbAppAccessTokenDTO.java b/src/main/java/com/newyetai/sdk/ssb/dto/SsbAppAccessTokenDTO.java new file mode 100644 index 0000000..42509b8 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/ssb/dto/SsbAppAccessTokenDTO.java @@ -0,0 +1,32 @@ +package com.newyetai.sdk.ssb.dto; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class SsbAppAccessTokenDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 2742615764546777525L; + + /** 接口获取授权后的 access_token。(2 小时有效) **/ + private String access_token; + /** 用来刷新 access_token 的有效期(24 小时有效, 用户必须重新进入授权入口之后才可以延长refresh_token 有效期) **/ + private String refresh_token; + /** access_token 的生命周期,单位是毫秒数(2 小时有效,客户端自行计时) 。 **/ + private String scope; + /** token 的类型 **/ + private String token_type; + /** 当前获取的可操作类型,目前只提供 read **/ + private String expires_in; + /** 用户标识位 **/ + private String username; + +} diff --git a/src/main/java/com/newyetai/sdk/ssb/dto/SsbAppAccessTokenReq.java b/src/main/java/com/newyetai/sdk/ssb/dto/SsbAppAccessTokenReq.java new file mode 100644 index 0000000..ce4dca2 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/ssb/dto/SsbAppAccessTokenReq.java @@ -0,0 +1,39 @@ +package com.newyetai.sdk.ssb.dto; + +import com.newyetai.sdk.common.dto.ISdkRequest; +import com.newyetai.sdk.wechat.constants.WechatConstants; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class SsbAppAccessTokenReq implements ISdkRequest{ + + /** **/ + private static final long serialVersionUID = 2742615764546777525L; + + /** 申请应用时分配的 AppKey。 **/ + private String client_id; + /** 调用 authorize 获得的 code 值 **/ + private String code; + /** 13 位系统时间戳(链接存在时效性,时间戳必须和北京时间一致 保证每次时间戳都是最新的,时间上下容错五分钟否则链接失效) **/ + private String timestamp; + /** 签名(client_id + client_secret + code+timestamp ) **/ + private String sign; + + @Override + public Class getResponseClass() { + return SsbAppAccessTokenDTO.class; + } + + @Override + public String getUri() { + return "https://api.eshimin.com/newOauth/accessToken"; + } + +} diff --git a/src/main/java/com/newyetai/sdk/ssb/dto/SsbAppReq.java b/src/main/java/com/newyetai/sdk/ssb/dto/SsbAppReq.java new file mode 100644 index 0000000..c372c56 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/ssb/dto/SsbAppReq.java @@ -0,0 +1,14 @@ +package com.newyetai.sdk.ssb.dto; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +import lombok.Data; + +@Data +public abstract class SsbAppReq { + + /** 请求地址 **/ + @JsonIgnore + private String url; + +} diff --git a/src/main/java/com/newyetai/sdk/ssb/dto/SsbAppRes.java b/src/main/java/com/newyetai/sdk/ssb/dto/SsbAppRes.java new file mode 100644 index 0000000..9bed3fa --- /dev/null +++ b/src/main/java/com/newyetai/sdk/ssb/dto/SsbAppRes.java @@ -0,0 +1,22 @@ +package com.newyetai.sdk.ssb.dto; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class SsbAppRes implements Serializable{ + + /** **/ + private static final long serialVersionUID = -8065958516522176350L; + + public static final String SUC_CODE= "0000"; + + private String data; + private String code; + +} diff --git a/src/main/java/com/newyetai/sdk/ssb/dto/SsbAppUserInfoDTO.java b/src/main/java/com/newyetai/sdk/ssb/dto/SsbAppUserInfoDTO.java new file mode 100644 index 0000000..f8b589b --- /dev/null +++ b/src/main/java/com/newyetai/sdk/ssb/dto/SsbAppUserInfoDTO.java @@ -0,0 +1,39 @@ +package com.newyetai.sdk.ssb.dto; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class SsbAppUserInfoDTO implements Serializable{ + + /** 已实名 **/ + public static final Integer AUTHENTICATIED = 1; + + /** **/ + private static final long serialVersionUID = 2742615764546777525L; + + /** 是否实名 0.非实名 1.实名 **/ + private Integer status; + /** 头像地址 **/ + private String head_pic; + /** 社保卡号 **/ + private String sscard; + /** 用户姓名 **/ + private String name; + /** 用户 ID **/ + private String userId; + /** 身份证号码 **/ + private String idcard; + /** 用户名 **/ + private String username; + /** 手机号码 **/ + private String mobile; + +} diff --git a/src/main/java/com/newyetai/sdk/ssb/dto/SsbAppUserInfoReq.java b/src/main/java/com/newyetai/sdk/ssb/dto/SsbAppUserInfoReq.java new file mode 100644 index 0000000..2f4aae1 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/ssb/dto/SsbAppUserInfoReq.java @@ -0,0 +1,41 @@ +package com.newyetai.sdk.ssb.dto; + +import com.newyetai.sdk.common.dto.ISdkRequest; +import com.newyetai.sdk.wechat.constants.WechatConstants; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class SsbAppUserInfoReq implements ISdkRequest{ + + /** **/ + private static final long serialVersionUID = 2742615764546777525L; + + /** 申请应用时分配的 AppKey。 **/ + private String client_id; + /** 授权令牌(2 小时有效) **/ + private String access_token; + /** 用户标识位 **/ + private String username; + /** 13 位系统时间戳(链接存在时效性,时间戳必须和北京时间一致 保证每次时间戳都是最新的,时间上下容错五分钟否则链接失效) **/ + private String timestamp; + /** 签名(client_id + client_secret + code+timestamp ) **/ + private String sign; + + @Override + public Class getResponseClass() { + return SsbAppUserInfoDTO.class; + } + + @Override + public String getUri() { + return "https://api.eshimin.com/newOauth/userInfo"; + } + +} diff --git a/src/main/java/com/newyetai/sdk/ssb/dto/SsbRes.java b/src/main/java/com/newyetai/sdk/ssb/dto/SsbRes.java new file mode 100644 index 0000000..1aa192f --- /dev/null +++ b/src/main/java/com/newyetai/sdk/ssb/dto/SsbRes.java @@ -0,0 +1,25 @@ +package com.newyetai.sdk.ssb.dto; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class SsbRes implements Serializable { + + /** **/ + private static final long serialVersionUID = 8271846024223081240L; + + /** 返回编码,200 表示成功,其他表示接口调用错误 **/ + private Integer status; + /** 错误信息 **/ + private String message; + /** AES 加密后的业务数据,使用对应密钥解密后,获得业务返回参数内容 **/ + private String data; + + +} diff --git a/src/main/java/com/newyetai/sdk/ssb/dto/SsbUserDTO.java b/src/main/java/com/newyetai/sdk/ssb/dto/SsbUserDTO.java new file mode 100644 index 0000000..e6b480e --- /dev/null +++ b/src/main/java/com/newyetai/sdk/ssb/dto/SsbUserDTO.java @@ -0,0 +1,56 @@ +package com.newyetai.sdk.ssb.dto; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class SsbUserDTO implements Serializable { + + /** **/ + private static final long serialVersionUID = 315891518492560183L; + + /** 是 用户类型(个人) **/ + private String zwdtsw_user_type; + /** 是 用户主键 UUID **/ + private String zwdtsw_user_id; + /** 邮箱 **/ + private String zwdtsw_email; + /** 用户姓名 初级及实名以上用户有值 **/ + private String zwdtsw_name; + /** 是 用户名 **/ + private String zwdtsw_account; + /** 身份证号 初级及实名以上用户有值 **/ + private String zwdtsw_cert_id; + /** 证件类型 身份证、中国护照、普护照、台湾居民通行证、港澳通行证等 **/ + private String zwdtsw_cert_type; + /** 手机号码 **/ + private String zwdtsw_link_phone; + /** 家庭住址 **/ + private String zwdtsw_link_address; + /** 邮政编码 **/ + private String zwdtsw_zip_code; + /** 是否激活(激活/未激活) 默认都是激活 **/ + private String zwdtsw_user_status; + /** 是 初级身份证实名验证状态(实名通过/实名未通过)初级实名过的用户 **/ + private String zwdtsw_after_certification; + /** 注册时间 **/ + private String zwdtsw_reg_time; + /** 更新时间 **/ + private String zwdtsw_last_update; + /** 是个人用户等级(法人无该字段)未实名、初级、中级、高级 **/ + private String zwdtsw_user_CAcert; + /** 是 个人用户等级字典用户等级0,1,2,3 分别表示未实名,初级,中级,高级 **/ + private Integer usergrade; + /** 是 用户类型字典 默认身份证 1("1", "居民身份证""414", "普通护照"(对应pc 总门户的中国护照)"3", "外国护照""513", "往来港澳通行证""517", "往来台湾通行证""516","港澳居民来往内地通行证""511", "台湾居民来往内地通行证"**/ + private Integer certType; + /** 姓名加身份证号散列值 (唯一) **/ + private String certKey; + /** 国籍默认为中国 **/ + private String citizenship; + +} diff --git a/src/main/java/com/newyetai/sdk/ssb/dto/SsbUserDataDTO.java b/src/main/java/com/newyetai/sdk/ssb/dto/SsbUserDataDTO.java new file mode 100644 index 0000000..f05c1c0 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/ssb/dto/SsbUserDataDTO.java @@ -0,0 +1,21 @@ +package com.newyetai.sdk.ssb.dto; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class SsbUserDataDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = -576144664556081564L; + + private String code; + private String msg; + private SsbUserDTO data; + +} diff --git a/src/main/java/com/newyetai/sdk/ssb/dto/SsbUserReq.java b/src/main/java/com/newyetai/sdk/ssb/dto/SsbUserReq.java new file mode 100644 index 0000000..bcf97d8 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/ssb/dto/SsbUserReq.java @@ -0,0 +1,26 @@ +package com.newyetai.sdk.ssb.dto; + +import java.io.Serializable; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class SsbUserReq implements Serializable{ + + /** **/ + private static final long serialVersionUID = -1531708833509490088L; + + + /** 用户令牌,2.2 跳转第三方应用时传递 **/ + @JsonProperty("access_token") + private String accessToken; + +} diff --git a/src/main/java/com/newyetai/sdk/ssb/service/SsbInvoker.java b/src/main/java/com/newyetai/sdk/ssb/service/SsbInvoker.java new file mode 100644 index 0000000..7cdc156 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/ssb/service/SsbInvoker.java @@ -0,0 +1,160 @@ +package com.newyetai.sdk.ssb.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.sdk.common.constant.SdkConstants; +import com.newyetai.sdk.common.dto.DefaultSdkInvokeLogDTO; +import com.newyetai.sdk.common.dto.ISdkRequest; +import com.newyetai.sdk.ssb.SsbProperties; +import com.newyetai.sdk.ssb.constant.SsbConstants; +import com.newyetai.sdk.ssb.dto.SsbAppAccessTokenDTO; +import com.newyetai.sdk.ssb.dto.SsbAppAccessTokenReq; +import com.newyetai.sdk.ssb.dto.SsbAppRes; +import com.newyetai.sdk.ssb.dto.SsbAppUserInfoDTO; +import com.newyetai.sdk.ssb.dto.SsbAppUserInfoReq; +import com.newyetai.sdk.ssb.dto.SsbRes; +import com.newyetai.sdk.ssb.dto.SsbUserDataDTO; +import com.newyetai.sdk.ssb.dto.SsbUserReq; +import com.newyetai.sdk.ssb.util.SM2Utils; +import com.newyetai.sdk.ssb.util.SsbRsaUtils; + +import lombok.extern.slf4j.Slf4j; + +@Service +@Slf4j +public class SsbInvoker { + + private RestTemplate restTemplate = new RestTemplate(); + + @Autowired + private SsbProperties ssbProperties; + + public AlitaResult getUser(SsbUserReq reqDTO) { + String timestamp = String.valueOf(System.currentTimeMillis()); + String clientId = ssbProperties.getClientId(); + String clientSecret = ssbProperties.getClientSecret(); + String sign = SsbRsaUtils.encryptMd5(clientId + timestamp + clientSecret); + HttpHeaders headers = new HttpHeaders(); + headers.set("client-id", clientId); + headers.set("api-id", ssbProperties.getApiId()); + headers.set("sign", sign); + headers.set("timestamp", timestamp); + try { + headers.set("aes-key", ssbProperties.getEnAesKey()); + headers.set("aes-iv", ssbProperties.getEnAesIv()); + } catch (Exception e) { + return AlitaResult.error(SdkConstants.SDK_INVOKE_NOT_REACH_CODE, + "随申办加密aes失败:" + e.getMessage()); + } + // headers.setContentType(MediaType.APPLICATION_JSON); + String encryptBodyStr; + SsbRes ssbRes = null; + try { + try { + encryptBodyStr = + ssbProperties.getAESEncryption().encrypt(JsonUtils.toDefaultJsonString(reqDTO)); + } catch (Exception e) { + log.info("随申办参数加密失败:", e); + return AlitaResult.error(SdkConstants.SDK_INVOKE_NOT_REACH_CODE, + "随申办参数加密失败:" + e.getMessage()); + } + HttpEntity request = new HttpEntity<>(encryptBodyStr, headers); + try { + log.debug("ssb request httpentity:{}", request); + ssbRes = + restTemplate.postForObject(ssbProperties.getGatewayUrl(), request, SsbRes.class); + } catch (Exception e) { + log.info("ssb rest error:", e); + return AlitaResult.error(SdkConstants.SDK_HTTP_INVOKE_ERROR_CODE, e.getMessage()); + } + if (SsbConstants.SUC_CODE.equals(ssbRes.getStatus())) { + try { + String responseDtoStr = ssbProperties.getAESEncryption().decrypt(ssbRes.getData()); + return AlitaResult.success(JsonUtils.toObject(responseDtoStr, SsbUserDataDTO.class)); + } catch (Exception e) { + return AlitaResult.error(SdkConstants.SDK_RESPONSE_CONVERT_ERROR_CODE, + "随申办参数解密失败:" + e.getMessage()); + } + } else { + return AlitaResult.error(SdkConstants.SDK_HTTP_INVOKE_RESPONSE_FAIL_CODE, + ssbRes.getMessage()); + } + } finally { + log.info("ssb user invoke:{}", + JsonUtils + .toJsonString( + DefaultSdkInvokeLogDTO.builder().requestData(reqDTO).responseData(ssbRes) + .build())); + } + } + + + public SsbAppAccessTokenDTO getAppAccessToken(String authCode) { + String timestamp = String.valueOf(System.currentTimeMillis()); + String sign = SM2Utils.sign(ssbProperties.getSm2PrivateKey(), + ssbProperties.getAppKey() + ssbProperties.getAppSecret() + authCode + timestamp, + ssbProperties.getAppKey()); + SsbAppAccessTokenReq ssbAppAccessTokenReq = + SsbAppAccessTokenReq.builder().client_id(ssbProperties.getAppKey()).code(authCode) + .timestamp(timestamp).sign(sign).build(); + return executeApp(ssbAppAccessTokenReq); + } + + public RES executeApp(ISdkRequest req) { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + HttpEntity httpEntity = new HttpEntity<>(req, headers); + SsbAppRes ssbAppRes = null; + try { + ssbAppRes = + restTemplate.postForObject(req.getUri(), httpEntity, + SsbAppRes.class); + String code = ssbAppRes.getCode(); + Assert.isTrue(SsbAppRes.SUC_CODE.equals(code), code); + String data = ssbAppRes.getData(); + return JsonUtils.toObject(SM2Utils.sm2Decrypt(ssbProperties.getSm2PrivateKey(), data), + req.getResponseClass()); + } catch (Exception e) { + log.info("ssb app err:", e); + throw new BusinessException("随申办app调用失败:" + e.getMessage()); + } finally { + log.info("ssb app invoke:{}", + JsonUtils + .toJsonString( + DefaultSdkInvokeLogDTO.builder().requestData(req) + .responseData(ssbAppRes) + .build())); + } + } + + + public SsbAppUserInfoDTO getAppUser(SsbAppAccessTokenDTO accessTokenDTO) { + String accessToken = accessTokenDTO.getAccess_token(); + String username = accessTokenDTO.getUsername(); + String timestamp = String.valueOf(System.currentTimeMillis()); + String sign = SM2Utils.sign(ssbProperties.getSm2PrivateKey(), + ssbProperties.getAppKey() + ssbProperties.getAppSecret() + accessToken + username + + timestamp, + ssbProperties.getAppKey()); + SsbAppUserInfoReq req = + SsbAppUserInfoReq.builder().client_id(ssbProperties.getAppKey()).access_token(accessToken) + .username(username).timestamp(timestamp).sign(sign).build(); + return executeApp(req); + } + + public SsbAppUserInfoDTO getAppUser(String authCode) { + SsbAppAccessTokenDTO accessTokenDTO = this.getAppAccessToken(authCode); + return this.getAppUser(accessTokenDTO); + + } + +} diff --git a/src/main/java/com/newyetai/sdk/ssb/util/AESEncryption.java b/src/main/java/com/newyetai/sdk/ssb/util/AESEncryption.java new file mode 100644 index 0000000..d030e51 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/ssb/util/AESEncryption.java @@ -0,0 +1,62 @@ +package com.newyetai.sdk.ssb.util; + + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.nio.charset.StandardCharsets; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; +import java.security.spec.X509EncodedKeySpec; +import java.util.Base64; + + +public class AESEncryption { + private static final String AES_ALGORITHM = "AES"; + private static final String AES_TRANSFORMATION = "AES/CBC/PKCS5Padding"; + + private SecretKeySpec secretKeySpec; + private IvParameterSpec ivParameterSpec; + + public AESEncryption(String aesKey, String aesIV) throws NoSuchAlgorithmException { + byte[] keyBytes = aesKey.getBytes(StandardCharsets.UTF_8); + byte[] ivBytes = aesIV.getBytes(StandardCharsets.UTF_8); + + // 仅取前16个字节 + byte[] key = new byte[16]; + System.arraycopy(keyBytes, 0, key, 0, 16); + + byte[] iv = new byte[16]; + System.arraycopy(ivBytes, 0, iv, 0, 16); + + secretKeySpec = new SecretKeySpec(key, AES_ALGORITHM); + ivParameterSpec = new IvParameterSpec(iv); + } + + public String encrypt(String plainText) throws Exception{ + Cipher cipher = Cipher.getInstance(AES_TRANSFORMATION); + cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec); + + byte[] encryptedBytes = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8)); + return Base64.getEncoder().encodeToString(encryptedBytes); + } + + public String decrypt(String encryptedText) + throws Exception { + Cipher cipher = Cipher.getInstance(AES_TRANSFORMATION); + cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec); + + byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedText)); + return new String(decryptedBytes, StandardCharsets.UTF_8); + } + + +} + + diff --git a/src/main/java/com/newyetai/sdk/ssb/util/Cipher.java b/src/main/java/com/newyetai/sdk/ssb/util/Cipher.java new file mode 100644 index 0000000..ded9724 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/ssb/util/Cipher.java @@ -0,0 +1,88 @@ +package com.newyetai.sdk.ssb.util; + +import java.math.BigInteger; +import org.bouncycastle.crypto.AsymmetricCipherKeyPair; +import org.bouncycastle.crypto.digests.SM3Digest; +import org.bouncycastle.crypto.params.ECPrivateKeyParameters; +import org.bouncycastle.crypto.params.ECPublicKeyParameters; +import org.bouncycastle.math.ec.ECPoint; + +public class Cipher { + private int ct = 1; + + private ECPoint p2; + + private SM3Digest sm3keybase; + + private SM3Digest sm3c3; + + private byte[] key = new byte[32]; + + private byte keyOff = 0; + + private void Reset() { + this.sm3keybase = new SM3Digest(); + this.sm3c3 = new SM3Digest(); + byte[] p = Util.byteConvert32Bytes(this.p2.getX().toBigInteger()); + this.sm3keybase.update(p, 0, p.length); + this.sm3c3.update(p, 0, p.length); + p = Util.byteConvert32Bytes(this.p2.getY().toBigInteger()); + this.sm3keybase.update(p, 0, p.length); + this.ct = 1; + NextKey(); + } + + private void NextKey() { + SM3Digest sm3keycur = new SM3Digest(this.sm3keybase); + sm3keycur.update((byte)(this.ct >> 24 & 0xFF)); + sm3keycur.update((byte)(this.ct >> 16 & 0xFF)); + sm3keycur.update((byte)(this.ct >> 8 & 0xFF)); + sm3keycur.update((byte)(this.ct & 0xFF)); + sm3keycur.doFinal(this.key, 0); + this.keyOff = 0; + this.ct++; + } + + public ECPoint Init_enc(SM2 sm2, ECPoint userKey) { + AsymmetricCipherKeyPair key = sm2.ecc_key_pair_generator.generateKeyPair(); + ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters)key.getPrivate(); + ECPublicKeyParameters ecpub = (ECPublicKeyParameters)key.getPublic(); + BigInteger k = ecpriv.getD(); + ECPoint c1 = ecpub.getQ(); + this.p2 = userKey.multiply(k); + Reset(); + return c1; + } + + public void Encrypt(byte[] data) { + this.sm3c3.update(data, 0, data.length); + for (int i = 0; i < data.length; i++) { + if (this.keyOff == this.key.length) + NextKey(); + data[i] = (byte)(data[i] ^ this.key[this.keyOff]); + this.keyOff = (byte)(this.keyOff + 1); + } + } + + public void Init_dec(BigInteger userD, ECPoint c1) { + this.p2 = c1.multiply(userD); + Reset(); + } + + public void Decrypt(byte[] data) { + for (int i = 0; i < data.length; i++) { + if (this.keyOff == this.key.length) + NextKey(); + data[i] = (byte)(data[i] ^ this.key[this.keyOff]); + this.keyOff = (byte)(this.keyOff + 1); + } + this.sm3c3.update(data, 0, data.length); + } + + public void Dofinal(byte[] c3) { + byte[] p = Util.byteConvert32Bytes(this.p2.getY().toBigInteger()); + this.sm3c3.update(p, 0, p.length); + this.sm3c3.doFinal(c3, 0); + Reset(); + } +} diff --git a/src/main/java/com/newyetai/sdk/ssb/util/SM2.java b/src/main/java/com/newyetai/sdk/ssb/util/SM2.java new file mode 100644 index 0000000..362dbf2 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/ssb/util/SM2.java @@ -0,0 +1,125 @@ +package com.newyetai.sdk.ssb.util; + +import java.math.BigInteger; +import java.security.SecureRandom; +import org.bouncycastle.crypto.KeyGenerationParameters; +import org.bouncycastle.crypto.digests.SM3Digest; +import org.bouncycastle.crypto.generators.ECKeyPairGenerator; +import org.bouncycastle.crypto.params.ECDomainParameters; +import org.bouncycastle.crypto.params.ECKeyGenerationParameters; +import org.bouncycastle.math.ec.ECCurve; +import org.bouncycastle.math.ec.ECFieldElement; +import org.bouncycastle.math.ec.ECPoint; + +public class SM2 { + public static String[] ecc_param = new String[] { "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC", "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93", "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0" }; + + public final BigInteger ecc_p; + + public final BigInteger ecc_a; + + public final BigInteger ecc_b; + + public final BigInteger ecc_n; + + public final BigInteger ecc_gx; + + public final BigInteger ecc_gy; + + public final ECCurve ecc_curve; + + public final ECPoint ecc_point_g; + + public final ECDomainParameters ecc_bc_spec; + + public final ECKeyPairGenerator ecc_key_pair_generator; + + public final ECFieldElement ecc_gx_fieldelement; + + public final ECFieldElement ecc_gy_fieldelement; + + public static SM2 Instance() { + return new SM2(); + } + + public SM2() { + this.ecc_p = new BigInteger(ecc_param[0], 16); + this.ecc_a = new BigInteger(ecc_param[1], 16); + this.ecc_b = new BigInteger(ecc_param[2], 16); + this.ecc_n = new BigInteger(ecc_param[3], 16); + this.ecc_gx = new BigInteger(ecc_param[4], 16); + this.ecc_gy = new BigInteger(ecc_param[5], 16); + this.ecc_gx_fieldelement = (ECFieldElement)new ECFieldElement.Fp(this.ecc_p, this.ecc_gx); + this.ecc_gy_fieldelement = (ECFieldElement)new ECFieldElement.Fp(this.ecc_p, this.ecc_gy); + this.ecc_curve = (ECCurve)new ECCurve.Fp(this.ecc_p, this.ecc_a, this.ecc_b); + this.ecc_point_g = (ECPoint)new ECPoint.Fp(this.ecc_curve, this.ecc_gx_fieldelement, this.ecc_gy_fieldelement); + this.ecc_bc_spec = new ECDomainParameters(this.ecc_curve, this.ecc_point_g, this.ecc_n); + ECKeyGenerationParameters ecc_ecgenparam = new ECKeyGenerationParameters(this.ecc_bc_spec, new SecureRandom()); + this.ecc_key_pair_generator = new ECKeyPairGenerator(); + this.ecc_key_pair_generator.init((KeyGenerationParameters)ecc_ecgenparam); + } + + public byte[] sm2GetZ(byte[] userId, ECPoint userKey) { + SM3Digest sm3 = new SM3Digest(); + int len = userId.length * 8; + sm3.update((byte)(len >> 8 & 0xFF)); + sm3.update((byte)(len & 0xFF)); + sm3.update(userId, 0, userId.length); + byte[] p = Util.byteConvert32Bytes(this.ecc_a); + sm3.update(p, 0, p.length); + p = Util.byteConvert32Bytes(this.ecc_b); + sm3.update(p, 0, p.length); + p = Util.byteConvert32Bytes(this.ecc_gx); + sm3.update(p, 0, p.length); + p = Util.byteConvert32Bytes(this.ecc_gy); + sm3.update(p, 0, p.length); + p = Util.byteConvert32Bytes(userKey.getX().toBigInteger()); + sm3.update(p, 0, p.length); + p = Util.byteConvert32Bytes(userKey.getY().toBigInteger()); + sm3.update(p, 0, p.length); + byte[] md = new byte[sm3.getDigestSize()]; + sm3.doFinal(md, 0); + return md; + } + + public void sm2Sign(byte[] md, BigInteger userD, ECPoint userKey, SM2Result sm2Result) { + BigInteger e = new BigInteger(1, md); + BigInteger k = null; + ECPoint kp = null; + BigInteger r = null; + BigInteger s = null; + while (true) { + String kS = "6CB28D99385C175C94F94E934817663FC176D925DD72B727260DBAAE1FB2F96F"; + k = new BigInteger(kS, 16); + kp = this.ecc_point_g.multiply(k); + r = e.add(kp.getX().toBigInteger()); + r = r.mod(this.ecc_n); + if (!r.equals(BigInteger.ZERO)) + if (!r.add(k).equals(this.ecc_n)) { + BigInteger da_1 = userD.add(BigInteger.ONE); + da_1 = da_1.modInverse(this.ecc_n); + s = r.multiply(userD); + s = k.subtract(s).mod(this.ecc_n); + s = da_1.multiply(s).mod(this.ecc_n); + if (!s.equals(BigInteger.ZERO)) { + sm2Result.r = r; + sm2Result.s = s; + return; + } + } + } + } + + public void sm2Verify(byte[] md, ECPoint userKey, BigInteger r, BigInteger s, SM2Result sm2Result) { + sm2Result.R = null; + BigInteger e = new BigInteger(1, md); + BigInteger t = r.add(s).mod(this.ecc_n); + if (!t.equals(BigInteger.ZERO)) { + ECPoint x1y1 = this.ecc_point_g.multiply(sm2Result.s); + x1y1 = x1y1.add(userKey.multiply(t)); + sm2Result.R = e.add(x1y1.getX().toBigInteger()).mod(this.ecc_n); + } + } + + public static void main(String[] args) {} +} diff --git a/src/main/java/com/newyetai/sdk/ssb/util/SM2Result.java b/src/main/java/com/newyetai/sdk/ssb/util/SM2Result.java new file mode 100644 index 0000000..0d55510 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/ssb/util/SM2Result.java @@ -0,0 +1,24 @@ +package com.newyetai.sdk.ssb.util; + +import java.math.BigInteger; +import org.bouncycastle.math.ec.ECPoint; + +public class SM2Result { + public BigInteger r; + + public BigInteger s; + + public BigInteger R; + + public byte[] sa; + + public byte[] sb; + + public byte[] s1; + + public byte[] s2; + + public ECPoint keyra; + + public ECPoint keyrb; +} diff --git a/src/main/java/com/newyetai/sdk/ssb/util/SM2Utils.java b/src/main/java/com/newyetai/sdk/ssb/util/SM2Utils.java new file mode 100644 index 0000000..351572d --- /dev/null +++ b/src/main/java/com/newyetai/sdk/ssb/util/SM2Utils.java @@ -0,0 +1,249 @@ +package com.newyetai.sdk.ssb.util; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.util.Enumeration; +import org.apache.commons.lang3.StringUtils; +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1InputStream; +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.DERInteger; +import org.bouncycastle.asn1.DEROctetString; +import org.bouncycastle.asn1.DEROutputStream; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.crypto.AsymmetricCipherKeyPair; +import org.bouncycastle.crypto.digests.SM3Digest; +import org.bouncycastle.crypto.params.ECPrivateKeyParameters; +import org.bouncycastle.crypto.params.ECPublicKeyParameters; +import org.bouncycastle.math.ec.ECPoint; +import org.bouncycastle.util.encoders.Base64; + +public class SM2Utils { + public static void main(String[] args) throws Exception { + String clientId = "xxxxxxx"; + MyKeyPair myKeyPair = getMyKeyPair(); + String smySm2Public = myKeyPair.getPublicKey(); + String smySm2Private = myKeyPair.getPrivateKey(); + System.out.println("publicKey:" + smySm2Public); + System.out.println("privateKey:" + smySm2Private); + String sourceData = "clientID+pwd+1.0.0+1630307772898"; + String encrypt = sm2Encrypt(smySm2Public, sourceData); + System.out.println("utils 加密"+ encrypt); + String decrypt = sm2Decrypt(smySm2Private, encrypt); + System.out.println("utils 解密"+ decrypt); + String sign = sign(smySm2Private, sourceData, clientId); + System.out.println("utils 签名"+ sign); + byte[] signByte = signByte(smySm2Private, sourceData, clientId); + System.out.println("utils 签名byte" + signByte); + boolean verifySign = verifySign(smySm2Public, sourceData, clientId, sign); + System.out.println("utils 签名验证"+ verifySign); + } + + public static MyKeyPair getMyKeyPair() { + MyKeyPair myKeyPair = (new SM2Utils()).generateKeyPair(); + return myKeyPair; + } + + public static String sm2Encrypt(String publicKey, String data) { + try { + return (!StringUtils.isEmpty(publicKey) && !StringUtils.isEmpty(data)) ? new String(Base64.encode(encrypt(Util.hexToByte(publicKey), data.getBytes()))) : null; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + public static String sm2Decrypt(String privateKey, String data) { + try { + return (!StringUtils.isEmpty(privateKey) && !StringUtils.isEmpty(data)) ? new String(decrypt(Util.hexToByte(privateKey), Base64.decode(data))) : null; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + public static String sign(String privateKey, String sourceData, String userId) { + try { + byte[] c = sign(userId.getBytes(), Util.hexToByte(privateKey), sourceData.getBytes()); + return Util.getHexString(c); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + public static boolean verifySign(String publicKey, String sourceData, String userId, String sign) { + try { + return verifySign(userId.getBytes(), Util.hexToByte(publicKey), sourceData.getBytes(), Util.hexToByte(sign)); + } catch (IOException e) { + e.printStackTrace(); + return false; + } + } + + public static byte[] signByte(String privateKey, String sourceData, String clientId) { + try { + return sign(clientId.getBytes(), Util.hexToByte(privateKey), sourceData.getBytes()); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + private MyKeyPair generateKeyPair() { + SM2 sm2 = SM2.Instance(); + AsymmetricCipherKeyPair key = sm2.ecc_key_pair_generator.generateKeyPair(); + ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters)key.getPrivate(); + ECPublicKeyParameters ecpub = (ECPublicKeyParameters)key.getPublic(); + BigInteger privateKey = ecpriv.getD(); + ECPoint publicKey = ecpub.getQ(); + MyKeyPair myKeyPair = new MyKeyPair(); + myKeyPair.setPrivateKey(Util.byteToHex(privateKey.toByteArray())); + myKeyPair.setPublicKey(Util.byteToHex(publicKey.getEncoded(false))); + return myKeyPair; + } + + private static byte[] encrypt(byte[] publicKey, byte[] data) throws IOException { + if (publicKey != null && publicKey.length != 0) { + if (data != null && data.length != 0) { + byte[] source = new byte[data.length]; + System.arraycopy(data, 0, source, 0, data.length); + Cipher cipher = new Cipher(); + SM2 sm2 = SM2.Instance(); + ECPoint userKey = sm2.ecc_curve.decodePoint(publicKey); + ECPoint c1 = cipher.Init_enc(sm2, userKey); + cipher.Encrypt(source); + byte[] c3 = new byte[32]; + cipher.Dofinal(c3); + DERInteger x = new DERInteger(c1.getX().toBigInteger()); + DERInteger y = new DERInteger(c1.getY().toBigInteger()); + DEROctetString derDig = new DEROctetString(c3); + DEROctetString derEnc = new DEROctetString(source); + ASN1EncodableVector v = new ASN1EncodableVector(); + v.add((ASN1Encodable)x); + v.add((ASN1Encodable)y); + v.add((ASN1Encodable)derDig); + v.add((ASN1Encodable)derEnc); + DERSequence seq = new DERSequence(v); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + DEROutputStream dos = new DEROutputStream(bos); + dos.writeObject((ASN1Encodable)seq); + return bos.toByteArray(); + } + return null; + } + return null; + } + + private static byte[] decrypt(byte[] privateKey, byte[] encryptedData) throws IOException { + if (privateKey != null && privateKey.length != 0) { + if (encryptedData != null && encryptedData.length != 0) { + byte[] enc = new byte[encryptedData.length]; + System.arraycopy(encryptedData, 0, enc, 0, encryptedData.length); + SM2 sm2 = SM2.Instance(); + BigInteger userD = new BigInteger(1, privateKey); + ByteArrayInputStream bis = new ByteArrayInputStream(enc); + ASN1InputStream dis = new ASN1InputStream(bis); + ASN1Primitive derObj = dis.readObject(); + ASN1Sequence asn1 = ASN1Sequence.getInstance(derObj); + ASN1Integer x = (ASN1Integer)asn1.getObjectAt(0); + ASN1Integer y = (ASN1Integer)asn1.getObjectAt(1); + ECPoint c1 = sm2.ecc_curve.createPoint(x.getValue(), y.getValue(), true); + Cipher cipher = new Cipher(); + cipher.Init_dec(userD, c1); + DEROctetString data = (DEROctetString)asn1.getObjectAt(3); + enc = data.getOctets(); + cipher.Decrypt(enc); + byte[] c3 = new byte[32]; + cipher.Dofinal(c3); + return enc; + } + return null; + } + return null; + } + + private static byte[] sign(byte[] userId, byte[] privateKey, byte[] sourceData) throws IOException { + if (privateKey != null && privateKey.length != 0) { + if (sourceData != null && sourceData.length != 0) { + SM2 sm2 = SM2.Instance(); + BigInteger userD = new BigInteger(privateKey); + ECPoint userKey = sm2.ecc_point_g.multiply(userD); + byte[] z = sm2.sm2GetZ(userId, userKey); + SM3Digest sm3 = new SM3Digest(); + sm3.update(z, 0, z.length); + sm3.update(sourceData, 0, sourceData.length); + byte[] md = new byte[32]; + sm3.doFinal(md, 0); + SM2Result sm2Result = new SM2Result(); + sm2.sm2Sign(md, userD, userKey, sm2Result); + DERInteger d_r = new DERInteger(sm2Result.r); + DERInteger d_s = new DERInteger(sm2Result.s); + ASN1EncodableVector v2 = new ASN1EncodableVector(); + v2.add((ASN1Encodable)d_r); + v2.add((ASN1Encodable)d_s); + DERSequence sign = new DERSequence(v2); + byte[] signdata = sign.getEncoded(); + return signdata; + } + return null; + } + return null; + } + + private static boolean verifySign(byte[] userId, byte[] publicKey, byte[] sourceData, byte[] signData) throws IOException { + if (publicKey != null && publicKey.length != 0) { + if (sourceData != null && sourceData.length != 0) { + SM2 sm2 = SM2.Instance(); + ECPoint userKey = sm2.ecc_curve.decodePoint(publicKey); + SM3Digest sm3 = new SM3Digest(); + byte[] z = sm2.sm2GetZ(userId, userKey); + sm3.update(z, 0, z.length); + sm3.update(sourceData, 0, sourceData.length); + byte[] md = new byte[32]; + sm3.doFinal(md, 0); + ByteArrayInputStream bis = new ByteArrayInputStream(signData); + ASN1InputStream dis = new ASN1InputStream(bis); + ASN1Primitive derObj = dis.readObject(); + ASN1Sequence asn1 = ASN1Sequence.getInstance(derObj); + Enumeration e = asn1.getObjects(); + BigInteger r = ((ASN1Integer)e.nextElement()).getValue(); + BigInteger s = ((ASN1Integer)e.nextElement()).getValue(); + SM2Result sm2Result = new SM2Result(); + sm2Result.r = r; + sm2Result.s = s; + sm2.sm2Verify(md, userKey, sm2Result.r, sm2Result.s, sm2Result); + return sm2Result.r.equals(sm2Result.R); + } + return false; + } + return false; + } + + public class MyKeyPair { + String publicKey; + + String privateKey; + + public String getPublicKey() { + return this.publicKey; + } + + public void setPublicKey(String publicKey) { + this.publicKey = publicKey; + } + + public String getPrivateKey() { + return this.privateKey; + } + + public void setPrivateKey(String privateKey) { + this.privateKey = privateKey; + } + } +} diff --git a/src/main/java/com/newyetai/sdk/ssb/util/SsbRsaUtils.java b/src/main/java/com/newyetai/sdk/ssb/util/SsbRsaUtils.java new file mode 100644 index 0000000..a5c746f --- /dev/null +++ b/src/main/java/com/newyetai/sdk/ssb/util/SsbRsaUtils.java @@ -0,0 +1,54 @@ +package com.newyetai.sdk.ssb.util; + +import org.apache.commons.codec.binary.Base64; + +import javax.crypto.Cipher; +import java.security.KeyFactory; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; +import java.security.spec.X509EncodedKeySpec; + + +public class SsbRsaUtils { + + public static String encryptByPublicKey(String publicKeyText, String text) throws Exception { + X509EncodedKeySpec x509EncodedKeySpec2 = + new X509EncodedKeySpec(Base64.decodeBase64(publicKeyText)); + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec2); + Cipher cipher = Cipher.getInstance("RSA"); + cipher.init(Cipher.ENCRYPT_MODE, publicKey); + byte[] result = cipher.doFinal(text.getBytes()); + return Base64.encodeBase64String(result); + } + + public static String encryptMd5(String plainText) { + String re_md5 = new String(); + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + md.update(plainText.getBytes()); + byte b[] = md.digest(); + + int i; + + StringBuffer buf = new StringBuffer(""); + for (int offset = 0; offset < b.length; offset++) { + i = b[offset]; + if (i < 0) + i += 256; + if (i < 16) + buf.append("0"); + buf.append(Integer.toHexString(i)); + } + + re_md5 = buf.toString(); + + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + return re_md5; + } + + +} diff --git a/src/main/java/com/newyetai/sdk/ssb/util/Util.java b/src/main/java/com/newyetai/sdk/ssb/util/Util.java new file mode 100644 index 0000000..64e6b7a --- /dev/null +++ b/src/main/java/com/newyetai/sdk/ssb/util/Util.java @@ -0,0 +1,378 @@ +package com.newyetai.sdk.ssb.util; + +import java.math.BigInteger; + +public class Util { + private static final char[] DIGITS_LOWER = new char[] { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f' }; + + private static final char[] DIGITS_UPPER = new char[] { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F' }; + + public static byte[] intToBytes(int num) { + byte[] bytes = { (byte)(0xFF & num >> 0), (byte)(0xFF & num >> 8), (byte)(0xFF & num >> 16), (byte)(0xFF & num >> 24) }; + return bytes; + } + + public static int byteToInt(byte[] bytes) { + int num = 0; + int temp = (0xFF & bytes[0]) << 0; + num |= temp; + temp = (0xFF & bytes[1]) << 8; + num |= temp; + temp = (0xFF & bytes[2]) << 16; + num |= temp; + temp = (0xFF & bytes[3]) << 24; + num |= temp; + return num; + } + + public static byte[] longToBytes(long num) { + byte[] bytes = new byte[8]; + for (int i = 0; i < 8; i++) + bytes[i] = (byte)(int)(0xFFL & num >> i * 8); + return bytes; + } + + public static byte[] byteConvert32Bytes(BigInteger n) { + byte[] tmpd = (byte[])null; + if (n == null) + return null; + if ((n.toByteArray()).length == 33) { + tmpd = new byte[32]; + System.arraycopy(n.toByteArray(), 1, tmpd, 0, 32); + } else if ((n.toByteArray()).length == 32) { + tmpd = n.toByteArray(); + } else { + tmpd = new byte[32]; + for (int i = 0; i < 32 - (n.toByteArray()).length; i++) + tmpd[i] = 0; + System.arraycopy(n.toByteArray(), 0, tmpd, 32 - (n.toByteArray()).length, (n.toByteArray()).length); + } + return tmpd; + } + + public static BigInteger byteConvertInteger(byte[] b) { + if (b[0] < 0) { + byte[] temp = new byte[b.length + 1]; + temp[0] = 0; + System.arraycopy(b, 0, temp, 1, b.length); + return new BigInteger(temp); + } + return new BigInteger(b); + } + + public static String getHexString(byte[] bytes) { + return getHexString(bytes, true); + } + + public static String getHexString(byte[] bytes, boolean upperCase) { + String ret = ""; + for (int i = 0; i < bytes.length; i++) + ret = ret + Integer.toString((bytes[i] & 0xFF) + 256, 16).substring(1); + return upperCase ? ret.toUpperCase() : ret; + } + + public static void printHexString(byte[] bytes) { + for (int i = 0; i < bytes.length; i++) { + String hex = Integer.toHexString(bytes[i] & 0xFF); + if (hex.length() == 1) + hex = '0' + hex; + System.out.print("0x" + hex.toUpperCase() + ","); + } + System.out.println(""); + } + + public static byte[] hexStringToBytes(String hexString) { + if (hexString != null && !hexString.equals("")) { + hexString = hexString.toUpperCase(); + int length = hexString.length() / 2; + char[] hexChars = hexString.toCharArray(); + byte[] d = new byte[length]; + for (int i = 0; i < length; i++) { + int pos = i * 2; + d[i] = (byte)(charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1])); + } + return d; + } + return null; + } + + public static byte charToByte(char c) { + return (byte)"0123456789ABCDEF".indexOf(c); + } + + public static char[] encodeHex(byte[] data) { + return encodeHex(data, true); + } + + public static char[] encodeHex(byte[] data, boolean toLowerCase) { + return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER); + } + + protected static char[] encodeHex(byte[] data, char[] toDigits) { + int l = data.length; + char[] out = new char[l << 1]; + int i = 0; + for (int var5 = 0; i < l; i++) { + out[var5++] = toDigits[(0xF0 & data[i]) >>> 4]; + out[var5++] = toDigits[0xF & data[i]]; + } + return out; + } + + public static String encodeHexString(byte[] data) { + return encodeHexString(data, true); + } + + public static String encodeHexString(byte[] data, boolean toLowerCase) { + return encodeHexString(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER); + } + + protected static String encodeHexString(byte[] data, char[] toDigits) { + return new String(encodeHex(data, toDigits)); + } + + public static byte[] decodeHex(char[] data) { + int len = data.length; + if ((len & 0x1) != 0) + throw new RuntimeException("Odd number of characters."); + byte[] out = new byte[len >> 1]; + int i = 0; + for (int j = 0; j < len; i++) { + int f = toDigit(data[j], j) << 4; + j++; + f |= toDigit(data[j], j); + j++; + out[i] = (byte)(f & 0xFF); + } + return out; + } + + protected static int toDigit(char ch, int index) { + int digit = Character.digit(ch, 16); + if (digit == -1) + throw new RuntimeException("Illegal hexadecimal character " + ch + " at index " + index); + return digit; + } + + public static String StringToAsciiString(String content) { + String result = ""; + int max = content.length(); + for (int i = 0; i < max; i++) { + char c = content.charAt(i); + String b = Integer.toHexString(c); + result = result + b; + } + return result; + } + + public static String hexStringToString(String hexString, int encodeType) { + String result = ""; + int max = hexString.length() / encodeType; + for (int i = 0; i < max; i++) { + char c = (char)hexStringToAlgorism(hexString.substring(i * encodeType, (i + 1) * encodeType)); + result = result + c; + } + return result; + } + + public static int hexStringToAlgorism(String hex) { + hex = hex.toUpperCase(); + int max = hex.length(); + int result = 0; + for (int i = max; i > 0; i--) { + char c = hex.charAt(i - 1); + int algorism = 0; + if (c >= '0' && c <= '9') { + algorism = c - 48; + } else { + algorism = c - 55; + } + result = (int)(result + Math.pow(16.0D, (max - i)) * algorism); + } + return result; + } + + public static String hexStringToBinary(String hex) { + hex = hex.toUpperCase(); + String result = ""; + int max = hex.length(); + for (int i = 0; i < max; i++) { + char c = hex.charAt(i); + switch (c) { + case '0': + result = result + "0000"; + break; + case '1': + result = result + "0001"; + break; + case '2': + result = result + "0010"; + break; + case '3': + result = result + "0011"; + break; + case '4': + result = result + "0100"; + break; + case '5': + result = result + "0101"; + break; + case '6': + result = result + "0110"; + break; + case '7': + result = result + "0111"; + break; + case '8': + result = result + "1000"; + break; + case '9': + result = result + "1001"; + break; + case 'A': + result = result + "1010"; + break; + case 'B': + result = result + "1011"; + break; + case 'C': + result = result + "1100"; + break; + case 'D': + result = result + "1101"; + break; + case 'E': + result = result + "1110"; + break; + case 'F': + result = result + "1111"; + break; + } + } + return result; + } + + public static String AsciiStringToString(String content) { + String result = ""; + int length = content.length() / 2; + for (int i = 0; i < length; i++) { + String c = content.substring(i * 2, i * 2 + 2); + int a = hexStringToAlgorism(c); + char b = (char)a; + String d = String.valueOf(b); + result = result + d; + } + return result; + } + + public static String algorismToHexString(int algorism, int maxLength) { + String result = ""; + result = Integer.toHexString(algorism); + if (result.length() % 2 == 1) + result = "0" + result; + return patchHexString(result.toUpperCase(), maxLength); + } + + public static String byteToString(byte[] bytearray) { + String result = ""; + int length = bytearray.length; + for (int i = 0; i < length; i++) { + char temp = (char)bytearray[i]; + result = result + temp; + } + return result; + } + + public static int binaryToAlgorism(String binary) { + int max = binary.length(); + int result = 0; + for (int i = max; i > 0; i--) { + char c = binary.charAt(i - 1); + int algorism = c - 48; + result = (int)(result + Math.pow(2.0D, (max - i)) * algorism); + } + return result; + } + + public static String algorismToHEXString(int algorism) { + String result = ""; + result = Integer.toHexString(algorism); + if (result.length() % 2 == 1) + result = "0" + result; + result = result.toUpperCase(); + return result; + } + + public static String patchHexString(String str, int maxLength) { + String temp = ""; + for (int i = 0; i < maxLength - str.length(); i++) + temp = "0" + temp; + str = (temp + str).substring(0, maxLength); + return str; + } + + public static int parseToInt(String s, int defaultInt, int radix) { + int i; + boolean var3 = false; + try { + i = Integer.parseInt(s, radix); + } catch (NumberFormatException var5) { + i = defaultInt; + } + return i; + } + + public static int parseToInt(String s, int defaultInt) { + int i; + boolean var2 = false; + try { + i = Integer.parseInt(s); + } catch (NumberFormatException var4) { + i = defaultInt; + } + return i; + } + + public static byte[] hexToByte(String hex) throws IllegalArgumentException { + if (hex.length() % 2 != 0) + throw new IllegalArgumentException(); + char[] arr = hex.toCharArray(); + byte[] b = new byte[hex.length() / 2]; + int i = 0; + int j = 0; + for (int l = hex.length(); i < l; j++) { + String swap = "" + arr[i++] + arr[i]; + int byteint = Integer.parseInt(swap, 16) & 0xFF; + b[j] = (new Integer(byteint)).byteValue(); + i++; + } + return b; + } + + public static String byteToHex(byte[] b) { + if (b == null) + throw new IllegalArgumentException("Argument b ( byte array ) is null! "); + String hs = ""; + String stmp = ""; + for (int n = 0; n < b.length; n++) { + stmp = Integer.toHexString(b[n] & 0xFF); + if (stmp.length() == 1) { + hs = hs + "0" + stmp; + } else { + hs = hs + stmp; + } + } + return hs.toUpperCase(); + } + + public static byte[] subByte(byte[] input, int startIndex, int length) { + byte[] bt = new byte[length]; + for (int i = 0; i < length; i++) + bt[i] = input[i + startIndex]; + return bt; + } +} diff --git a/src/main/java/com/newyetai/sdk/tencent/map/IRequestPostProcess.java b/src/main/java/com/newyetai/sdk/tencent/map/IRequestPostProcess.java new file mode 100644 index 0000000..8e43456 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tencent/map/IRequestPostProcess.java @@ -0,0 +1,15 @@ +package com.newyetai.sdk.tencent.map; + +/** + * 请求发布过程 + * + * @author Carlye + * @date 2022/04/15 + */ +public interface IRequestPostProcess { + + /** + * 请求前处理 + */ + void postProcessBeforeRequest(); +} diff --git a/src/main/java/com/newyetai/sdk/tencent/map/TencentMapContext.java b/src/main/java/com/newyetai/sdk/tencent/map/TencentMapContext.java new file mode 100644 index 0000000..d36bb68 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tencent/map/TencentMapContext.java @@ -0,0 +1,216 @@ +package com.newyetai.sdk.tencent.map; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.sdk.common.dto.DefaultSdkInvokeLogDTO; +import com.newyetai.sdk.common.util.HttpUtils; +import com.newyetai.sdk.tencent.map.config.TencentMapProperties; +import com.newyetai.sdk.tencent.map.dto.TencentMapBaseResDTO; +import com.newyetai.sdk.tencent.map.dto.TencentMapGcoderReqDTO; +import com.newyetai.sdk.tencent.map.dto.TencentMapGeocoderReqDTO; +import com.newyetai.sdk.tencent.map.dto.TencentMapGeocoderResDTO; +import com.newyetai.sdk.tencent.map.dto.TencentMapLocationV1IpResDTO; +import com.newyetai.sdk.tencent.map.dto.TencentMapPlaceSearchReqDTO; +import com.newyetai.sdk.tencent.map.dto.TencentMapPlaceSearchResDTO; +import com.newyetai.sdk.tencent.map.dto.TencentMapWsDistanceV1MatrixReqDTO; +import com.newyetai.sdk.tencent.map.dto.TencentMapWsLocationV1IpReqDTO; +import com.newyetai.sdk.tencent.map.dto.TencentWsDistanceV1MatrixResDTO; + +import java.util.Map; +import java.util.Objects; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriComponentsBuilder; + +@Slf4j +@Component +public class TencentMapContext { + + @Autowired + private RestTemplate restTemplate; + + @Autowired + private TencentMapProperties properties; + + + /** + * @param reqDTO + * @return {@link AlitaResult}<{@link ?}> + */ + public AlitaResult webServiceGcoder(TencentMapGcoderReqDTO reqDTO){ + reqDTO.setKey(properties.getKey()); + String[] reqParam = new String[]{properties.getBaseUrl() + reqDTO.getUri() + "?key={key}","location={location}"}; + if (Objects.nonNull(reqDTO.getGet_poi())){ + reqParam[2] = "get_poi={get_poi}"; + } + if (Objects.nonNull(reqDTO.getPoi_options())){ + reqParam[3] = ("poi_options={poi_options}"); + } + String fullUrl = String.join("&",reqParam) ; + Map stringObjectMap = buildReq(reqDTO); + TencentMapBaseResDTO resDTO; + try { + resDTO = restTemplate.getForObject(fullUrl, + TencentMapBaseResDTO.class, + stringObjectMap); + } catch (Exception e) { + resDTO = null; + log.error("webServiceGcoder {} invoke error:{}",JsonUtils.toJsonString(reqDTO), + e); + } + if (Objects.isNull(resDTO)){ + return AlitaResult.error("网络异常"); + } + if (resDTO.isSuccess()){ + return AlitaResult.success(resDTO.getResult()); + } + return AlitaResult.error(resDTO.getMessage()); + } + + /** + * @param reqDTO + * @return {@link AlitaResult}<{@link ?}> + */ + public AlitaResult webServiceGeocoder(TencentMapGeocoderReqDTO reqDTO){ + reqDTO.setKey(properties.getKey()); + ParameterizedTypeReference> responseType = new ParameterizedTypeReference>() {}; + + ResponseEntity> result = null; + try { + UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(properties.getBaseUrl() + reqDTO.getUri()) + .queryParam("key",reqDTO.getKey() ) + .queryParam("address", reqDTO.getAddress()) + .queryParam("region", reqDTO.getRegion()); + + result = restTemplate.exchange(builder.toUriString(), HttpMethod.GET, null, responseType); + if (result.getBody().isSuccess()){ + return AlitaResult.success(result.getBody().getResult()); + }else { + log.error("webServiceGeocoder {} invoke error:{}",JsonUtils.toJsonString(reqDTO), + result.getBody().getMessage()); + return AlitaResult.error(result.getBody().getMessage()); + } + } catch (Exception e) { + log.error("webServiceGeocoder {} invoke error:{}",JsonUtils.toJsonString(reqDTO), + e); + return AlitaResult.error("网络异常"); + } finally { + log.info("webServiceGeocoder invoke:{}", + JsonUtils + .toJsonString( + DefaultSdkInvokeLogDTO.builder().requestData(reqDTO).responseData(result) + .build())); + } + } + + /** + * @param req + */ + public Map buildReq(Object req){ + if (Objects.isNull(req)){ + return null; + } + if (req instanceof IRequestPostProcess){ + IRequestPostProcess process = (IRequestPostProcess)req; + process.postProcessBeforeRequest(); + } + return JsonUtils.toMap(JsonUtils.toJsonString(req)); + } + + public AlitaResult webServiceWsLocationV1Ip(TencentMapWsLocationV1IpReqDTO reqDTO){ + reqDTO.setKey(properties.getKey()); + ParameterizedTypeReference> responseType = new ParameterizedTypeReference>() {}; + + ResponseEntity> result = null; + try { + UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(properties.getBaseUrl() + reqDTO.getUri()) + .queryParam("key",reqDTO.getKey() ) + .queryParam("ip", reqDTO.getIp()); + + result = restTemplate.exchange(builder.toUriString(), HttpMethod.GET, null, responseType); + if (result.getBody().isSuccess()){ + return AlitaResult.success(result.getBody().getResult()); + }else { + log.error("webServiceWsLocationV1Ip {} invoke error:{}",JsonUtils.toJsonString(reqDTO), + result.getBody().getMessage()); + return AlitaResult.error(result.getBody().getMessage()); + } + } catch (Exception e) { + log.error("webServiceWsLocationV1Ip {} invoke error:{}",JsonUtils.toJsonString(reqDTO), + e); + return AlitaResult.error("网络异常"); + } finally { + log.info("webServiceWsLocationV1Ip invoke:{}", + JsonUtils + .toJsonString( + DefaultSdkInvokeLogDTO.builder().requestData(reqDTO).responseData(result) + .build())); + } + } + + public AlitaResult wsDistanceV1MatrixReqDTO(TencentMapWsDistanceV1MatrixReqDTO reqDTO){ + reqDTO.setKey(properties.getKey()); + ParameterizedTypeReference> responseType = new ParameterizedTypeReference>() {}; + + ResponseEntity> result = null; + try { + HttpEntity requestEntity = new HttpEntity(reqDTO); + result = HttpUtils.restTemplate.exchange(properties.getBaseUrl() + reqDTO.getUri(), HttpMethod.POST, requestEntity, responseType); + if (result.getBody().isSuccess()){ + return AlitaResult.success(result.getBody().getResult()); + }else { + log.error("wsDistanceV1MatrixReqDTO {} invoke error:{}",JsonUtils.toJsonString(reqDTO), + result.getBody().getMessage()); + return AlitaResult.error(result.getBody().getMessage()); + } + } catch (Exception e) { + log.error("wsDistanceV1MatrixReqDTO {} invoke error:{}",JsonUtils.toJsonString(reqDTO), + e); + return AlitaResult.error("网络异常"); + } finally { + log.info("wsDistanceV1MatrixReqDTO invoke:{}", + JsonUtils + .toJsonString( + DefaultSdkInvokeLogDTO.builder().requestData(reqDTO).responseData(result) + .build())); + } + } + + public AlitaResult placeSearch(TencentMapPlaceSearchReqDTO reqDTO){ + reqDTO.setKey(properties.getKey()); + ParameterizedTypeReference> responseType = new ParameterizedTypeReference>() {}; + + ResponseEntity> result = null; + try { + UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(properties.getBaseUrl() + reqDTO.getUri()) + .queryParam("key",reqDTO.getKey() ) + .queryParam("keyword", reqDTO.getKeyword()) + .queryParam("boundary", reqDTO.getBoundary()); + + result = restTemplate.exchange(builder.toUriString(), HttpMethod.GET, null, responseType); + if (result.getBody().isSuccess()){ + return AlitaResult.success(result.getBody().getData()); + }else { + log.error("placeSearch {} invoke error:{}",JsonUtils.toJsonString(reqDTO), + result.getBody().getMessage()); + return AlitaResult.error(result.getBody().getMessage()); + } + } catch (Exception e) { + log.error("placeSearch {} invoke error:{}",JsonUtils.toJsonString(reqDTO), + e); + return AlitaResult.error("网络异常"); + } finally { + log.info("placeSearch invoke:{}", + JsonUtils + .toJsonString( + DefaultSdkInvokeLogDTO.builder().requestData(reqDTO).responseData(result) + .build())); + } + } +} diff --git a/src/main/java/com/newyetai/sdk/tencent/map/config/TencentMapProperties.java b/src/main/java/com/newyetai/sdk/tencent/map/config/TencentMapProperties.java new file mode 100644 index 0000000..870c23c --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tencent/map/config/TencentMapProperties.java @@ -0,0 +1,30 @@ +package com.newyetai.sdk.tencent.map.config; + +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +/** + * 腾讯地图配置 + * + * @author sr on 2020-08-11 + */ +@Data +@NoArgsConstructor +@Configuration +@ConfigurationProperties(prefix = TencentMapProperties.PREFIX) +public class TencentMapProperties { + + public static final String PREFIX = "tencent.map"; + + /** + * key + */ + private String key; + + /** + * url前缀 + */ + private String baseUrl; +} diff --git a/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentMapBaseReqDTO.java b/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentMapBaseReqDTO.java new file mode 100644 index 0000000..92e57d7 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentMapBaseReqDTO.java @@ -0,0 +1,31 @@ +package com.newyetai.sdk.tencent.map.dto; + +import java.io.Serializable; +import javax.validation.constraints.NotEmpty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public abstract class TencentMapBaseReqDTO implements Serializable { + + private static final long serialVersionUID = -6669699584755546491L; + + + /** + * 开发密钥(Key) + */ + @NotEmpty(message = "秘钥不能为空") + private String key; + + /** + * 获取uri + * + * @return {@link String} + */ + protected abstract String getUri(); +} diff --git a/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentMapBaseResDTO.java b/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentMapBaseResDTO.java new file mode 100644 index 0000000..52b9859 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentMapBaseResDTO.java @@ -0,0 +1,30 @@ +package com.newyetai.sdk.tencent.map.dto; + +import java.io.Serializable; +import java.util.Objects; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public class TencentMapBaseResDTO implements Serializable { + + + private static final long serialVersionUID = -3285179468910345476L; + + private Integer status; + + private String message; + + private String request_id; + + private T result; + + public boolean isSuccess(){ + return Objects.nonNull(status) && status == 0; + } +} diff --git a/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentMapGcoderReqDTO.java b/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentMapGcoderReqDTO.java new file mode 100644 index 0000000..07ac399 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentMapGcoderReqDTO.java @@ -0,0 +1,54 @@ +package com.newyetai.sdk.tencent.map.dto; + +import javax.validation.constraints.NotEmpty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@EqualsAndHashCode(callSuper = true) +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public class TencentMapGcoderReqDTO extends TencentMapBaseReqDTO { + + + private static final long serialVersionUID = 4494672021783484087L; + /** + * 经纬度(GCJ02坐标系),格式:location=lat<纬度>,lng<经度> + */ + @NotEmpty(message = "经纬度不能为空") + private String location; + + /** + * 是否返回周边地点(POI)列表,可选值: + * 0 不返回(默认) + * 1 返回 + */ + private String get_poi; + + + /** + * 周边POI列表控制参数: + * 1 poi_options=address_format=short + * 返回短地址,缺省时返回长地址 + * 2 poi_options=radius=5000 + * 半径,取值范围 1-5000(米) + * 3 poi_options=policy=1/2/3/4/5 + * 控制返回场景, + * policy=1[默认] 以地标+主要的路+近距离POI为主,着力描述当前位置; + * policy=2 到家场景:筛选合适收货的POI,并会细化收货地址,精确到楼栋; + * policy=3 出行场景:过滤掉车辆不易到达的POI(如一些景区内POI),增加道路出入口、交叉口、大区域出入口类POI,排序会根据真实API大用户的用户点击自动优化。 + * policy=4 社交签到场景,针对用户签到的热门 地点进行优先排序。 + * policy=5 位置共享场景,用户经常用于发送位置、位置分享等场景的热门地点优先排序 + * 4 注:policy=1/2/3最多返回10条周边POI,policy=4/5最多返回20条, + */ + private String poi_options; + + @Override + public String getUri() { + return "geocoder/v1"; + } +} diff --git a/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentMapGeocoderReqDTO.java b/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentMapGeocoderReqDTO.java new file mode 100644 index 0000000..0f703d1 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentMapGeocoderReqDTO.java @@ -0,0 +1,46 @@ +package com.newyetai.sdk.tencent.map.dto; + +import java.net.URLEncoder; +import javax.validation.constraints.NotEmpty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; +import org.apache.commons.lang3.StringUtils; + +import com.newyetai.sdk.tencent.map.IRequestPostProcess; + +@EqualsAndHashCode(callSuper = true) +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public class TencentMapGeocoderReqDTO extends TencentMapBaseReqDTO implements IRequestPostProcess { + + private static final long serialVersionUID = -309616473226679969L; + + /** + * 地址(注:地址中请包含城市名称,以及需要对地址进行URL编码,否则会影响解析效果) + */ + @NotEmpty(message = "地址不能为空") + private String address; + + /** + * 地址所在城市(若地址中包含城市名称侧可不传) + */ + private String region; + + @Override + public void postProcessBeforeRequest() { + String address = getAddress(); + if (StringUtils.isNotEmpty(address)){ + setAddress(URLEncoder.encode(address)); + } + } + + @Override + public String getUri() { + return "/ws/geocoder/v1"; + } +} diff --git a/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentMapGeocoderResDTO.java b/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentMapGeocoderResDTO.java new file mode 100644 index 0000000..0062424 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentMapGeocoderResDTO.java @@ -0,0 +1,46 @@ +package com.newyetai.sdk.tencent.map.dto; + +import java.io.Serializable; +import java.math.BigDecimal; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @description: + * @author: guixinman + * @create: 2025-01-14 17:23 + **/ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class TencentMapGeocoderResDTO implements Serializable { + + private TencentMapGeocoderLocationResDTO location; + private TencentMapGeocoderAddressComponentsDTO address_components; + private TencentMapGeocoderAdInfo ad_info; + + @Data + public class TencentMapGeocoderLocationResDTO implements Serializable { + private BigDecimal lat; + private BigDecimal lng; + } + + @Data + public class TencentMapGeocoderAddressComponentsDTO implements Serializable { + private String province; + private String city; + private String district; + private String street; + private String street_number; + + } + + @Data + public class TencentMapGeocoderAdInfo implements Serializable { + private String adcode; + } +} diff --git a/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentMapLocationV1IpResDTO.java b/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentMapLocationV1IpResDTO.java new file mode 100644 index 0000000..2ed314f --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentMapLocationV1IpResDTO.java @@ -0,0 +1,46 @@ +package com.newyetai.sdk.tencent.map.dto; + +import java.io.Serializable; +import java.math.BigDecimal; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @description: + * @author: guixinman + * @create: 2025-01-15 09:56 + **/ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class TencentMapLocationV1IpResDTO implements Serializable { + private String ip; + private TencentMapLocationDTO location; + private TencentMapLocationAdInfoDTO ad_info; + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class TencentMapLocationDTO implements Serializable{ + private BigDecimal lat; + private BigDecimal lng; + } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class TencentMapLocationAdInfoDTO implements Serializable{ + private String nation; + private String nation_code; + private String province; + private String city; + private String district; + private String adcode; + } +} diff --git a/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentMapPlaceSearchReqDTO.java b/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentMapPlaceSearchReqDTO.java new file mode 100644 index 0000000..0c05609 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentMapPlaceSearchReqDTO.java @@ -0,0 +1,31 @@ +package com.newyetai.sdk.tencent.map.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @description: 地点搜索 + * @author: guixinman + * @create: 2025-01-15 15:00 + **/ +@EqualsAndHashCode(callSuper = true) +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public class TencentMapPlaceSearchReqDTO extends TencentMapBaseReqDTO{ + + private String keyword; + private String boundary; + + + @Override + public String getUri() { + return "/ws/place/v1/search"; + } + + +} diff --git a/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentMapPlaceSearchResDTO.java b/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentMapPlaceSearchResDTO.java new file mode 100644 index 0000000..b6fd3b9 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentMapPlaceSearchResDTO.java @@ -0,0 +1,37 @@ +package com.newyetai.sdk.tencent.map.dto; + +import org.apache.poi.ss.formula.functions.T; + +import java.io.Serializable; +import java.util.Objects; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @description: + * @author: guixinman + * @create: 2025-01-15 15:22 + **/ +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public class TencentMapPlaceSearchResDTO implements Serializable { + + private Integer status; + + private String message; + + private String request_id; + + private T Data; + + private T region; + + public boolean isSuccess(){ + return Objects.nonNull(status) && status == 0; + } +} diff --git a/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentMapWsDistanceV1MatrixReqDTO.java b/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentMapWsDistanceV1MatrixReqDTO.java new file mode 100644 index 0000000..3f0fe29 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentMapWsDistanceV1MatrixReqDTO.java @@ -0,0 +1,29 @@ +package com.newyetai.sdk.tencent.map.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @description: 距离矩阵 + * @author: guixinman + * @create: 2024-12-18 14:48 + **/ +@EqualsAndHashCode(callSuper = true) +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public class TencentMapWsDistanceV1MatrixReqDTO extends TencentMapBaseReqDTO{ + + private String from; + private String to; + private String mode; + + @Override + public String getUri() { + return "/ws/distance/v1/matrix"; + } +} diff --git a/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentMapWsLocationV1IpReqDTO.java b/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentMapWsLocationV1IpReqDTO.java new file mode 100644 index 0000000..2f423ee --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentMapWsLocationV1IpReqDTO.java @@ -0,0 +1,27 @@ +package com.newyetai.sdk.tencent.map.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @description: IP定位 + * @author: guixinman + * @create: 2024-12-18 13:54 + **/ +@EqualsAndHashCode(callSuper = true) +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public class TencentMapWsLocationV1IpReqDTO extends TencentMapBaseReqDTO{ + + private String ip; + + @Override + public String getUri() { + return "/ws/location/v1/ip"; + } +} diff --git a/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentWsDistanceV1MatrixElementsResDTO.java b/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentWsDistanceV1MatrixElementsResDTO.java new file mode 100644 index 0000000..186a351 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentWsDistanceV1MatrixElementsResDTO.java @@ -0,0 +1,23 @@ +package com.newyetai.sdk.tencent.map.dto; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @description: + * @author: guixinman + * @create: 2024-12-19 09:12 + **/ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class TencentWsDistanceV1MatrixElementsResDTO implements Serializable { + private long distance; + private long duration; + private long status; +} diff --git a/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentWsDistanceV1MatrixElementsRowResDTO.java b/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentWsDistanceV1MatrixElementsRowResDTO.java new file mode 100644 index 0000000..c2c813f --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentWsDistanceV1MatrixElementsRowResDTO.java @@ -0,0 +1,16 @@ +package com.newyetai.sdk.tencent.map.dto; + +import java.io.Serializable; +import java.util.List; + +import lombok.Data; + +/** + * @description: + * @author: guixinman + * @create: 2024-12-19 10:03 + **/ +@Data +public class TencentWsDistanceV1MatrixElementsRowResDTO implements Serializable { + private List elements; +} diff --git a/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentWsDistanceV1MatrixResDTO.java b/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentWsDistanceV1MatrixResDTO.java new file mode 100644 index 0000000..088e93e --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tencent/map/dto/TencentWsDistanceV1MatrixResDTO.java @@ -0,0 +1,16 @@ +package com.newyetai.sdk.tencent.map.dto; + +import java.io.Serializable; +import java.util.List; + +import lombok.Data; + +/** + * @description: + * @author: guixinman + * @create: 2024-12-19 10:09 + **/ +@Data +public class TencentWsDistanceV1MatrixResDTO implements Serializable { + private List rows; +} diff --git a/src/main/java/com/newyetai/sdk/tonglian/adapter/TongLianAdapter.java b/src/main/java/com/newyetai/sdk/tonglian/adapter/TongLianAdapter.java new file mode 100644 index 0000000..baef1b0 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tonglian/adapter/TongLianAdapter.java @@ -0,0 +1,210 @@ +package com.newyetai.sdk.tonglian.adapter; + +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.common.util.ParameterizedTypeImpl; +import com.newyetai.sdk.tonglian.config.TokenProvider; +import com.newyetai.sdk.tonglian.config.TongLianProperties; +import com.newyetai.sdk.tonglian.dto.check.RequestCheck; +import com.newyetai.sdk.tonglian.dto.common.BaseReqDTO; +import com.newyetai.sdk.tonglian.dto.common.TongLianBaseReqDTO; +import com.newyetai.sdk.tonglian.dto.common.TongLianBaseResDTO; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.security.KeyFactory; +import java.security.PrivateKey; +import java.security.Signature; +import java.security.spec.PKCS8EncodedKeySpec; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; +import javax.validation.ConstraintViolation; +import javax.validation.Validator; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.util.Base64Utils; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestTemplate; + +@Slf4j +public class TongLianAdapter { + + @Autowired + private TongLianProperties tongLianProperties; + + @Lazy + @Autowired + private TokenProvider tokenProvider; + + @Autowired + private RestTemplate restTemplate; + + @Autowired + private Validator validator; + + public void invoke(BaseReqDTO req){ + if(validator != null) { + //普通参数校验 + String errorMsg = validator.validate(req).stream() + .map(ConstraintViolation::getMessage) + .collect(Collectors.joining(",")); + if (StringUtils.isNotEmpty(errorMsg)) { + req.setResult(TongLianBaseResDTO.error(errorMsg)); + return; + } + } + //自定义检查 + if (req instanceof RequestCheck){ + String errorMsg = ((RequestCheck) req).check(); + if (StringUtils.isNotEmpty(errorMsg)){ + req.setResult(TongLianBaseResDTO.error(errorMsg)); + return; + } + } + + TongLianBaseReqDTO baseReqDTO = packageReq(req); + if (Boolean.TRUE.equals(req.getNeedToken())){ + String token = tokenProvider.getToken(false,req); + if (StringUtils.isEmpty(token)){ + req.setResult(TongLianBaseResDTO.error("token获取失败")); + return; + } + Map params = baseReqDTO.getParams(); + params.put("token",token); + } + + String sign = getSign(baseReqDTO.toString(), tongLianProperties.getPrivateKey()); + if (StringUtils.isEmpty(sign)){ + req.setResult(TongLianBaseResDTO.error("签名异常")); + return; + } + baseReqDTO.setSign(sign); + + + String reqUri = tongLianProperties.getDomain() + baseReqDTO.getInterfaceStr(); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + HttpEntity requestEntity = new HttpEntity<>(baseReqDTO.toMap(), headers); + log.info("tonglian http invoke:{}, ", JsonUtils + .toJsonString(baseReqDTO)); + try { + ParameterizedType parameterizedType = (ParameterizedType)req.getClass().getGenericSuperclass(); + Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); + ParameterizedTypeReference objectParameterizedTypeReference = ParameterizedTypeReference.forType( + new ParameterizedTypeImpl(actualTypeArguments,TongLianBaseResDTO.class, TongLianBaseResDTO.class)); + + ResponseEntity exchange = restTemplate.exchange(reqUri, + HttpMethod.POST, requestEntity, objectParameterizedTypeReference); + HttpStatus statusCode = exchange.getStatusCode(); + if (statusCode.isError()){ + req.setResult(TongLianBaseResDTO.error("网络异常")); + return; + } + TongLianBaseResDTO resDTO = (TongLianBaseResDTO)exchange.getBody(); + if (Objects.isNull(resDTO)){ + req.setResult(TongLianBaseResDTO.error("网络请求异常")); + return; + } + + //获取authId,放到响应体,用于 身份证手机号解密 + if (StringUtils.isNotBlank(req.appId())){ + TongLianProperties.TongLianAppProperties appProperties = tongLianProperties.getApps() + .stream() + .filter(tongLianAppProperties -> StringUtils.equals(tongLianAppProperties.getAppId(), req.appId())) + .findFirst() + .orElse(null); + if (appProperties == null) { + throw new BusinessException("根据appId未找到secretNo,请联系管理员"); + } + resDTO.setAuthId(appProperties.getAuthId()); + }else { + resDTO.setAuthId(tongLianProperties.getApps().get(0).getAuthId()); + } + + log.info("tonglian http invoke result : [{}]", JsonUtils.toJsonString(resDTO)); + if (resDTO.isSuccess()){ + req.setResult(resDTO); + }else { + //token失效 + if (StringUtils.equals(resDTO.getErrorCode(),"0") + && StringUtils.contains(resDTO.getMessage(),"token")){ + if (req.getRetryNum() > 0){ + req.setResult(TongLianBaseResDTO.error("重试次数超限")); + return; + } + req.setRetryNum(req.getRetryNum() + 1); + tokenProvider.getToken(true,req); + invoke(req); + }else { + req.setResult(resDTO); + } + } + } catch (RestClientException e) { + log.info("tonglian http invoke error", e); + req.setResult(TongLianBaseResDTO.error("网络异常.")); + } + } + + /** + * 请求报文加签机制 + * 1.公共请求参数字段按字典升序排序(sign不参与排序), + * 2.键=值&符号拼接请求参数(sing不参与拼接) + * 范例: + * "appId=HO/d3EbvgufqDCyT3Jfo3Q==&interface=servicepro/Commpany/openAcct¶ms={"enterpriseId":"MUx0cDhrbTdZWkE3RnA3b2YvQTYyZz09","batchList":[{"personalId":"NlI5b0QrQ0Z0b2xJYkZlcG16RDFxQT09","workId":"TXpraU0vSjdVck5BT3pDK2hsZkZjZz09","money":1}]}×tamp=20201216112515&version=1.0" + * 2:对拼接后得到的字符串进行md5加密处理 + * 3:将md5加密后的结果转换成大写 + * 4:使用用户私钥进行SHA1WithRSA加密生成sign 签名串 + * 5:对生成的sign签名串进行base64编码 + * + * @param signBase + */ + private static String getSign(String signBase,String privateKey){ + String sign = null; + String md5 = DigestUtils.md5Hex(signBase); + String md5Upper = StringUtils.upperCase(md5); + + try { + PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64Utils.decodeFromString(privateKey)); + KeyFactory keyf = KeyFactory.getInstance("RSA"); + PrivateKey priKey = keyf.generatePrivate(priPKCS8); + // 这里签名使用的是 SHA1WithRSA + Signature signature = Signature.getInstance("SHA1WithRSA"); + // 以私钥字符串初始化签名 + signature.initSign(priKey); + // 将原始串注入签名中 + signature.update(md5Upper.getBytes()); + // 签名后的结果,以字符数组形式存在 + byte[] signed = signature.sign(); + // 签名后的结果,以base64编码形式存在 + sign = Base64Utils.encodeToString(signed); + } catch (Exception e) { + log.info("tonglian 加密异常,",e); + } + return sign; + } + + /** + * 构建请求对象 + * + * @param req 要求事情 + * @return {@link TongLianBaseReqDTO} + */ + private TongLianBaseReqDTO packageReq(BaseReqDTO req){ + TongLianBaseReqDTO baseReqDTO = new TongLianBaseReqDTO(); + baseReqDTO.setAppId(StringUtils.isNotBlank(req.appId()) ? req.appId() : tongLianProperties.getApps().get(0).getAppId()); + baseReqDTO.setVersion(tongLianProperties.getVersion()); + baseReqDTO.setInterfaceStr(req.interfaceStr()); + baseReqDTO.setParams(req.params()); + return baseReqDTO; + } +} diff --git a/src/main/java/com/newyetai/sdk/tonglian/config/StandardTokenProvider.java b/src/main/java/com/newyetai/sdk/tonglian/config/StandardTokenProvider.java new file mode 100644 index 0000000..a239869 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tonglian/config/StandardTokenProvider.java @@ -0,0 +1,90 @@ +package com.newyetai.sdk.tonglian.config; + +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.frame.redis.dto.LockDTO; +import com.newyetai.frame.redis.redisson.RedissonUtils; +import com.newyetai.frame.redis.util.RedisUtils; +import com.newyetai.sdk.tonglian.adapter.TongLianAdapter; +import com.newyetai.sdk.tonglian.dto.GetTokenReqDTO; +import com.newyetai.sdk.tonglian.dto.GetTokenResDTO; +import com.newyetai.sdk.tonglian.dto.common.BaseReqDTO; +import com.newyetai.sdk.tonglian.dto.common.TongLianBaseResDTO; +import java.util.Objects; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; + +@Slf4j +public class StandardTokenProvider implements TokenProvider { + + private static final String TOKEN_KEY_PREFIX = "tl"; + private static final long TOKEN_EXPIRE = 55 * 60; + + private TongLianProperties tongLianProperties; + + private TongLianAdapter tongLianAdapter; + + public StandardTokenProvider(TongLianProperties tongLianProperties,TongLianAdapter tongLianAdapter){ + this.tongLianProperties = tongLianProperties; + this.tongLianAdapter = tongLianAdapter; + } + + @Override + public String getToken(Boolean refresh, BaseReqDTO req) { + String appId = ""; + String secretNo = ""; + if (StringUtils.isNotBlank(req.appId())){ + TongLianProperties.TongLianAppProperties appProperties = tongLianProperties.getApps() + .stream() + .filter(tongLianAppProperties -> StringUtils.equals(tongLianAppProperties.getAppId(), req.appId())) + .findFirst() + .orElse(null); + if (appProperties == null) { + throw new BusinessException("根据appId未找到secretNo,请联系管理员"); + } + secretNo = appProperties.getSecretNo(); + appId = appProperties.getAppId(); + }else { + secretNo = tongLianProperties.getApps().get(0).getSecretNo(); + appId = tongLianProperties.getApps().get(0).getAppId(); + } + + String tokenKey = String.join(":", TOKEN_KEY_PREFIX, appId, "token"); + Object tokenObj = RedisUtils.get(tokenKey); + //重新获取令牌 + if (Boolean.TRUE.equals(refresh) + || tokenObj == null) { + String tokenLock = String.join(":", TOKEN_KEY_PREFIX, appId, "lock"); + LockDTO lockDTONew = LockDTO.builder() + .tryLockWaitTime(10L) + .lockTimeout(60 * 5L) + .methodName(tokenLock) + .build(); + try { + Assert.isTrue(RedissonUtils.tryLock(lockDTONew), "token正在获取中"); + tokenObj = RedisUtils.get(tokenKey); + if (tokenObj != null) { + return tokenObj.toString(); + } + GetTokenReqDTO reqDTO = new GetTokenReqDTO(); + reqDTO.setNeedToken(Boolean.FALSE); + reqDTO.setSecretNo(secretNo); + reqDTO.setAppId(appId); + tongLianAdapter.invoke(reqDTO); + TongLianBaseResDTO result = reqDTO.getResult(); + if (Objects.nonNull(result) && result.isSuccess()) { + GetTokenResDTO data = result.getData(); + // 1小时有效期 这里设置55分钟 + RedisUtils.add(tokenKey, data.getToken(), TOKEN_EXPIRE); + return data.getToken(); + } + } catch (Exception e) { + log.info("获取token异常 ",e); + return null; + }finally { + RedissonUtils.unlock(lockDTONew); + } + } + return tokenObj.toString(); + } +} diff --git a/src/main/java/com/newyetai/sdk/tonglian/config/TokenProvider.java b/src/main/java/com/newyetai/sdk/tonglian/config/TokenProvider.java new file mode 100644 index 0000000..252c8c5 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tonglian/config/TokenProvider.java @@ -0,0 +1,15 @@ +package com.newyetai.sdk.tonglian.config; + +import com.newyetai.sdk.tonglian.dto.common.BaseReqDTO; + +public interface TokenProvider { + + + /** + * 获得令牌 + * + * @param refresh 刷新 重新从第三方获取令牌 + * @return {@link String} + */ + String getToken(Boolean refresh, BaseReqDTO req); +} diff --git a/src/main/java/com/newyetai/sdk/tonglian/config/TongLianConfig.java b/src/main/java/com/newyetai/sdk/tonglian/config/TongLianConfig.java new file mode 100644 index 0000000..cc6b015 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tonglian/config/TongLianConfig.java @@ -0,0 +1,42 @@ +package com.newyetai.sdk.tonglian.config; + +import com.newyetai.sdk.tonglian.adapter.TongLianAdapter; +import lombok.Data; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Lazy; + +/** + * tonglian 配置属性 + * + * @author Carlye + * @date 2022/03/17 + */ +@Data +@Configuration +@EnableConfigurationProperties(TongLianProperties.class) +@ConditionalOnProperty(name = TongLianConfig.TONGLIAN_ENABLE, havingValue = "true") +@ComponentScan(basePackages = {"com.newyetai.sdk.tonglian"}) +public class TongLianConfig { + + static final String TONGLIAN_ENABLE = "tong.lian.enable"; + + @Bean + @Lazy + public TongLianAdapter tongLianAdapter(){ + return new TongLianAdapter(); + } + + @Bean + @Lazy + @ConditionalOnMissingBean(TokenProvider.class) + public TokenProvider tokenProvider(TongLianProperties tongLianProperties,TongLianAdapter tongLianAdapter){ + return new StandardTokenProvider(tongLianProperties,tongLianAdapter); + } + + +} diff --git a/src/main/java/com/newyetai/sdk/tonglian/config/TongLianProperties.java b/src/main/java/com/newyetai/sdk/tonglian/config/TongLianProperties.java new file mode 100644 index 0000000..a0c53b5 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tonglian/config/TongLianProperties.java @@ -0,0 +1,57 @@ +package com.newyetai.sdk.tonglian.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +import java.util.List; + +/** + * tonglian 配置属性 + * + * @author Carlye + * @date 2022/03/17 + */ +@Data +@ConfigurationProperties(prefix = TongLianProperties.PREFIX) +public class TongLianProperties { + + /** + * 创蓝配置前缀 + **/ + static final String PREFIX = "tong.lian"; + + /** + * 版本 + */ + private String version; + + /** + * 请求接口的前缀 + */ + private String domain; + + /** + * 私钥 + */ + private String privateKey; + + private List apps; + + + @Data + public static class TongLianAppProperties { + + /** + * 应用程序id + */ + private String appId; + + /** + * secret_no + */ + private String secretNo; + + private String authId; + + } +} diff --git a/src/main/java/com/newyetai/sdk/tonglian/constants/TongLianConstants.java b/src/main/java/com/newyetai/sdk/tonglian/constants/TongLianConstants.java new file mode 100644 index 0000000..70adf94 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tonglian/constants/TongLianConstants.java @@ -0,0 +1,16 @@ +package com.newyetai.sdk.tonglian.constants; + +/** + * 通连常量 + * + * @author Carlye + * @date 2022/03/18 + */ +public interface TongLianConstants { + + /** + * 服务调用是否成功 + */ + String STATUS_OK = "OK"; + String STATUS_ERROR = "error"; +} diff --git a/src/main/java/com/newyetai/sdk/tonglian/dto/GetTokenReqDTO.java b/src/main/java/com/newyetai/sdk/tonglian/dto/GetTokenReqDTO.java new file mode 100644 index 0000000..f6dc2ed --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tonglian/dto/GetTokenReqDTO.java @@ -0,0 +1,44 @@ +package com.newyetai.sdk.tonglian.dto; + +import com.google.common.collect.Maps; +import com.newyetai.sdk.tonglian.dto.common.BaseReqDTO; +import java.util.Map; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 同步个人用户数据 + * + * @author Carlye + * @date 2022/03/18 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class GetTokenReqDTO extends BaseReqDTO { + + private static final long serialVersionUID = -7828198385545023898L; + /** + * 身份证列表,多个用','分割 + */ + private String secretNo; + + private String appId; + + @Override + public String interfaceStr() { + return "api/auth/get_token"; + } + + @Override + public Map params() { + Map params = Maps.newLinkedHashMap(); + params.put("secret_no",getSecretNo()); + return params; + } + + @Override + public String appId() { + return this.appId; + } + +} diff --git a/src/main/java/com/newyetai/sdk/tonglian/dto/GetTokenResDTO.java b/src/main/java/com/newyetai/sdk/tonglian/dto/GetTokenResDTO.java new file mode 100644 index 0000000..7ee7ee5 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tonglian/dto/GetTokenResDTO.java @@ -0,0 +1,22 @@ +package com.newyetai.sdk.tonglian.dto; + +import java.io.Serializable; +import lombok.Data; + +@Data +public class GetTokenResDTO implements Serializable { + + private static final long serialVersionUID = 644712532066127542L; + /** + * 响应状态 + */ + private String res; + /** + * token + */ + private String token; + /** + * 响应信息 + */ + private String msg; +} diff --git a/src/main/java/com/newyetai/sdk/tonglian/dto/SynWalletDTO.java b/src/main/java/com/newyetai/sdk/tonglian/dto/SynWalletDTO.java new file mode 100644 index 0000000..3b4a2ac --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tonglian/dto/SynWalletDTO.java @@ -0,0 +1,94 @@ +package com.newyetai.sdk.tonglian.dto; + +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.util.AESUtils; + +import org.apache.commons.lang3.StringUtils; + +import java.io.Serializable; + +import lombok.Data; + +/** + * @description: 同步钱包信息接口 + * @author: guixinman + * @create: 2024-02-22 16:39 + **/ +@Data +public class SynWalletDTO implements Serializable { + + /** + * 类型 1出账 0进账 + */ + private String type; + + /** + * 交易金额 + */ + private String act_amt; + + /** + * 交易时间 + */ + private String trans_time; + + /** + * 出账账户名 + */ + private String from_act_name; + + /** + * 入账账户名 + */ + private String to_act_name; + + /** + * 交易单号 + */ + private String act_sn; + + /** + * 备注 + */ + private String bak; + + /** + * 状态 0处理中 1成功 2失败 + */ + private String status; + + /** + * 转出方电子账户 + */ + private String from_custid; + + + /** + * 转入方电子账户 当bak为佣金发放成功时则代表C端用户电子账户 + */ + private String to_custid; + + /** + * 支付账单编号 默认0 当返回bak备注说明不为 '合作服务费收入' 或 '佣金发放成功'为0 + */ + private Integer bill_id; + + /** + * 当bak备注说明为 '佣金发放成功' 返回,bill_id的加密,用于获取支付账单回单 + */ + private String bill_id_enc; + + /** + * 提报批次编号 默认0 当返回bak备注说明不为 '合作服务费收入' 或 '佣金发放成功'为0 + */ + private Integer monthbase_id; + + private String mobile; + + private String id_card; + + /** + * 委托方(实际支付方) 当bak为佣金发放成功时返回 + */ + private String from_client_name; +} diff --git a/src/main/java/com/newyetai/sdk/tonglian/dto/SynWalletReqDTO.java b/src/main/java/com/newyetai/sdk/tonglian/dto/SynWalletReqDTO.java new file mode 100644 index 0000000..fda1587 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tonglian/dto/SynWalletReqDTO.java @@ -0,0 +1,76 @@ +package com.newyetai.sdk.tonglian.dto; + +import com.google.common.collect.Maps; + +import com.newyetai.sdk.tonglian.dto.check.RequestCheck; +import com.newyetai.sdk.tonglian.dto.common.BasePageReqDTO; + +import org.apache.commons.lang3.StringUtils; + +import java.util.Map; + +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @description: 同步钱包信息接口 + * @author: guixinman + * @create: 2024-02-22 16:18 + **/ +@EqualsAndHashCode(callSuper = true) +@Data +@Builder +public class SynWalletReqDTO extends BasePageReqDTO implements RequestCheck { + + /** + * 通联税源地appId + */ + private String appId; + + /** + * 交易时间起 yyyy-MM-dd + */ + private String timeBegin; + + /** + * 交易时间止 yyyy-MM-dd + */ + private String timeEnd; + + @Override + public String check() { + if (StringUtils.isBlank(getAppId())) { + return "appId必传"; + } + if (StringUtils.isBlank(getTimeBegin())) { + return "timeBegin必传"; + } + if (StringUtils.isBlank(getTimeEnd())) { + return "timeEnd必传"; + } + return null; + } + + @Override + public String interfaceStr() { + return "api/commit/service/synWalletData"; + } + + @Override + public Map params() { + Map params = Maps.newLinkedHashMap(); + params.put("timeBegin", getTimeBegin()); + params.put("timeEnd", getTimeEnd()); + params.put("curPage", getCurPage()); + params.put("pageSize", getPageSize()); + params.put("token", getToken()); + params.put("passageway", 1); + return params; + } + + @Override + public String appId() { + return this.appId; + } +} diff --git a/src/main/java/com/newyetai/sdk/tonglian/dto/SynWalletResDTO.java b/src/main/java/com/newyetai/sdk/tonglian/dto/SynWalletResDTO.java new file mode 100644 index 0000000..1ed8836 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tonglian/dto/SynWalletResDTO.java @@ -0,0 +1,36 @@ +package com.newyetai.sdk.tonglian.dto; + +import java.io.Serializable; +import java.util.List; + +import lombok.Data; + +/** + * @description: 同步钱包信息接口 + * @author: guixinman + * @create: 2024-02-22 16:19 + **/ +@Data +public class SynWalletResDTO implements Serializable { + + /** + * 请求表示 1=成功 0=失败 + */ + private String res; + /** + * 响应信息 + */ + private String msg; + /** + * 当前页 + */ + private String current_page; + /** + * 单页显示条数 + */ + private String per_page; + /** + * 响应数据列表 + */ + private List list; +} diff --git a/src/main/java/com/newyetai/sdk/tonglian/dto/SysUserContractDTO.java b/src/main/java/com/newyetai/sdk/tonglian/dto/SysUserContractDTO.java new file mode 100644 index 0000000..e55e304 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tonglian/dto/SysUserContractDTO.java @@ -0,0 +1,18 @@ +package com.newyetai.sdk.tonglian.dto; + +import java.io.Serializable; +import lombok.Data; + +@Data +public class SysUserContractDTO implements Serializable { + + private static final long serialVersionUID = 8873108969832616738L; + /** + * 合同查看地址 + */ + private String viewUrl; + /** + * 合同下载地址 + */ + private String downloadUrl; +} diff --git a/src/main/java/com/newyetai/sdk/tonglian/dto/SysUserDTO.java b/src/main/java/com/newyetai/sdk/tonglian/dto/SysUserDTO.java new file mode 100644 index 0000000..2415416 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tonglian/dto/SysUserDTO.java @@ -0,0 +1,51 @@ +package com.newyetai.sdk.tonglian.dto; + +import java.io.Serializable; +import java.util.List; +import lombok.Data; + +@Data +public class SysUserDTO implements Serializable { + + private static final long serialVersionUID = 2253570557412435722L; + /** + * 用户编号 + */ + private String userNo; + /** + * 用户姓名 + */ + private String name; + /** + * 注册电话 + */ + private String mobile; + /** + * 身份证编号 + */ + private String idNo; + /** + * 身份证正面 + */ + private String idCardFront; + /** + * 身份证反面 + */ + private String idCardBack; + /** + * 电子钱包编号 + */ + private String allinpayNo; + /** + * 用户状态 + */ + private String status; + /** + * 创建时间 + */ + private String createTime; + /** + * 合同列表 + */ + private List contractList; +} diff --git a/src/main/java/com/newyetai/sdk/tonglian/dto/SysUserReqDTO.java b/src/main/java/com/newyetai/sdk/tonglian/dto/SysUserReqDTO.java new file mode 100644 index 0000000..ab542ca --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tonglian/dto/SysUserReqDTO.java @@ -0,0 +1,75 @@ +package com.newyetai.sdk.tonglian.dto; + +import com.google.common.collect.Maps; +import com.newyetai.sdk.tonglian.dto.check.RequestCheck; +import com.newyetai.sdk.tonglian.dto.common.BasePageReqDTO; +import java.util.Map; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.apache.commons.lang3.StringUtils; + +/** + * 同步个人用户数据 + * + * @author Carlye + * @date 2022/03/18 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@Builder +public class SysUserReqDTO extends BasePageReqDTO implements RequestCheck { + + private static final long serialVersionUID = -5929153041130241087L; + /** + * 身份证列表,多个用','分割 + */ + private String cardNoList; + + /** + * 手机号列表 + */ + private String mobileList; + + /** + * 账单编号 + */ + private String batchNo; + + /** + * 应用程序id + */ + private String appId; + + + @Override + public String interfaceStr() { + return "api/commit/service/synUser"; + } + + @Override + public Map params() { + Map params = Maps.newLinkedHashMap(); + params.put("cardNoList",getCardNoList()); + params.put("mobileList",getMobileList()); + params.put("batchNo",getBatchNo()); + params.put("curPage",getCurPage()); + params.put("pageSize",getPageSize()); + params.put("token",getToken()); + return params; + } + + @Override + public String check() { + if (StringUtils.isAllEmpty(getCardNoList(),getBatchNo(),getMobileList())){ + return "身份证列表/账单编号/手机号列表 三选一必传"; + } + return null; + } + + @Override + public String appId() { + return this.appId; + } + +} diff --git a/src/main/java/com/newyetai/sdk/tonglian/dto/SysUserResDTO.java b/src/main/java/com/newyetai/sdk/tonglian/dto/SysUserResDTO.java new file mode 100644 index 0000000..abd07ed --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tonglian/dto/SysUserResDTO.java @@ -0,0 +1,31 @@ +package com.newyetai.sdk.tonglian.dto; + +import java.io.Serializable; +import java.util.List; +import lombok.Data; + +@Data +public class SysUserResDTO implements Serializable { + + private static final long serialVersionUID = 2253570557412435722L; + /** + * 用户编号 + */ + private String res; + /** + * 用户姓名 + */ + private String msg; + /** + * 当前页 + */ + private String current_page; + /** + * + */ + private String per_page; + /** + * 用户信息列表 + */ + private List list; +} diff --git a/src/main/java/com/newyetai/sdk/tonglian/dto/check/RequestCheck.java b/src/main/java/com/newyetai/sdk/tonglian/dto/check/RequestCheck.java new file mode 100644 index 0000000..ef930ac --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tonglian/dto/check/RequestCheck.java @@ -0,0 +1,11 @@ +package com.newyetai.sdk.tonglian.dto.check; + +public interface RequestCheck { + + /** + * 检查 + * + * @return {@link String} 返回错误信息 , 如果没错误信息返回null + */ + String check(); +} diff --git a/src/main/java/com/newyetai/sdk/tonglian/dto/common/BasePageReqDTO.java b/src/main/java/com/newyetai/sdk/tonglian/dto/common/BasePageReqDTO.java new file mode 100644 index 0000000..ab16ed9 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tonglian/dto/common/BasePageReqDTO.java @@ -0,0 +1,39 @@ +package com.newyetai.sdk.tonglian.dto.common; + +import java.util.Objects; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = true) +@Data +public abstract class BasePageReqDTO extends BaseReqDTO { + /** + * 页码 + */ + private Integer curPage; + + /** + * 每页展示条数 : 区间 1-100 + */ + private Integer pageSize; + + public Integer getCurPage() { + if (Objects.isNull(curPage)){ + curPage = 1; + } + return curPage; + } + + public Integer getPageSize() { + if (Objects.isNull(pageSize)){ + pageSize = 100; + }else { + if (pageSize <= 1){ + pageSize = 1; + }else if (pageSize >= 100){ + pageSize = 100; + } + } + return pageSize; + } +} diff --git a/src/main/java/com/newyetai/sdk/tonglian/dto/common/BaseReqDTO.java b/src/main/java/com/newyetai/sdk/tonglian/dto/common/BaseReqDTO.java new file mode 100644 index 0000000..de1bd03 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tonglian/dto/common/BaseReqDTO.java @@ -0,0 +1,57 @@ +package com.newyetai.sdk.tonglian.dto.common; + +import java.io.Serializable; +import java.util.Map; +import java.util.Objects; +import lombok.Data; + +@Data +public abstract class BaseReqDTO implements Serializable { + + /** + * 令牌 + */ + private String token; + + /** + * 需要令牌 + */ + private Boolean needToken; + + /** + * 重试次数 + */ + private int retryNum; + + /** + * 处理结果 + */ + private TongLianBaseResDTO result; + + public Boolean getNeedToken() { + if (Objects.isNull(needToken)){ + needToken = Boolean.TRUE; + } + return needToken; + } + + /** + * 接口str + * + * @return {@link String} + */ + public abstract String interfaceStr(); + + /** + * 参数个数 + * + * @return {@link Map}<{@link String}, {@link Object}> + */ + public abstract Map params(); + + /** + * appId + */ + public abstract String appId(); + +} diff --git a/src/main/java/com/newyetai/sdk/tonglian/dto/common/TongLianBaseReqDTO.java b/src/main/java/com/newyetai/sdk/tonglian/dto/common/TongLianBaseReqDTO.java new file mode 100644 index 0000000..aefd8bd --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tonglian/dto/common/TongLianBaseReqDTO.java @@ -0,0 +1,78 @@ +package com.newyetai.sdk.tonglian.dto.common; + +import com.google.common.collect.Maps; +import com.newyetai.common.util.JsonUtils; +import java.io.Serializable; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Map; +import java.util.Objects; +import lombok.Data; + +@Data +public class TongLianBaseReqDTO implements Serializable { + + private static final long serialVersionUID = 3088759886459500676L; + /** + * 应用程序id + */ + private String appId; + + /** + * 时间戳 + */ + private String timestamp; + + /** + * 版本 + */ + private String version; + + /** + * 请求接口(接口名称) + */ + private String interfaceStr; + + /** + * 签名串 + */ + private String sign; + + /** + * 请求参数 + */ + private Map params; + + public String getTimestamp() { + if (Objects.isNull(timestamp)){ + DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); + timestamp = format.format(LocalDateTime.now()); + } + return timestamp; + } + + @Override + public String toString(){ +// Map params = getParams(); +// HashMap stringObjectHashMap = Maps.newHashMap(params); +// stringObjectHashMap.remove("token"); + return String.join("&" + ,String.join("=","appId",getAppId()) + ,String.join("=","interface",getInterfaceStr()) + ,String.join("=","params", JsonUtils.toJsonString(getParams())) + ,String.join("=","timestamp",getTimestamp()) + ,String.join("=","version",getVersion()) + ); + } + + public Map toMap(){ + Map map = Maps.newLinkedHashMap(); + map.put("appId",getAppId()); + map.put("timestamp",getTimestamp()); + map.put("version",getVersion()); + map.put("interface",getInterfaceStr()); + map.put("params",JsonUtils.toJsonString(getParams())); + map.put("sign",getSign()); + return map; + } +} diff --git a/src/main/java/com/newyetai/sdk/tonglian/dto/common/TongLianBaseResDTO.java b/src/main/java/com/newyetai/sdk/tonglian/dto/common/TongLianBaseResDTO.java new file mode 100644 index 0000000..841cb5f --- /dev/null +++ b/src/main/java/com/newyetai/sdk/tonglian/dto/common/TongLianBaseResDTO.java @@ -0,0 +1,58 @@ +package com.newyetai.sdk.tonglian.dto.common; + +import com.newyetai.common.AlitaResult; +import com.newyetai.sdk.tonglian.constants.TongLianConstants; +import java.io.Serializable; +import lombok.Data; +import org.apache.commons.lang3.StringUtils; + +@Data +public class TongLianBaseResDTO implements Serializable { + + private static final long serialVersionUID = -6153821486129399320L; + /** + * 服务调用是否成功 + */ + private String status; + + /** + * 错误代码 + */ + private String errorCode; + + /** + * 错误信息 + */ + private String message; + + /** + * 返回参数 + */ + private RES data; + + /** + * 签名串 + */ + private String sign; + + private String authId; + + public static TongLianBaseResDTO error(String errorMsg){ + TongLianBaseResDTO resDTO = new TongLianBaseResDTO<>(); + resDTO.setStatus(TongLianConstants.STATUS_ERROR); + resDTO.setMessage(errorMsg); + return resDTO; + } + + public Boolean isSuccess(){ + return StringUtils.equals(TongLianConstants.STATUS_OK,getStatus()); + } + + public AlitaResult toAlitaRes(){ + String status = getStatus(); + if (StringUtils.equals(TongLianConstants.STATUS_OK,status)){ + return AlitaResult.success(data); + } + return AlitaResult.error(message); + } +} diff --git a/src/main/java/com/newyetai/sdk/wechat/WechatClient.java b/src/main/java/com/newyetai/sdk/wechat/WechatClient.java new file mode 100644 index 0000000..b0b0040 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/WechatClient.java @@ -0,0 +1,201 @@ +package com.newyetai.sdk.wechat; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.springframework.http.MediaType; +import org.springframework.http.RequestEntity; +import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.web.client.RestTemplate; + +import com.google.common.collect.Lists; +import com.newyetai.common.AlitaResult; +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.common.util.RandomUtils; +import com.newyetai.sdk.common.constant.SdkConstants; +import com.newyetai.sdk.common.dto.DefaultSdkInvokeLogDTO; +import com.newyetai.sdk.common.dto.ISdkRequest; +import com.newyetai.sdk.wechat.constants.WechatConstants; +import com.newyetai.sdk.wechat.convert.WechatAppletWXACodeHttpMessageConverter; +import com.newyetai.sdk.wechat.model.AccessTokenDTO; +import com.newyetai.sdk.wechat.model.AccessTokenReq; +import com.newyetai.sdk.wechat.model.BaseWeChatDTO; +import com.newyetai.sdk.wechat.model.BatchUnionDTO; +import com.newyetai.sdk.wechat.model.BatchUnionReq; +import com.newyetai.sdk.wechat.model.BufferDTO; +import com.newyetai.sdk.wechat.model.Code2SessionDTO; +import com.newyetai.sdk.wechat.model.Code2SessionReq; +import com.newyetai.sdk.wechat.model.FullUserInfoDTO; +import com.newyetai.sdk.wechat.model.JsApiTicketDTO; +import com.newyetai.sdk.wechat.model.JsApiTicketReq; +import com.newyetai.sdk.wechat.model.PhoneNumberDTO; +import com.newyetai.sdk.wechat.model.PhoneNumberReq; +import com.newyetai.sdk.wechat.model.SubscibeMessageReq; +import com.newyetai.sdk.wechat.model.TemplateMessageReq; +import com.newyetai.sdk.wechat.model.UniformMessageReq; +import com.newyetai.sdk.wechat.model.UnlimitedWxacodeReq; +import com.newyetai.sdk.wechat.model.UrlSchemeDTO; +import com.newyetai.sdk.wechat.model.UrlSchemeReq; +import com.newyetai.sdk.wechat.model.CodeUserInfoReq; +import com.newyetai.sdk.wechat.model.SubscibeUserDTO; +import com.newyetai.sdk.wechat.model.SubscibeUserReq; +import com.newyetai.sdk.wechat.model.WxacodeReq; +import com.newyetai.sdk.wechat.util.WechatConvertUtils; + +import lombok.extern.slf4j.Slf4j; + +/** + * @author sr on 2021-02-03 + */ +@Slf4j +public class WechatClient implements Serializable { + + /** **/ + private static final long serialVersionUID = -7442540577253368037L; + private static RestTemplate restOperations; + + static { + restOperations = new RestTemplate(); + List> messageConverters = new ArrayList>(); + MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); + WechatAppletWXACodeHttpMessageConverter wxConvert = new WechatAppletWXACodeHttpMessageConverter(); + List mediaTypes = + Lists.newArrayList(MediaType.TEXT_PLAIN, MediaType.APPLICATION_JSON_UTF8); + converter.setSupportedMediaTypes(mediaTypes); + messageConverters.add(converter); + messageConverters.add(wxConvert); + restOperations.setMessageConverters(messageConverters); + } + + protected String appId; + protected String secret; + + public WechatClient(String appId, String secret) { + this.appId = appId; + this.secret = secret; + } + + public AlitaResult getAccessToken() { + AccessTokenReq param = AccessTokenReq.builder().appId(this.appId) + .secret(this.secret).build(); + return execute(WechatConvertUtils::convert, + param); + } + + public AlitaResult code2Session(String code) { + Code2SessionReq param = Code2SessionReq.builder().appId(this.appId) + .secret(this.secret).code(code).build(); + return execute(WechatConvertUtils::convert, + param); + } + + public static AlitaResult getJsApiTicket(String accessToken) { + JsApiTicketReq param = + JsApiTicketReq.builder().accessToken(accessToken).build(); + return execute(WechatConvertUtils::convert, + param); + } + + public static AlitaResult sendTemplateMessage( + TemplateMessageReq req) { + return execute(WechatConvertUtils::convertPost, req); + } + + public static AlitaResult getUrlscheme( + UrlSchemeReq req) { + return execute(WechatConvertUtils::convertPost, + req); + } + + public static AlitaResult getWxacode( + WxacodeReq req) { + return execute(WechatConvertUtils::convertPost, + req); + } + + public static AlitaResult getUnlimitedWxacode( + UnlimitedWxacodeReq req) { + String page = req.getPage(); + if (StringUtils.isNoneBlank(page) && page.startsWith("/")) { + req.setPage(page.substring(1)); + } + return execute(WechatConvertUtils::convertPost, + req); + } + + public static AlitaResult sendUniformMessage(UniformMessageReq req) { + return execute(WechatConvertUtils::convertPost, + req); + } + + public static AlitaResult subscibeMessage(SubscibeMessageReq req) { + return execute(WechatConvertUtils::convertPost, + req); + } + + public static AlitaResult getSubscibeUser(SubscibeUserReq req) { + return execute(WechatConvertUtils::convert, + req); + } + + public static AlitaResult getUserInfo(CodeUserInfoReq req) { + return execute(WechatConvertUtils::convert, + req); + } + + public static AlitaResult batchUnion(BatchUnionReq req) { + return execute(WechatConvertUtils::convertPost, + req); + } + + public static AlitaResult phoneNumber(PhoneNumberReq req) { + return execute(WechatConvertUtils::convertPost, + req); + } + + public static AlitaResult execute( + Function converter, S dto) { + // 日志记录调用结果 + Serializable responseData = null; + String requestId = RandomUtils.generateUUID(); + try { + // 获得request + RequestEntity request = converter + .apply(dto); + ResponseEntity response; + // 执行 + try { + response = restOperations.exchange(request, dto.getResponseClass()); + } catch (Exception e) { + e.printStackTrace(); + responseData = ExceptionUtils.getStackTrace(e); + return AlitaResult.error(SdkConstants.SDK_HTTP_INVOKE_ERROR_CODE, e.getMessage()); + } + T result = response.getBody(); + responseData = result; + String errCode = result.getErrcode(); + // 成功 + if (StringUtils.isBlank(errCode) + || WechatConstants.REQUEST_OK_CODE.equals(errCode)) { + return AlitaResult.success(result).setRequestId(requestId); + } + return AlitaResult.error(SdkConstants.SDK_HTTP_INVOKE_RESPONSE_FAIL_CODE, + String.join(CommonConstants.COLON, errCode, result.getErrmsg())) + .setRequestId(requestId); + } finally { + log.info("wechat invoke:{}", + JsonUtils + .toJsonString( + DefaultSdkInvokeLogDTO.builder().requestData(dto).responseData(responseData) + .requestId(requestId).methodType(dto.getMethodName()).build())); + } + } + +} diff --git a/src/main/java/com/newyetai/sdk/wechat/constants/WechatConstants.java b/src/main/java/com/newyetai/sdk/wechat/constants/WechatConstants.java new file mode 100644 index 0000000..4c39af1 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/constants/WechatConstants.java @@ -0,0 +1,64 @@ +package com.newyetai.sdk.wechat.constants; + +public interface WechatConstants { + + /** code授权获取用户信息 **/ + String USER_INFO_URL_FORMAT = + "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=%s"; + + /** 获取access_token **/ + String ACCESS_TOKEN_URL_FORMAT = + "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s"; + + /** 获取api_ticket **/ + String JS_API_TICKET_URL_FORMAT = + "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=%s&type=%s"; + + /** 获取小程序授权码换session信息 **/ + String CODE2SESSION_URL_FORMAT = + "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code"; + + /** 获取小程序 scheme 码(weixin:):30 天,无永久 **/ + String URLSCHEME_URL_PREFIX = + "https://api.weixin.qq.com/wxa/generatescheme?access_token="; + + /** 获取小程序 URL Link(跳H5 中间页) **/ + String URLLINK_URL_PREFIX = + "https://api.weixin.qq.com/wxa/generate_urllink?access_token="; + + + /** 获取小程序码-永久有效,有数量限制(10w) **/ + String WXACODE_PREFIX = "https://api.weixin.qq.com/wxa/getwxacode?access_token="; + + /** 获取小程序码-永久有效,数量暂无限制 **/ + String UNLIMITED_WXACODE_PREFIX = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token="; + + /** 模版消息请求前缀 **/ + String TEMPLATE_MESSAGE_URL_PREFIX = + "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token="; + + /** 统一服务消息前缀 **/ + String UNIFORM_MESSAGE_PREFIX = + "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/uniform_send?access_token="; + + /** 订阅消息前缀 **/ + String SUBSCIBE_MESSAGE_PREFIX = + "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token="; + /** 公共号关注者列表 **/ + String SUBSCIBE_USER_FORMAT = + "https://api.weixin.qq.com/cgi-bin/user/get?access_token=%s&next_openid=%s"; + + /** 获取用户unionId **/ + String UNION_FORMAT = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=%s&openid=%s&lang=&s"; + /** 批量获取用户unionId **/ + String BATCH_UNION_PREFIX = "https://api.weixin.qq.com/cgi-bin/user/info/batchget?access_token="; + + /** 获取手机号 **/ + String PHONE_NUMBER_PREFIX = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token="; + + + String JS_API_TICKET_TYPE = "jsapi"; + + String REQUEST_OK_CODE = "0"; + +} diff --git a/src/main/java/com/newyetai/sdk/wechat/constants/WechatErrorCodeEnum.java b/src/main/java/com/newyetai/sdk/wechat/constants/WechatErrorCodeEnum.java new file mode 100644 index 0000000..7351ff1 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/constants/WechatErrorCodeEnum.java @@ -0,0 +1,33 @@ +package com.newyetai.sdk.wechat.constants; + +/** + * 标识:微信(04) + * + * @author sr on 2021-02-03 + */ +public enum WechatErrorCodeEnum { + + /** 放心签调用返回错误码 **/ + ACCESS_TOKEN_ERROR("060401", "获取token失败"), + /** 放心签调用成功,但信息不匹配 **/ + TICKET_ERROR("060402", "获取ticket失败"); + + /** 错误码 **/ + private String code; + /** 错误信息 **/ + private String msg; + + WechatErrorCodeEnum(String code, String msg){ + this.code = code; + this.msg = msg; + } + + public String getCode() { + return code; + } + + public String getMsg() { + return msg; + } + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/sdk/wechat/constants/WechatMethodEnum.java b/src/main/java/com/newyetai/sdk/wechat/constants/WechatMethodEnum.java new file mode 100644 index 0000000..87ce0d3 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/constants/WechatMethodEnum.java @@ -0,0 +1,34 @@ +package com.newyetai.sdk.wechat.constants; + +/** + * 微信方法 + * @author sr on 2021-03-18 + */ +public enum WechatMethodEnum { + + ACCESS_TOKEN, + JS_API_TICKET, + USER_INFO, + TEMPLATE_MESSAGE, + LITE_ACCESS_TOKEN, + /** 小程序scheme **/ + URLSCHEME, + /** 小程序链接 **/ + URLLINK, + /** 有限制小程序码 **/ + WXACODE, + /** 无限制小程序码 **/ + UNLIMITED_WXACODE, + /** 统一服务消息 **/ + UNIFORM_MESSAGE, + /** 订阅消息 **/ + SUBSCIBE_MESSAGE, + /** 公共号关注者列表 **/ + SUBSCIBE_USER, + /** 获取unionId **/ + UNION, + /** 批量获取unionId **/ + BATCH_UNION, + /** 获取手机号 **/ + PHONE_NUMBER, +} diff --git a/src/main/java/com/newyetai/sdk/wechat/convert/WechatAppletWXACodeHttpMessageConverter.java b/src/main/java/com/newyetai/sdk/wechat/convert/WechatAppletWXACodeHttpMessageConverter.java new file mode 100644 index 0000000..1ceea9e --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/convert/WechatAppletWXACodeHttpMessageConverter.java @@ -0,0 +1,50 @@ +package com.newyetai.sdk.wechat.convert; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Collections; + +import org.springframework.http.HttpInputMessage; +import org.springframework.http.HttpOutputMessage; +import org.springframework.http.MediaType; +import org.springframework.http.converter.AbstractHttpMessageConverter; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.http.converter.HttpMessageNotWritableException; +import org.springframework.util.StreamUtils; + +import com.newyetai.sdk.wechat.model.BufferDTO; + +public class WechatAppletWXACodeHttpMessageConverter + extends AbstractHttpMessageConverter { + + public WechatAppletWXACodeHttpMessageConverter() { + super.setSupportedMediaTypes(Collections.singletonList(MediaType.IMAGE_JPEG)); + } + + @Override + protected boolean supports(Class clazz) { + return BufferDTO.class == clazz; + } + + @Override + protected BufferDTO readInternal(Class clazz, HttpInputMessage inputMessage) + throws IOException, HttpMessageNotReadableException { + long contentLength = inputMessage.getHeaders().getContentLength(); + ByteArrayOutputStream bos = + new ByteArrayOutputStream( + contentLength >= 0 ? (int) contentLength : StreamUtils.BUFFER_SIZE); + StreamUtils.copy(inputMessage.getBody(), bos); + bos.toByteArray(); + BufferDTO bufferDTO = new BufferDTO(); + bufferDTO.setBuffer(bos.toByteArray()); + bufferDTO.setErrcode("0"); + bufferDTO.setErrmsg("ok"); + return bufferDTO; + } + + @Override + protected void writeInternal(BufferDTO bufferDTO, HttpOutputMessage outputMessage) + throws IOException, HttpMessageNotWritableException { + StreamUtils.copy(bufferDTO.getBuffer(), outputMessage.getBody()); + } +} diff --git a/src/main/java/com/newyetai/sdk/wechat/model/AbstractAccessTokenReq.java b/src/main/java/com/newyetai/sdk/wechat/model/AbstractAccessTokenReq.java new file mode 100644 index 0000000..7ff95d9 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/model/AbstractAccessTokenReq.java @@ -0,0 +1,25 @@ +package com.newyetai.sdk.wechat.model; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.newyetai.sdk.common.dto.ISdkRequest; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * accessToken + * @author sr on 2021-12-24 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class AbstractAccessTokenReq implements ISdkRequest { + + /** 接口调用凭证 **/ + @JsonIgnore + private String accessToken; + +} diff --git a/src/main/java/com/newyetai/sdk/wechat/model/AccessTokenDTO.java b/src/main/java/com/newyetai/sdk/wechat/model/AccessTokenDTO.java new file mode 100644 index 0000000..fdce0d2 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/model/AccessTokenDTO.java @@ -0,0 +1,36 @@ +package com.newyetai.sdk.wechat.model; + +import java.io.Serializable; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2021-01-15 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +public class AccessTokenDTO extends BaseWeChatDTO implements Serializable { + + /** **/ + private static final long serialVersionUID = -1105568745155586204L; + + /** + * 接口调用凭证 + */ + @JsonProperty("access_token") + private String accessToken; + + /** + * access_token接口调用凭证超时时间,单位(秒) + */ + @JsonProperty("expires_in") + private String expiresIn; + +} diff --git a/src/main/java/com/newyetai/sdk/wechat/model/AccessTokenReq.java b/src/main/java/com/newyetai/sdk/wechat/model/AccessTokenReq.java new file mode 100644 index 0000000..ac90941 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/model/AccessTokenReq.java @@ -0,0 +1,49 @@ +package com.newyetai.sdk.wechat.model; + +import org.springframework.data.annotation.Transient; + +import com.newyetai.common.annotation.Mask; +import com.newyetai.sdk.common.dto.ISdkRequest; +import com.newyetai.sdk.wechat.constants.WechatConstants; +import com.newyetai.sdk.wechat.constants.WechatMethodEnum; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2021-01-15 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class AccessTokenReq implements ISdkRequest{ + + /** **/ + private static final long serialVersionUID = 4948765691546131290L; + + /** 第三方用户唯一凭证 **/ + private String appId; + /** 第三方用户唯一凭证密钥,即appsecret **/ + @Transient + @Mask + private String secret; + + @Override + public String getMethodName() { + return WechatMethodEnum.ACCESS_TOKEN.name(); + } + + @Override + public Class getResponseClass() { + return AccessTokenDTO.class; + } + + @Override + public String getUri() { + return WechatConstants.ACCESS_TOKEN_URL_FORMAT; + } + +} diff --git a/src/main/java/com/newyetai/sdk/wechat/model/BaseWeChatDTO.java b/src/main/java/com/newyetai/sdk/wechat/model/BaseWeChatDTO.java new file mode 100644 index 0000000..52aa248 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/model/BaseWeChatDTO.java @@ -0,0 +1,23 @@ +package com.newyetai.sdk.wechat.model; + +import lombok.Data; + +import java.io.Serializable; + +/** + * @author leijiaping + */ +@Data +public class BaseWeChatDTO implements Serializable { + + /** + * 错误编码 + */ + private String errcode; + + /** + * 错误信息 + */ + private String errmsg; + +} diff --git a/src/main/java/com/newyetai/sdk/wechat/model/BatchUnionDTO.java b/src/main/java/com/newyetai/sdk/wechat/model/BatchUnionDTO.java new file mode 100644 index 0000000..fd6333d --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/model/BatchUnionDTO.java @@ -0,0 +1,24 @@ +package com.newyetai.sdk.wechat.model; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +@AllArgsConstructor +public class BatchUnionDTO extends BaseWeChatDTO{ + + /** **/ + private static final long serialVersionUID = -4977565962655123684L; + + @JsonProperty("user_info_list") + private List userInfoList; + +} diff --git a/src/main/java/com/newyetai/sdk/wechat/model/BatchUnionReq.java b/src/main/java/com/newyetai/sdk/wechat/model/BatchUnionReq.java new file mode 100644 index 0000000..792fb1d --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/model/BatchUnionReq.java @@ -0,0 +1,49 @@ +package com.newyetai.sdk.wechat.model; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.newyetai.sdk.wechat.constants.WechatConstants; +import com.newyetai.sdk.wechat.constants.WechatMethodEnum; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.Singular; +import lombok.Builder.Default; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2021-01-15 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class BatchUnionReq extends AbstractAccessTokenReq{ + + /** **/ + private static final long serialVersionUID = 4948765691546131290L; + + @JsonProperty("user_list") + @Singular + private List users; + + @Override + public String getMethodName() { + return WechatMethodEnum.BATCH_UNION.name(); + } + + @Override + public Class getResponseClass() { + return BatchUnionDTO.class; + } + + @Override + public String getUri() { + return WechatConstants.BATCH_UNION_PREFIX; + } + + +} diff --git a/src/main/java/com/newyetai/sdk/wechat/model/BufferDTO.java b/src/main/java/com/newyetai/sdk/wechat/model/BufferDTO.java new file mode 100644 index 0000000..7d051ea --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/model/BufferDTO.java @@ -0,0 +1,24 @@ +package com.newyetai.sdk.wechat.model; + +import com.newyetai.common.annotation.Mask; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +@AllArgsConstructor +public class BufferDTO extends BaseWeChatDTO{ + + /** **/ + private static final long serialVersionUID = -1193016127255040596L; + + @Mask + private byte[] buffer; + + + +} diff --git a/src/main/java/com/newyetai/sdk/wechat/model/Code2SessionDTO.java b/src/main/java/com/newyetai/sdk/wechat/model/Code2SessionDTO.java new file mode 100644 index 0000000..793c5b8 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/model/Code2SessionDTO.java @@ -0,0 +1,35 @@ +package com.newyetai.sdk.wechat.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @author leijiaping + */ +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +public class Code2SessionDTO extends BaseWeChatDTO implements Serializable { + + /** + * 授权用户唯一标识 + */ + @JsonProperty("openid") + private String openId; + + /** + * 当且仅当该网站应用已获得该用户的userinfo授权时,才会出现该字段 + */ + @JsonProperty("unionid") + private String unionId; + + @JsonProperty("session_key") + private String sessionKey; +} diff --git a/src/main/java/com/newyetai/sdk/wechat/model/Code2SessionReq.java b/src/main/java/com/newyetai/sdk/wechat/model/Code2SessionReq.java new file mode 100644 index 0000000..235536f --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/model/Code2SessionReq.java @@ -0,0 +1,52 @@ +package com.newyetai.sdk.wechat.model; + +import org.springframework.data.annotation.Transient; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.newyetai.common.annotation.Mask; +import com.newyetai.sdk.common.dto.ISdkRequest; +import com.newyetai.sdk.wechat.constants.WechatConstants; +import com.newyetai.sdk.wechat.constants.WechatMethodEnum; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2021-01-15 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class Code2SessionReq implements ISdkRequest{ + + /** **/ + private static final long serialVersionUID = 4948765691546131290L; + /** 第三方用户唯一凭证 **/ + private String appId; + /** 第三方用户唯一凭证密钥,即appsecret **/ + @Transient + @Mask + private String secret; + /** 授权码 **/ + private String code; + + + @Override + public String getMethodName() { + return WechatMethodEnum.LITE_ACCESS_TOKEN.name(); + } + + @Override + public Class getResponseClass() { + return Code2SessionDTO.class; + } + + @Override + public String getUri() { + return WechatConstants.CODE2SESSION_URL_FORMAT; + } + +} diff --git a/src/main/java/com/newyetai/sdk/wechat/model/CodeUserInfoReq.java b/src/main/java/com/newyetai/sdk/wechat/model/CodeUserInfoReq.java new file mode 100644 index 0000000..11d547c --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/model/CodeUserInfoReq.java @@ -0,0 +1,43 @@ +package com.newyetai.sdk.wechat.model; + + +import com.newyetai.sdk.wechat.constants.WechatConstants; +import com.newyetai.sdk.wechat.constants.WechatMethodEnum; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2021-02-03 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class CodeUserInfoReq extends AbstractAccessTokenReq { + + /** **/ + private static final long serialVersionUID = -6862280353550142248L; + + /** code换取的token **/ + private String accessToken; + private String openId; + + @Override + public String getMethodName() { + return WechatMethodEnum.USER_INFO.name(); + } + + @Override + public Class getResponseClass() { + return FullUserInfoDTO.class; + } + + @Override + public String getUri() { + return WechatConstants.USER_INFO_URL_FORMAT; + } + +} diff --git a/src/main/java/com/newyetai/sdk/wechat/model/FullUserInfoDTO.java b/src/main/java/com/newyetai/sdk/wechat/model/FullUserInfoDTO.java new file mode 100644 index 0000000..9ef4b11 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/model/FullUserInfoDTO.java @@ -0,0 +1,36 @@ +package com.newyetai.sdk.wechat.model; + +import java.io.Serializable; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.newyetai.sdk.common.dto.LiteUserPhoneDTO; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 完整用户信息(包括敏感数据) + * @author sr on 2021-11-23 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class FullUserInfoDTO extends BaseWeChatDTO{ + + private static final long serialVersionUID = 267960916655973459L; + + + /** 用户唯一标识 **/ + @JsonProperty("openid") + private String openId; + private String nickname; + private Integer sex; + private String province; + private String city; + private String country; + private String headimgurl; + @JsonProperty("unionid") + private String unionId; + +} diff --git a/src/main/java/com/newyetai/sdk/wechat/model/JsApiTicketDTO.java b/src/main/java/com/newyetai/sdk/wechat/model/JsApiTicketDTO.java new file mode 100644 index 0000000..3136ae3 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/model/JsApiTicketDTO.java @@ -0,0 +1,29 @@ +package com.newyetai.sdk.wechat.model; + +import java.io.Serializable; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2021-01-15 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +@AllArgsConstructor +public class JsApiTicketDTO extends BaseWeChatDTO { + + /** **/ + private static final long serialVersionUID = 1038878005278639836L; + + private String ticket; + + @JsonProperty("expires_in") + private String expiresIn; + +} diff --git a/src/main/java/com/newyetai/sdk/wechat/model/JsApiTicketReq.java b/src/main/java/com/newyetai/sdk/wechat/model/JsApiTicketReq.java new file mode 100644 index 0000000..e1cf98b --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/model/JsApiTicketReq.java @@ -0,0 +1,43 @@ +package com.newyetai.sdk.wechat.model; + +import com.newyetai.sdk.common.dto.ISdkRequest; +import com.newyetai.sdk.wechat.constants.WechatConstants; +import com.newyetai.sdk.wechat.constants.WechatMethodEnum; + +import lombok.AllArgsConstructor; +import lombok.Builder.Default; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2021-01-15 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class JsApiTicketReq extends AbstractAccessTokenReq{ + + /** **/ + private static final long serialVersionUID = -6514900861070288478L; + + /** 类型 **/ + @Default + private String type = "jsapi"; + @Override + public String getMethodName() { + return WechatMethodEnum.JS_API_TICKET.name(); + } + + @Override + public Class getResponseClass() { + return JsApiTicketDTO.class; + } + + @Override + public String getUri() { + return WechatConstants.JS_API_TICKET_URL_FORMAT; + } + +} diff --git a/src/main/java/com/newyetai/sdk/wechat/model/JumpWxa.java b/src/main/java/com/newyetai/sdk/wechat/model/JumpWxa.java new file mode 100644 index 0000000..e3d2a7d --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/model/JumpWxa.java @@ -0,0 +1,33 @@ +package com.newyetai.sdk.wechat.model; + +import java.io.Serializable; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 跳转到的目标小程序信息 + * @author sr on 2021-08-31 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class JumpWxa implements Serializable{ + + /** **/ + private static final long serialVersionUID = -1294493512859560222L; + + /** 通过 scheme 码进入的小程序页面路径,必须是已经发布的小程序存在的页面,不可携带 query。path 为空时会跳转小程序主页 **/ + private String path; + /** 通过 scheme 码进入小程序时的 query,最大1024个字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~% **/ + private String query; + /** 要打开的小程序版本。正式版为"release",体验版为"trial",开发版为"develop",仅在微信外打开时生效 **/ + @JsonProperty("env_version") + private String envVersion; + +} diff --git a/src/main/java/com/newyetai/sdk/wechat/model/KeyData.java b/src/main/java/com/newyetai/sdk/wechat/model/KeyData.java new file mode 100644 index 0000000..6a06c1d --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/model/KeyData.java @@ -0,0 +1,28 @@ +package com.newyetai.sdk.wechat.model; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 模板数据 + * + * @author sr on 2021-02-03 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class KeyData implements Serializable{ + + /** **/ + private static final long serialVersionUID = 5875606119889091983L; + + private String value; + /** 模板内容字体颜色,不填默认为黑色 **/ + private String color; + +} diff --git a/src/main/java/com/newyetai/sdk/wechat/model/MiniProgram.java b/src/main/java/com/newyetai/sdk/wechat/model/MiniProgram.java new file mode 100644 index 0000000..75088d3 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/model/MiniProgram.java @@ -0,0 +1,29 @@ +package com.newyetai.sdk.wechat.model; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 跳小程序所需数据,不需跳小程序可不用传该数据 + * + * @author sr on 2021-02-03 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class MiniProgram implements Serializable { + + /** **/ + private static final long serialVersionUID = 1722801393721577667L; + + /** 必填;所需跳转到的小程序appid(该小程序appid必须与发模板消息的公众号是绑定关联关系,暂不支持小游戏) **/ + private String appid; + /** 所需跳转到小程序的具体页面路径,支持带参数,(示例index?foo=bar),要求该小程序已发布,暂不支持小游戏 **/ + private String pagepath; + +} diff --git a/src/main/java/com/newyetai/sdk/wechat/model/MpTemplateMsg.java b/src/main/java/com/newyetai/sdk/wechat/model/MpTemplateMsg.java new file mode 100644 index 0000000..f3998a8 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/model/MpTemplateMsg.java @@ -0,0 +1,39 @@ +package com.newyetai.sdk.wechat.model; + +import java.io.Serializable; +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 公众号模板消息相关的信息 + * @author sr on 2021-12-27 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class MpTemplateMsg implements Serializable{ + + /** **/ + private static final long serialVersionUID = 3061379199546766297L; + + /** 必填;公众号appid,要求与小程序有绑定且同主体 **/ + @JsonProperty("appid") + private String appId; + /** 必填;公众号模板id **/ + @JsonProperty("template_id") + private String templateId; + /** 必填;公众号模板消息所要跳转的url **/ + private String url; + /** 必填;公众号模板消息所要跳转的小程序,小程序的必须与公众号具有绑定关系 **/ + private MiniProgram miniprogram; + /** 必填;公众号模板消息的数据 **/ + private Map data; + +} diff --git a/src/main/java/com/newyetai/sdk/wechat/model/PhoneNumberDTO.java b/src/main/java/com/newyetai/sdk/wechat/model/PhoneNumberDTO.java new file mode 100644 index 0000000..06d08e7 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/model/PhoneNumberDTO.java @@ -0,0 +1,21 @@ +package com.newyetai.sdk.wechat.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.newyetai.sdk.common.dto.LiteUserPhoneDTO; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class PhoneNumberDTO extends BaseWeChatDTO{ + /** **/ + private static final long serialVersionUID = -4550034374482312096L; + + /** 用户手机号信息 **/ + @JsonProperty("phone_info") + private LiteUserPhoneDTO phoneInfo; + +} diff --git a/src/main/java/com/newyetai/sdk/wechat/model/PhoneNumberReq.java b/src/main/java/com/newyetai/sdk/wechat/model/PhoneNumberReq.java new file mode 100644 index 0000000..8243380 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/model/PhoneNumberReq.java @@ -0,0 +1,39 @@ +package com.newyetai.sdk.wechat.model; + +import com.newyetai.sdk.wechat.constants.WechatConstants; +import com.newyetai.sdk.wechat.constants.WechatMethodEnum; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class PhoneNumberReq extends AbstractAccessTokenReq { + + + /** **/ + private static final long serialVersionUID = 5602209770449461997L; + + /** 手机号获取凭证 **/ + private String code; + + @Override + public String getMethodName() { + return WechatMethodEnum.PHONE_NUMBER.name(); + } + + @Override + public String getUri() { + return WechatConstants.PHONE_NUMBER_PREFIX; + } + + @Override + public Class getResponseClass() { + return PhoneNumberDTO.class; + } + +} diff --git a/src/main/java/com/newyetai/sdk/wechat/model/SubscibeMessageReq.java b/src/main/java/com/newyetai/sdk/wechat/model/SubscibeMessageReq.java new file mode 100644 index 0000000..59d77f0 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/model/SubscibeMessageReq.java @@ -0,0 +1,57 @@ +package com.newyetai.sdk.wechat.model; + +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.newyetai.sdk.wechat.constants.WechatConstants; +import com.newyetai.sdk.wechat.constants.WechatMethodEnum; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 下发小程序和公众号统一的服务消息 + * @author sr on 2021-12-27 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class SubscibeMessageReq extends AbstractAccessTokenReq { + + /** **/ + private static final long serialVersionUID = -5132718249745640058L; + + /** 是;接收者(用户)的 openid **/ + @JsonProperty("touser") + private String touser; + /** 是;所需下发的订阅模板id **/ + @JsonProperty("template_id") + private String templateId; + /** 否;点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转。 **/ + private String page; + /** 是;模板内容,格式形如 { "key1": { "value": any }, "key2": { "value": any } } **/ + private Map data; + /** 否;跳转小程序类型:developer为开发版;trial为体验版;formal为正式版;默认为正式版 **/ + @JsonProperty("miniprogram_state") + private String miniprogramState; + /** 否;进入小程序查看”的语言类型,支持zh_CN(简体中文)、en_US(英文)、zh_HK(繁体中文)、zh_TW(繁体中文),默认为zh_CN **/ + private String lang; + + @Override + public String getMethodName() { + return WechatMethodEnum.SUBSCIBE_MESSAGE.name(); + } + + @Override + public Class getResponseClass() { + return BaseWeChatDTO.class; + } + + @Override + public String getUri() { + return WechatConstants.SUBSCIBE_MESSAGE_PREFIX; + } +} diff --git a/src/main/java/com/newyetai/sdk/wechat/model/SubscibeUserDTO.java b/src/main/java/com/newyetai/sdk/wechat/model/SubscibeUserDTO.java new file mode 100644 index 0000000..9f5815b --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/model/SubscibeUserDTO.java @@ -0,0 +1,35 @@ +package com.newyetai.sdk.wechat.model; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +@AllArgsConstructor +public class SubscibeUserDTO extends BaseWeChatDTO{ + + /** **/ + private static final long serialVersionUID = -1777884193437529632L; + + private Long total; + private Long count; + private UserData data; + + @Data + @NoArgsConstructor + @AllArgsConstructor + public class UserData{ + @JsonProperty("openid") + private List openId; + @JsonProperty("next_openid") + private String nextOpenId; + } + +} diff --git a/src/main/java/com/newyetai/sdk/wechat/model/SubscibeUserReq.java b/src/main/java/com/newyetai/sdk/wechat/model/SubscibeUserReq.java new file mode 100644 index 0000000..4b67fa6 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/model/SubscibeUserReq.java @@ -0,0 +1,44 @@ +package com.newyetai.sdk.wechat.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.newyetai.sdk.wechat.constants.WechatConstants; +import com.newyetai.sdk.wechat.constants.WechatMethodEnum; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 一次拉取调用最多拉取10000个关注者的OpenID + * @author sr on 2021-01-15 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class SubscibeUserReq extends AbstractAccessTokenReq{ + + /** **/ + private static final long serialVersionUID = 4948765691546131290L; + + /** 第一个拉取的OPENID,不填默认从头开始拉取 **/ + @JsonProperty("next_openid") + private String nextOpenId; + + @Override + public String getMethodName() { + return WechatMethodEnum.SUBSCIBE_USER.name(); + } + + @Override + public Class getResponseClass() { + return SubscibeUserDTO.class; + } + + @Override + public String getUri() { + return WechatConstants.SUBSCIBE_USER_FORMAT; + } + +} diff --git a/src/main/java/com/newyetai/sdk/wechat/model/TemplateMessageReq.java b/src/main/java/com/newyetai/sdk/wechat/model/TemplateMessageReq.java new file mode 100644 index 0000000..ed7ea19 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/model/TemplateMessageReq.java @@ -0,0 +1,54 @@ +package com.newyetai.sdk.wechat.model; + +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.newyetai.sdk.common.dto.ISdkRequest; +import com.newyetai.sdk.wechat.constants.WechatConstants; +import com.newyetai.sdk.wechat.constants.WechatMethodEnum; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class TemplateMessageReq extends AbstractAccessTokenReq { + + /** **/ + private static final long serialVersionUID = 9107415797489637178L; + + /** 必填;不参与body序列化 **/ + /** 必填;接收者openid **/ + @JsonProperty("touser") + private String toUser; + /** 必填;模板ID **/ + @JsonProperty("template_id") + private String templateId; + /** 模板跳转链接(海外帐号没有跳转能力) **/ + private String url; + /** 跳小程序所需数据,不需跳小程序可不用传该数据 **/ + @JsonProperty("miniprogram") + private MiniProgram miniProgram; + /** 必填;模板数据 **/ + private Map data; + + @Override + public String getMethodName() { + return WechatMethodEnum.TEMPLATE_MESSAGE.name(); + } + + @Override + public Class getResponseClass() { + return BaseWeChatDTO.class; + } + + @Override + public String getUri() { + return WechatConstants.TEMPLATE_MESSAGE_URL_PREFIX; + } + +} diff --git a/src/main/java/com/newyetai/sdk/wechat/model/UniformMessageReq.java b/src/main/java/com/newyetai/sdk/wechat/model/UniformMessageReq.java new file mode 100644 index 0000000..6767e1f --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/model/UniformMessageReq.java @@ -0,0 +1,48 @@ +package com.newyetai.sdk.wechat.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.newyetai.sdk.wechat.constants.WechatConstants; +import com.newyetai.sdk.wechat.constants.WechatMethodEnum; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 下发小程序和公众号统一的服务消息 + * @author sr on 2021-12-27 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class UniformMessageReq extends AbstractAccessTokenReq { + + /** **/ + private static final long serialVersionUID = -5132718249745640058L; + + /** 必填;用户openid,可以是小程序的openid,也可以是mp_template_msg.appid对应的公众号的openid **/ + private String touser; + /** 小程序模板消息相关的信息,可以参考小程序模板消息接口; 有此节点则优先发送小程序模板消息;(小程序模板消息已下线,不用传此节点) **/ + @JsonProperty("weapp_template_msg") + private WeappTemplateMsg weappTemplateMsg; + /** 公众号模板消息相关的信息,可以参考公众号模板消息接口;有此节点并且没有weapp_template_msg节点时,发送公众号模板消息 **/ + @JsonProperty("mp_template_msg") + private MpTemplateMsg mpTemplateMsg; + + @Override + public String getMethodName() { + return WechatMethodEnum.UNIFORM_MESSAGE.name(); + } + + @Override + public Class getResponseClass() { + return BaseWeChatDTO.class; + } + + @Override + public String getUri() { + return WechatConstants.UNIFORM_MESSAGE_PREFIX; + } +} diff --git a/src/main/java/com/newyetai/sdk/wechat/model/UnionDTO.java b/src/main/java/com/newyetai/sdk/wechat/model/UnionDTO.java new file mode 100644 index 0000000..63e2e91 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/model/UnionDTO.java @@ -0,0 +1,52 @@ +package com.newyetai.sdk.wechat.model; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +@AllArgsConstructor +public class UnionDTO extends BaseWeChatDTO{ + + /** **/ + private static final long serialVersionUID = 2798332163629305353L; + + /** 用户是否订阅该公众号标识,值为0时,代表此用户没有关注该公众号,拉取不到其余信息。 **/ + private Integer subscribe; + /** 用户的标识,对当前公众号唯一 **/ + @JsonProperty("openid") + private String openId; + /** 用户的语言,简体中文为zh_CN **/ + private String language; + /** 用户关注时间,为时间戳。如果用户曾多次关注,则取最后关注时间 **/ + @JsonProperty("subscribe_time") + private String subscribe_time; + /** 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。 **/ + @JsonProperty("unionid") + private String unionId; + /** 公众号运营者对粉丝的备注,公众号运营者可在微信公众平台用户管理界面对粉丝添加备注 **/ + private String remark; + /** 用户所在的分组ID(兼容旧的用户分组接口) **/ + @JsonProperty("groupid") + private String groupId; + /** 用户被打上的标签ID列表 **/ + @JsonProperty("tagid_list") + private List tagidList; + /** 返回用户关注的渠道来源,ADD_SCENE_SEARCH 公众号搜索,ADD_SCENE_ACCOUNT_MIGRATION 公众号迁移,ADD_SCENE_PROFILE_CARD 名片分享,ADD_SCENE_QR_CODE 扫描二维码,ADD_SCENE_PROFILE_LINK 图文页内名称点击,ADD_SCENE_PROFILE_ITEM 图文页右上角菜单,ADD_SCENE_PAID 支付后关注,ADD_SCENE_WECHAT_ADVERTISEMENT 微信广告,ADD_SCENE_REPRINT 他人转载 ,ADD_SCENE_LIVESTREAM 视频号直播,ADD_SCENE_CHANNELS 视频号 , ADD_SCENE_OTHERS其他 **/ + @JsonProperty("subscribe_scene") + private String subscribeScene; + /** 二维码扫码场景(开发者自定义) **/ + @JsonProperty("qr_scene") + private String qrScene; + /** 二维码扫码场景描述(开发者自定义) **/ + @JsonProperty("qr_scene_str") + private String qrSceneStr; + +} diff --git a/src/main/java/com/newyetai/sdk/wechat/model/UnionReq.java b/src/main/java/com/newyetai/sdk/wechat/model/UnionReq.java new file mode 100644 index 0000000..a72ed20 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/model/UnionReq.java @@ -0,0 +1,42 @@ +package com.newyetai.sdk.wechat.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.newyetai.sdk.wechat.constants.WechatConstants; +import com.newyetai.sdk.wechat.constants.WechatMethodEnum; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2021-01-15 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class UnionReq extends AbstractAccessTokenReq{ + + /** **/ + private static final long serialVersionUID = 4948765691546131290L; + + @JsonProperty("openid") + private String openId; + + @Override + public String getMethodName() { + return WechatMethodEnum.UNION.name(); + } + + @Override + public Class getResponseClass() { + return UnionDTO.class; + } + + @Override + public String getUri() { + return WechatConstants.UNION_FORMAT; + } + +} diff --git a/src/main/java/com/newyetai/sdk/wechat/model/UnionUser.java b/src/main/java/com/newyetai/sdk/wechat/model/UnionUser.java new file mode 100644 index 0000000..4a59376 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/model/UnionUser.java @@ -0,0 +1,22 @@ +package com.newyetai.sdk.wechat.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.Builder.Default; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class UnionUser{ + + @JsonProperty("openid") + private String openId; + @Default + private String lang = "zh_CN"; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/sdk/wechat/model/UnlimitedWxacodeReq.java b/src/main/java/com/newyetai/sdk/wechat/model/UnlimitedWxacodeReq.java new file mode 100644 index 0000000..01f9cc1 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/model/UnlimitedWxacodeReq.java @@ -0,0 +1,60 @@ +package com.newyetai.sdk.wechat.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.newyetai.sdk.wechat.constants.WechatConstants; +import com.newyetai.sdk.wechat.constants.WechatMethodEnum; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class UnlimitedWxacodeReq extends AbstractAccessTokenReq { + + /** **/ + private static final long serialVersionUID = -8932288648630324802L; + + /** + * 必填;最大32个可见字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~,其它字符请自行编码为合法字符(因不支持%,中文无法使用 urlencode 处理,请使用其他编码方式) + **/ + private String scene; + /** 页面 page,例如 pages/index/index,根路径前不要填加 /,不能携带参数(参数请放在scene字段里),如果不填写这个字段,默认跳主页面 **/ + private String page; + /** 检查page 是否存在,为 true 时 page 必须是已经发布的小程序存在的页面(否则报错);为 false 时允许小程序未发布或者 page 不存在, 但page 有数量上限(60000个)请勿滥用 **/ + @JsonProperty("check_path") + private Boolean checkPath; + /** 要打开的小程序版本。正式版为 "release",体验版为 "trial",开发版为 "develop" **/ + @JsonProperty("env_version") + private String envVersion; + /** 二维码的宽度,单位 px。最小 280px,最大 1280px **/ + private Integer width; + /** 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调 **/ + @JsonProperty("auto_color") + private Boolean autoColor; + /** auto_color 为 false 时生效,使用 rgb 设置颜色 例如 {"r":"xxx","g":"xxx","b":"xxx"} 十进制表示 **/ + @JsonProperty("line_color") + private String lineColor; + /** 是否需要透明底色,为 true 时,生成透明底色的小程序码 **/ + @JsonProperty("is_hyaline") + private Boolean isHyaline; + + @Override + public String getMethodName() { + return WechatMethodEnum.UNLIMITED_WXACODE.name(); + } + + @Override + public Class getResponseClass() { + return BufferDTO.class; + } + + @Override + public String getUri() { + return WechatConstants.UNLIMITED_WXACODE_PREFIX; + } + +} diff --git a/src/main/java/com/newyetai/sdk/wechat/model/UrlLinkDTO.java b/src/main/java/com/newyetai/sdk/wechat/model/UrlLinkDTO.java new file mode 100644 index 0000000..69d7f03 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/model/UrlLinkDTO.java @@ -0,0 +1,29 @@ +package com.newyetai.sdk.wechat.model; + +import java.io.Serializable; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2021-08-31 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +@AllArgsConstructor +public class UrlLinkDTO extends BaseWeChatDTO { + + /** **/ + private static final long serialVersionUID = 1038878005278639836L; + + /** 生成的小程序 URL Link **/ + @JsonProperty("url_link") + private String urlLink; + + +} diff --git a/src/main/java/com/newyetai/sdk/wechat/model/UrlLinkReq.java b/src/main/java/com/newyetai/sdk/wechat/model/UrlLinkReq.java new file mode 100644 index 0000000..40c8f16 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/model/UrlLinkReq.java @@ -0,0 +1,56 @@ +package com.newyetai.sdk.wechat.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.newyetai.sdk.wechat.constants.WechatConstants; +import com.newyetai.sdk.wechat.constants.WechatMethodEnum; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class UrlLinkReq extends AbstractAccessTokenReq { + + /** **/ + private static final long serialVersionUID = -1711028840697002351L; + + /** 否 通过 URL Link 进入的小程序页面路径,必须是已经发布的小程序存在的页面,不可携带 query 。path 为空时会跳转小程序主页 **/ + private String path; + /** 否 通过 URL Link 进入小程序时的query,最大1024个字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~% **/ + private String query; + /** 否 默认值false。生成的 URL Link 类型,到期失效:true,永久有效:false。注意,永久有效 Link 和有效时间超过180天的到期失效 Link 的总数上限为10万个,详见获取 URL Link,生成 Link 前请仔细确认。 **/ + @JsonProperty("is_expire") + private Boolean isExpire; + /** 否 默认值0.小程序 URL Link 失效类型,失效时间:0,失效间隔天数:1 **/ + @JsonProperty("expire_type") + private Integer expireType; + /** 否 到期失效的 URL Link 的失效时间,为 Unix 时间戳。生成的到期失效 URL Link 在该时间前有效。最长有效期为1年。expire_type 为 0 必填 **/ + @JsonProperty("expire_time") + private Long expireTime; + /** 否 到期失效的URL Link的失效间隔天数。生成的到期失效URL Link在该间隔时间到达前有效。最长间隔天数为365天。expire_type 为 1 必填 **/ + @JsonProperty("expire_interval") + private Integer expireInterval; + /** 要打开的小程序版本。正式版为"release",体验版为"trial",开发版为"develop",仅在微信外打开时生效 **/ + @JsonProperty("env_version") + private String envVersion; + + @Override + public String getMethodName() { + return WechatMethodEnum.URLLINK.name(); + } + + @Override + public String getUri() { + return WechatConstants.URLLINK_URL_PREFIX; + } + + @Override + public Class getResponseClass() { + return UrlLinkDTO.class; + } + +} diff --git a/src/main/java/com/newyetai/sdk/wechat/model/UrlSchemeDTO.java b/src/main/java/com/newyetai/sdk/wechat/model/UrlSchemeDTO.java new file mode 100644 index 0000000..192731f --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/model/UrlSchemeDTO.java @@ -0,0 +1,26 @@ +package com.newyetai.sdk.wechat.model; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2021-08-31 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +@AllArgsConstructor +public class UrlSchemeDTO extends BaseWeChatDTO implements Serializable { + + /** **/ + private static final long serialVersionUID = 1038878005278639836L; + + /** 生成的小程序 scheme 码 **/ + private String openlink; + + +} diff --git a/src/main/java/com/newyetai/sdk/wechat/model/UrlSchemeReq.java b/src/main/java/com/newyetai/sdk/wechat/model/UrlSchemeReq.java new file mode 100644 index 0000000..4d7e06e --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/model/UrlSchemeReq.java @@ -0,0 +1,56 @@ +package com.newyetai.sdk.wechat.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.newyetai.sdk.common.dto.ISdkRequest; +import com.newyetai.sdk.wechat.constants.WechatConstants; +import com.newyetai.sdk.wechat.constants.WechatMethodEnum; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class UrlSchemeReq extends AbstractAccessTokenReq { + + /** **/ + private static final long serialVersionUID = -4150840251643273167L; + + /** 跳转到的目标小程序信息 **/ + @JsonProperty("jump_wxa") + private JumpWxa jumpWxa; + /** 生成的 scheme 码类型, + * 到期失效:true, + * 永久有效:false。注意,永久有效 scheme 和有效时间超过180天的到期失效 scheme 的总数上限为10万个,详见获取 URL scheme,生成 scheme 码前请仔细确认 **/ + @JsonProperty("is_expire") + private Boolean isExpire; + /** 到期失效的 scheme 码失效类型,失效时间:0,失效间隔天数:1 **/ + @JsonProperty("expire_type") + private Integer expireType; + /** 到期失效的 scheme 码的失效时间,为 Unix 时间戳。生成的到期失效 scheme 码在该时间前有效。最长有效期为1年。is_expire 为 true 且 expire_type 为 0 时必填 **/ + @JsonProperty("expire_time") + private Long expireTime; + /** 到期失效的 scheme 码的失效间隔天数。生成的到期失效 scheme 码在该间隔时间到达前有效。最长间隔天数为365天。is_expire 为 true 且 expire_type 为 1 时必填 **/ + @JsonProperty("expire_interval") + private Integer expireInterval; + + + @Override + public String getMethodName() { + return WechatMethodEnum.URLSCHEME.name(); + } + + @Override + public Class getResponseClass() { + return UrlSchemeDTO.class; + } + + @Override + public String getUri() { + return WechatConstants.URLSCHEME_URL_PREFIX; + } + +} diff --git a/src/main/java/com/newyetai/sdk/wechat/model/Watermark.java b/src/main/java/com/newyetai/sdk/wechat/model/Watermark.java new file mode 100644 index 0000000..8539579 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/model/Watermark.java @@ -0,0 +1,29 @@ +package com.newyetai.sdk.wechat.model; + +import java.io.Serializable; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 敏感数据加上的数据水印 + * @author sr on 2021-11-23 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class Watermark implements Serializable{ + + /** **/ + private static final long serialVersionUID = -109291749778239377L; + + /** 敏感数据归属 appId,开发者可校验此参数与自身 appId 是否一致 **/ + @JsonProperty("appid") + private String appId; + /** 敏感数据获取的时间戳, 开发者可以用于数据时效性校验 **/ + private Integer timestamp; + +} diff --git a/src/main/java/com/newyetai/sdk/wechat/model/WeappTemplateMsg.java b/src/main/java/com/newyetai/sdk/wechat/model/WeappTemplateMsg.java new file mode 100644 index 0000000..db9aae6 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/model/WeappTemplateMsg.java @@ -0,0 +1,39 @@ +package com.newyetai.sdk.wechat.model; + +import java.io.Serializable; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 小程序模板消息相关的信息 + * @author sr on 2021-12-27 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class WeappTemplateMsg implements Serializable{ + + /** **/ + private static final long serialVersionUID = 5229761630079036441L; + + /** 必填;小程序模板ID **/ + @JsonProperty("template_id") + private String templateId; + /** 必填;小程序页面路径 **/ + private String page; + /** 必填;小程序模板消息formid **/ + @JsonProperty("form_id") + private String formId; + /** 必填;小程序模板数据 **/ + private String data; + /** 必填;小程序模板放大关键词 **/ + @JsonProperty("emphasis_keyword") + private String emphasisKeyword; + +} diff --git a/src/main/java/com/newyetai/sdk/wechat/model/WxacodeReq.java b/src/main/java/com/newyetai/sdk/wechat/model/WxacodeReq.java new file mode 100644 index 0000000..3f451ad --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/model/WxacodeReq.java @@ -0,0 +1,54 @@ +package com.newyetai.sdk.wechat.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.newyetai.sdk.wechat.constants.WechatConstants; +import com.newyetai.sdk.wechat.constants.WechatMethodEnum; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class WxacodeReq extends AbstractAccessTokenReq { + + /** **/ + private static final long serialVersionUID = -8932288648630324802L; + + /** + * 必填;扫码进入的小程序页面路径,最大长度 128 字节,不能为空; + * 对于小游戏,可以只传入 query 部分,来实现传参效果, + * 如:传入 "?foo=bar",即可在 wx.getLaunchOptionsSync 接口中的 query 参数获取到 {foo:"bar"} + **/ + private String path; + /** 二维码的宽度,单位 px。最小 280px,最大 1280px **/ + private Integer width; + /** 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调 **/ + @JsonProperty("auto_color") + private Boolean autoColor; + /** auto_color 为 false 时生效,使用 rgb 设置颜色 例如 {"r":"xxx","g":"xxx","b":"xxx"} 十进制表示 **/ + @JsonProperty("line_color") + private String lineColor; + /** 是否需要透明底色,为 true 时,生成透明底色的小程序码 **/ + @JsonProperty("is_hyaline") + private Boolean isHyaline; + + @Override + public String getMethodName() { + return WechatMethodEnum.WXACODE.name(); + } + + @Override + public Class getResponseClass() { + return BufferDTO.class; + } + + @Override + public String getUri() { + return WechatConstants.WXACODE_PREFIX; + } + +} diff --git a/src/main/java/com/newyetai/sdk/wechat/util/MessageParamUtils.java b/src/main/java/com/newyetai/sdk/wechat/util/MessageParamUtils.java new file mode 100644 index 0000000..34bbfcf --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/util/MessageParamUtils.java @@ -0,0 +1,38 @@ +package com.newyetai.sdk.wechat.util; + +import java.util.Collections; +import java.util.Map; + +import com.google.common.collect.Maps; +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.sdk.wechat.model.KeyData; +import org.apache.commons.lang3.StringUtils; + +public class MessageParamUtils { + + public static final String THING_PREFIX = "thing"; + public static final int THING_LIMIT = 20; + + public static Map dealData(Map params) { + if (params == null) { + return Collections.emptyMap(); + } + Map data = Maps.newHashMapWithExpectedSize(params.size()); + params.forEach((k, v) -> { + String value = v == null ? null: v.toString(); + if (k.startsWith(THING_PREFIX)) { + value = dealThing(value); + } + data.put(k, KeyData.builder().value(value).build()); + }); + return data; + } + + public static String dealThing(String value) { + if (StringUtils.isBlank(value)) { + return CommonConstants.HYPHEN; + } + return value.length() > THING_LIMIT ? (value.substring(0, 17) + CommonConstants.ELLIPSIS) : value; + } + +} diff --git a/src/main/java/com/newyetai/sdk/wechat/util/WechatConvertUtils.java b/src/main/java/com/newyetai/sdk/wechat/util/WechatConvertUtils.java new file mode 100644 index 0000000..cc3ef7e --- /dev/null +++ b/src/main/java/com/newyetai/sdk/wechat/util/WechatConvertUtils.java @@ -0,0 +1,87 @@ +package com.newyetai.sdk.wechat.util; + +import java.net.URI; +import java.util.Collections; +import java.util.Optional; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.http.RequestEntity; +import org.springframework.web.util.UriComponentsBuilder; + +import com.newyetai.sdk.wechat.constants.WechatConstants; +import com.newyetai.sdk.wechat.model.AbstractAccessTokenReq; +import com.newyetai.sdk.wechat.model.AccessTokenReq; +import com.newyetai.sdk.wechat.model.Code2SessionReq; +import com.newyetai.sdk.wechat.model.CodeUserInfoReq; +import com.newyetai.sdk.wechat.model.FullUserInfoDTO; +import com.newyetai.sdk.wechat.model.JsApiTicketReq; +import com.newyetai.sdk.wechat.model.SubscibeUserReq; +import com.newyetai.sdk.wechat.model.UnionReq; + +public class WechatConvertUtils { + + public static RequestEntity convert(AccessTokenReq param) { + HttpHeaders headers = new HttpHeaders(); + headers.setAccept(Collections.singletonList(MediaType.TEXT_PLAIN)); + String url = + String.format(param.getUri(), param.getAppId(), + param.getSecret()); + URI uri = UriComponentsBuilder.fromUriString(url).build().toUri(); + return new RequestEntity<>(headers, HttpMethod.GET, uri); + } + + public static RequestEntity convert(Code2SessionReq param) { + String url = + String.format(param.getUri(), param.getAppId(), + param.getSecret(), param.getCode()); + URI uri = UriComponentsBuilder.fromUriString(url).build().toUri(); + return new RequestEntity<>(HttpMethod.GET, uri); + } + + public static RequestEntity convert(JsApiTicketReq param) { + HttpHeaders headers = new HttpHeaders(); + headers.setAccept(Collections.singletonList(MediaType.TEXT_PLAIN)); + String url = + String.format(param.getUri(), param.getAccessToken(), + param.getType()); + URI uri = UriComponentsBuilder.fromUriString(url).build().toUri(); + return new RequestEntity<>(headers, HttpMethod.GET, uri); + } + + public static RequestEntity convert(CodeUserInfoReq param) { + HttpHeaders headers = new HttpHeaders(); + headers.setAccept(Collections.singletonList(MediaType.TEXT_PLAIN)); + String url = + String.format(WechatConstants.USER_INFO_URL_FORMAT, + param.getAccessToken(), param.getOpenId(), "zh_CN"); + URI uri = UriComponentsBuilder.fromUriString(url).build().toUri(); + return new RequestEntity<>(headers, HttpMethod.GET, uri); + } + + public static RequestEntity convertPost(AbstractAccessTokenReq req) { + URI uri = UriComponentsBuilder + .fromUriString( + req.getUri() + req.getAccessToken()) + .build().toUri(); + return new RequestEntity<>(req, HttpMethod.POST, uri); + } + + public static RequestEntity convert(SubscibeUserReq param) { + String url = + String.format(param.getUri(), param.getAccessToken(), + Optional.ofNullable(param.getNextOpenId()).orElse("")); + URI uri = UriComponentsBuilder.fromUriString(url).build().toUri(); + return new RequestEntity<>(HttpMethod.GET, uri); + } + + public static RequestEntity convert(UnionReq param) { + String url = + String.format(param.getUri(), param.getAccessToken(), + param.getOpenId(), "zh_CN"); + URI uri = UriComponentsBuilder.fromUriString(url).build().toUri(); + return new RequestEntity<>(HttpMethod.GET, uri); + } + +} diff --git a/src/main/java/com/newyetai/sdk/workwechat/constant/WorkWechatConstants.java b/src/main/java/com/newyetai/sdk/workwechat/constant/WorkWechatConstants.java new file mode 100644 index 0000000..63efb92 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/workwechat/constant/WorkWechatConstants.java @@ -0,0 +1,10 @@ +package com.newyetai.sdk.workwechat.constant; + +/** + * @author sr on 2020-07-06 + */ +public interface WorkWechatConstants { + + String AT_ALL = "@all"; + +} diff --git a/src/main/java/com/newyetai/sdk/workwechat/model/WwrArticleMsg.java b/src/main/java/com/newyetai/sdk/workwechat/model/WwrArticleMsg.java new file mode 100644 index 0000000..0ac7c82 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/workwechat/model/WwrArticleMsg.java @@ -0,0 +1,45 @@ +package com.newyetai.sdk.workwechat.model; + +import java.io.Serializable; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.newyetai.sdk.robot.constant.WorkWechatMsgTypeEnum; +import com.newyetai.sdk.robot.model.IWorkWechatMsg; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * 企业微信机器人消息-图文 + * + * @author sr on 2020-07-06 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class WwrArticleMsg extends IWorkWechatMsg implements Serializable { + + /** **/ + private static final long serialVersionUID = -1870915544362911162L; + + /** 标题,不超过128个字节,超过会自动截断 **/ + private String title; + /** 描述,不超过512个字节,超过会自动截断 **/ + private String description; + /** 点击后跳转的链接 **/ + private String url; + /** 图文消息的图片链接,支持JPG、PNG格式,较好的效果为大图 1068*455,小图150*150 **/ + @JsonProperty("picurl") + private String picUrl; + + @Override + public String getMsgType() { + return WorkWechatMsgTypeEnum.NEWS.getType(); + } + +} diff --git a/src/main/java/com/newyetai/sdk/workwechat/model/WwrImageMsg.java b/src/main/java/com/newyetai/sdk/workwechat/model/WwrImageMsg.java new file mode 100644 index 0000000..427d2b0 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/workwechat/model/WwrImageMsg.java @@ -0,0 +1,40 @@ +package com.newyetai.sdk.workwechat.model; + +import java.io.Serializable; + +import com.newyetai.sdk.robot.constant.WorkWechatMsgTypeEnum; +import com.newyetai.sdk.robot.model.IWorkWechatMsg; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * 企业微信机器人消息-图片 + * + * @author sr on 2020-07-06 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class WwrImageMsg extends IWorkWechatMsg implements Serializable { + + /** **/ + private static final long serialVersionUID = 388617076942476152L; + + /** 图片内容的base64编码 **/ + private String base64; + /** 图片内容(base64编码前)的md5值 **/ + private String md5; + + + @Override + public String getMsgType() { + return WorkWechatMsgTypeEnum.IMAGE.getType(); + } + +} diff --git a/src/main/java/com/newyetai/sdk/workwechat/model/WwrMarkdownMsg.java b/src/main/java/com/newyetai/sdk/workwechat/model/WwrMarkdownMsg.java new file mode 100644 index 0000000..6369816 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/workwechat/model/WwrMarkdownMsg.java @@ -0,0 +1,37 @@ +package com.newyetai.sdk.workwechat.model; + +import java.io.Serializable; + +import com.newyetai.sdk.robot.constant.WorkWechatMsgTypeEnum; +import com.newyetai.sdk.robot.model.IWorkWechatMsg; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * 企业微信机器人消息-markdown + * + * @author sr on 2020-07-06 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class WwrMarkdownMsg extends IWorkWechatMsg implements Serializable { + + /** **/ + private static final long serialVersionUID = 3127170367241501732L; + + /** markdown内容,最长不超过4096个字节,必须是utf8编码 **/ + private String content; + + @Override + public String getMsgType() { + return WorkWechatMsgTypeEnum.MARKDOWN.getType(); + } + +} diff --git a/src/main/java/com/newyetai/sdk/workwechat/model/WwrTextMsg.java b/src/main/java/com/newyetai/sdk/workwechat/model/WwrTextMsg.java new file mode 100644 index 0000000..e735bc8 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/workwechat/model/WwrTextMsg.java @@ -0,0 +1,45 @@ +package com.newyetai.sdk.workwechat.model; + +import java.io.Serializable; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.newyetai.sdk.robot.constant.WorkWechatMsgTypeEnum; +import com.newyetai.sdk.robot.model.IWorkWechatMsg; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * 企业微信机器人消息-文本 + * + * @author sr on 2020-07-06 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class WwrTextMsg extends IWorkWechatMsg implements Serializable{ + + /** **/ + private static final long serialVersionUID = 6281117623858493719L; + + /** 文本内容,最长不超过2048个字节,必须是utf8编码 **/ + private String content; + + @JsonProperty("mentioned_list") + private List mentionedList; + + @JsonProperty("mentioned_mobile_list") + private List mentionedMobileList; + + @Override + public String getMsgType() { + return WorkWechatMsgTypeEnum.TEXT.getType(); + } + +} diff --git a/src/main/java/com/newyetai/sdk/workwechat/service/WorkWechatRobotService.java b/src/main/java/com/newyetai/sdk/workwechat/service/WorkWechatRobotService.java new file mode 100644 index 0000000..6d1a8da --- /dev/null +++ b/src/main/java/com/newyetai/sdk/workwechat/service/WorkWechatRobotService.java @@ -0,0 +1,19 @@ +package com.newyetai.sdk.workwechat.service; + +import com.newyetai.sdk.robot.model.IWorkWechatMsg; + +/** + * @author sr on 2020-07-06 + */ +public interface WorkWechatRobotService { + + /** + * 发送消息 + * + * @param robotKey 机器人key + * @param msg + * @author sr on 2020-07-07 + */ + void send(String robotKey, IWorkWechatMsg msg); + +} diff --git a/src/main/java/com/newyetai/sdk/workwechat/service/impl/WorkWechatRobotServiceImpl.java b/src/main/java/com/newyetai/sdk/workwechat/service/impl/WorkWechatRobotServiceImpl.java new file mode 100644 index 0000000..7786e33 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/workwechat/service/impl/WorkWechatRobotServiceImpl.java @@ -0,0 +1,59 @@ +package com.newyetai.sdk.workwechat.service.impl; + +import java.util.Arrays; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import com.dingtalk.api.DefaultDingTalkClient; +import com.dingtalk.api.DingTalkClient; +import com.dingtalk.api.request.OapiRobotSendRequest; +import com.dingtalk.api.response.OapiRobotSendResponse; +import com.newyetai.sdk.robot.model.IDingTalkMsg; +import com.newyetai.sdk.robot.model.IMsg; +import com.newyetai.sdk.robot.model.IWorkWechatMsg; +import com.newyetai.sdk.robot.model.TextMsg; +import com.newyetai.sdk.workwechat.service.WorkWechatRobotService; +import com.newyetai.sdk.workwechat.util.WorkWechatUtils; +import com.taobao.api.ApiException; + +import lombok.extern.slf4j.Slf4j; + +/** + * @author sr on 2020-07-06 + */ +@Service +@Slf4j +public class WorkWechatRobotServiceImpl implements WorkWechatRobotService { + + private static final String URL_PREFIX = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key="; + + @Autowired + private RestTemplate restTemplate; + + public void send(String robotKey, IWorkWechatMsg msg) { + try { + restTemplate.postForEntity(URL_PREFIX + robotKey, WorkWechatUtils.parsePostData(msg), + Object.class); + } catch (Exception e) { + log.info("WorkWechatRobot send error:{}", e.getMessage()); + } + } + + public void sendDingText(String robotKey, TextMsg textMsg) { + // 76651782e4a03b420aff022e1a5e9010b3606648c40d2ab698d3d3e4ee691538 + + OapiRobotSendRequest request = new OapiRobotSendRequest(); + request.setMsgtype("text"); + OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text(); + text.setContent("前方高能😯😯:\n从前有座山..."); + request.setText(text); + OapiRobotSendRequest.At at = new OapiRobotSendRequest.At(); + at.setAtMobiles(Arrays.asList("13611806907")); + // isAtAll类型如果不为Boolean,请升级至最新SDK + // at.setIsAtAll(true); + request.setAt(at); + } + +} diff --git a/src/main/java/com/newyetai/sdk/workwechat/util/WorkWechatUtils.java b/src/main/java/com/newyetai/sdk/workwechat/util/WorkWechatUtils.java new file mode 100644 index 0000000..7956692 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/workwechat/util/WorkWechatUtils.java @@ -0,0 +1,40 @@ +package com.newyetai.sdk.workwechat.util; + +import java.util.Map; + +import com.google.common.collect.Maps; +import com.newyetai.sdk.robot.constant.WorkWechatMsgTypeEnum; +import com.newyetai.sdk.robot.model.IWorkWechatMsg; +import com.newyetai.sdk.workwechat.model.WwrTextMsg; + +/** + * @author sr on 2020-07-06 + */ +public class WorkWechatUtils { + + private static final String MSG_TYPE = "msgtype"; + + /** + * 转换消息发送对象数据 + * + * @param msg + * @return + * @author sr on 2020-07-06 + */ + public static Map parsePostData(IWorkWechatMsg msg) { + Map data = Maps.newHashMap(); + String msgType = msg.getMsgType(); + data.put(MSG_TYPE, msgType); + if (WorkWechatMsgTypeEnum.TEXT.getType().equals(msgType)) { + // 文本消息截取500长度 + WwrTextMsg textMsg = (WwrTextMsg) msg; + String context = textMsg.getContent(); + if (context.length() > 500) { + textMsg.setContent(textMsg.getContent().substring(0, 500)); + } + } + data.put(msgType, msg); + return data; + } + +} diff --git a/src/main/java/com/newyetai/sdk/xf/config/XfProperties.java b/src/main/java/com/newyetai/sdk/xf/config/XfProperties.java new file mode 100644 index 0000000..41c53f6 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/xf/config/XfProperties.java @@ -0,0 +1,38 @@ +package com.newyetai.sdk.xf.config; + +import java.io.Serializable; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@ConfigurationProperties(prefix = XfProperties.PREFIX) +@Data +@Component +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class XfProperties implements Serializable{ + + /** **/ + private static final long serialVersionUID = 6362606996602121889L; + + public static final String PREFIX = "xf"; + + /** 控制台获取http服务接口认证信息中的APIPassword **/ + private String httpAPIPassword; + + /** 在控制台-我的应用获取 **/ + private String appId; + private String apiSecret; + private String apiKey; + /** 语音听写地址 **/ + private String iatHostUrl; + /** 语音合成地址 **/ + private String ttsHostUrl; + +} diff --git a/src/main/java/com/newyetai/sdk/xf/dto/InterviewContentDTO.java b/src/main/java/com/newyetai/sdk/xf/dto/InterviewContentDTO.java new file mode 100644 index 0000000..853fc9a --- /dev/null +++ b/src/main/java/com/newyetai/sdk/xf/dto/InterviewContentDTO.java @@ -0,0 +1,22 @@ +package com.newyetai.sdk.xf.dto; + +import java.io.Serializable; +import java.util.List; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.Singular; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class InterviewContentDTO implements Serializable{ + + private String positionName; + @Singular + private List qas; + +} diff --git a/src/main/java/com/newyetai/sdk/xf/dto/InterviewQaDTO.java b/src/main/java/com/newyetai/sdk/xf/dto/InterviewQaDTO.java new file mode 100644 index 0000000..69bf9bb --- /dev/null +++ b/src/main/java/com/newyetai/sdk/xf/dto/InterviewQaDTO.java @@ -0,0 +1,23 @@ +package com.newyetai.sdk.xf.dto; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class InterviewQaDTO implements Serializable{ + + private Integer qno; + private String q; + private String a; + private String ua; + private String score; + private String advice; + +} diff --git a/src/main/java/com/newyetai/sdk/xf/model/ChatReq.java b/src/main/java/com/newyetai/sdk/xf/model/ChatReq.java new file mode 100644 index 0000000..284c43d --- /dev/null +++ b/src/main/java/com/newyetai/sdk/xf/model/ChatReq.java @@ -0,0 +1,27 @@ +package com.newyetai.sdk.xf.model; + +import java.io.Serializable; +import java.util.List; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.Singular; +import lombok.Builder.Default; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class ChatReq implements Serializable{ + + @Default + private String model = "4.0Ultra"; + @Singular + private List messages; + + + + +} diff --git a/src/main/java/com/newyetai/sdk/xf/model/ChatRes.java b/src/main/java/com/newyetai/sdk/xf/model/ChatRes.java new file mode 100644 index 0000000..56a41ed --- /dev/null +++ b/src/main/java/com/newyetai/sdk/xf/model/ChatRes.java @@ -0,0 +1,24 @@ +package com.newyetai.sdk.xf.model; + +import java.io.Serializable; +import java.util.List; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.Singular; +import lombok.Builder.Default; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class ChatRes implements Serializable{ + + private String code; + private String message; + private List choices; + + +} diff --git a/src/main/java/com/newyetai/sdk/xf/model/ChoiceDTO.java b/src/main/java/com/newyetai/sdk/xf/model/ChoiceDTO.java new file mode 100644 index 0000000..f3ca1e7 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/xf/model/ChoiceDTO.java @@ -0,0 +1,17 @@ +package com.newyetai.sdk.xf.model; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class ChoiceDTO { + + private MessageDTO message; + private Integer index; + +} diff --git a/src/main/java/com/newyetai/sdk/xf/model/MessageDTO.java b/src/main/java/com/newyetai/sdk/xf/model/MessageDTO.java new file mode 100644 index 0000000..17998f3 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/xf/model/MessageDTO.java @@ -0,0 +1,22 @@ +package com.newyetai.sdk.xf.model; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class MessageDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 4026941416873536216L; + + private String role; + private String content; + +} diff --git a/src/main/java/com/newyetai/sdk/xf/service/XfSparkProvider.java b/src/main/java/com/newyetai/sdk/xf/service/XfSparkProvider.java new file mode 100644 index 0000000..b4a654f --- /dev/null +++ b/src/main/java/com/newyetai/sdk/xf/service/XfSparkProvider.java @@ -0,0 +1,72 @@ +package com.newyetai.sdk.xf.service; + +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.sdk.common.constant.SdkConstants; +import com.newyetai.sdk.common.dto.DefaultSdkInvokeLogDTO; +import com.newyetai.sdk.common.util.HttpUtils; +import com.newyetai.sdk.xf.config.XfProperties; +import com.newyetai.sdk.xf.model.ChatReq; +import com.newyetai.sdk.xf.model.ChatRes; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class XfSparkProvider { + + private static XfProperties xfProperties; + + private XfSparkProvider(XfProperties xfProperties) { + XfSparkProvider.xfProperties = xfProperties; + } + + public static AlitaResult httpChat(ChatReq req) { + return httpChat(req, xfProperties.getHttpAPIPassword()); + } + + public static AlitaResult httpChat(ChatReq req, String httpAPIPassword) { + ResponseEntity response = null; + try { + try { + HttpHeaders header = new HttpHeaders(); + header.add("Authorization", "Bearer " + httpAPIPassword); + header.add("Content-Type", "application/json"); + // 发送请求 + HttpEntity requestEntity = new HttpEntity(req, header); + response = + HttpUtils.restTemplate.exchange("https://spark-api-open.xf-yun.com/v1/chat/completions", + HttpMethod.POST, requestEntity, ChatRes.class); + } catch (Exception e) { + log.error("xfSpark http error:{}", e.getMessage()); + return AlitaResult.error(SdkConstants.SDK_HTTP_INVOKE_ERROR_CODE, e.getMessage()); + } + try { + String content = response.getBody().getChoices().get(0).getMessage().getContent(); + content = dealJson(content); + return AlitaResult.success(content); + } catch (Exception e) { + return AlitaResult.error(SdkConstants.SDK_RESPONSE_CONVERT_ERROR_CODE, "xf返回结果获取content失败"); + } + + } finally { + log.info("xfSpark invoke:{}", + JsonUtils + .toJsonString( + DefaultSdkInvokeLogDTO.builder().requestData(req).responseData(response) + .build())); + } + } + + public static String dealJson(String content) { + return content.replaceAll("(```json\n)|(\n```)|(\n)", ""); + } + + +} diff --git a/src/main/java/com/newyetai/sdk/xf/util/WebIATWS.java b/src/main/java/com/newyetai/sdk/xf/util/WebIATWS.java new file mode 100644 index 0000000..8274032 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/xf/util/WebIATWS.java @@ -0,0 +1,427 @@ +package com.newyetai.sdk.xf.util; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.nio.charset.Charset; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Base64; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.newyetai.common.AlitaResult; +import com.newyetai.sdk.xf.config.XfProperties; + +import lombok.extern.slf4j.Slf4j; +import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.WebSocket; +import okhttp3.WebSocketListener; + +/** + * 语音听写流式 WebAPI 接口调用示例 接口文档(必看):https://doc.xfyun.cn/rest_api/语音听写(流式版).html + * webapi 听写服务参考帖子(必看):http://bbs.xfyun.cn/forum.php?mod=viewthread&tid=38947&extra= + * 语音听写流式WebAPI 服务,热词使用方式:登陆开放平台https://www.xfyun.cn/后,找到控制台--我的应用---语音听写---个性化热词,上传热词 + * 注意:热词只能在识别的时候会增加热词的识别权重,需要注意的是增加相应词条的识别率,但并不是绝对的,具体效果以您测试为准。 + * 错误码链接:https://www.xfyun.cn/document/error-code (code返回错误码时必看) + * 语音听写流式WebAPI 服务,方言或小语种试用方法:登陆开放平台https://www.xfyun.cn/后,在控制台--语音听写(流式)--方言/语种处添加 + * 添加后会显示该方言/语种的参数值 + * @author iflytek + */ +@Slf4j +public class WebIATWS extends WebSocketListener { + // private static final String hostUrl = "https://iat-api.xfyun.cn/v2/iat"; //中英文,http url 不支持解析 ws/wss schema + // private static final String hostUrl = "https://iat-niche-api.xfyun.cn/v2/iat";//小语种 + public static final int StatusFirstFrame = 0; + public static final int StatusContinueFrame = 1; + public static final int StatusLastFrame = 2; + public static final Gson json = new Gson(); + Decoder decoder = new Decoder(); + // 开始时间 + private static Date dateBegin = new Date(); + // 结束时间 + private static Date dateEnd = new Date(); + private static final SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd HH:mm:ss.SSS"); + + InputStream is; + private String appId; + // mp3格式 + private String encoding = "lame"; + private AlitaResult result; + + WebIATWS(InputStream is, String appId) { + this.is = is; + this.appId = appId; + } + + public AlitaResult getResult() { + return result; + } + + + @Override + public void onOpen(WebSocket webSocket, Response response) { + super.onOpen(webSocket, response); + new Thread(() -> { + //连接成功,开始发送数据 + // int frameSize = 1280; //每一帧音频的大小,建议每 40ms 发送 122B + int frameSize = 1280 * 64; //每一帧音频的大小,建议每 40ms 发送 122B + int intervel = 40; + // int intervel = 0; + int status = 0; // 音频的状态 + try { + byte[] buffer = new byte[frameSize]; + // 发送音频 + end: while (true) { + int len = is.read(buffer); + if (len == -1) { + status = StatusLastFrame; //文件读完,改变status 为 2 + } + + switch (status) { + case StatusFirstFrame: // 第一帧音频status = 0 + JsonObject frame = new JsonObject(); + JsonObject business = new JsonObject(); //第一帧必须发送 + JsonObject common = new JsonObject(); //第一帧必须发送 + JsonObject data = new JsonObject(); //每一帧都要发送 + // 填充common + common.addProperty("app_id", this.appId); + //填充business + business.addProperty("language", "zh_cn"); + //business.addProperty("language", "en_us");//英文 + //business.addProperty("language", "ja_jp");//日语,在控制台可添加试用或购买 + //business.addProperty("language", "ko_kr");//韩语,在控制台可添加试用或购买 + //business.addProperty("language", "ru-ru");//俄语,在控制台可添加试用或购买 + business.addProperty("domain", "iat"); + business.addProperty("accent", "mandarin");//中文方言请在控制台添加试用,添加后即展示相应参数值 + //business.addProperty("nunum", 0); + //business.addProperty("ptt", 0);//标点符号 + //business.addProperty("rlang", "zh-hk"); // zh-cn :简体中文(默认值)zh-hk :繁体香港(若未授权不生效,在控制台可免费开通) + //business.addProperty("vinfo", 1); + business.addProperty("dwa", "wpgs");//动态修正(若未授权不生效,在控制台可免费开通) + //business.addProperty("nbest", 5);// 句子多候选(若未授权不生效,在控制台可免费开通) + //business.addProperty("wbest", 3);// 词级多候选(若未授权不生效,在控制台可免费开通) + //填充data + data.addProperty("status", StatusFirstFrame); + data.addProperty("format", "audio/L16;rate=16000"); + // data.addProperty("encoding", "raw"); + data.addProperty("encoding", this.encoding); + data.addProperty("audio", + Base64.getEncoder().encodeToString(Arrays.copyOf(buffer, len))); + //填充frame + frame.add("common", common); + frame.add("business", business); + frame.add("data", data); + webSocket.send(frame.toString()); + status = StatusContinueFrame; // 发送完第一帧改变status 为 1 + break; + case StatusContinueFrame: //中间帧status = 1 + JsonObject frame1 = new JsonObject(); + JsonObject data1 = new JsonObject(); + data1.addProperty("status", StatusContinueFrame); + data1.addProperty("format", "audio/L16;rate=16000"); + data1.addProperty("encoding", this.encoding); + data1.addProperty("audio", + Base64.getEncoder().encodeToString(Arrays.copyOf(buffer, len))); + frame1.add("data", data1); + webSocket.send(frame1.toString()); + // log.info("send continue"); + break; + case StatusLastFrame: // 最后一帧音频status = 2 ,标志音频发送结束 + JsonObject frame2 = new JsonObject(); + JsonObject data2 = new JsonObject(); + data2.addProperty("status", StatusLastFrame); + data2.addProperty("audio", ""); + data2.addProperty("format", "audio/L16;rate=16000"); + // data2.addProperty("encoding", "raw"); + data2.addProperty("encoding", this.encoding); + frame2.add("data", data2); + webSocket.send(frame2.toString()); + log.info("sendlast"); + break end; + } + Thread.sleep(intervel); //模拟音频采样延时 + } + log.info("all data is send"); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }).start(); + } + + @Override + public void onMessage(WebSocket webSocket, String text) { + super.onMessage(webSocket, text); + //log.info(text); + ResponseData resp = json.fromJson(text, ResponseData.class); + if (resp != null) { + if (resp.getCode() != 0) { + // log.info( "code=>" + resp.getCode() + " error=>" + resp.getMessage() + " sid=" + resp.getSid()); + // log.info( "错误码查询链接:https://www.xfyun.cn/document/error-code"); + result = AlitaResult.error(resp.getCode() + ":" + resp.getMessage()); + webSocket.close(1000, ""); + return; + } + if (resp.getData() != null) { + if (resp.getData().getResult() != null) { + Text te = resp.getData().getResult().getText(); + //log.info(te.toString()); + try { + decoder.decode(te); + log.debug("中间识别结果 ==》" + decoder.toString()); + } catch (Exception e) { + e.printStackTrace(); + } + } + if (resp.getData().getStatus() == 2) { + // todo resp.data.status ==2 说明数据全部返回完毕,可以关闭连接,释放资源 + // log.info("session end "); + dateEnd = new Date(); + log.info("开始-{},结束-{},耗时:{}", sdf.format(dateBegin), sdf.format(dateEnd), + (dateEnd.getTime() - dateBegin.getTime()) + "ms"); + String resultStr = decoder.toString(); + log.info("最终识别结果 ==》{},本次识别sid ==》{}", resultStr, resp.getSid()); + decoder.discard(); + webSocket.close(1000, ""); + result = AlitaResult.success(resultStr); + } else { + // todo 根据返回的数据处理 + } + } + } + } + + @Override + public void onFailure(WebSocket webSocket, Throwable t, Response response) { + super.onFailure(webSocket, t, response); + try { + if (null != response) { + int code = response.code(); + log.info("onFailure code:" + code); + log.info("onFailure body:" + response.body().string()); + if (101 != code) { + log.info("connection failed"); + System.exit(0); + } + } + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + public static AlitaResult execute(InputStream is, XfProperties xfProperties) { + try { + // 构建鉴权url + String authUrl = getAuthUrl(xfProperties.getIatHostUrl(), xfProperties.getApiKey(), + xfProperties.getApiSecret()); + OkHttpClient client = new OkHttpClient.Builder().build(); + //将url中的 schema http://和https://分别替换为ws:// 和 wss:// + String url = authUrl.toString().replace("http://", "ws://").replace("https://", "wss://"); + Request request = new Request.Builder().url(url).build(); + WebIATWS webIATWS = new WebIATWS(is, xfProperties.getAppId()); + WebSocket webSocket = client.newWebSocket(request, webIATWS); + while (webIATWS.getResult() == null) { + // 未拿到结果等待 + Thread.sleep(1000l); + } + return webIATWS.getResult(); + } catch (Exception e) { + log.info("err ", e); + return AlitaResult.error("语音听写失败:{}", e.getMessage()); + } + + } + + public static String getAuthUrl(String hostUrl, String apiKey, String apiSecret) + throws Exception { + URL url = new URL(hostUrl); + SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US); + format.setTimeZone(TimeZone.getTimeZone("GMT")); + String date = format.format(new Date()); + StringBuilder builder = new StringBuilder("host: ").append(url.getHost()).append("\n").// + append("date: ").append(date).append("\n").// + append("GET ").append(url.getPath()).append(" HTTP/1.1"); + //log.info(builder); + Charset charset = Charset.forName("UTF-8"); + Mac mac = Mac.getInstance("hmacsha256"); + SecretKeySpec spec = new SecretKeySpec(apiSecret.getBytes(charset), "hmacsha256"); + mac.init(spec); + byte[] hexDigits = mac.doFinal(builder.toString().getBytes(charset)); + String sha = Base64.getEncoder().encodeToString(hexDigits); + + //log.info(sha); + String authorization = + String.format("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", apiKey, + "hmac-sha256", "host date request-line", sha); + //log.info(authorization); + HttpUrl httpUrl = HttpUrl.parse("https://" + url.getHost() + url.getPath()).newBuilder().// + addQueryParameter("authorization", + Base64.getEncoder().encodeToString(authorization.getBytes(charset))) + .// + addQueryParameter("date", date).// + addQueryParameter("host", url.getHost()).// + build(); + return httpUrl.toString(); + } + + public static class ResponseData { + private int code; + private String message; + private String sid; + private Data data; + + public int getCode() { + return code; + } + + public String getMessage() { + return this.message; + } + + public String getSid() { + return sid; + } + + public Data getData() { + return data; + } + } + public static class Data { + private int status; + private Result result; + + public int getStatus() { + return status; + } + + public Result getResult() { + return result; + } + } + public static class Result { + int bg; + int ed; + String pgs; + int[] rg; + int sn; + Ws[] ws; + boolean ls; + JsonObject vad; + + public Text getText() { + Text text = new Text(); + StringBuilder sb = new StringBuilder(); + for (Ws ws : this.ws) { + sb.append(ws.cw[0].w); + } + text.sn = this.sn; + text.text = sb.toString(); + text.sn = this.sn; + text.rg = this.rg; + text.pgs = this.pgs; + text.bg = this.bg; + text.ed = this.ed; + text.ls = this.ls; + text.vad = this.vad == null ? null : this.vad; + return text; + } + } + public static class Ws { + Cw[] cw; + int bg; + int ed; + } + public static class Cw { + int sc; + String w; + } + public static class Text { + int sn; + int bg; + int ed; + String text; + String pgs; + int[] rg; + boolean deleted; + boolean ls; + JsonObject vad; + + @Override + public String toString() { + return "Text{" + + "bg=" + bg + + ", ed=" + ed + + ", ls=" + ls + + ", sn=" + sn + + ", text='" + text + '\'' + + ", pgs=" + pgs + + ", rg=" + Arrays.toString(rg) + + ", deleted=" + deleted + + ", vad=" + (vad == null ? "null" : vad.getAsJsonArray("ws").toString()) + + '}'; + } + } + //解析返回数据,仅供参考 + public static class Decoder { + private Text[] texts; + private int defc = 10; + + public Decoder() { + this.texts = new Text[this.defc]; + } + + public synchronized void decode(Text text) { + if (text.sn >= this.defc) { + this.resize(); + } + if ("rpl".equals(text.pgs)) { + for (int i = text.rg[0]; i <= text.rg[1]; i++) { + this.texts[i].deleted = true; + } + } + this.texts[text.sn] = text; + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + for (Text t : this.texts) { + if (t != null && !t.deleted) { + sb.append(t.text); + } + } + return sb.toString(); + } + + public void resize() { + int oc = this.defc; + this.defc <<= 1; + Text[] old = this.texts; + this.texts = new Text[this.defc]; + for (int i = 0; i < oc; i++) { + this.texts[i] = old[i]; + } + } + + public void discard() { + for (int i = 0; i < this.texts.length; i++) { + this.texts[i] = null; + } + } + } +} diff --git a/src/main/java/com/newyetai/sdk/xf/util/WebTtsWS.java b/src/main/java/com/newyetai/sdk/xf/util/WebTtsWS.java new file mode 100644 index 0000000..27528e1 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/xf/util/WebTtsWS.java @@ -0,0 +1,215 @@ +package com.newyetai.sdk.xf.util; + +import java.io.ByteArrayInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.text.SimpleDateFormat; +import java.util.Base64; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; + +import org.apache.tomcat.util.http.fileupload.ByteArrayOutputStream; + +import com.google.gson.Gson; +import com.newyetai.common.AlitaResult; +import com.newyetai.sdk.xf.config.XfProperties; + +import lombok.extern.slf4j.Slf4j; +import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.WebSocket; +import okhttp3.WebSocketListener; + +/** + * 语音合成流式 WebAPI 接口调用示例 接口文档(必看):https://www.xfyun.cn/doc/tts/online_tts/API.html + * 发音人使用方式:登陆开放平台https://www.xfyun.cn/后,到控制台-我的应用-语音合成-添加试用或购买发音人,添加后即显示该发音人参数值 + * 错误码链接:https://www.xfyun.cn/document/error-code (code返回错误码时必看) + * 小语种需要传输小语种文本、使用小语种发音人vcn、tte=unicode以及修改文本编码方式 + * + * @author xlliu24 + */ +@Slf4j +public class WebTtsWS extends WebSocketListener { + public static final int StatusFirstFrame = 0; + public static final int StatusContinueFrame = 1; + public static final int StatusLastFrame = 2; + public static final Gson json = new Gson(); + // mp3格式 + private String encoding = "lame"; + private AlitaResult result; + + private String text; + private String appId; + OutputStream outputStream; + // 合成文本编码格式 + public static final String TTE = "UTF8"; // 小语种必须使用UNICODE编码作为值 + // 发音人参数。到控制台-我的应用-语音合成-添加试用或购买发音人,添加后即显示该发音人参数值,若试用未添加的发音人会报错11200 + public static final String VCN = "xiaoyan"; + + WebTtsWS(String text, String appId, OutputStream outputStream){ + this.text = text; + this.appId = appId; + this.outputStream = outputStream; + } + + public AlitaResult getResult() { + return result; + } + + + @Override + public void onOpen(WebSocket webSocket, Response response) { + super.onOpen(webSocket, response); + log.info("ws建立连接成功..."); + String requestJson;//请求参数json串 + requestJson = "{\n" + + " \"common\": {\n" + + " \"app_id\": \"" + appId + "\"\n" + + " },\n" + + " \"business\": {\n" + + " \"aue\": \"lame\",\n" + + " \"sfl\": 1,\n" + + " \"tte\": \"" + TTE + "\",\n" + + " \"ent\": \"intp65\",\n" + + " \"vcn\": \"" + VCN + "\",\n" + + " \"pitch\": 50,\n" + + " \"speed\": 50\n" + + " },\n" + + " \"data\": {\n" + + " \"status\": 2,\n" + + " \"text\": \"" + + Base64.getEncoder().encodeToString(text.getBytes(StandardCharsets.UTF_8)) + "\"\n" + + //" \"text\": \"" + Base64.getEncoder().encodeToString(TEXT.getBytes("UTF-16LE")) + "\"\n" + + " }\n" + + "}"; + webSocket.send(requestJson); + + } + + @Override + public void onMessage(WebSocket webSocket, String text) { + super.onMessage(webSocket, text); + JsonParse myJsonParse = json.fromJson(text, JsonParse.class); + if (myJsonParse.code != 0) { + log.info("发生错误,错误码为:" + myJsonParse.code); + log.info("本次请求的sid为:" + myJsonParse.sid); + result = AlitaResult.error(myJsonParse.code + ":" + myJsonParse.sid); + webSocket.close(1000, ""); + return; + } + if (myJsonParse.data != null) { + try { + byte[] textBase64Decode = Base64.getDecoder().decode(myJsonParse.data.audio); + outputStream.write(textBase64Decode); + outputStream.flush(); + log.info("本次请求的状态==>" + myJsonParse.data.status); + } catch (Exception e) { + e.printStackTrace(); + } + if (myJsonParse.data.status == 2) { + result = AlitaResult.success(); + log.info("本次请求的sid==>" + myJsonParse.sid); + // 可以关闭连接,释放资源 + webSocket.close(1000, ""); + } + } + + } + + @Override + public void onFailure(WebSocket webSocket, Throwable t, Response response) { + super.onFailure(webSocket, t, response); + try { + if (null != response) { + int code = response.code(); + log.info("onFailure code:" + code); + log.info("onFailure body:" + response.body().string()); + if (101 != code) { + log.info("connection failed"); + System.exit(0); + } + } + } catch (IOException e) { + log.info("failure:", e); + } + } + + public static AlitaResult execute(String text, XfProperties xfProperties, OutputStream outputStream) { + try { + // 构建鉴权url + String authUrl = getAuthUrl(xfProperties.getTtsHostUrl(), xfProperties.getApiKey(), + xfProperties.getApiSecret()); + OkHttpClient client = new OkHttpClient.Builder().build(); + //将url中的 schema http://和https://分别替换为ws:// 和 wss:// + String url = authUrl.toString().replace("http://", "ws://").replace("https://", "wss://"); + Request request = new Request.Builder().url(url).build(); + WebTtsWS webIATWS = new WebTtsWS(text, xfProperties.getAppId(), outputStream); + WebSocket webSocket = client.newWebSocket(request, webIATWS); + while (webIATWS.result == null) { + // 未拿到结果等待 + Thread.sleep(1000l); + } + return AlitaResult.success(); + } catch (Exception e) { + log.info("err ", e); + return AlitaResult.error("语音听写失败:{}", e.getMessage()); + } + + } + + public static String getAuthUrl(String hostUrl, String apiKey, String apiSecret) + throws Exception { + URL url = new URL(hostUrl); + SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US); + format.setTimeZone(TimeZone.getTimeZone("GMT")); + String date = format.format(new Date()); + StringBuilder builder = new StringBuilder("host: ").append(url.getHost()).append("\n").// + append("date: ").append(date).append("\n").// + append("GET ").append(url.getPath()).append(" HTTP/1.1"); + //log.info(builder); + Charset charset = Charset.forName("UTF-8"); + Mac mac = Mac.getInstance("hmacsha256"); + SecretKeySpec spec = new SecretKeySpec(apiSecret.getBytes(charset), "hmacsha256"); + mac.init(spec); + byte[] hexDigits = mac.doFinal(builder.toString().getBytes(charset)); + String sha = Base64.getEncoder().encodeToString(hexDigits); + + //log.info(sha); + String authorization = + String.format("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", apiKey, + "hmac-sha256", "host date request-line", sha); + //log.info(authorization); + HttpUrl httpUrl = HttpUrl.parse("https://" + url.getHost() + url.getPath()).newBuilder().// + addQueryParameter("authorization", + Base64.getEncoder().encodeToString(authorization.getBytes(charset))) + .// + addQueryParameter("date", date).// + addQueryParameter("host", url.getHost()).// + build(); + return httpUrl.toString(); + } + +//返回的json结果拆解 + class JsonParse { + int code; + String sid; + Data data; + } + + class Data { + int status; + String audio; +} + +} diff --git a/src/main/java/com/newyetai/sdk/xf/util/XfUtils.java b/src/main/java/com/newyetai/sdk/xf/util/XfUtils.java new file mode 100644 index 0000000..043ee77 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/xf/util/XfUtils.java @@ -0,0 +1,232 @@ +package com.newyetai.sdk.xf.util; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.tomcat.util.http.fileupload.ByteArrayOutputStream; +import org.springframework.stereotype.Component; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.component.file.entity.FileRecord; +import com.newyetai.component.file.service.FileRecordService; +import com.newyetai.component.file.service.FileService; +import com.newyetai.component.file.util.FileUtils; +import com.newyetai.config.service.ConfigService; +import com.newyetai.sdk.xf.config.XfProperties; +import com.newyetai.sdk.xf.dto.InterviewContentDTO; +import com.newyetai.sdk.xf.model.ChatReq; +import com.newyetai.sdk.xf.model.MessageDTO; +import com.newyetai.sdk.xf.service.XfSparkProvider; + +@Component +public class XfUtils { + + private static ConfigService configService; + private static XfProperties xfProperties; + private static FileService fileService; + private static FileRecordService fileRecordService; + + XfUtils(ConfigService configService, XfProperties xfProperties, FileService fileService, FileRecordService fileRecordService){ + XfUtils.configService = configService; + XfUtils.xfProperties = xfProperties; + XfUtils.fileService = fileService; + XfUtils.fileRecordService = fileRecordService; + } + + /** + * 生成面试问题 + * @return InterviewContentDTO json + * @author sr on 2024-12-10 + */ + public static String generateInterviewQuestion(InterviewContentDTO content) { + ChatReq req = ChatReq.builder() + .message(MessageDTO.builder().role("system") + .content("你是一位专业的HR。目标任务:请根据我给出的positionName生成5个相关的面试中可能会问到的问题,并为每个问题都生成一个参考答案,并从1开始生成问题序号") + .build()) + .message(MessageDTO.builder().role("system") + .content("全部数据以JSON模版的形式返回,格式为:{positionName:岗位信息, qas:[{qno:问题序号,q:问题,a:参考答案}]}").build()) + .message(MessageDTO.builder().role("user").content(JsonUtils.toNoEmptyJson(content)).build()).build(); + AlitaResult result = XfSparkProvider.httpChat(req); + Assert.isTrue(result.getSuccess(), result.getMsg()); + return result.getData(); + } + + /** + * 评分面试 + * @return InterviewContentDTO json + * @author sr on 2024-12-10 + */ + public static String gradeInterview(InterviewContentDTO content) { + ChatReq req = ChatReq.builder() + .message(MessageDTO.builder().role("system") + .content("全部数据以JSON模版的形式返回,格式为:{positionName:岗位信息, qas:[{qno:问题序号,q:问题,a:参考答案,score:得分,根据问题q,结合参考答案a,对用户回答ua,在1-10分范围内为用户回答打分赋值,advice:作为资深的position_name提供该问题的回答建议,针对用户回答ua给出建议advice,建议内容包含不足之处+建议}]}") + .build()) + .message(MessageDTO.builder().role("user") + .content(JsonUtils.toNoEmptyJson(content)).build()) + .build(); + AlitaResult result = XfSparkProvider.httpChat(req); + Assert.isTrue(result.getSuccess(), result.getMsg()); + return result.getData(); + } + + /** + * 生成简历 + * @return + * @author sr on 2024-12-10 + */ + public static String generateResume(String content) { + String key01 = configService.getConfigValue("ai_jianli_key01", CommonConstants.PLATFORM_ORG_ID, true); + String key02 = configService.getConfigValue("ai_jianli_key02", CommonConstants.PLATFORM_ORG_ID, true); + String key03 = configService.getConfigValue("ai_jianli_key03", CommonConstants.PLATFORM_ORG_ID, true); + ChatReq req = ChatReq.builder() + .message(MessageDTO.builder().role("system") + .content(key01) + .build()) + .message(MessageDTO.builder().role("system").content(key02).build()) + .message(MessageDTO.builder().role("system").content(key03).build()) + .message(MessageDTO.builder().role("user").content(content).build()) + .build(); + AlitaResult result = XfSparkProvider.httpChat(req); + Assert.isTrue(result.getSuccess(), result.getMsg()); + return result.getData(); + } + + /** + * 语音听写 + * @param filePath + * @return + * @author sr on 2025-01-09 + */ + public static String iat(String fileCode) { + FileRecord fileRecord = fileRecordService.find(FileRecord.builder().fileCode(fileCode).build()); + try (InputStream is = FileUtils.convertWebmToMp3(new File(fileRecord.getFilePath()))){ + AlitaResult result = WebIATWS.execute(is, xfProperties); + Assert.isTrue(result.getSuccess(), result.getMsg()); + return result.getData(); + } catch (Exception e) { + throw new BusinessException("语音听写异常:" + e.getMessage()); + } + + } + + /** + * 语音合成 + * @param filePath + * @return + * @author sr on 2025-01-09 + */ + public static String tts(String text) { + try(ByteArrayOutputStream outputStream = new ByteArrayOutputStream()){ + AlitaResult result = WebTtsWS.execute(text, xfProperties, outputStream); + Assert.isTrue(result.getSuccess(), result.getMsg()); + FileRecord fileRecord = fileService.upload("语音合成.mp3", outputStream.toByteArray()); + return fileRecord.getFileCode(); + } catch (IOException e) { + throw new BusinessException("语音合成异常:" + e.getMessage()); + } + } + + + /** + * 生成自我评价 + * @return + */ + public static String generateSelfEvaluate(String content) { + ChatReq req = ChatReq.builder() + .message(MessageDTO.builder().role("system") + .content("你是一位专业的简历撰写专家。目标任务:请根据我给出的信息,生成指定的内容。需求说明:要求在与原文语意一致的基础上扩写内容,风格设定,简明扼要。") + .build()) + .message(MessageDTO.builder().role("system") + .content("根据我输入的信息,输出1段自我评价,包含学习能力、工作态度、团队协作等方面,字数在300字左右") + .build()) + .message(MessageDTO.builder().role("system") + .content("全部数据以JSON模版的形式返回, 格式为:{'selfEva':xxx}") + .build()) + .message(MessageDTO.builder().role("user").content(content).build()).build(); + AlitaResult result = XfSparkProvider.httpChat(req); + Assert.isTrue(result.getSuccess(), result.getMsg()); + return result.getData(); + } + + /** + * 生成工作经历 + * @return + */ + public static String generateWorkExperience(String content) { + ChatReq req = ChatReq.builder() + .message(MessageDTO.builder().role("system") + .content("你是一位专业的简历撰写专家。目标任务:请根据我给出的信息,生成一份履历丰富的简历。") + .build()) + .message(MessageDTO.builder().role("system") + .content("简历内容包含个人信息简介、工作经历、教育背景、掌握技能、自我评价。以JSON格式返回,每个点作为一个对象。") + .build()) + .message(MessageDTO.builder().role("system") + .content("个人信息输出格式为:{姓名:xxx, 年龄:xxx,联系电话:xxx,联系邮箱:xxx}") + .build()) + .message(MessageDTO.builder().role("system") + .content("工作经历以数组的形式返回。输出格式为:[{企业名称:xxx, 岗位:xxx,工作职责:[xxx,xxx,xxx],工作时间:xxx-xxx}]") + .build()) + .message(MessageDTO.builder().role("system") + .content("掌握技能必须作为数组输出") + .build()) + .message(MessageDTO.builder().role("system") + .content("自我评价必须作为数组输出") + .build()) + .message(MessageDTO.builder().role("user").content(content).build()).build(); + AlitaResult result = XfSparkProvider.httpChat(req); + Assert.isTrue(result.getSuccess(), result.getMsg()); + return result.getData(); + } + + /** + * 分析简历 + * @param content + * @return + */ + public static String analyseResume(String content) { + ChatReq req = ChatReq.builder() + .message(MessageDTO.builder().role("system") + .content("你是一位专业的简历分析专家。目标任务:请根据我给出的信息,分析得出简历信息,不要自己填充json信息。") + .build()) + .message(MessageDTO.builder().role("system") + .content("请生成一个包含以下信息的 JSON 数据,根据用户给出的实际信息解析,值都可为空:\n" + + "- name(字符串类型):表示用户的姓名。\n" + + "- sex(字符串类型):表示用户的性别,值为 \"1\"(男)或 \"2\"(女),身份证号倒数第二位,奇数是男,偶数是女。\n" + + "- phone(字符串类型):表示用户的联系电话,可为空,不为空的格式为 以 1 开头,共 11 位数字。\n" + + "- email(字符串类型):表示用户的联系电子邮箱地址,可为空,不为空的格式为 包含 @ 符号,且 @ 前后至少有一个字符 及 域名部分至少包含一个 . 符号。\n" + + "- intentionPosition(字符串类型):表示用户的意向职位。\n" + + "- major(字符串类型):表示用户的专业。\n" + + "- birthday(日期类型):表示用户的出生日期,格式为 YYYY-MM。\n" + + "- jobTime(日期类型):表示用户的参加工作时间,格式为 YYYY-MM。\n" + + "- school(字符串类型):表示用户的毕业院校。\n" + + "- education(字符串类型):表示用户的学历,值为:\n" + + " - \"1\":\"博士\"\n" + + " - \"2\":\"硕士\"\n" + + " - \"3\":\"本科\"\n" + + " - \"4\":\"大专\"\n" + + " - \"5\":\"中专\"\n" + + " - \"6\":\"技校\"\n" + + " - \"7\":\"职高\"\n" + + " - \"9\":\"高中\"\n" + + " - \"10\":\"初中\"\n" + + " - \"11\":\"小学\"\n" + + "- workExperience(字符串类型):表示用户的工作经历,格式为文本,包含以下信息:\n" + + " - 企业名称\n" + + " - 岗位\n" + + " - 工作时间\n" + + " - 工作职责\n" + + "- selfEvaluation(字符串类型):表示用户的自我评价,格式为文本。") + .build()) + .message(MessageDTO.builder().role("system").content("如果用户回答与简历无关,则返回空json,不回答其他无关问题,只返回能解析到的json数据。").build()) + .message(MessageDTO.builder().role("user").content(content).build()).build(); + AlitaResult result = XfSparkProvider.httpChat(req); + Assert.isTrue(result.getSuccess(), result.getMsg()); + return result.getData(); + } + +} diff --git a/src/main/java/com/newyetai/security/access/intercept/FilterSecurityInterceptor.java b/src/main/java/com/newyetai/security/access/intercept/FilterSecurityInterceptor.java new file mode 100644 index 0000000..e942497 --- /dev/null +++ b/src/main/java/com/newyetai/security/access/intercept/FilterSecurityInterceptor.java @@ -0,0 +1,224 @@ +/* + * Copyright 2004, 2005, 2006 Acegi Technology Pty Limited + * + * 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.newyetai.security.access.intercept; + +import java.io.IOException; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.access.SecurityMetadataSource; +import org.springframework.security.access.intercept.AbstractSecurityInterceptor; +import org.springframework.security.access.intercept.InterceptorStatusToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.FilterInvocation; +import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.util.matcher.RequestMatcher; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.ResponseUtils; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.security.access.request.AuthDtoUtils; +import com.newyetai.security.expection.BadLoginException; +import com.newyetai.security.util.SecurityPropertyUtils; +import com.newyetai.security.util.SecurityUtils; +import com.newyetai.usercenter.user.constant.UserTypeEnum; +import com.newyetai.usercenter.user.login.service.UserLoginService; + +import lombok.extern.slf4j.Slf4j; + + +/** + * 菜单安全拦截器 + * + * @author on 2019-11-05 + */ +@Slf4j +public class FilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter { + + // ~ Static fields/initializers + // ===================================================================================== + + private static final String FILTER_APPLIED = + "__spring_security_filterSecurityInterceptor_filterApplied_2"; + + public static final String AUTH_URL = "/sys_security_auth"; + public static final String ERROR_URL = "/error"; + + // ~ Instance fields + // ================================================================================================ + + private FilterInvocationSecurityMetadataSource securityMetadataSource; + private boolean observeOncePerRequest = true; + + // ~ Methods + // ======================================================================================================== + + /** + * Not used (we rely on IoC container lifecycle services instead) + * + * @param arg0 ignored + * + * @throws ServletException never thrown + */ + @Override + public void init(FilterConfig arg0) throws ServletException {} + + /** + * Not used (we rely on IoC container lifecycle services instead) + */ + @Override + public void destroy() {} + + /** + * Method that is actually called by the filter chain. Simply delegates to the + * {@link #invoke(FilterInvocation)} method. + * + * @param request the servlet request + * @param response the servlet response + * @param chain the filter chain + * + * @throws IOException if the filter chain fails + * @throws ServletException if the filter chain fails + */ + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + FilterInvocation fi = new FilterInvocation(request, response, chain); + invoke(fi); + } + + public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() { + return this.securityMetadataSource; + } + + @Override + public SecurityMetadataSource obtainSecurityMetadataSource() { + return this.securityMetadataSource; + } + + public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource newSource) { + this.securityMetadataSource = newSource; + } + + @Override + public Class getSecureObjectClass() { + return FilterInvocation.class; + } + + private RequestMatcher authRequestMatcher = new AntPathRequestMatcher(AUTH_URL, "POST"); + + private UserLoginService userLoginService; + + public void setUserLoginService(UserLoginService userLoginService) { + this.userLoginService = userLoginService; + } + + public void invoke(FilterInvocation fi) throws IOException, ServletException { + if (fi.getRequestUrl().equals(ERROR_URL)) { + log.info("访问资源不存在"); + throw new BadLoginException("访问资源不存在"); + } + // 如果是其他系统,调用用户中心鉴权 + // 如果是用户中心,其他系统鉴权路径, + HttpServletRequest request = fi.getRequest(); + HttpServletResponse response = fi.getResponse(); + // 外部系统调用用户中心鉴权 + boolean authInvoke = authRequestMatcher.matches(request); + if (authInvoke) { + FilterInvocation authFilterInvocation = AuthDtoUtils.analy(request); + try { + userLoginService.checkActive(request); + InterceptorStatusToken token = super.beforeInvocation(authFilterInvocation); + ResponseUtils.printJson(response, AlitaResult.success()); + return; + } catch (BadLoginException be) { + ResponseUtils.printJson(response, be.getResult()); + } catch (Exception e) { + log.error("鉴权失败", e); + ResponseUtils.printJson(response, + AlitaResult.error(AlitaResult.LOGIN_ERROR_CODE, e.getMessage())); + } + return; + } + Authentication auth = SecurityContextHolder.getContext().getAuthentication(); + + boolean isAnno = auth.isAuthenticated() && SecurityPropertyUtils.isAnon(request); + boolean isUnac = !isAnno && SecurityPropertyUtils.isUnac(request); + boolean hasLogin = UserContextHolder.getLoginUser() != null; + // 匿名路径 | 未激活路径且已登录 直接过 + boolean isAllowed = + (request != null) && (request.getAttribute(FILTER_APPLIED) != null) && observeOncePerRequest + || isAnno + || (hasLogin && isUnac); + if (isAllowed) { + // filter already applied to this request and user wants us to observe + // once-per-request handling, so don't re-do security checking + fi.getChain().doFilter(request, response); + } else { + // 未登录 去登录 + Assert.isTrue(hasLogin, new BadLoginException(AlitaResult.unLogin())); + // first time this request being called, so perform security checking + if (request != null && observeOncePerRequest) { + request.setAttribute(FILTER_APPLIED, Boolean.TRUE); + } + InterceptorStatusToken token = null; + // 用户中心鉴权 + userLoginService.checkActive(request); + token = super.beforeInvocation(fi); + if (token == null) { + // TODO token 为空,资源未被分配,又不在白名单(只要登录就可访问),默认无权访问 + // throw AccessDeniedException ; + } + try { + fi.getChain().doFilter(request, response); + } finally { + super.finallyInvocation(token); + } + + super.afterInvocation(token, null); + } + } + + /** + * Indicates whether once-per-request handling will be observed. By default this is + * true, meaning the FilterSecurityInterceptor will only execute + * once-per-request. Sometimes users may wish it to execute more than once per request, such as + * when JSP forwards are being used and filter security is desired on each included fragment of + * the HTTP request. + * + * @return true (the default) if once-per-request is honoured, otherwise + * false if FilterSecurityInterceptor will enforce + * authorizations for each and every fragment of the HTTP request. + */ + public boolean isObserveOncePerRequest() { + return observeOncePerRequest; + } + + public void setObserveOncePerRequest(boolean observeOncePerRequest) { + this.observeOncePerRequest = observeOncePerRequest; + } +} diff --git a/src/main/java/com/newyetai/security/access/metadata/ResourceSecurityMetadataSource.java b/src/main/java/com/newyetai/security/access/metadata/ResourceSecurityMetadataSource.java new file mode 100644 index 0000000..8b32444 --- /dev/null +++ b/src/main/java/com/newyetai/security/access/metadata/ResourceSecurityMetadataSource.java @@ -0,0 +1,66 @@ +package com.newyetai.security.access.metadata; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.annotation.AnnotationAwareOrderComparator; +import org.springframework.security.access.ConfigAttribute; +import org.springframework.stereotype.Component; + +import com.google.common.collect.Maps; +import com.newyetai.common.entity.BaseEntity; +import com.newyetai.security.access.provider.ResourceConfigAttributeProvider; +import com.newyetai.usercenter.authority.dto.PermissionQueryDTO; +import com.newyetai.usercenter.dto.Resource; + +import lombok.RequiredArgsConstructor; + + +/** + * 资源安全元数据源 + * + * @author on 2019-11-05 + */ +@Component +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class ResourceSecurityMetadataSource { + + private final List providers; + + public Collection getAttributes(Object object, + PermissionQueryDTO permissionQueryDTO) throws IllegalArgumentException { + if (!this.supports(object.getClass())) { + return Collections.emptyList(); + } + Long resourceId = ((Resource) object).getId(); + Collection attributes = + getComponentMap(object, permissionQueryDTO).get(resourceId); + return attributes == null ? Collections.emptyList() : attributes; + } + + public Map> getComponentMap(Object object, + PermissionQueryDTO permissionQueryDTO) { + AnnotationAwareOrderComparator.sort(providers); + Map> componentMap = Maps.newLinkedHashMap(); + providers.forEach(provider -> { + // 选择支持的提供者 + if (!provider.supports(object.getClass())) { + return; + } + Map> map = provider.provide(permissionQueryDTO); + if (map != null && !map.isEmpty()) { + componentMap.putAll(map); + } + + }); + return componentMap; + } + + public boolean supports(Class clazz) { + return Resource.class.isAssignableFrom(clazz); + } + +} diff --git a/src/main/java/com/newyetai/security/access/metadata/UrlFilterInvocationSecurityMetadataSource.java b/src/main/java/com/newyetai/security/access/metadata/UrlFilterInvocationSecurityMetadataSource.java new file mode 100644 index 0000000..2ad5e71 --- /dev/null +++ b/src/main/java/com/newyetai/security/access/metadata/UrlFilterInvocationSecurityMetadataSource.java @@ -0,0 +1,76 @@ +package com.newyetai.security.access.metadata; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map.Entry; + +import javax.servlet.http.HttpServletRequest; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.annotation.AnnotationAwareOrderComparator; +import org.springframework.security.access.ConfigAttribute; +import org.springframework.security.web.FilterInvocation; +import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.stereotype.Component; + +import com.newyetai.common.util.SpringContextHolder; +import com.newyetai.security.access.provider.FilterConfigAttributeProvider; +import com.newyetai.security.access.request.AuthDtoUtils; + +/** + * 菜单安全元数据源 + * + * @author on 2019-11-05 + */ +@Component +public class UrlFilterInvocationSecurityMetadataSource + implements FilterInvocationSecurityMetadataSource { + + @Autowired + private List providers; + + + @Override + public Collection getAllConfigAttributes() { + /*Set allAttributes = new HashSet(); + + for (Map.Entry> entry : getRequestMap() + .entrySet()) { + allAttributes.addAll(entry.getValue()); + }*/ + return Collections.emptyList(); + } + + @Override + public Collection getAttributes(Object object) { + final HttpServletRequest request = ((FilterInvocation) object).getRequest(); + Integer systemCode = AuthDtoUtils.getSystemCode(SpringContextHolder.getRequest()); + return getAttributes(request, systemCode); + } + + public Collection getAttributes(HttpServletRequest request, Integer systemCode) { + for (FilterConfigAttributeProvider provider : providers) { + for (Entry> entry : provider.provide(systemCode).entrySet()) { + if (new AntPathRequestMatcher("/" + entry.getKey(), null).matches(request)) { + return entry.getValue(); + } + } + } + return Collections.emptyList(); + } + + + @Override + public boolean supports(Class clazz) { + return FilterInvocation.class.isAssignableFrom(clazz); + } + + @Autowired + public void setProvider(List providers) { + AnnotationAwareOrderComparator.sort(providers); + this.providers = providers; + } + +} diff --git a/src/main/java/com/newyetai/security/access/provider/FilterConfigAttributeProvider.java b/src/main/java/com/newyetai/security/access/provider/FilterConfigAttributeProvider.java new file mode 100644 index 0000000..c7f2f2a --- /dev/null +++ b/src/main/java/com/newyetai/security/access/provider/FilterConfigAttributeProvider.java @@ -0,0 +1,24 @@ +package com.newyetai.security.access.provider; + +import java.util.Collection; +import java.util.Map; +import org.springframework.security.access.ConfigAttribute; +import org.springframework.security.web.util.matcher.RequestMatcher; + +import com.newyetai.usercenter.authority.dto.PermissionQueryDTO; + +/** + * 访问菜单权限信息提供者 + * 资源被谁配置列表(可扩展configAttribute,可以有role_(目前),resource_等) + * + * @author on 2019-11-05 + */ +public interface FilterConfigAttributeProvider { + /** + * 提供菜单权限信息,以Map结构返回,Key为路径,
+ * Value为对应的权限信息 + * + * @return 权限信息 + */ + Map> provide(Integer systemCode); +} diff --git a/src/main/java/com/newyetai/security/access/provider/GrantedAuthorityProvider.java b/src/main/java/com/newyetai/security/access/provider/GrantedAuthorityProvider.java new file mode 100644 index 0000000..e5d8f0b --- /dev/null +++ b/src/main/java/com/newyetai/security/access/provider/GrantedAuthorityProvider.java @@ -0,0 +1,25 @@ +package com.newyetai.security.access.provider; + +import java.util.Collection; + +import org.springframework.security.core.GrantedAuthority; + +import com.newyetai.usercenter.dto.IUserDetail; + +/** + * 授权信息提供者 + * 人被分配角色列表(后面可扩展authority,可以有role_(目前),resource_等) + * + * @author on 2019-11-05 + */ +public interface GrantedAuthorityProvider { + + /** + * 提供授权权限信息 + * + * @param userDetails 用户信息 + * @return 授权信息 + */ + Collection provide(IUserDetail userDetails); + +} diff --git a/src/main/java/com/newyetai/security/access/provider/IConfigAttribute.java b/src/main/java/com/newyetai/security/access/provider/IConfigAttribute.java new file mode 100644 index 0000000..ff90956 --- /dev/null +++ b/src/main/java/com/newyetai/security/access/provider/IConfigAttribute.java @@ -0,0 +1,23 @@ +package com.newyetai.security.access.provider; + +import java.io.Serializable; + +import org.springframework.security.access.ConfigAttribute; + +/** + * 资源权限 + * + * @author sr on 2020-09-04 + * @param + */ +public interface IConfigAttribute extends ConfigAttribute { + + /** + * 唯一标识 + * + * @return + * @author sr on 2020-09-04 + */ + K getKey(); + +} diff --git a/src/main/java/com/newyetai/security/access/provider/IUrlConfigAttribute.java b/src/main/java/com/newyetai/security/access/provider/IUrlConfigAttribute.java new file mode 100644 index 0000000..90e71e9 --- /dev/null +++ b/src/main/java/com/newyetai/security/access/provider/IUrlConfigAttribute.java @@ -0,0 +1,15 @@ +package com.newyetai.security.access.provider; + +import java.io.Serializable; + +/** + * 请求资源权限 + * + * @author sr on 2020-09-07 + * @param + */ +public interface IUrlConfigAttribute extends IConfigAttribute { + + String getUrl(); + +} diff --git a/src/main/java/com/newyetai/security/access/provider/ResourceConfigAttributeProvider.java b/src/main/java/com/newyetai/security/access/provider/ResourceConfigAttributeProvider.java new file mode 100644 index 0000000..0d7aadb --- /dev/null +++ b/src/main/java/com/newyetai/security/access/provider/ResourceConfigAttributeProvider.java @@ -0,0 +1,54 @@ +package com.newyetai.security.access.provider; + +import java.io.Serializable; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import com.google.common.collect.Sets; +import com.newyetai.usercenter.authority.dto.PermissionQueryDTO; + +/** + * 资源权限信息提供者 + * + * @author on 2019-11-05 + */ +public interface ResourceConfigAttributeProvider> { + /** + * 提供资源权限信息 + * + * @return 权限信息 + */ + List list(PermissionQueryDTO permissionQueryDTO); + + /** + * 支持类型 + * + * @param clazz + * @return + * @author sr on 2019-11-05 + */ + boolean supports(Class clazz); + + /** + * + * @return + * @author sr on 2020-09-07 + */ + default Map> provide(PermissionQueryDTO permissionQueryDTO) { + return this.list(permissionQueryDTO) + .stream() + .collect( + Collectors.toMap( + IConfigAttribute::getKey, v -> { + Collection values = Sets.newHashSet(); + values.add(v); + return values; + }, + (v1, v2) -> { + v1.addAll(v2); + return v1; + })); + } +} diff --git a/src/main/java/com/newyetai/security/access/provider/impl/ComponentConfigAttributeProvider.java b/src/main/java/com/newyetai/security/access/provider/impl/ComponentConfigAttributeProvider.java new file mode 100644 index 0000000..fb26058 --- /dev/null +++ b/src/main/java/com/newyetai/security/access/provider/impl/ComponentConfigAttributeProvider.java @@ -0,0 +1,42 @@ +package com.newyetai.security.access.provider.impl; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import com.newyetai.security.access.provider.ResourceConfigAttributeProvider; +import com.newyetai.usercenter.authority.dto.ComponentPermissionDTO; +import com.newyetai.usercenter.authority.dto.PermissionQueryDTO; +import com.newyetai.usercenter.authority.service.UcPermissionService; +import com.newyetai.usercenter.constants.SecurityConstants; +import com.newyetai.usercenter.resource.dto.ComponentDTO; + +/** + * 默认组件权限信息提供者 + * + * @author on 2019-11-05 + */ +@Order(100) +@Component +public class ComponentConfigAttributeProvider + implements ResourceConfigAttributeProvider { + + @Autowired + private UcPermissionService ucPermissionService; + + @Override + public boolean supports(Class clazz) { + return ComponentDTO.class.isAssignableFrom(clazz); + } + + @Override + @Cacheable(cacheNames = SecurityConstants.CacheName.COMPONENT_ATTRIBUTE_MAP_CACHE_KEY, + key = SecurityConstants.CACHE_KEY_PERMISSION_ORG_SYSTEM) + public List list(PermissionQueryDTO permissionQueryDTO) { + return ucPermissionService.listComponent(permissionQueryDTO); + } + +} diff --git a/src/main/java/com/newyetai/security/access/provider/impl/UrlConfigAttributeProvider.java b/src/main/java/com/newyetai/security/access/provider/impl/UrlConfigAttributeProvider.java new file mode 100644 index 0000000..05ab77f --- /dev/null +++ b/src/main/java/com/newyetai/security/access/provider/impl/UrlConfigAttributeProvider.java @@ -0,0 +1,42 @@ +package com.newyetai.security.access.provider.impl; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import com.newyetai.security.access.provider.ResourceConfigAttributeProvider; +import com.newyetai.usercenter.authority.dto.PermissionQueryDTO; +import com.newyetai.usercenter.authority.dto.UrlPermissionDTO; +import com.newyetai.usercenter.authority.service.UcPermissionService; +import com.newyetai.usercenter.constants.SecurityConstants; +import com.newyetai.usercenter.resource.dto.UrlDTO; + +/** + * 默认菜单权限信息提供者 + * + * @author on 2019-11-05 + */ +@Component +@Order(100) +public class UrlConfigAttributeProvider + implements ResourceConfigAttributeProvider { + + @Autowired + private UcPermissionService ucPermissionService; + + @Override + public boolean supports(Class clazz) { + return UrlDTO.class.isAssignableFrom(clazz); + } + + @Override + @Cacheable(cacheNames = SecurityConstants.CacheName.URL_ATTRIBUTE_MAP_CACHE_KEY, + key = SecurityConstants.CACHE_KEY_PERMISSION_ORG_SYSTEM) + public List list(PermissionQueryDTO permissionQueryDTO) { + return ucPermissionService.listUrl(permissionQueryDTO).getData(); + } + +} diff --git a/src/main/java/com/newyetai/security/access/provider/impl/UrlFilterConfigAttribueProvider.java b/src/main/java/com/newyetai/security/access/provider/impl/UrlFilterConfigAttribueProvider.java new file mode 100644 index 0000000..e74b888 --- /dev/null +++ b/src/main/java/com/newyetai/security/access/provider/impl/UrlFilterConfigAttribueProvider.java @@ -0,0 +1,60 @@ +package com.newyetai.security.access.provider.impl; + +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.core.annotation.Order; +import org.springframework.security.access.ConfigAttribute; +import org.springframework.stereotype.Component; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.security.access.provider.FilterConfigAttributeProvider; +import com.newyetai.security.service.IPermissionSecurityService; +import com.newyetai.usercenter.authority.dto.PermissionQueryDTO; +import com.newyetai.usercenter.authority.dto.UrlPermissionDTO; +import com.newyetai.usercenter.constants.SecurityConstants; +import com.newyetai.usercenter.resource.enums.UrlTypeEnum; + +/** + * 默认菜单权限信息提供者 + * + * @author on 2019-11-05 + */ +@Component +@Order(100) +public class UrlFilterConfigAttribueProvider implements FilterConfigAttributeProvider { + + @Autowired + private IPermissionSecurityService iPermissionSecurityService; + + @Override + @Cacheable(cacheNames = SecurityConstants.CacheName.URL_FILTER_ATTRIBUTE_MAP_CACHE_KEY, + key = SecurityConstants.CACHE_KEY_SYSTEM) + public Map> provide( + Integer systemCode) { + // 应用下所有授权信息 + PermissionQueryDTO permissionQueryDTO = + PermissionQueryDTO.builder().systemCode(systemCode).build(); + AlitaResult> result = + iPermissionSecurityService.listUrl(permissionQueryDTO); + Assert.isTrue(result.getSuccess(), "资源权限获取失败"); + return result.getData().stream().filter(p -> StringUtils.isNotBlank(p.getLink()) + && UrlTypeEnum.INTERFACE.getType().toString().equals(p.getResourceType())) + .collect(Collectors.toMap(UrlPermissionDTO::getLink, v -> { + Collection values = new HashSet(); + values.add(v); + return values; + }, (v1, v2) -> { + v1.addAll(v2); + return v1; + })); + } + +} diff --git a/src/main/java/com/newyetai/security/access/provider/impl/UserGrantedAuthorityProvider.java b/src/main/java/com/newyetai/security/access/provider/impl/UserGrantedAuthorityProvider.java new file mode 100644 index 0000000..f15cbd9 --- /dev/null +++ b/src/main/java/com/newyetai/security/access/provider/impl/UserGrantedAuthorityProvider.java @@ -0,0 +1,40 @@ +package com.newyetai.security.access.provider.impl; + +import java.util.Collection; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.stereotype.Component; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.security.access.provider.GrantedAuthorityProvider; +import com.newyetai.security.service.IRoleAllocationSecurityService; +import com.newyetai.usercenter.authority.dto.RoleAllocationDTO; +import com.newyetai.usercenter.constants.SecurityConstants; +import com.newyetai.usercenter.dto.IUserDetail; + +/** + * 默认用户授权信息提供者 + * + * @author on 2019-11-05 + */ +@Component +public class UserGrantedAuthorityProvider implements GrantedAuthorityProvider { + + @Autowired + private IRoleAllocationSecurityService iRoleAllocationSecurityService; + + @Override + @Cacheable(cacheNames = SecurityConstants.CacheName.USER_GRANTED_AUTHORITY_CACHE_KEY, + key = SecurityConstants.CACHE_KEY_ORG_USER) + public Collection provide(IUserDetail userDetails) { + AlitaResult> result = + iRoleAllocationSecurityService.findByUserId(userDetails.getId()); + Assert.isTrue(result.getSuccess(), "用户权限获取失败"); + return result.getData(); + } + +} diff --git a/src/main/java/com/newyetai/security/access/request/AuthDTO.java b/src/main/java/com/newyetai/security/access/request/AuthDTO.java new file mode 100644 index 0000000..6082107 --- /dev/null +++ b/src/main/java/com/newyetai/security/access/request/AuthDTO.java @@ -0,0 +1,28 @@ +package com.newyetai.security.access.request; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2020-09-09 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class AuthDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = -6816336716189522975L; + + private String url; + + private String method; + + private Integer systemCode; + +} diff --git a/src/main/java/com/newyetai/security/access/request/AuthDtoUtils.java b/src/main/java/com/newyetai/security/access/request/AuthDtoUtils.java new file mode 100644 index 0000000..13b23c6 --- /dev/null +++ b/src/main/java/com/newyetai/security/access/request/AuthDtoUtils.java @@ -0,0 +1,58 @@ +package com.newyetai.security.access.request; + +import javax.servlet.http.HttpServletRequest; + +import org.springframework.security.web.FilterInvocation; + +import com.newyetai.common.util.EnvironmentUtils; + +/** + * @author sr on 2020-09-10 + */ +public abstract class AuthDtoUtils { + + public static final String PARAM_URL = "url"; + public static final String PARAM_METHOD = "method"; + public static final String PARAM_SYSTEMCODE = "systemCode"; + + /** + * 转换request为认证对象 + * + * @param request + * @return + * @author sr on 2020-09-10 + */ + public static AuthDTO convert(HttpServletRequest request) { + return AuthDTO.builder().url(request.getServletPath()).method(request.getMethod()) + .systemCode(EnvironmentUtils.getSystemCode()).build(); + } + + /** + * 根据请求对象解析成拦截器调用对象 + * + * @param request + * @return + * @author sr on 2020-09-10 + */ + public static FilterInvocation analy(HttpServletRequest request) { + return new FilterInvocation(request.getParameter(PARAM_URL), + request.getParameter(PARAM_METHOD)); + } + + + /** + * 获取请求的应用标识 + * + * @param request + * @return + * @author sr on 2020-09-10 + */ + public static Integer getSystemCode(HttpServletRequest request) { + String systemCodeStr = null; + if (request == null || (systemCodeStr = request.getParameter(PARAM_SYSTEMCODE)) == null) { + return EnvironmentUtils.getSystemCode(); + } + return Integer.valueOf(systemCodeStr); + } + +} diff --git a/src/main/java/com/newyetai/security/access/vote/AccessDecisionManagerImpl.java b/src/main/java/com/newyetai/security/access/vote/AccessDecisionManagerImpl.java new file mode 100644 index 0000000..8d83c37 --- /dev/null +++ b/src/main/java/com/newyetai/security/access/vote/AccessDecisionManagerImpl.java @@ -0,0 +1,76 @@ +package com.newyetai.security.access.vote; + +import java.util.Collection; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.AccessDecisionVoter; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.access.ConfigAttribute; +import org.springframework.security.access.vote.AbstractAccessDecisionManager; +import org.springframework.security.authentication.InsufficientAuthenticationException; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Component; + +import com.newyetai.security.config.SecurityProperties; +import com.newyetai.security.dto.SecurityUserDTO; + +/** + * 默认访问决策管理器 + * + * @author on 2019-11-05 + */ +@Component +public class AccessDecisionManagerImpl extends AbstractAccessDecisionManager { + + private List> decisionVoters; + + @Autowired + public AccessDecisionManagerImpl(List> decisionVoters, SecurityProperties securityProperties) { + super(decisionVoters); + this.decisionVoters = decisionVoters; + this.setAllowIfAllAbstainDecisions(securityProperties.getAllowIfAllAbstainDecisions()); + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + @Override + public void decide(Authentication authentication, Object object, + Collection configAttributes) + throws AccessDeniedException, InsufficientAuthenticationException { + Object principal = authentication.getPrincipal(); + if (principal instanceof SecurityUserDTO + && ((SecurityUserDTO) principal).getSupeiror()) { + // 平台管理员放行 + return; + } + int deny = 0; + if (!configAttributes.isEmpty()) { + for (AccessDecisionVoter voter : getDecisionVoters()) { + if (voter.supports(object.getClass())) { + int result = voter.vote(authentication, object, configAttributes); + if (logger.isDebugEnabled()) { + logger.debug("Voter: " + voter + ", returned: " + result); + } + switch (result) { + case AccessDecisionVoter.ACCESS_GRANTED: + return; + case AccessDecisionVoter.ACCESS_DENIED: + deny++; + break; + default: + break; + } + } + } + } + + if (deny > 0) { + throw new AccessDeniedException( + messages.getMessage("AbstractAccessDecisionManager.accessDenied", "Access is denied")); + } + + checkAllowIfAllAbstainDecisions(); + + } + +} diff --git a/src/main/java/com/newyetai/security/access/vote/ResourceRoleVoter.java b/src/main/java/com/newyetai/security/access/vote/ResourceRoleVoter.java new file mode 100644 index 0000000..47a14e3 --- /dev/null +++ b/src/main/java/com/newyetai/security/access/vote/ResourceRoleVoter.java @@ -0,0 +1,100 @@ +/* + * Copyright 2004, 2005, 2006 Acegi Technology Pty Limited + * + * 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.newyetai.security.access.vote; + +import java.util.Collection; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.AccessDecisionVoter; +import org.springframework.security.access.ConfigAttribute; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.web.FilterInvocation; +import org.springframework.stereotype.Component; + +import com.newyetai.security.service.GrantedAuthorityService; +import com.newyetai.usercenter.dto.IUserDetail; +import com.newyetai.usercenter.dto.Resource; + +/** + * 资源角色投票器 重写RoleVoter,获取用户授权信息authorities方式更改 + * + * @author on 2019-11-05 + */ +@Component +public class ResourceRoleVoter implements AccessDecisionVoter { + + @Autowired + private GrantedAuthorityService grantedAuthorityService; + + private String rolePrefix = "ROLE_"; + + + public String getRolePrefix() { + return rolePrefix; + } + + public void setRolePrefix(String rolePrefix) { + this.rolePrefix = rolePrefix; + } + + @Override + public boolean supports(ConfigAttribute attribute) { + if ((attribute.getAttribute() != null) + && attribute.getAttribute().startsWith(getRolePrefix())) { + return true; + } else { + return false; + } + } + + @Override + public boolean supports(Class clazz) { + return FilterInvocation.class.isAssignableFrom(clazz) || Resource.class.isAssignableFrom(clazz); + } + + @Override + public int vote(Authentication authentication, Object object, + Collection attributes) { + if (authentication == null) { + return ACCESS_DENIED; + } + + int result = ACCESS_ABSTAIN; + Collection authorities = extractAuthorities(authentication); + + for (ConfigAttribute attribute : attributes) { + if (this.supports(attribute)) { + result = ACCESS_DENIED; + + for (GrantedAuthority authority : authorities) { + if (attribute.getAttribute().equals(authority.getAuthority())) { + return ACCESS_GRANTED; + } + } + } + } + + return result; + } + + Collection extractAuthorities(Authentication authentication) { + if (authentication.getPrincipal() instanceof IUserDetail) { + IUserDetail userDetails = (IUserDetail) authentication.getPrincipal(); + return grantedAuthorityService.getGrantedAuthorities(userDetails); + } + return authentication.getAuthorities(); + } +} diff --git a/src/main/java/com/newyetai/security/cas/CasAuthenticationToken.java b/src/main/java/com/newyetai/security/cas/CasAuthenticationToken.java new file mode 100644 index 0000000..3491e0e --- /dev/null +++ b/src/main/java/com/newyetai/security/cas/CasAuthenticationToken.java @@ -0,0 +1,60 @@ +package com.newyetai.security.cas; + +import java.util.Collection; + +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.core.GrantedAuthority; + +/** + * cas认证信息 + * + * @author sr on 2020-06-04 + */ +public class CasAuthenticationToken extends AbstractAuthenticationToken { + + /** **/ + private static final long serialVersionUID = 4078096826251434490L; + + private final Object principal; + private String credentials; + + public CasAuthenticationToken(Object principal, String credentials) { + super(null); + this.principal = principal; + this.credentials = credentials; + setAuthenticated(false); + } + + public CasAuthenticationToken(Object principal, + Collection authorities) { + super(authorities); + this.principal = principal; + this.credentials = null; + super.setAuthenticated(true); + } + + @Override + public Object getCredentials() { + return this.credentials; + } + + @Override + public Object getPrincipal() { + return this.principal; + } + + @Override + public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException { + if (isAuthenticated) { + throw new IllegalArgumentException( + "Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead"); + } + super.setAuthenticated(false); + } + + @Override + public void eraseCredentials() { + super.eraseCredentials(); + credentials = null; + } +} diff --git a/src/main/java/com/newyetai/security/config/SecurityConfiguration.java b/src/main/java/com/newyetai/security/config/SecurityConfiguration.java new file mode 100644 index 0000000..e5b70cb --- /dev/null +++ b/src/main/java/com/newyetai/security/config/SecurityConfiguration.java @@ -0,0 +1,88 @@ +package com.newyetai.security.config; + +import org.springframework.boot.autoconfigure.AutoConfigurationPackage; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +import com.newyetai.security.handle.MyAuthenctiationFailureHandler; +import com.newyetai.security.mobile.MobileAuthenticationProvider; +import com.newyetai.security.social.service.StandardClientRegistrationRepository; +import com.newyetai.security.social.wechat.service.WechatOauthLoginProvider; +import com.newyetai.security.ssb.SsbAuthenticationProvider; +import com.newyetai.security.temptoken.TokenAuthenticationProvider; +import com.newyetai.security.upassword.UpasswordAuthenticationProvider; +import com.newyetai.security.util.SecurityPropertyUtils; +import com.newyetai.usercenter.constants.SecurityConstants; +import com.newyetai.usercenter.user.login.service.UserLoginService; + +/** + * security配置类 + * + * @author on 2019-11-05 + */ +@Configuration +@AutoConfigurationPackage +public class SecurityConfiguration { + + private SecurityProperties securityProperties; + + SecurityConfiguration(SecurityProperties securityProperties){ + this.securityProperties = securityProperties; + SecurityPropertyUtils.setSecurityProperties(securityProperties); + } + + /** + * 声明密码加密方式 + */ + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + @Bean + MyAuthenctiationFailureHandler myAuthenctiationFailureHandler() { + return new MyAuthenctiationFailureHandler(securityProperties.getLoginPage()); + } + + @Bean + @ConditionalOnProperty(name = SecurityConstants.PROP_KEY_SECURITY_OAUTH2_USEDB, havingValue = "true", + matchIfMissing = false) + StandardClientRegistrationRepository standardClientRegistrationRepository(UserLoginService userLoginService) { + return new StandardClientRegistrationRepository(userLoginService); + } + + @Bean + @ConditionalOnBean(UserLoginService.class) + MobileAuthenticationProvider mobileAuthenticationProvider(UserLoginService userLoginService) { + return new MobileAuthenticationProvider(userLoginService); + } + + @Bean + @ConditionalOnBean(UserLoginService.class) + WechatOauthLoginProvider wechatOauthLoginProvider(UserLoginService userLoginService) { + return new WechatOauthLoginProvider(userLoginService); + } + + @Bean + @ConditionalOnBean(UserLoginService.class) + TokenAuthenticationProvider tokenAuthenticationProvider(UserLoginService userLoginService) { + return new TokenAuthenticationProvider(userLoginService); + } + + @Bean + @ConditionalOnBean(UserLoginService.class) + UpasswordAuthenticationProvider upasswordAuthenticationProvider(UserLoginService userLoginService) { + return new UpasswordAuthenticationProvider(userLoginService); + } + + @Bean + @ConditionalOnBean(UserLoginService.class) + SsbAuthenticationProvider ssbAuthenticationProvider(UserLoginService userLoginService) { + return new SsbAuthenticationProvider(userLoginService); + } + +} diff --git a/src/main/java/com/newyetai/security/config/SecurityProperties.java b/src/main/java/com/newyetai/security/config/SecurityProperties.java new file mode 100644 index 0000000..cff5481 --- /dev/null +++ b/src/main/java/com/newyetai/security/config/SecurityProperties.java @@ -0,0 +1,76 @@ +package com.newyetai.security.config; + +import com.newyetai.security.jwt.JwtProperties; +import lombok.Data; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * 安全相关配置项 + * + * @author guhong + */ +@Component +@Data +@ConfigurationProperties(prefix = SecurityProperties.PREFIX) +public class SecurityProperties { + + /** 配置前缀 **/ + public final static String PREFIX = "security"; + + /** + * 匿名访问的url + */ + private String anonymous; + + /** + * 忽略的资源,直接跳过spring security权限校验,一般是用做静态资源 + */ + private String ignoring; + + /** 登录页面 **/ + private String loginPage; + + private String loginSuccessPage; + /** h5登录成功页 **/ + private String loginH5SuccessPage; + + /** 登录请求路径 **/ + private String loginProcessingUrl; + + private Boolean allowIfAllAbstainDecisions; + + /** 域名 **/ + private String domain; + + private Boolean superiorOnly; + + /** 不记日志路径,contains匹配 **/ + private String notLogs; + + private JwtProperties jwt = new JwtProperties(); + + /** 是否调用本地认证鉴权,默认本地;调用户中心配置false **/ + private Boolean useLocal; + + private Oauth2Properties oauth2 = new Oauth2Properties(); + + public String[] getAnonymousArray() { + return StringUtils.isBlank(anonymous) ? ArrayUtils.EMPTY_STRING_ARRAY : anonymous.split(","); + } + + public String[] getIgnoringArray() { + return StringUtils.isBlank(ignoring) ? ArrayUtils.EMPTY_STRING_ARRAY : ignoring.split(","); + } + + @Data + public class Oauth2Properties{ + /** 是否启用 **/ + private Boolean enable; + /** oauth配置类型:true使用数据库配置,否则配置文件 **/ + private Boolean usedb; + } + +} diff --git a/src/main/java/com/newyetai/security/config/WebSecurityConfigurer.java b/src/main/java/com/newyetai/security/config/WebSecurityConfigurer.java new file mode 100644 index 0000000..373be32 --- /dev/null +++ b/src/main/java/com/newyetai/security/config/WebSecurityConfigurer.java @@ -0,0 +1,247 @@ +package com.newyetai.security.config; + +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.AccessDecisionManager; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; +import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter; +import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; +import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; +import org.springframework.security.web.authentication.AnonymousAuthenticationFilter; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.stereotype.Component; + +import com.newyetai.security.access.intercept.FilterSecurityInterceptor; +import com.newyetai.security.handle.MyAuthenctiationFailureHandler; +import com.newyetai.security.handle.MyLoginSuccessHandler; +import com.newyetai.security.handle.MyLoginUrlAuthenticationEntryPoint; +import com.newyetai.security.handle.MyLogoutSuccessHandler; +import com.newyetai.security.jwt.JwtAuthenticationTokenFilter; +import com.newyetai.security.mobile.MobileAuthenticationFilter; +import com.newyetai.security.mobile.MobileAuthenticationProvider; +import com.newyetai.security.social.service.StandardAuthorizationCodeTokenResponseClient; +import com.newyetai.security.social.service.StandardOAuth2UserService; +import com.newyetai.security.social.service.StandardOauth2AuthorizationRequestResolver; +import com.newyetai.security.ssb.SsbAuthenticationFilter; +import com.newyetai.security.ssb.SsbAuthenticationProvider; +import com.newyetai.security.temptoken.TokenAuthenticationFilter; +import com.newyetai.security.temptoken.TokenAuthenticationProvider; +import com.newyetai.security.upassword.UpasswordAuthenticationFilter; +import com.newyetai.security.upassword.UpasswordAuthenticationProvider; +import com.newyetai.swagger.config.SwaggerConfig; +import com.newyetai.usercenter.user.login.service.UserLoginService; +import com.newyetai.usercenter.websocket.util.WebSocketUtils; + +import lombok.extern.slf4j.Slf4j; + +/** + * security配置 + * + * @author on 2019-11-05 + */ +@Slf4j +@Component +public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter { + + @Autowired + private SecurityProperties securityProperties; + + @Autowired + private MyLogoutSuccessHandler myLogoutSuccessHandler; + + @Autowired + private MyLoginSuccessHandler myLoginSuccessHandler; + + @Autowired + private MyAuthenctiationFailureHandler myAuthenctiationFailureHandler; + + @Autowired + private FilterInvocationSecurityMetadataSource securityMetadataSource; + + @Autowired + private AccessDecisionManager accessDecisionManager; + + @Autowired(required = false) + private UpasswordAuthenticationProvider upasswordAuthenticationProvider; + + @Autowired(required = false) + private MobileAuthenticationProvider mobileAuthenticationProvider; + + @Autowired(required = false) + private TokenAuthenticationProvider tokenAuthenticationProvider; + @Autowired + private SsbAuthenticationProvider ssbAuthenticationProvider; + + @Autowired + private SwaggerConfig swaggerConfig; + + @Autowired(required = false) + private UserLoginService userLoginService; + + @Autowired(required = false) + private ClientRegistrationRepository standardClientRegistrationRepository; + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // 添加cas认证提供者 + auth.authenticationProvider(upasswordAuthenticationProvider) + .authenticationProvider(mobileAuthenticationProvider) + .authenticationProvider(tokenAuthenticationProvider) + .authenticationProvider(ssbAuthenticationProvider) + ; + } + + @Override + public void configure(WebSecurity web) throws Exception { + String[] ignoringArray = securityProperties.getIgnoringArray(); + // swagger 接口文档,不设置访问权限 + if (swaggerConfig.isSwaggerEnable() && StringUtils.isNotBlank(SwaggerConfig.ACCESS_PREFIX)) { + ignoringArray = ArrayUtils.addAll(ignoringArray, SwaggerConfig.ACCESS_PREFIX.split(",")); + } + // websocket + if (StringUtils.isNotBlank(WebSocketUtils.getPath())) { + ignoringArray = ArrayUtils.add(ignoringArray, WebSocketUtils.getPath()); + } + // 忽略的资源,直接跳过spring security权限校验 + web.ignoring() + .antMatchers(ignoringArray)/*.antMatchers(securityProperties.getAnonymousArray())*/; + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + log.info("------WebSecurityConfigurer configure"); + http + .logout() + .logoutSuccessHandler(myLogoutSuccessHandler).and() + // 自定义认证失败处理器 + .exceptionHandling().authenticationEntryPoint( + new MyLoginUrlAuthenticationEntryPoint(securityProperties.getLoginPage())) + .and(); + + if (BooleanUtils.isTrue(securityProperties.getOauth2().getEnable())) { + // oauth2 + http.oauth2Login() + .authorizationEndpoint() + .authorizationRequestResolver( + new StandardOauth2AuthorizationRequestResolver( + this.standardClientRegistrationRepository, + OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI)) + .and() + .tokenEndpoint() + .accessTokenResponseClient(new StandardAuthorizationCodeTokenResponseClient()) + .and() + .userInfoEndpoint().userService(new StandardOAuth2UserService()).and() + .failureHandler(myAuthenctiationFailureHandler) + .successHandler(myLoginSuccessHandler).and(); + } + http.addFilterAfter(upasswordAuthenticationFilter(), + UsernamePasswordAuthenticationFilter.class); + http.addFilterAfter(mobileAuthenticationFilter(), UpasswordAuthenticationFilter.class); + http.addFilterAfter(tokenAuthenticationFilter(), UpasswordAuthenticationFilter.class); + http.addFilterAfter(ssbAuthenticationFilter(), UpasswordAuthenticationFilter.class); + + // 禁用CSRF + http.csrf().disable(); + http.headers().frameOptions().deny(); + http.headers().xssProtection().block(true); + http.headers().contentTypeOptions(); + + // 拦截器 + FilterSecurityInterceptor securityInterceptor = createFilterSecurityInterceptor(); + http.addFilterAfter(securityInterceptor, + org.springframework.security.web.access.intercept.FilterSecurityInterceptor.class); + + http.setSharedObject(FilterSecurityInterceptor.class, securityInterceptor); + + // 启用jwt + if (Boolean.TRUE.equals(securityProperties.getJwt().getEnable())) { + JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter = + createJwtAuthenticationTokenFilter(); + http.addFilterAfter(jwtAuthenticationTokenFilter, + AnonymousAuthenticationFilter.class); + // 禁用session + http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); + } + + } + + private JwtAuthenticationTokenFilter createJwtAuthenticationTokenFilter() { + return new JwtAuthenticationTokenFilter(securityProperties); + } + + /** + * 拦截器 + * + * @return + * @throws Exception + * @author sr on 2019-11-28 + */ + private FilterSecurityInterceptor createFilterSecurityInterceptor() throws Exception { + FilterSecurityInterceptor securityInterceptor = new FilterSecurityInterceptor(); + securityInterceptor.setSecurityMetadataSource(securityMetadataSource); + securityInterceptor.setAccessDecisionManager(accessDecisionManager); + // httpSecurity中shareobject共用的authenticationBuilder + securityInterceptor.setAuthenticationManager(this.authenticationManagerBean()); + securityInterceptor.setUserLoginService(userLoginService); + securityInterceptor.afterPropertiesSet(); + return securityInterceptor; + } + + /** + * 手机号登录请求过滤器 + * + * @param authenticationManager + * @return + * @author sr on 2020-06-04 + * @throws Exception + */ + private MobileAuthenticationFilter mobileAuthenticationFilter() throws Exception { + MobileAuthenticationFilter filter = new MobileAuthenticationFilter(); + addHandler(filter); + return filter; + } + + private void addHandler(AbstractAuthenticationProcessingFilter filter) throws Exception { + filter.setAuthenticationManager(this.authenticationManagerBean()); + filter.setAuthenticationSuccessHandler(myLoginSuccessHandler); + filter.setAuthenticationFailureHandler(myAuthenctiationFailureHandler); + } + + /** + * 账号密码 + * @return + * @throws Exception + * @author sr on 2021-06-22 + */ + private UpasswordAuthenticationFilter upasswordAuthenticationFilter() throws Exception { + UpasswordAuthenticationFilter filter = new UpasswordAuthenticationFilter(); + addHandler(filter); + return filter; + } + + /** + * 临时token + * @return + * @throws Exception + * @author sr on 2021-06-22 + */ + private TokenAuthenticationFilter tokenAuthenticationFilter() throws Exception { + TokenAuthenticationFilter filter = new TokenAuthenticationFilter(); + addHandler(filter); + return filter; + } + + private SsbAuthenticationFilter ssbAuthenticationFilter() throws Exception { + SsbAuthenticationFilter filter = new SsbAuthenticationFilter(); + addHandler(filter); + return filter; + } + +} diff --git a/src/main/java/com/newyetai/security/decision/manager/SecurityDecisionManager.java b/src/main/java/com/newyetai/security/decision/manager/SecurityDecisionManager.java new file mode 100644 index 0000000..f63f9a5 --- /dev/null +++ b/src/main/java/com/newyetai/security/decision/manager/SecurityDecisionManager.java @@ -0,0 +1,45 @@ +package com.newyetai.security.decision.manager; + +import java.util.Collection; + +import org.springframework.security.access.ConfigAttribute; +import org.springframework.security.core.userdetails.UserDetails; + +import com.newyetai.usercenter.authority.dto.PermissionQueryDTO; +import com.newyetai.usercenter.dto.Resource; + +/** + * 权限决策管理器。
+ * 实现{@link org.springframework.security.access.SecurityMetadataSource}来
+ * 提供自己定义资源的权限信息,就可以实现权限决策判断 + * + * @author on 2019-11-05 + */ +public interface SecurityDecisionManager { + + /** + * 决策给定的资源,当前登录用户是否有权限 + * + * @param resource 资源 + * @return 结果。true为有权限,否则没有 + */ + boolean decide(Resource resource, PermissionQueryDTO permissionQueryDTO); + + /** + * 根据资源获取权限信息 + * + * @param resource 资源 + * @return 权限列表 + */ + Collection findConfigAttributes(Resource resource, PermissionQueryDTO permissionQueryDTO); + + /** + * 决策给定的资源,给定用户是否有权限 + * + * @param userDetails 用户实体 + * @param resource 资源 + * @return 结果。true为有权限,否则没有 + * @author sr on 2019-10-16 + */ + boolean decide(UserDetails userDetails, Resource resource, PermissionQueryDTO permissionQueryDTO); +} diff --git a/src/main/java/com/newyetai/security/decision/manager/impl/SecurityDecisionManagerImpl.java b/src/main/java/com/newyetai/security/decision/manager/impl/SecurityDecisionManagerImpl.java new file mode 100644 index 0000000..c34ddf6 --- /dev/null +++ b/src/main/java/com/newyetai/security/decision/manager/impl/SecurityDecisionManagerImpl.java @@ -0,0 +1,86 @@ +package com.newyetai.security.decision.manager.impl; + +import java.util.Collection; +import java.util.Collections; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.AccessDecisionManager; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.access.ConfigAttribute; +import org.springframework.security.authentication.InsufficientAuthenticationException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import com.newyetai.security.access.metadata.ResourceSecurityMetadataSource; +import com.newyetai.security.decision.manager.SecurityDecisionManager; +import com.newyetai.usercenter.authority.dto.PermissionQueryDTO; +import com.newyetai.usercenter.dto.Resource; + +/** + * 权限决策管理器 + * + * @author on 2019-11-05 + */ +@Service +public class SecurityDecisionManagerImpl implements SecurityDecisionManager { + + @Autowired + private ResourceSecurityMetadataSource resourceSecurityMetadataSource; + + @Autowired + private AccessDecisionManager accessDecisionManager; + + @Override + public boolean decide(Resource resource, PermissionQueryDTO permissionQueryDTO) { + return decide(SecurityContextHolder.getContext().getAuthentication(), resource, permissionQueryDTO); + } + + + @Override + public boolean decide(UserDetails userDetails, Resource resource, + PermissionQueryDTO permissionQueryDTO) { + return decide(getAuthentication(userDetails), resource, permissionQueryDTO); + } + + private boolean decide(Authentication authentication, Resource resource, + PermissionQueryDTO permissionQueryDTO) { + try { + Collection attributes = findConfigAttributes(resource, permissionQueryDTO); + accessDecisionManager.decide(authentication, resource, attributes); + return true; + } catch (AccessDeniedException e) { + return false; + } catch (InsufficientAuthenticationException e) { + return false; + } + } + + /** + * 获取用户认证信息 + * + * @return + * @author sr on 2019-10-16 + */ + protected Authentication getAuthentication(UserDetails userDetails) { + return userDetails != null ? new UsernamePasswordAuthenticationToken(userDetails, null) + : SecurityContextHolder.getContext().getAuthentication(); + } + + @Override + public Collection findConfigAttributes(Resource resource, + PermissionQueryDTO permissionQueryDTO) { + Collection attributes = resource.getAttributes(); + if (CollectionUtils.isEmpty(attributes) + && resourceSecurityMetadataSource.supports(resource.getClass())) { + return resourceSecurityMetadataSource.getAttributes(resource, permissionQueryDTO); + } + return Collections.emptyList(); + } + + + +} diff --git a/src/main/java/com/newyetai/security/dto/RoleDTO.java b/src/main/java/com/newyetai/security/dto/RoleDTO.java new file mode 100644 index 0000000..d5fd3ce --- /dev/null +++ b/src/main/java/com/newyetai/security/dto/RoleDTO.java @@ -0,0 +1,62 @@ +package com.newyetai.security.dto; + +import java.io.Serializable; +import java.util.Date; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 角色 + * + * @author sr on 2019-11-05 + */ +@ApiModel("角色") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class RoleDTO implements Serializable { + + /** **/ + private static final long serialVersionUID = -1148469623294607563L; + + @ApiModelProperty("角色id") + @NotNull(message = "角色id不能为空", groups = {Update.class}) + private Long id; + + @ApiModelProperty("名称") + @NotBlank(message = "角色名称不能为空", groups = {Create.class}) + @Size(max = 128) + private String name; + + /** 类型 **/ + @JsonIgnore + private String type; + + @ApiModelProperty("是否启用") + private Boolean enabled; + + @ApiModelProperty("描述") + @Size(max = 64, groups = {Create.class, Update.class}) + private String description; + + @ApiModelProperty("标准角色类型:见role_standard_type") + private String standardType; + + @ApiModelProperty("创建时间") + private Date createTime; + +} diff --git a/src/main/java/com/newyetai/security/dto/SecurityUserDTO.java b/src/main/java/com/newyetai/security/dto/SecurityUserDTO.java new file mode 100644 index 0000000..5e963bf --- /dev/null +++ b/src/main/java/com/newyetai/security/dto/SecurityUserDTO.java @@ -0,0 +1,102 @@ +package com.newyetai.security.dto; + +import java.io.Serializable; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; + +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.oauth2.core.user.OAuth2User; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.google.common.collect.Sets; +import com.newyetai.usercenter.dto.IUserDetail; +import com.newyetai.usercenter.user.login.dto.UserDetailDTO; + +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +/** + * userDetails + * + * @author sr on 2020-06-10 + */ +@NoArgsConstructor +@AllArgsConstructor +@Setter +@ToString +public class SecurityUserDTO extends UserDetailDTO implements Serializable, IUserDetail, UserDetails, OAuth2User { + + /** **/ + private static final long serialVersionUID = -4158044873830314665L; + + /** 标签 **/ + private String tag; + + @JsonIgnore + private Collection authorities; + + + @Override + public String getTag() { + return tag; + } + + @JsonIgnore + public Boolean getAccountNonExpired() { + return super.getAccountNonExpired(); + } + + @JsonIgnore + public Boolean getAccountNonLocked() { + return super.getAccountNonLocked(); + } + + @JsonIgnore + public Boolean getCredentialsNonExpired() { + return super.getCredentialsNonExpired(); + } + + @Override + @JsonIgnore + public Collection getAuthorities() { + return authorities == null ? Sets.newHashSet() : authorities; + } + + @Override + public boolean isAccountNonExpired() { + return !Boolean.FALSE.equals(getAccountNonExpired()); + } + + @Override + public boolean isAccountNonLocked() { + return !Boolean.FALSE.equals(getAccountNonLocked()); + } + + @Override + public boolean isCredentialsNonExpired() { + return !Boolean.FALSE.equals(getCredentialsNonExpired()); + } + + @Override + public boolean isEnabled() { + return !Boolean.FALSE.equals(getEnabled()); + } + + + @Override + @JsonIgnore + public String getName() { + return getUsername(); + } + + @Override + @JsonIgnore + public Map getAttributes() { + return Collections.emptyMap(); + } + +} diff --git a/src/main/java/com/newyetai/security/dto/UserInfoDTO.java b/src/main/java/com/newyetai/security/dto/UserInfoDTO.java new file mode 100644 index 0000000..861c76d --- /dev/null +++ b/src/main/java/com/newyetai/security/dto/UserInfoDTO.java @@ -0,0 +1,61 @@ +package com.newyetai.security.dto; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2019-10-22 + */ +@ApiModel("用户信息") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class UserInfoDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = -684945131805466713L; + + @ApiModelProperty("账号") + private String username; + + @ApiModelProperty("用户类型") + private Integer userType; + + @ApiModelProperty("昵称") + private String nickname; + + @ApiModelProperty("机构id") + private Long orgId; + + @ApiModelProperty("机构名称") + private String orgName; + + @ApiModelProperty("机构类型") + private String orgType; + + @ApiModelProperty("电话") + private String phone; + + @ApiModelProperty("邮箱") + private String email; + + @ApiModelProperty("是否已初始密码") + private Boolean initialedPassword; + + @ApiModelProperty("是否忽略初始密码") + private Boolean ignoreInitPwd; + + @ApiModelProperty("招聘岗位类型") + private String recruitPositionType; + + private String avatar; + + +} diff --git a/src/main/java/com/newyetai/security/expection/BadLoginException.java b/src/main/java/com/newyetai/security/expection/BadLoginException.java new file mode 100644 index 0000000..890fda2 --- /dev/null +++ b/src/main/java/com/newyetai/security/expection/BadLoginException.java @@ -0,0 +1,38 @@ +package com.newyetai.security.expection; + +import org.springframework.security.core.AuthenticationException; + +import com.newyetai.common.AlitaResult; + +/** + * 登录信息异常 + * + * @author sr on 2020-06-15 + */ +public class BadLoginException extends AuthenticationException { + + /** **/ + private static final long serialVersionUID = -5461032165020284506L; + + private AlitaResult result; + + public BadLoginException(String msg) { + super(msg); + result = AlitaResult.error(AlitaResult.LOGIN_ERROR_CODE, msg); + } + + public BadLoginException(String msg, Throwable t) { + super(msg, t); + result = AlitaResult.error(AlitaResult.LOGIN_ERROR_CODE, msg); + } + + public BadLoginException(AlitaResult result) { + super(result.getMsg()); + this.result = result; + } + + public AlitaResult getResult(){ + return result; + } + +} diff --git a/src/main/java/com/newyetai/security/expection/DuplicateOrgException.java b/src/main/java/com/newyetai/security/expection/DuplicateOrgException.java new file mode 100644 index 0000000..f1ec938 --- /dev/null +++ b/src/main/java/com/newyetai/security/expection/DuplicateOrgException.java @@ -0,0 +1,31 @@ +package com.newyetai.security.expection; + +import com.newyetai.common.AlitaResult; +import com.newyetai.security.temptoken.dto.DuplUserToken; + +/** + * 多个登录机构异常 + * + * @author sr on 2020-06-15 + */ +public class DuplicateOrgException extends BadLoginException { + + /** **/ + private static final long serialVersionUID = -5461032165020284506L; + + /** 用户信息 **/ + private final DuplUserToken duplUserToken; + + public static final String MSG = "登录用户存在多机构"; + + public DuplicateOrgException(DuplUserToken duplUserToken) { + super(AlitaResult.error(AlitaResult.DUPLICATE_ORG_CODE, MSG, duplUserToken)); + super.getResult().setErrorData(duplUserToken); + this.duplUserToken = duplUserToken; + } + + public DuplUserToken getDuplUserToken() { + return this.duplUserToken; + } + +} diff --git a/src/main/java/com/newyetai/security/expection/DuplicateUserException.java b/src/main/java/com/newyetai/security/expection/DuplicateUserException.java new file mode 100644 index 0000000..9aabb92 --- /dev/null +++ b/src/main/java/com/newyetai/security/expection/DuplicateUserException.java @@ -0,0 +1,38 @@ +package com.newyetai.security.expection; + +import java.util.List; + +import com.newyetai.common.AlitaResult; +import com.newyetai.security.temptoken.dto.DuplMobileToken; + +/** + * 多个登录用户异常 + * + * @author sr on 2020-06-15 + */ +public class DuplicateUserException extends BadLoginException { + + /** **/ + private static final long serialVersionUID = -5461032165020284506L; + + /** 用户信息 **/ + private final DuplMobileToken duplMobileToken; + + public static final String MSG = "登录用户存在多用户"; + + public DuplicateUserException(DuplMobileToken duplMobileToken) { + super(AlitaResult.error(AlitaResult.DUPLICATE_USER_CODE, + MSG, duplMobileToken)); + super.getResult().setErrorData(duplMobileToken); + this.duplMobileToken = duplMobileToken; + } + + public DuplMobileToken getDuplMobileToken() { + return this.duplMobileToken; + } + + public List getUsers(){ + return this.duplMobileToken.getUsers(); + } + +} diff --git a/src/main/java/com/newyetai/security/handle/MyAuthenctiationFailureHandler.java b/src/main/java/com/newyetai/security/handle/MyAuthenctiationFailureHandler.java new file mode 100644 index 0000000..fa30dd0 --- /dev/null +++ b/src/main/java/com/newyetai/security/handle/MyAuthenctiationFailureHandler.java @@ -0,0 +1,63 @@ +package com.newyetai.security.handle; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.DisabledException; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.util.RequestUtils; +import com.newyetai.common.util.ResponseUtils; +import com.newyetai.security.expection.BadLoginException; +import com.newyetai.security.expection.DuplicateOrgException; +import com.newyetai.security.expection.DuplicateUserException; + +import lombok.extern.slf4j.Slf4j; + +/** + * @author guhong + * @date 2019/8/25 + */ +@Slf4j +public class MyAuthenctiationFailureHandler extends SimpleUrlAuthenticationFailureHandler { + + private static final String DIABLE_MSG = "用户被禁用"; + private static final String BAD_CREDENTIALS_MSG = "账号和密码不匹配,请重新登录"; + + + public MyAuthenctiationFailureHandler(String loginFormUrl) { + super(loginFormUrl); + } + + @Override + public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, + AuthenticationException exception) throws IOException, ServletException { + log.debug("登录失败:{}", exception); + if (exception instanceof BadLoginException) { + ResponseUtils.printJson(response, ((BadLoginException) exception).getResult()); + return; + } + if (RequestUtils.isAjaxRequest(request)) { + ResponseUtils.printJson(response, AlitaResult.error(dealExceptionMsg(exception))); + } else { + super.onAuthenticationFailure(request, response, exception); + } + } + + public String dealExceptionMsg(AuthenticationException exception) { + if (exception instanceof DisabledException) { + return DIABLE_MSG; + } + if (exception instanceof BadCredentialsException) { + return BAD_CREDENTIALS_MSG; + } + return exception.getMessage(); + } + +} diff --git a/src/main/java/com/newyetai/security/handle/MyLoginSuccessHandler.java b/src/main/java/com/newyetai/security/handle/MyLoginSuccessHandler.java new file mode 100644 index 0000000..cdba3a0 --- /dev/null +++ b/src/main/java/com/newyetai/security/handle/MyLoginSuccessHandler.java @@ -0,0 +1,91 @@ +package com.newyetai.security.handle; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; +import org.springframework.stereotype.Component; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.dto.CasTokenDTO; +import com.newyetai.common.util.CookieUtils; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.common.util.RequestUtils; +import com.newyetai.common.util.ResponseUtils; +import com.newyetai.security.config.SecurityProperties; +import com.newyetai.security.dto.SecurityUserDTO; +import com.newyetai.security.jwt.JwtTokenUtils; +import com.newyetai.security.ssb.SsbAuthenticationFilter; +import com.newyetai.security.util.SecurityUtils; + +import lombok.extern.slf4j.Slf4j; + +/** + * 登录成功处理器 + * + * @author guhong + * @date 2019/8/19 + */ +@Slf4j +@Component +public class MyLoginSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler { + + @Autowired + private SecurityProperties securityProperties; + + @Autowired + private JwtTokenUtils jwtTokenUtils; + + @Override + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, + Authentication authentication) throws ServletException, IOException { + Object principal = authentication.getPrincipal(); + + log.debug("------MyLoginSuccessHandler onAuthenticationSuccess userDTO: {}", + JsonUtils.toJsonString(principal)); + CasTokenDTO caseTokenDTO = null; + if (principal instanceof SecurityUserDTO) { + SecurityUserDTO securityUserDto = (SecurityUserDTO) principal; + caseTokenDTO = CasTokenDTO.builder().register(securityUserDto.getRegister()) + .token(jwtTokenUtils.generateToken(securityUserDto)).build(); + } else if (principal instanceof CasTokenDTO) { + caseTokenDTO = (CasTokenDTO) principal; + } else { + throw new RuntimeException("数据异常"); + } + String token = caseTokenDTO.getToken(); + this.dealCookie(token, request, response); + if (RequestUtils.isAjaxRequest(request) || RequestUtils.isFeignRequest(request)) { + // ajax + ResponseUtils.printJson(response, + AlitaResult.success(CasTokenDTO.builder().token(token).build())); + } else { + String successPage = securityProperties.getLoginSuccessPage(); + if (request.getRequestURI().contains(SsbAuthenticationFilter.LOGIN_URI)) { + successPage = securityProperties.getLoginH5SuccessPage(); + } + String successToUrl = + SecurityUtils.dealSuccessUrl(request, successPage, token); + response.sendRedirect(successToUrl); + } + } + + private void dealCookie(String token, HttpServletRequest request, + HttpServletResponse response) { + // 处理cookie + String domainStr = RequestUtils.getRootDomain(request); + String key = CookieUtils.getLoginTokenCookieKey(); + Cookie cookie = CookieUtils.createCookie(key, token, domainStr, + null, jwtTokenUtils.getExpiration().intValue()); + //写入Cookie + response.addCookie(cookie); + + } + +} diff --git a/src/main/java/com/newyetai/security/handle/MyLoginUrlAuthenticationEntryPoint.java b/src/main/java/com/newyetai/security/handle/MyLoginUrlAuthenticationEntryPoint.java new file mode 100644 index 0000000..105612f --- /dev/null +++ b/src/main/java/com/newyetai/security/handle/MyLoginUrlAuthenticationEntryPoint.java @@ -0,0 +1,49 @@ +package com.newyetai.security.handle; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.util.RequestUtils; +import com.newyetai.common.util.ResponseUtils; +import com.newyetai.security.expection.BadLoginException; + +/** + * 自定义认证失败处理器 + * @author guhong + * @date 2019/8/25 + */ +public class MyLoginUrlAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint { + + /** + * @param loginFormUrl URL where the login page can be found. Should either be relative to the + * web-app context path (include a leading {@code /}) or an absolute URL. + */ + public MyLoginUrlAuthenticationEntryPoint(String loginFormUrl) { + super(loginFormUrl); + } + + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, + AuthenticationException authException) throws IOException, ServletException { + // ajax|feign + if (RequestUtils.isAjaxRequest(request) || RequestUtils.isFeignRequest(request)) { + if (authException instanceof BadLoginException) { + ResponseUtils.printJson(response, ((BadLoginException) authException).getResult()); + return; + } + ResponseUtils.printJson(response, + AlitaResult.error(AlitaResult.LOGIN_ERROR_CODE, "鉴权失败:" + authException.getMessage())); + } else { + super.commence(request, response, authException); + } + } + + +} diff --git a/src/main/java/com/newyetai/security/handle/MyLogoutSuccessHandler.java b/src/main/java/com/newyetai/security/handle/MyLogoutSuccessHandler.java new file mode 100644 index 0000000..5703d92 --- /dev/null +++ b/src/main/java/com/newyetai/security/handle/MyLogoutSuccessHandler.java @@ -0,0 +1,37 @@ +package com.newyetai.security.handle; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; +import org.springframework.stereotype.Component; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.util.CookieUtils; +import com.newyetai.common.util.RequestUtils; +import com.newyetai.common.util.ResponseUtils; + +/** + * @author guhong + */ +@Component +public class MyLogoutSuccessHandler implements LogoutSuccessHandler { + + @Override + public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, + Authentication authentication) throws IOException, ServletException { + //清空Cookie + CookieUtils.removeCookie(CookieUtils.getLoginTokenCookieKey(), + RequestUtils.getRootDomain(request), request, response); + // ajax登出 + if (RequestUtils.isAjaxRequest(request)) { + ResponseUtils.printJson(response, AlitaResult.success()); + } else { + response.sendRedirect("/"); + } + } +} diff --git a/src/main/java/com/newyetai/security/jwt/JwtAuthenticationTokenFilter.java b/src/main/java/com/newyetai/security/jwt/JwtAuthenticationTokenFilter.java new file mode 100644 index 0000000..991dc78 --- /dev/null +++ b/src/main/java/com/newyetai/security/jwt/JwtAuthenticationTokenFilter.java @@ -0,0 +1,113 @@ +package com.newyetai.security.jwt; + +import java.io.IOException; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.web.filter.GenericFilterBean; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.exception.ChangeTokenException; +import com.newyetai.common.util.CookieUtils; +import com.newyetai.common.util.RequestUtils; +import com.newyetai.common.util.ResponseUtils; +import com.newyetai.common.util.StrUtils; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.security.config.SecurityProperties; +import com.newyetai.security.util.HostContextHolder; +import com.newyetai.usercenter.constants.OrgConstants; +import com.newyetai.usercenter.dto.IUserDetail; + +import lombok.extern.slf4j.Slf4j; + +/** + * jwt过滤器 解析token,setContext + * + * @author sr on 2019-12-21 + */ +@Slf4j +public class JwtAuthenticationTokenFilter extends GenericFilterBean { + + private SecurityProperties securityProperties; + + public JwtAuthenticationTokenFilter(SecurityProperties securityProperties) { + this.securityProperties = securityProperties; + } + + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, + FilterChain chain) throws ServletException, IOException {} + + @Override + public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) + throws IOException, ServletException { + HttpServletRequest request = (HttpServletRequest) req; + HttpServletResponse response = (HttpServletResponse) res; + IUserDetail userDto = UserContextHolder.getLoginUser(); + String headerToken = request.getHeader(securityProperties.getJwt().getHeader()); + String feignHeader = request.getHeader(RequestUtils.FEIGN_REQUEST_HEADER_KEY); + try { + dealHostHeader(request); + // 未登录,但有token + if (userDto == null) { + if (StrUtils.isNotNull(headerToken)) { + log.debug("analyse header toke:{}", headerToken); + userDto = JwtTokenUtils.getUserLoginDtoFromToken(headerToken); + } + String cookieToken = + CookieUtils.getCookieValue(CookieUtils.getLoginTokenCookieKey(), request.getCookies()); + if (userDto == null && StrUtils.isNotNull(cookieToken)) { + log.debug("analyse cookie toke :{}", cookieToken); + userDto = JwtTokenUtils.getUserLoginDtoFromToken(cookieToken); + } + if (userDto != null) { + SecurityContextHolder.getContext() + .setAuthentication(JwtTokenUtils.getAuthentication(userDto)); + UserContextHolder.setContext(userDto); + } + } + + // 登录用户只有平台用户能使用: 已登录 且 平台用户 且 非内部调用 + //&& !StringUtils.equals(OrgConstants.ORG_TYPE_AGENT,userDto.getOrgType()) 开放代理机构登录中台判断条件 + if (!RequestUtils.FEIGN_REQUEST_HEADER_VALUE.equals(feignHeader) + && Boolean.TRUE.equals(securityProperties.getSuperiorOnly()) + && userDto != null + && !OrgConstants.PLATFORM_ORG_ID.equals(userDto.getOrgId())) { + ResponseUtils.printJson(response, AlitaResult.error("该用户不能使用系统")); + return; + } + chain.doFilter(request, response); + + } catch (ChangeTokenException cte) { + ResponseUtils.printJson(response, cte.getResult()); + } catch (Throwable e) { + throw e; + } finally { + // 清理上下文 + UserContextHolder.clearContext(); + HostContextHolder.clearHost(); + log.debug("clear context...."); + } + } + + private static void dealHostHeader(HttpServletRequest request) { + if (HostContextHolder.getHost() != null) { + return; + } + String hostHeader = request.getHeader(RequestUtils.ORIGIN_HOST_HEADER_KEY); + if (StringUtils.isNoneBlank(hostHeader)) { + HostContextHolder.setHost(hostHeader); + log.debug("get request head origin_host:{}", hostHeader); + } else { + HostContextHolder.setHost(RequestUtils.getDomain(request)); + } + } + +} + diff --git a/src/main/java/com/newyetai/security/jwt/JwtProperties.java b/src/main/java/com/newyetai/security/jwt/JwtProperties.java new file mode 100644 index 0000000..e8b57a3 --- /dev/null +++ b/src/main/java/com/newyetai/security/jwt/JwtProperties.java @@ -0,0 +1,22 @@ +package com.newyetai.security.jwt; + +import lombok.Data; + +/** + * jwt属性 + * @author sr on 2019-12-21 + */ +@Data +public class JwtProperties { + /** 是否启用 **/ + private Boolean enable; + /** 加密密钥 **/ + private String secret; + /** 过期时间(秒) **/ + private Long expiration; + /** token对应request header的key **/ + private String header = "Authorization"; + /** token发行者 **/ + private String iss; + +} diff --git a/src/main/java/com/newyetai/security/jwt/JwtTokenUtils.java b/src/main/java/com/newyetai/security/jwt/JwtTokenUtils.java new file mode 100644 index 0000000..1d67a09 --- /dev/null +++ b/src/main/java/com/newyetai/security/jwt/JwtTokenUtils.java @@ -0,0 +1,344 @@ +package com.newyetai.security.jwt; + +import java.util.Date; +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Component; + +import com.google.common.base.Strings; +import com.google.common.collect.Maps; +import com.newyetai.common.dto.CasTokenDTO; +import com.newyetai.common.exception.ChangeTokenException; +import com.newyetai.common.util.EnvironmentUtils; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.security.dto.SecurityUserDTO; +import com.newyetai.security.util.UserLoginUtils; +import com.newyetai.usercenter.constants.SecurityConstants; +import com.newyetai.usercenter.dto.IUserDetail; +import com.newyetai.usercenter.user.constant.UserTypeEnum; +import com.newyetai.usercenter.user.dto.UserDetailQueryDTO; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.ExpiredJwtException; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.MalformedJwtException; +import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.UnsupportedJwtException; +import lombok.extern.slf4j.Slf4j; + +/** + * @author sr on 2020-06-18 + */ +@Component +@Slf4j +public class JwtTokenUtils { + + /** + * Authorization认证开头是"bearer " + */ + private static final String BEARER = "Bearer "; + + /** 默认过期时间-秒 **/ + private static final Long DEFAULT_EXPIRATION = 3600 * 2L; + + /** 默认密钥 **/ + private static final String DEFAULT_SECRET = "ca0f2602eacd4db79e92c8f1f7ff3d66"; + + /** 登录信息前缀 **/ + private static final String LOGIN_INFO_KEY_PREFIX = "login:info:uid:"; + private static final String TAG_KEY = "tag:"; + private static final String PRINCIPAL = "principal"; + + /** 默认 **/ + private static final int DEFAULT_TAG_LENGTH = 6; + + /** + * 过期时间 + * + * @return + * @author sr on 2020-06-10 + */ + public static Long getExpiration() { + Object time = EnvironmentUtils.getProperty(SecurityConstants.PROP_KEY_JWT_EXPIRATION); + try { + return Long.parseLong((String) time); + } catch (NumberFormatException e) { + return DEFAULT_EXPIRATION; + } + } + + /** + * 密钥 + * + * @return + * @author sr on 2020-06-10 + */ + public static String getSecret() { + String secret = (String) EnvironmentUtils.getProperty(SecurityConstants.PROP_KEY_JWT_SECRET); + return Strings.isNullOrEmpty(secret) ? DEFAULT_SECRET : secret; + } + + + /** + * 从数据声明生成令牌 + * + * @param claims 数据声明 + * @return 令牌 + */ + private static String generateTokenByClaims(Map claims) { + Date expirationDate = + new Date(System.currentTimeMillis() + getExpiration() * 1000); + return Jwts.builder().setClaims(claims).setExpiration(expirationDate) + .signWith(SignatureAlgorithm.HS512, getSecret().getBytes()) + .compact(); + } + + /** + * 从令牌中获取数据声明 + * + * @param token 令牌 + * @return 数据声明 + */ + private static Claims getClaimsFromToken(String token) { + try { + if (token.startsWith(BEARER)) { + token = StringUtils.substring(token, BEARER.length()); + } + return Jwts.parser().setSigningKey(getSecret().getBytes()) + .parseClaimsJws(token).getBody(); + } catch (SecurityException | MalformedJwtException e) { + log.info("Invalid JWT signature."); + log.trace("Invalid JWT signature trace: {}", e); + } catch (ExpiredJwtException e) { + Claims claims = e.getClaims(); + SecurityUserDTO securityUserDTO = JsonUtils.objToClassObj(claims.get(PRINCIPAL), SecurityUserDTO.class); + if (UserTypeEnum.PERSON.getType().equals(securityUserDTO.getType())) { + changeToken(securityUserDTO.getId()); + } + log.info("Expired JWT token."); + log.trace("Expired JWT token trace: {}", e); + } catch (UnsupportedJwtException e) { + log.info("Unsupported JWT token."); + log.trace("Unsupported JWT token trace: {}", e); + } catch (IllegalArgumentException e) { + log.info("JWT token compact of handler are invalid."); + log.trace("JWT token compact of handler are invalid trace: {}", e); + } + return null; + } + + /** + * 根据securityUserDetail登录用户对象生成token + * + * @param securityUserDTO + * @return + * @author sr on 2020-06-19 + */ + public static String generateToken(SecurityUserDTO securityUserDTO) { + try { + if (securityUserDTO == null) { + return null; + } + Map claims = Maps.newHashMap(); + claims.put("created", new Date()); + claims.put(PRINCIPAL, securityUserDTO); + return generateTokenByClaims(claims); + } catch (Exception e) { + log.info("generateToken error : {}", e.getMessage()); + return null; + } + } + + /** + * 根据登录用户生成token + * + * @return + * @author sr on 2020-06-19 + */ + public String generateTokenByUserDetail(IUserDetail userDetail) { + return generateToken((SecurityUserDTO) userDetail); + } + + /** + * 根据当前登录用户生成token + * + * @return + * @author sr on 2020-06-19 + */ + public String generateTokenByCurrentLoginUser() { + return this.generateTokenByUserDetail(UserContextHolder.getLoginUser()); + } + + + /** + * 根据用户id获取用户信息生成token + * + * @param userId + * @return + * @author sr on 2020-06-19 + */ + @Deprecated + public String generateToken(Long userId) { + return generateToken(UserDetailQueryDTO.builder().userId(userId).build()); + } + + /** + * 根据登录关键信息获取登录对象,生成token + * + * @param userDetailQueryDto + * @return + * @author sr on 2020-06-19 + */ + public static String generateToken(UserDetailQueryDTO userDetailQueryDto) { + return generateToken(UserLoginUtils.loadUserToMock(userDetailQueryDto)); + } + + /** + * 替换token(个人) + * @param userId + * @throws ChangeTokenException + * @author sr on 2021-08-10 + */ + public static void changeToken(Long userId) + throws ChangeTokenException { + changeToken(userId, null); + } + + /** + * 替换token(企业) + * @param userDetailQueryDto + * @throws ChangeTokenException + * @author sr on 2021-07-07 + */ + public static void changeToken(Long userId, Long orgId) + throws ChangeTokenException { + String token = generateToken(UserDetailQueryDTO.builder().userId(userId).orgId(orgId).build()); + throw new ChangeTokenException(CasTokenDTO.builder().userId(userId).token(token).build()); + } + + + /** + * 根据token解析登录用户对象信息 + * + * @param token + * @return securityUserDetail + * @author sr on 2020-06-19 + */ + public static SecurityUserDTO getUserLoginDtoFromToken(String token) { + Claims claims = getClaimsFromToken(token); + if (claims == null) { + return null; + } + return JsonUtils.objToClassObj(claims.get(PRINCIPAL), SecurityUserDTO.class); + } + + /** + * 从令牌中获取认证信息 + * + * @param token + * @return + */ + public static Authentication getAuthentication(IUserDetail securityUserDTO) { + try { + if (securityUserDTO == null) { + return null; + } + // TODO 凭证暂为null + Object credentials = null; + return new UsernamePasswordAuthenticationToken(securityUserDTO, + credentials == null ? "N/A" : credentials, null); + } catch (Exception e) { + log.info("getAuthenticationFromToken error : {}", e.getMessage()); + } + return null; + } + + /** + * 获取当前登录用户 + * + * @param auth + * @return + * @author sr on 2020-06-16 + */ + public static IUserDetail getLoginUser(Authentication auth) { + Object principal = auth == null ? null : auth.getPrincipal(); + if (principal != null && principal instanceof IUserDetail) { + try { + return (IUserDetail) principal; + } catch (Exception e) { + log.info("context user not userDetail..."); + return null; + } + } + return null; + } + + /** + * 从令牌中获取账号 + * + * @param token 令牌 + * @return 账号 + */ + public String getUsernameFromToken(String token) { + String username; + try { + Claims claims = getClaimsFromToken(token); + username = claims.getSubject(); + } catch (Exception e) { + username = null; + } + return username; + } + + /** + * 判断令牌是否过期 + * + * @param token 令牌 + * @return 是否过期 + */ + public Boolean isTokenExpired(String token) { + try { + Claims claims = getClaimsFromToken(token); + Date expiration = claims.getExpiration(); + return expiration.before(new Date()); + } catch (Exception e) { + return false; + } + } + + /** + * 刷新令牌 + * + * @param token 原令牌 + * @return 新令牌 + */ + public String refreshToken(String token) { + String refreshedToken; + try { + Claims claims = getClaimsFromToken(token); + claims.put("created", new Date()); + refreshedToken = generateTokenByClaims(claims); + } catch (Exception e) { + refreshedToken = null; + } + return refreshedToken; + } + + + /** + * 获取登录Redis存储的key key=login:uid:${userId} + * + * @param userId 用户ID + * @param tag 唯一标示 + * @return + */ + public String getLoginInfoRedisKey(Long userId, String tag) { + log.info("------getLoginRedisKey userId: {}, tag: {}", userId, tag); + return LOGIN_INFO_KEY_PREFIX + userId + TAG_KEY + tag; + } + +} diff --git a/src/main/java/com/newyetai/security/mapstruct/AuthDetailMapMapper.java b/src/main/java/com/newyetai/security/mapstruct/AuthDetailMapMapper.java new file mode 100644 index 0000000..3165c3b --- /dev/null +++ b/src/main/java/com/newyetai/security/mapstruct/AuthDetailMapMapper.java @@ -0,0 +1,24 @@ +package com.newyetai.security.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +import com.newyetai.usercenter.auth.dto.AuthDetailLoginDTO; +import com.newyetai.usercenter.auth.wechat.dto.WechatAuthUserInfoDTO; + +@Mapper +public interface AuthDetailMapMapper{ + + AuthDetailMapMapper INSTANCE = Mappers.getMapper(AuthDetailMapMapper.class); + + @Mappings(value = { + @Mapping(target = "avatar", source = "headimgurl"), + @Mapping(target = "gender", source = "sex"), + @Mapping(target = "uniqueId", source = "unionid"), + }) + AuthDetailLoginDTO toDto(WechatAuthUserInfoDTO wechatDto); + + +} diff --git a/src/main/java/com/newyetai/security/mapstruct/UserMapMapper.java b/src/main/java/com/newyetai/security/mapstruct/UserMapMapper.java new file mode 100644 index 0000000..3fe3918 --- /dev/null +++ b/src/main/java/com/newyetai/security/mapstruct/UserMapMapper.java @@ -0,0 +1,29 @@ +package com.newyetai.security.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; + +import com.newyetai.security.dto.SecurityUserDTO; +import com.newyetai.usercenter.user.login.dto.UserDetailDTO; + +/** + * @author sr on 2020-06-08 + */ +@Mapper +public interface UserMapMapper { + + UserMapMapper INSTANCE = Mappers.getMapper(UserMapMapper.class); + + /** + * to dto + * + * @param userDto + * @return + * @author sr on 2020-06-08 + */ + @Mapping(target = "tag", expression = "java(com.newyetai.common.util.RandomUtils.getRandomString(6))") + SecurityUserDTO dtoToDto(UserDetailDTO userDto); + + +} diff --git a/src/main/java/com/newyetai/security/mobile/MobileAuthenticationFilter.java b/src/main/java/com/newyetai/security/mobile/MobileAuthenticationFilter.java new file mode 100644 index 0000000..7cf4e8f --- /dev/null +++ b/src/main/java/com/newyetai/security/mobile/MobileAuthenticationFilter.java @@ -0,0 +1,78 @@ +package com.newyetai.security.mobile; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.authentication.AuthenticationServiceException; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; + +import com.newyetai.common.exception.util.Assert; +import com.newyetai.security.expection.BadLoginException; +import com.newyetai.usercenter.constants.SecurityConstants; +import com.newyetai.usercenter.user.login.dto.LoginPhoneDTO; + +/** + * 手机号认证过滤器,指定请求组装token,调起认证 + * + * @author sr on 2020-06-04 + */ +public class MobileAuthenticationFilter extends AbstractAuthenticationProcessingFilter { + + private boolean postOnly = true; + + public static final String REQUEST_METHOD = "POST"; + public static final AntPathRequestMatcher requiresAuthenticationRequestMatcher = + new AntPathRequestMatcher("/login_phone", REQUEST_METHOD); + + public MobileAuthenticationFilter() { + super(requiresAuthenticationRequestMatcher); + } + + @Override + public Authentication attemptAuthentication(HttpServletRequest request, + HttpServletResponse response) throws AuthenticationException, IOException, ServletException { + + if (postOnly && !REQUEST_METHOD.equals(request.getMethod())) { + throw new AuthenticationServiceException( + "Authentication method not supported: " + request.getMethod()); + } + + String userTypeStr = request.getParameter(SecurityConstants.LOGIN_USER_TYPE_KEY); + Assert.isTrue(StringUtils.isNotBlank(userTypeStr), new BadLoginException("用户类型不能为空")); + Integer userType = null; + try { + userType = Integer.valueOf(userTypeStr); + } catch (NumberFormatException e) { + throw new BadLoginException("用户类型错误:" + userTypeStr); + } + + String phone = request.getParameter(SecurityConstants.LOGIN_PHONE_KEY); + String code = request.getParameter(SecurityConstants.LOGIN_CODE_KEY); + String registerCode = request.getParameter(SecurityConstants.LOGIN_REGISTER_CODE_KEY); + String entrypoint = request.getParameter(SecurityConstants.LOGIN_ENTRYPOINT_KEY); + phone = phone == null ? "" : phone.trim(); + code = code == null ? "" : code.trim(); + + AbstractAuthenticationToken authRequest = new MobileAuthenticationToken( + LoginPhoneDTO.builder().phone(phone).code(code).userType(userType) + .registerCode(registerCode).entrypoint(entrypoint).build(), + code); + + // Allow subclasses to set the "details" property + setDetails(request, authRequest); + + return this.getAuthenticationManager().authenticate(authRequest); + } + + protected void setDetails(HttpServletRequest request, AbstractAuthenticationToken authRequest) { + authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); + } +} diff --git a/src/main/java/com/newyetai/security/mobile/MobileAuthenticationProvider.java b/src/main/java/com/newyetai/security/mobile/MobileAuthenticationProvider.java new file mode 100644 index 0000000..819e103 --- /dev/null +++ b/src/main/java/com/newyetai/security/mobile/MobileAuthenticationProvider.java @@ -0,0 +1,65 @@ +package com.newyetai.security.mobile; + +import java.util.HashSet; +import java.util.Set; + +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.validation.util.ValidateUtils; +import com.newyetai.security.dto.SecurityUserDTO; +import com.newyetai.security.expection.BadLoginException; +import com.newyetai.security.mapstruct.UserMapMapper; +import com.newyetai.usercenter.user.login.dto.LoginPhoneDTO; +import com.newyetai.usercenter.user.login.dto.UserDetailDTO; +import com.newyetai.usercenter.user.login.service.UserLoginService; + +/** + * 手机号认证provider,比对信息是否匹配 + * + * @author sr on 2020-06-04 + */ +public class MobileAuthenticationProvider implements AuthenticationProvider { + + private UserLoginService userLoginService; + + public MobileAuthenticationProvider(UserLoginService userLoginService) { + this.userLoginService = userLoginService; + } + + @Override + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + LoginPhoneDTO loginPhoneDTO = (LoginPhoneDTO) authentication.getPrincipal(); + String errMsg = ValidateUtils.validate(loginPhoneDTO); + Assert.isTrue(errMsg == null, new BadLoginException(errMsg)); + SecurityUserDTO loadedUser = null; + try { + UserDetailDTO userDetailDTO = this.userLoginService.loadUser(loginPhoneDTO); + loadedUser = UserMapMapper.INSTANCE.dtoToDto(userDetailDTO); + } catch (BadLoginException be) { + throw be; + } catch (Exception e) { + throw new BadLoginException(e.getMessage(), e); + } + + MobileAuthenticationToken result = + new MobileAuthenticationToken(loadedUser, listUserGrantedAuthorities(loadedUser)); + result.setDetails(authentication.getDetails()); + return result; + } + + @Override + public boolean supports(Class authentication) { + return (MobileAuthenticationToken.class.isAssignableFrom(authentication)); + } + + private Set listUserGrantedAuthorities(UserDetails userDetails) { + // 什么都不用做,访问资源鉴权的时会拿userDetail去缓存获取对应权限 + return new HashSet(); + } + +} diff --git a/src/main/java/com/newyetai/security/mobile/MobileAuthenticationToken.java b/src/main/java/com/newyetai/security/mobile/MobileAuthenticationToken.java new file mode 100644 index 0000000..d9f8bc5 --- /dev/null +++ b/src/main/java/com/newyetai/security/mobile/MobileAuthenticationToken.java @@ -0,0 +1,25 @@ +package com.newyetai.security.mobile; + +import java.util.Collection; + +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.GrantedAuthority; + +/** + * 手机号认证信息 + * + * @author sr on 2020-06-04 + */ +public class MobileAuthenticationToken extends UsernamePasswordAuthenticationToken { + + public MobileAuthenticationToken(Object principal, Object credentials) { + super(principal, credentials); + } + + public MobileAuthenticationToken(Object principal, Object credentials, + Collection authorities) { + super(principal, credentials, authorities); + } + +} diff --git a/src/main/java/com/newyetai/security/service/GrantedAuthorityService.java b/src/main/java/com/newyetai/security/service/GrantedAuthorityService.java new file mode 100644 index 0000000..88f42b9 --- /dev/null +++ b/src/main/java/com/newyetai/security/service/GrantedAuthorityService.java @@ -0,0 +1,26 @@ +package com.newyetai.security.service; + +import java.util.Collection; + +import org.springframework.security.core.GrantedAuthority; + +import com.newyetai.usercenter.dto.IUserDetail; + +/** + * 主要提供用户的授权信息的收集功能 + * + * @author on 2019-11-05 + */ +public interface GrantedAuthorityService { + + /** + * 获取用户的授权信息 + * + * @param userDetails 用户信息 + * @return 权限信息 + */ + Collection getGrantedAuthorities(IUserDetail userDetails); + + + +} diff --git a/src/main/java/com/newyetai/security/service/IPermissionSecurityService.java b/src/main/java/com/newyetai/security/service/IPermissionSecurityService.java new file mode 100644 index 0000000..474d5fe --- /dev/null +++ b/src/main/java/com/newyetai/security/service/IPermissionSecurityService.java @@ -0,0 +1,22 @@ +package com.newyetai.security.service; + +import java.util.List; + +import org.springframework.web.bind.annotation.GetMapping; + +import com.newyetai.common.AlitaResult; +import com.newyetai.usercenter.authority.dto.PermissionQueryDTO; +import com.newyetai.usercenter.authority.dto.UrlPermissionDTO; + +import io.swagger.annotations.ApiOperation; + +/** + * @author sr on 2020-09-07 + */ +public interface IPermissionSecurityService { + + @ApiOperation("查询角色权限分配菜单接口") + @GetMapping("/permission/list_url") + AlitaResult> listUrl(PermissionQueryDTO permissionQueryDTO); + +} diff --git a/src/main/java/com/newyetai/security/service/IResourceSecurityService.java b/src/main/java/com/newyetai/security/service/IResourceSecurityService.java new file mode 100644 index 0000000..91a2cef --- /dev/null +++ b/src/main/java/com/newyetai/security/service/IResourceSecurityService.java @@ -0,0 +1,51 @@ +package com.newyetai.security.service; + +import java.util.List; + +import com.newyetai.usercenter.dto.IUserDetail; +import com.newyetai.usercenter.resource.dto.ComponentDTO; +import com.newyetai.usercenter.resource.dto.UrlDTO; + +/** + * @author sr on 2020-09-08 + */ +public interface IResourceSecurityService { + + /** + * 查询当前登录用户资源树状列表(包含菜单组件) + * @param systemCode + * @return + * @author sr on 2019-10-15 + */ + List listResource(Integer systemCode, IUserDetail iUserDetail); + + /** + * 获取当前登录用户指定角色的资源树状列表(包含菜单组件) + * @param systemCode + * @param roleId + * @return + * @author sr on 2019-10-16 + */ + List listResource(Integer systemCode, IUserDetail iUserDetail, Long roleId); + + /** + * 根据应用+机构获取url资源 + * + * @param systemCode + * @param orgId + * @return + * @author sr on 2020-09-08 + */ + List listUrlDTO(Integer systemCode, Long orgId); + + /** + * 根据应用+机构获取Component资源 + * + * @param systemCode + * @param orgId + * @return + * @author sr on 2020-09-08 + */ + List listComponentDTO(Integer systemCode, Long orgId); + +} diff --git a/src/main/java/com/newyetai/security/service/IRoleAllocationSecurityService.java b/src/main/java/com/newyetai/security/service/IRoleAllocationSecurityService.java new file mode 100644 index 0000000..1d2047b --- /dev/null +++ b/src/main/java/com/newyetai/security/service/IRoleAllocationSecurityService.java @@ -0,0 +1,22 @@ +package com.newyetai.security.service; + +import java.util.List; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; + +import com.newyetai.common.AlitaResult; +import com.newyetai.usercenter.authority.dto.RoleAllocationDTO; + +import io.swagger.annotations.ApiOperation; + +/** + * @author sr on 2020-09-07 + */ +public interface IRoleAllocationSecurityService { + + @ApiOperation("查询用户分配的角色") + @GetMapping("/role/findByUserId/{userId}") + AlitaResult> findByUserId(@PathVariable("userId") Long userId); + +} diff --git a/src/main/java/com/newyetai/security/service/IUserSecurityService.java b/src/main/java/com/newyetai/security/service/IUserSecurityService.java new file mode 100644 index 0000000..caaba48 --- /dev/null +++ b/src/main/java/com/newyetai/security/service/IUserSecurityService.java @@ -0,0 +1,20 @@ +package com.newyetai.security.service; + +import org.springframework.web.bind.annotation.PostMapping; + +import com.newyetai.common.AlitaResult; +import com.newyetai.usercenter.user.dto.UserDetailQueryDTO; +import com.newyetai.usercenter.user.login.dto.UserDetailDTO; + +import io.swagger.annotations.ApiOperation; + +/** + * @author sr on 2020-09-07 + */ +public interface IUserSecurityService { + + @ApiOperation("根据登录信息获取用户信息") + @PostMapping("/anon/user/find_user_detail_dto") + AlitaResult findUserDetailDTOResult(UserDetailQueryDTO userDetailQueryDto); + +} diff --git a/src/main/java/com/newyetai/security/service/impl/GrantedAuthorityServiceImpl.java b/src/main/java/com/newyetai/security/service/impl/GrantedAuthorityServiceImpl.java new file mode 100644 index 0000000..ddf4c5f --- /dev/null +++ b/src/main/java/com/newyetai/security/service/impl/GrantedAuthorityServiceImpl.java @@ -0,0 +1,56 @@ +package com.newyetai.security.service.impl; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.annotation.AnnotationAwareOrderComparator; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.Assert; + +import com.newyetai.security.access.provider.GrantedAuthorityProvider; +import com.newyetai.security.service.GrantedAuthorityService; +import com.newyetai.usercenter.dto.IUserDetail; + +/** + * 主要提供用户的授权信息的收集功能 + * + * @author on 2019-11-05 + */ +@Service +@Transactional(readOnly = true) +public class GrantedAuthorityServiceImpl implements GrantedAuthorityService, InitializingBean { + + @Autowired + private List providers; + + /** + * 获取用户的授权信息 + * + * @param userDetails 用户信息 + * @return 权限信息 + */ + @Override + public Collection getGrantedAuthorities(IUserDetail userDetails) { + Collection grantedAuthorities = new ArrayList(); + for (GrantedAuthorityProvider provider : providers) { + Collection list = provider.provide(userDetails); + if (list != null && !list.isEmpty()) { + grantedAuthorities.addAll(list); + } + } + return grantedAuthorities; + } + + @Override + public void afterPropertiesSet() throws Exception { + Assert.notEmpty(providers, "providers can not be empty"); + AnnotationAwareOrderComparator.sort(providers); + } + + +} diff --git a/src/main/java/com/newyetai/security/social/service/CommonOAuth2Provider.java b/src/main/java/com/newyetai/security/social/service/CommonOAuth2Provider.java new file mode 100644 index 0000000..baeb0f3 --- /dev/null +++ b/src/main/java/com/newyetai/security/social/service/CommonOAuth2Provider.java @@ -0,0 +1,104 @@ +package com.newyetai.security.social.service; + +import org.springframework.security.oauth2.client.registration.ClientRegistration; +import org.springframework.security.oauth2.client.registration.ClientRegistration.Builder; +import org.springframework.security.oauth2.core.AuthorizationGrantType; +import org.springframework.security.oauth2.core.ClientAuthenticationMethod; + +import com.newyetai.security.ssb.SsbAuthenticationFilter; +import com.newyetai.usercenter.auth.constant.AuthTypeEnum; + +public enum CommonOAuth2Provider { + + WECHAT { + + @Override + public Builder getBuilder(String registrationId) { + ClientRegistration.Builder builder = getBuilder(registrationId, + ClientAuthenticationMethod.BASIC, DEFAULT_REDIRECT_URL); + builder.scope("snsapi_userinfo"); + builder.authorizationUri("https://open.weixin.qq.com/connect/oauth2/authorize"); + builder.tokenUri("https://api.weixin.qq.com/sns/oauth2/access_token"); + builder.userInfoUri("https://api.weixin.qq.com/sns/userinfo"); + builder.userNameAttributeName("openid"); + builder.clientName(AuthTypeEnum.WECHAT.name()); + builder.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE); + return builder; + } + }, + + SSBAPP { + + @Override + public Builder getBuilder(String registrationId) { + ClientRegistration.Builder builder = getBuilder(registrationId, + ClientAuthenticationMethod.BASIC, DEFAULT_REDIRECT_URL); + builder.authorizationUri("https://api.eshimin.com/newOauth/authorize"); + builder.tokenUri("https://api.eshimin.com/newOauth/accessToken"); + builder.userInfoUri("https://api.eshimin.com/newOauth/userInfo"); + builder.clientName(AuthTypeEnum.SSB_APP.name()); + builder.scope("read"); + builder.redirectUriTemplate("{baseUrl}/" + SsbAuthenticationFilter.LOGIN_URI); + builder.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE); + return builder; + } + }, + + WECHAT_LITE { + + @Override + public Builder getBuilder(String registrationId) { + ClientRegistration.Builder builder = getBuilder(registrationId, + ClientAuthenticationMethod.BASIC, DEFAULT_REDIRECT_URL); + builder.clientName(AuthTypeEnum.WECHAT_LITE.name()); + return builder; + } + }, + + ALIPAY { + + @Override + public Builder getBuilder(String registrationId) { + ClientRegistration.Builder builder = getBuilder(registrationId, + ClientAuthenticationMethod.POST, DEFAULT_REDIRECT_URL); + builder.clientName(AuthTypeEnum.ALIPAY.name()); + return builder; + } + }, + + ALIPAY_LITE { + + @Override + public Builder getBuilder(String registrationId) { + ClientRegistration.Builder builder = getBuilder(registrationId, + ClientAuthenticationMethod.BASIC, DEFAULT_REDIRECT_URL); + builder.clientName(AuthTypeEnum.ALIPAY_LITE.name()); + return builder; + } + }, + + ; + + + private static final String DEFAULT_REDIRECT_URL = + "{baseUrl}/{action}/oauth2/code/{registrationId}"; + + protected final ClientRegistration.Builder getBuilder(String registrationId, + ClientAuthenticationMethod method, String redirectUri) { + ClientRegistration.Builder builder = ClientRegistration.withRegistrationId(registrationId); + builder.clientAuthenticationMethod(method); + builder.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE); + builder.redirectUriTemplate(redirectUri); + return builder; + } + + /** + * Create a new + * {@link org.springframework.security.oauth2.client.registration.ClientRegistration.Builder + * ClientRegistration.Builder} pre-configured with provider defaults. + * @param registrationId the registration-id used with the new builder + * @return a builder instance + */ + public abstract ClientRegistration.Builder getBuilder(String registrationId); + +} diff --git a/src/main/java/com/newyetai/security/social/service/IOauthProvider.java b/src/main/java/com/newyetai/security/social/service/IOauthProvider.java new file mode 100644 index 0000000..237fa94 --- /dev/null +++ b/src/main/java/com/newyetai/security/social/service/IOauthProvider.java @@ -0,0 +1,66 @@ +package com.newyetai.security.social.service; + +import javax.servlet.http.HttpServletRequest; + +import org.springframework.core.convert.converter.Converter; +import org.springframework.http.RequestEntity; +import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest; +import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; +import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; +import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; +import org.springframework.security.oauth2.core.user.OAuth2User; + +public interface IOauthProvider { + + String getName(); + + /** + * 修改默认auth的请求地址 + * + * @param request + * @param authorizationRequest + * @return + * @author sr on 2021-06-28 + */ + default OAuth2AuthorizationRequest decorateRequest(HttpServletRequest request, + OAuth2AuthorizationRequest authorizationRequest) { + return authorizationRequest; + } + + default OAuth2AccessTokenResponse getTokenResponse( + OAuth2AuthorizationCodeGrantRequest authorizationCodeGrantRequest) { + return null; + } + + /** + * 获取token转换器(无则OAuth2AuthorizationCodeGrantRequestEntityConverter) + * @return + * @author sr on 2021-06-28 + */ + default Converter> getTokenConvert(){ + return null; + } + + /** + * 获取用户转换器(无则OAuth2UserRequestEntityConverter) + * @return + * @author sr on 2021-06-28 + */ + default Converter> getUserConvert(){ + return null; + } + + + /** + * 处理第三方用户信息,获取登录用户 + * @param userRequest + * @param userJsonStr + * @return + * @author sr on 2021-06-28 + */ + default OAuth2User dealUser(OAuth2UserRequest userRequest, String userJsonStr) { + return null; + } + + +} diff --git a/src/main/java/com/newyetai/security/social/service/OAuth2ClientRegistrationAdapter.java b/src/main/java/com/newyetai/security/social/service/OAuth2ClientRegistrationAdapter.java new file mode 100644 index 0000000..f704a1c --- /dev/null +++ b/src/main/java/com/newyetai/security/social/service/OAuth2ClientRegistrationAdapter.java @@ -0,0 +1,74 @@ +package com.newyetai.security.social.service; + +import java.util.Map; + +import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientProperties; +import org.springframework.boot.context.properties.PropertyMapper; +import org.springframework.boot.convert.ApplicationConversionService; +import org.springframework.core.convert.ConversionException; +import org.springframework.security.oauth2.client.registration.ClientRegistration; +import org.springframework.security.oauth2.client.registration.ClientRegistration.Builder; +import org.springframework.security.oauth2.core.AuthorizationGrantType; +import org.springframework.security.oauth2.core.ClientAuthenticationMethod; +import org.springframework.util.StringUtils; + +import com.google.common.collect.Maps; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.usercenter.auth.constant.AuthTypeEnum; +import com.newyetai.usercenter.auth.dto.AuthClientDTO; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class OAuth2ClientRegistrationAdapter { + + private static Map providers = Maps.newConcurrentMap(); + + private OAuth2ClientRegistrationAdapter() {} + + public static ClientRegistration getClientRegistration(String registrationId, + AuthTypeEnum authTypeEnum, + AuthClientDTO authClientDTO) { + Assert.isTrue(authTypeEnum != null, new IllegalArgumentException("非法授权标识")); + OAuth2ClientProperties.Registration registration = + JsonUtils.toObject(authClientDTO.getParamData(), OAuth2ClientProperties.Registration.class); + return getClientRegistration(registrationId, authTypeEnum, registration); + } + + private static ClientRegistration getClientRegistration(String registrationId, + AuthTypeEnum authTypeEnum, + OAuth2ClientProperties.Registration registration) { + Assert.isTrue(authTypeEnum != null, new IllegalArgumentException("非法授权标识")); + Builder builder = getBuilder(authTypeEnum.name()).getBuilder(registrationId); + PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); + map.from(registration::getClientId).to(builder::clientId); + map.from(registration::getClientSecret).to(builder::clientSecret); + map.from(registration::getClientAuthenticationMethod).as(ClientAuthenticationMethod::new) + .to(builder::clientAuthenticationMethod); + map.from(registration::getAuthorizationGrantType).as(AuthorizationGrantType::new) + .to(builder::authorizationGrantType); + map.from(registration::getRedirectUri).to(builder::redirectUriTemplate); + map.from(registration::getScope).as((scope) -> StringUtils.toStringArray(scope)) + .to(builder::scope); + map.from(registration::getClientName).to(builder::clientName); + return builder.build(); + } + + public static CommonOAuth2Provider getBuilder(String authTypeName) { + CommonOAuth2Provider provider = providers.get(authTypeName); + if (provider == null) { + try { + provider = + ApplicationConversionService.getSharedInstance().convert(authTypeName, + CommonOAuth2Provider.class); + providers.put(authTypeName, provider); + } catch (ConversionException ex) { + log.error("授权类型标识错误,未找到对应的oauth2提供者:{}", authTypeName); + throw new IllegalArgumentException("授权类型标识错误,未找到对应的oauth2提供者:" + authTypeName, ex); + } + } + return provider; + } + +} diff --git a/src/main/java/com/newyetai/security/social/service/StandardAuthorizationCodeTokenResponseClient.java b/src/main/java/com/newyetai/security/social/service/StandardAuthorizationCodeTokenResponseClient.java new file mode 100644 index 0000000..31f5d8c --- /dev/null +++ b/src/main/java/com/newyetai/security/social/service/StandardAuthorizationCodeTokenResponseClient.java @@ -0,0 +1,103 @@ +package com.newyetai.security.social.service; + + +import java.util.Arrays; + +import org.springframework.core.convert.converter.Converter; +import org.springframework.http.RequestEntity; +import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.FormHttpMessageConverter; +import org.springframework.http.converter.StringHttpMessageConverter; +import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient; +import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest; +import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequestEntityConverter; +import org.springframework.security.oauth2.client.http.OAuth2ErrorResponseErrorHandler; +import org.springframework.security.oauth2.core.OAuth2AuthorizationException; +import org.springframework.security.oauth2.core.OAuth2Error; +import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; +import org.springframework.security.oauth2.core.http.converter.OAuth2AccessTokenResponseHttpMessageConverter; +import org.springframework.util.Assert; +import org.springframework.util.CollectionUtils; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestOperations; +import org.springframework.web.client.RestTemplate; + +import com.newyetai.security.social.util.Oauth2ProviderUtils; + +/** + * code获取token + * + * @author sr on 2021-01-12 + */ +public class StandardAuthorizationCodeTokenResponseClient + implements OAuth2AccessTokenResponseClient { + public static final String INVALID_TOKEN_RESPONSE_ERROR_CODE = "invalid_token_response"; + public static final RestOperations restOperations; + + private Converter> requestEntityConverter = + new OAuth2AuthorizationCodeGrantRequestEntityConverter(); + + static { + RestTemplate restTemplate = new RestTemplate(Arrays.asList( + new FormHttpMessageConverter(), new OAuth2AccessTokenResponseHttpMessageConverter(), + new StringHttpMessageConverter())); + restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler()); + restOperations = restTemplate; + } + + @Override + public OAuth2AccessTokenResponse getTokenResponse( + OAuth2AuthorizationCodeGrantRequest authorizationCodeGrantRequest) { + + Assert.notNull(authorizationCodeGrantRequest, "authorizationCodeGrantRequest cannot be null"); + + // 不同类型不同请求体 + OAuth2AccessTokenResponse tokenResponse = Oauth2ProviderUtils + .getProvider(authorizationCodeGrantRequest.getClientRegistration().getClientName()) + .getTokenResponse(authorizationCodeGrantRequest); + + if (tokenResponse != null) { + return tokenResponse; + } + + RequestEntity request = this.requestEntityConverter.convert(authorizationCodeGrantRequest); + + ResponseEntity response; + try { + response = restOperations.exchange(request, OAuth2AccessTokenResponse.class); + } catch (RestClientException ex) { + OAuth2Error oauth2Error = new OAuth2Error(INVALID_TOKEN_RESPONSE_ERROR_CODE, + "An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: " + + ex.getMessage(), + null); + throw new OAuth2AuthorizationException(oauth2Error, ex); + } + + tokenResponse = response.getBody(); + + if (CollectionUtils.isEmpty(tokenResponse.getAccessToken().getScopes())) { + // As per spec, in Section 5.1 Successful Access Token Response + // https://tools.ietf.org/html/rfc6749#section-5.1 + // If AccessTokenResponse.scope is empty, then default to the scope + // originally requested by the client in the Token Request + tokenResponse = OAuth2AccessTokenResponse.withResponse(tokenResponse) + .scopes(authorizationCodeGrantRequest.getClientRegistration().getScopes()) + .build(); + } + + return tokenResponse; + } + + /** + * Sets the {@link Converter} used for converting the {@link OAuth2AuthorizationCodeGrantRequest} + * to a {@link RequestEntity} representation of the OAuth 2.0 Access Token Request. + * + * @param requestEntityConverter the {@link Converter} used for converting to a {@link RequestEntity} representation of the Access Token Request + */ + public void setRequestEntityConverter( + Converter> requestEntityConverter) { + Assert.notNull(requestEntityConverter, "requestEntityConverter cannot be null"); + this.requestEntityConverter = requestEntityConverter; + } + +} diff --git a/src/main/java/com/newyetai/security/social/service/StandardClientRegistrationRepository.java b/src/main/java/com/newyetai/security/social/service/StandardClientRegistrationRepository.java new file mode 100644 index 0000000..16143fc --- /dev/null +++ b/src/main/java/com/newyetai/security/social/service/StandardClientRegistrationRepository.java @@ -0,0 +1,50 @@ +package com.newyetai.security.social.service; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.security.oauth2.client.registration.ClientRegistration; +import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; + +import com.newyetai.common.exception.util.Assert; +import com.newyetai.usercenter.auth.constant.AuthTypeEnum; +import com.newyetai.usercenter.auth.dto.AuthClientDTO; +import com.newyetai.usercenter.auth.dto.AuthClientQueryDTO; +import com.newyetai.usercenter.user.login.service.UserLoginService; + +public class StandardClientRegistrationRepository implements ClientRegistrationRepository { + + private UserLoginService userLoginService; + + public StandardClientRegistrationRepository(UserLoginService userLoginService) { + this.userLoginService = userLoginService; + } + + @Override + public ClientRegistration findByRegistrationId(String registrationId) { + Assert.isTrue(StringUtils.isNotBlank(registrationId), + new IllegalArgumentException("oauth授权注册标识不能为空")); + AuthClientDTO authClientDTO = userLoginService + .findAuthClientDTO(AuthClientQueryDTO.builder().id(Long.valueOf(registrationId)).build()); + AuthTypeEnum authTypeEnum = AuthTypeEnum.getByCode(authClientDTO.getAuthTypeCode()); + return OAuth2ClientRegistrationAdapter.getClientRegistration(authClientDTO.getId().toString(), + authTypeEnum, authClientDTO); + } + + public ClientRegistration findByRegistrationId(String authTypeName, String domainOrIp) { + AuthTypeEnum authTypeEnum = AuthTypeEnum.valueOf(authTypeName.toUpperCase()); + return this.findByRegistrationId(authTypeEnum, domainOrIp); + } + + public ClientRegistration findByRegistrationId(Integer authTypeCode, String domainOrIp) { + AuthTypeEnum authTypeEnum = AuthTypeEnum.getByCode(authTypeCode); + return this.findByRegistrationId(authTypeEnum, domainOrIp); + } + + private ClientRegistration findByRegistrationId(AuthTypeEnum authTypeEnum, String domainOrIp) { + AuthClientDTO authClientDTO = userLoginService.findAuthClientDTO( + AuthClientQueryDTO.builder().domainOrIp(domainOrIp).authTypeCode(authTypeEnum.getCode()) + .build()); + return OAuth2ClientRegistrationAdapter.getClientRegistration(authClientDTO.getId().toString(), + authTypeEnum, authClientDTO); + } + +} diff --git a/src/main/java/com/newyetai/security/social/service/StandardOAuth2UserService.java b/src/main/java/com/newyetai/security/social/service/StandardOAuth2UserService.java new file mode 100644 index 0000000..29f3e4b --- /dev/null +++ b/src/main/java/com/newyetai/security/social/service/StandardOAuth2UserService.java @@ -0,0 +1,109 @@ +package com.newyetai.security.social.service; + +import org.springframework.core.convert.converter.Converter; +import org.springframework.http.RequestEntity; +import org.springframework.http.ResponseEntity; +import org.springframework.security.oauth2.client.http.OAuth2ErrorResponseErrorHandler; +import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; +import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequestEntityConverter; +import org.springframework.security.oauth2.client.userinfo.OAuth2UserService; +import org.springframework.security.oauth2.core.OAuth2AuthenticationException; +import org.springframework.security.oauth2.core.OAuth2AuthorizationException; +import org.springframework.security.oauth2.core.OAuth2Error; +import org.springframework.security.oauth2.core.user.OAuth2User; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestOperations; +import org.springframework.web.client.RestTemplate; + +import com.newyetai.security.social.util.Oauth2ProviderUtils; + +public class StandardOAuth2UserService implements OAuth2UserService { + + private static final String MISSING_USER_INFO_URI_ERROR_CODE = "missing_user_info_uri"; + + private static final String MISSING_USER_NAME_ATTRIBUTE_ERROR_CODE = + "missing_user_name_attribute"; + + private static final String INVALID_USER_INFO_RESPONSE_ERROR_CODE = "invalid_user_info_response"; + + private Converter> requestEntityConverter = + new OAuth2UserRequestEntityConverter(); + + private RestOperations restOperations; + + public StandardOAuth2UserService() { + RestTemplate restTemplate = new RestTemplate(); + restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler()); + this.restOperations = restTemplate; + } + + @Override + public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException { + Assert.notNull(userRequest, "userRequest cannot be null"); + + if (!StringUtils.hasText( + userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri())) { + OAuth2Error oauth2Error = new OAuth2Error(MISSING_USER_INFO_URI_ERROR_CODE, + "Missing required UserInfo Uri in UserInfoEndpoint for Client Registration: " + + userRequest.getClientRegistration().getRegistrationId(), + null); + throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString()); + } + + String userNameAttributeName = userRequest.getClientRegistration().getProviderDetails() + .getUserInfoEndpoint().getUserNameAttributeName(); + if (!StringUtils.hasText(userNameAttributeName)) { + OAuth2Error oauth2Error = new OAuth2Error(MISSING_USER_NAME_ATTRIBUTE_ERROR_CODE, + "Missing required \"user name\" attribute name in UserInfoEndpoint for Client Registration: " + + userRequest.getClientRegistration().getRegistrationId(), + null); + throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString()); + } + + IOauthProvider provider = Oauth2ProviderUtils + .getProvider(userRequest.getClientRegistration().getClientName()); + // 不同类型不同请求体 + Converter> converter = + provider.getUserConvert(); + if (converter == null) { + converter = requestEntityConverter; + } + + // 获得request + RequestEntity request = converter.convert(userRequest); + + ResponseEntity response; + try { + // 执行request + response = this.restOperations.exchange(request, String.class); + } catch (OAuth2AuthorizationException ex) { + OAuth2Error oauth2Error = ex.getError(); + StringBuilder errorDetails = new StringBuilder(); + errorDetails.append("Error details: ["); + errorDetails.append("UserInfo Uri: ").append( + userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri()); + errorDetails.append(", Error Code: ").append(oauth2Error.getErrorCode()); + if (oauth2Error.getDescription() != null) { + errorDetails.append(", Error Description: ").append(oauth2Error.getDescription()); + } + errorDetails.append("]"); + oauth2Error = new OAuth2Error(INVALID_USER_INFO_RESPONSE_ERROR_CODE, + "An error occurred while attempting to retrieve the UserInfo Resource: " + + errorDetails.toString(), + null); + throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString(), ex); + } catch (RestClientException ex) { + OAuth2Error oauth2Error = new OAuth2Error(INVALID_USER_INFO_RESPONSE_ERROR_CODE, + "An error occurred while attempting to retrieve the UserInfo Resource: " + + ex.getMessage(), + null); + throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString(), ex); + } + + // 解析response + String userAttributes = response.getBody(); + return provider.dealUser(userRequest, userAttributes); + } +} diff --git a/src/main/java/com/newyetai/security/social/service/StandardOauth2AuthorizationRequestResolver.java b/src/main/java/com/newyetai/security/social/service/StandardOauth2AuthorizationRequestResolver.java new file mode 100644 index 0000000..d846f0b --- /dev/null +++ b/src/main/java/com/newyetai/security/social/service/StandardOauth2AuthorizationRequestResolver.java @@ -0,0 +1,189 @@ +package com.newyetai.security.social.service; + +import java.util.Base64; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.security.crypto.keygen.Base64StringKeyGenerator; +import org.springframework.security.crypto.keygen.StringKeyGenerator; +import org.springframework.security.oauth2.client.registration.ClientRegistration; +import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; +import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter; +import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestResolver; +import org.springframework.security.oauth2.core.AuthorizationGrantType; +import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; +import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; +import org.springframework.security.web.util.UrlUtils; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.util.Assert; +import org.springframework.web.util.UriComponentsBuilder; + +import com.newyetai.common.util.RequestUtils; +import com.newyetai.security.social.util.Oauth2ProviderUtils; +import com.newyetai.usercenter.constants.SecurityConstants; +import com.newyetai.usercenter.user.constant.UserTypeEnum; + +/** +* An implementation of an {@link OAuth2AuthorizationRequestResolver} that attempts to +* resolve an {@link OAuth2AuthorizationRequest} from the provided {@code HttpServletRequest} +* using the default request {@code URI} pattern {@code /oauth2/authorization/{registrationId}}. +* +*

+* NOTE: The default base {@code URI} {@code /oauth2/authorization} may be overridden +* via it's constructor {@link #DefaultOAuth2AuthorizationRequestResolver(ClientRegistrationRepository, String)}. +* +* @author Joe Grandja +* @author Rob Winch +* @since 5.1 +* @see OAuth2AuthorizationRequestResolver +* @see OAuth2AuthorizationRequestRedirectFilter +*/ +public final class StandardOauth2AuthorizationRequestResolver + implements OAuth2AuthorizationRequestResolver { + private static final String REGISTRATION_ID_URI_VARIABLE_NAME = "registrationId"; + private final ClientRegistrationRepository clientRegistrationRepository; + private final AntPathRequestMatcher authorizationRequestMatcher; + private final StringKeyGenerator stateGenerator = + new Base64StringKeyGenerator(Base64.getUrlEncoder()); + + /** + * Constructs a {@code DefaultOAuth2AuthorizationRequestResolver} using the provided parameters. + * + * @param clientRegistrationRepository the repository of client registrations + * @param authorizationRequestBaseUri the base {@code URI} used for resolving authorization requests + */ + public StandardOauth2AuthorizationRequestResolver( +// StandardClientRegistrationRepository standardClientRegistrationRepository, + ClientRegistrationRepository standardClientRegistrationRepository, + String authorizationRequestBaseUri) { + Assert.notNull(standardClientRegistrationRepository, + "clientRegistrationRepository cannot be null"); + Assert.hasText(authorizationRequestBaseUri, "authorizationRequestBaseUri cannot be empty"); + this.clientRegistrationRepository = standardClientRegistrationRepository; + this.authorizationRequestMatcher = new AntPathRequestMatcher( + authorizationRequestBaseUri + "/{" + REGISTRATION_ID_URI_VARIABLE_NAME + "}"); + } + + @Override + public OAuth2AuthorizationRequest resolve(HttpServletRequest request) { + String registrationId = this.resolveRegistrationId(request); + String redirectUriAction = getAction(request, "login"); + return resolve(request, registrationId, redirectUriAction); + } + + @Override + public OAuth2AuthorizationRequest resolve(HttpServletRequest request, String registrationId) { + if (registrationId == null) { + return null; + } + String redirectUriAction = getAction(request, "authorize"); + return resolve(request, registrationId, redirectUriAction); + } + + private String getAction(HttpServletRequest request, String defaultAction) { + String action = request.getParameter("action"); + if (action == null) { + return defaultAction; + } + return action; + } + + private OAuth2AuthorizationRequest resolve(HttpServletRequest request, String registrationId, + String redirectUriAction) { + if (registrationId == null) { + return null; + } + String domainOrIp = RequestUtils.getDomain(request); + ClientRegistration clientRegistration = null; + if (clientRegistrationRepository instanceof StandardClientRegistrationRepository) { + clientRegistration = + ((StandardClientRegistrationRepository) this.clientRegistrationRepository) + .findByRegistrationId(registrationId, domainOrIp); + } else { + clientRegistration = this.clientRegistrationRepository.findByRegistrationId(registrationId); + } + + if (clientRegistration == null) { + throw new IllegalArgumentException("Invalid Client Registration with Id: " + registrationId); + } + + OAuth2AuthorizationRequest.Builder builder; + if (AuthorizationGrantType.AUTHORIZATION_CODE + .equals(clientRegistration.getAuthorizationGrantType())) { + builder = OAuth2AuthorizationRequest.authorizationCode(); + } else if (AuthorizationGrantType.IMPLICIT + .equals(clientRegistration.getAuthorizationGrantType())) { + builder = OAuth2AuthorizationRequest.implicit(); + } else { + throw new IllegalArgumentException("Invalid Authorization Grant Type (" + + clientRegistration.getAuthorizationGrantType().getValue() + + ") for Client Registration with Id: " + clientRegistration.getRegistrationId()); + } + + String redirectUriStr = this.expandRedirectUri(request, clientRegistration, redirectUriAction); + + Map additionalParameters = new HashMap<>(); + additionalParameters.put(OAuth2ParameterNames.REGISTRATION_ID, + clientRegistration.getRegistrationId()); + String userType = request.getParameter(SecurityConstants.LOGIN_USER_TYPE_KEY); + String registerCode = request.getParameter(SecurityConstants.LOGIN_REGISTER_CODE_KEY); + String entrypoint = request.getParameter(SecurityConstants.LOGIN_ENTRYPOINT_KEY); + if (StringUtils.isBlank(userType)) { + userType = UserTypeEnum.PERSON.getType().toString(); + } + additionalParameters.put(SecurityConstants.LOGIN_USER_TYPE_KEY, userType); + if (StringUtils.isNotBlank(registerCode)) { + additionalParameters.put(SecurityConstants.LOGIN_REGISTER_CODE_KEY, registerCode); + } + if (StringUtils.isNotBlank(entrypoint)) { + additionalParameters.put(SecurityConstants.LOGIN_ENTRYPOINT_KEY, entrypoint); + } + + OAuth2AuthorizationRequest authorizationRequest = builder + .clientId(clientRegistration.getClientId()) + .authorizationUri(clientRegistration.getProviderDetails().getAuthorizationUri()) + .redirectUri(redirectUriStr) + .scopes(clientRegistration.getScopes()) + .state(this.stateGenerator.generateKey()) + .additionalParameters(additionalParameters) + .build(); + // 不同授权需要额外修饰 + IOauthProvider oauthProvider = Oauth2ProviderUtils.getProvider(registrationId); + if (oauthProvider != null) { + return oauthProvider.decorateRequest(request, authorizationRequest); + } + return authorizationRequest; + } + + private String resolveRegistrationId(HttpServletRequest request) { + if (this.authorizationRequestMatcher.matches(request)) { + return this.authorizationRequestMatcher + .extractUriTemplateVariables(request).get(REGISTRATION_ID_URI_VARIABLE_NAME); + } + return null; + } + + private String expandRedirectUri(HttpServletRequest request, + ClientRegistration clientRegistration, String action) { + // Supported URI variables -> baseUrl, action, registrationId + // Used in -> CommonOAuth2Provider.DEFAULT_REDIRECT_URL = "{baseUrl}/{action}/oauth2/code/{registrationId}" + Map uriVariables = new HashMap<>(); + uriVariables.put("registrationId", clientRegistration.getRegistrationId()); + String baseUrl = UriComponentsBuilder.fromHttpUrl(UrlUtils.buildFullRequestUrl(request)) + .replaceQuery(null) + .replacePath(request.getContextPath()) + .build() + .toUriString(); + uriVariables.put("baseUrl", baseUrl); + if (action != null) { + uriVariables.put("action", action); + } + return UriComponentsBuilder.fromUriString(clientRegistration.getRedirectUriTemplate()) + .buildAndExpand(uriVariables) + .toUriString(); + } +} diff --git a/src/main/java/com/newyetai/security/social/ssb/service/SsbOauthLoginProvider.java b/src/main/java/com/newyetai/security/social/ssb/service/SsbOauthLoginProvider.java new file mode 100644 index 0000000..853a026 --- /dev/null +++ b/src/main/java/com/newyetai/security/social/ssb/service/SsbOauthLoginProvider.java @@ -0,0 +1,67 @@ +package com.newyetai.security.social.ssb.service; + +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; +import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; +import org.springframework.stereotype.Service; + +import com.newyetai.sdk.ssb.SsbProperties; +import com.newyetai.sdk.ssb.util.SM2Utils; +import com.newyetai.security.social.service.IOauthProvider; +import com.newyetai.security.util.SecurityUtils; +import com.newyetai.usercenter.auth.constant.AuthTypeEnum; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class SsbOauthLoginProvider implements IOauthProvider { + + private static final String AUTH_URL = + "https://api.eshimin.com/newOauth/authorize?client_id=%s&response_type=authorization_code&scope=read&redirect_uri=%s×tamp=%s&sign=%s&state=%s"; + + @Autowired + private SsbProperties ssbProperties; + + + @Override + public String getName() { + return AuthTypeEnum.SSB_APP.name(); + } + + @Override + public OAuth2AuthorizationRequest decorateRequest(HttpServletRequest request, + OAuth2AuthorizationRequest authorizationRequest) { + String timestamp = String.valueOf(System.currentTimeMillis()); + String sign = SM2Utils.sign(ssbProperties.getSm2PrivateKey(), + ssbProperties.getAppKey() + ssbProperties.getAppSecret() + timestamp, + ssbProperties.getAppKey()); + + // 指定成功跳转地址 + String redirectUrl = + SecurityUtils.dealRedirectUrl(request, authorizationRequest.getRedirectUri()); + + String state = "123"; + + // 微信Authorization Request URL + String authorizationRequestUri = + String.format(AUTH_URL, + authorizationRequest.getClientId(), + SecurityUtils.encodeURL(redirectUrl), + timestamp, + sign, + state); + + return OAuth2AuthorizationRequest.from(authorizationRequest) + .authorizationRequestUri(authorizationRequestUri) + .build(); + + } + + +} diff --git a/src/main/java/com/newyetai/security/social/util/Oauth2ProviderUtils.java b/src/main/java/com/newyetai/security/social/util/Oauth2ProviderUtils.java new file mode 100644 index 0000000..b2d4711 --- /dev/null +++ b/src/main/java/com/newyetai/security/social/util/Oauth2ProviderUtils.java @@ -0,0 +1,26 @@ +package com.newyetai.security.social.util; + +import java.util.List; +import java.util.Map; + +import org.apache.commons.collections4.map.CaseInsensitiveMap; +import org.springframework.stereotype.Component; + +import com.newyetai.common.exception.util.Assert; +import com.newyetai.security.social.service.IOauthProvider; + +@Component +public class Oauth2ProviderUtils { + + private static Map providerMap = new CaseInsensitiveMap(); + + private Oauth2ProviderUtils(List providers) { + providers.forEach(provider -> providerMap.put(provider.getName(), provider)); + } + + public static IOauthProvider getProvider(String providerName) { + IOauthProvider provider = providerMap.get(providerName); + return provider; + } + +} diff --git a/src/main/java/com/newyetai/security/social/wechat/constant/WechatConstants.java b/src/main/java/com/newyetai/security/social/wechat/constant/WechatConstants.java new file mode 100644 index 0000000..38723db --- /dev/null +++ b/src/main/java/com/newyetai/security/social/wechat/constant/WechatConstants.java @@ -0,0 +1,20 @@ +package com.newyetai.security.social.wechat.constant; + +/** + * @author sr on 2021-01-13 + */ +public interface WechatConstants { + + /** 授权code获取token **/ + String TOKEN_URL_FORMAT = + "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=%s"; + + /** openId换取用户信息 **/ + String USER_URL_FORMAT = + "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=%s"; + + /** 调起微信授权地址 **/ + String AUTH_URL_FORMAT = + "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=%s&scope=%s&state=%s#wechat_redirect"; + +} diff --git a/src/main/java/com/newyetai/security/social/wechat/convert/WeChatAuthorizationCodeGrantRequestEntityConverter.java b/src/main/java/com/newyetai/security/social/wechat/convert/WeChatAuthorizationCodeGrantRequestEntityConverter.java new file mode 100644 index 0000000..d8afd73 --- /dev/null +++ b/src/main/java/com/newyetai/security/social/wechat/convert/WeChatAuthorizationCodeGrantRequestEntityConverter.java @@ -0,0 +1,57 @@ +package com.newyetai.security.social.wechat.convert; + +import java.net.URI; +import java.util.Collections; + +import org.springframework.core.convert.converter.Converter; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.http.RequestEntity; +import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest; +import org.springframework.security.oauth2.client.registration.ClientRegistration; +import org.springframework.web.util.UriComponentsBuilder; + +import com.newyetai.security.social.wechat.constant.WechatConstants; + +import lombok.extern.slf4j.Slf4j; + + +/** + * code换token + * + * @author sr on 2021-01-12 + */ +@Slf4j +public class WeChatAuthorizationCodeGrantRequestEntityConverter + implements Converter> { + + @Override + public RequestEntity convert( + OAuth2AuthorizationCodeGrantRequest authorizationCodeGrantRequest) { + HttpHeaders headers = getTokenRequestHeaders(); + URI uri = buildUri(authorizationCodeGrantRequest); + return new RequestEntity<>(headers, HttpMethod.GET, uri); + } + + private HttpHeaders getTokenRequestHeaders() { + HttpHeaders headers = new HttpHeaders(); + headers.setAccept(Collections.singletonList(MediaType.TEXT_PLAIN)); + return headers; + } + + private URI buildUri(OAuth2AuthorizationCodeGrantRequest authorizationCodeGrantRequest) { + ClientRegistration clientRegistration = authorizationCodeGrantRequest.getClientRegistration(); + String tokenUri = clientRegistration.getProviderDetails().getTokenUri(); + String appid = clientRegistration.getClientId(); + String secret = clientRegistration.getClientSecret(); + String code = authorizationCodeGrantRequest.getAuthorizationExchange() + .getAuthorizationResponse().getCode(); + String grantType = authorizationCodeGrantRequest.getGrantType().getValue(); + + String uriString = + String.format(WechatConstants.TOKEN_URL_FORMAT, + appid, secret, code, grantType); + return UriComponentsBuilder.fromUriString(uriString).build().toUri(); + } +} diff --git a/src/main/java/com/newyetai/security/social/wechat/convert/WeChatUserRequestEntityConverter.java b/src/main/java/com/newyetai/security/social/wechat/convert/WeChatUserRequestEntityConverter.java new file mode 100644 index 0000000..c529da7 --- /dev/null +++ b/src/main/java/com/newyetai/security/social/wechat/convert/WeChatUserRequestEntityConverter.java @@ -0,0 +1,44 @@ +package com.newyetai.security.social.wechat.convert; + +import java.net.URI; +import java.util.Collections; + +import org.springframework.core.convert.converter.Converter; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.http.RequestEntity; +import org.springframework.security.oauth2.client.registration.ClientRegistration; +import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; +import org.springframework.web.util.UriComponentsBuilder; + +import com.newyetai.security.social.wechat.constant.WechatConstants; + +public class WeChatUserRequestEntityConverter + implements Converter> { + + @Override + public RequestEntity convert(OAuth2UserRequest userRequest) { + HttpHeaders headers = getUserRequestHeaders(); + URI uri = buildUri(userRequest); + return new RequestEntity<>(headers, HttpMethod.GET, uri); + } + + private HttpHeaders getUserRequestHeaders() { + HttpHeaders headers = new HttpHeaders(); + headers.setAccept(Collections.singletonList(MediaType.TEXT_PLAIN)); + return headers; + } + + private URI buildUri(OAuth2UserRequest userRequest) { + ClientRegistration clientRegistration = userRequest.getClientRegistration(); + String uri = clientRegistration.getProviderDetails().getUserInfoEndpoint().getUri(); + String accessToken = userRequest.getAccessToken().getTokenValue(); + String openId = (String) userRequest.getAdditionalParameters().get("openid"); + + String userInfoUrl = + String.format(WechatConstants.USER_URL_FORMAT, + accessToken, openId, "zh_CN"); + return UriComponentsBuilder.fromUriString(userInfoUrl).build().toUri(); + } +} diff --git a/src/main/java/com/newyetai/security/social/wechat/service/WeChatAccessTokenResponse.java b/src/main/java/com/newyetai/security/social/wechat/service/WeChatAccessTokenResponse.java new file mode 100644 index 0000000..373704b --- /dev/null +++ b/src/main/java/com/newyetai/security/social/wechat/service/WeChatAccessTokenResponse.java @@ -0,0 +1,70 @@ +package com.newyetai.security.social.wechat.service; + +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest; +import org.springframework.security.oauth2.core.OAuth2AccessToken; +import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.security.social.service.IOauthProvider; +import com.newyetai.usercenter.constants.SecurityConstants; + +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; + +@Getter +@Setter +@Slf4j +public class WeChatAccessTokenResponse { + @JsonProperty("access_token") + private String accessToken; + @JsonProperty("expires_in") + private Long expiresIn; + @JsonProperty("refresh_token") + private String refreshToken; + private String openid; + private String scope; + + private WeChatAccessTokenResponse() { + + } + + public static WeChatAccessTokenResponse build(String json) { + try { + return JsonUtils.toObject(json, WeChatAccessTokenResponse.class); + } catch (Exception e) { + log.error("An error occurred while attempting to parse the WeiXin Access Token Response: " + + e.getMessage()); + return null; + } + } + + public OAuth2AccessTokenResponse toOAuth2AccessTokenResponse( + OAuth2AuthorizationCodeGrantRequest authorizationCodeGrantRequest) { + OAuth2AccessTokenResponse.Builder builder = OAuth2AccessTokenResponse.withToken(accessToken); + builder.tokenType(OAuth2AccessToken.TokenType.BEARER); + builder.expiresIn(expiresIn); + builder.refreshToken(refreshToken); + + String[] scopes = scope.split(","); + Set scopeSet = new HashSet<>(); + Collections.addAll(scopeSet, scopes); + builder.scopes(scopeSet); + + Map additionalParameters = new LinkedHashMap<>(); + additionalParameters.put("openid", openid); + Map originParam = authorizationCodeGrantRequest.getAuthorizationExchange().getAuthorizationRequest() + .getAdditionalParameters(); + additionalParameters.putAll(originParam); + builder.additionalParameters(additionalParameters); + return builder.build(); + } + +} diff --git a/src/main/java/com/newyetai/security/social/wechat/service/WechatOauthLoginProvider.java b/src/main/java/com/newyetai/security/social/wechat/service/WechatOauthLoginProvider.java new file mode 100644 index 0000000..b963aa4 --- /dev/null +++ b/src/main/java/com/newyetai/security/social/wechat/service/WechatOauthLoginProvider.java @@ -0,0 +1,157 @@ +package com.newyetai.security.social.wechat.service; + +import java.io.UnsupportedEncodingException; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.MapUtils; +import org.springframework.core.convert.converter.Converter; +import org.springframework.http.RequestEntity; +import org.springframework.http.ResponseEntity; +import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest; +import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; +import org.springframework.security.oauth2.core.OAuth2AuthorizationException; +import org.springframework.security.oauth2.core.OAuth2Error; +import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; +import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; +import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationResponseType; +import org.springframework.security.oauth2.core.user.OAuth2User; +import org.springframework.web.client.RestClientException; + +import com.newyetai.common.util.JsonUtils; +import com.newyetai.security.mapstruct.AuthDetailMapMapper; +import com.newyetai.security.mapstruct.UserMapMapper; +import com.newyetai.security.social.service.IOauthProvider; +import com.newyetai.security.social.service.StandardAuthorizationCodeTokenResponseClient; +import com.newyetai.security.social.wechat.constant.WechatConstants; +import com.newyetai.security.social.wechat.convert.WeChatAuthorizationCodeGrantRequestEntityConverter; +import com.newyetai.security.social.wechat.convert.WeChatUserRequestEntityConverter; +import com.newyetai.security.util.SecurityUtils; +import com.newyetai.usercenter.auth.constant.AuthTypeEnum; +import com.newyetai.usercenter.auth.dto.AuthDetailLoginDTO; +import com.newyetai.usercenter.auth.wechat.dto.WechatAuthUserInfoDTO; +import com.newyetai.usercenter.constants.SecurityConstants; +import com.newyetai.usercenter.user.login.dto.UserDetailDTO; +import com.newyetai.usercenter.user.login.service.UserLoginService; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class WechatOauthLoginProvider implements IOauthProvider { + + private Converter> tokenConverter = + new WeChatAuthorizationCodeGrantRequestEntityConverter(); + + private Converter> userConverter = + new WeChatUserRequestEntityConverter(); + + private UserLoginService userLoginService; + + public WechatOauthLoginProvider(UserLoginService userLoginService) { + this.userLoginService = userLoginService; + } + + @Override + public String getName() { + return AuthTypeEnum.WECHAT.name(); + } + + @Override + public OAuth2AuthorizationRequest decorateRequest(HttpServletRequest request, + OAuth2AuthorizationRequest authorizationRequest) { + // 指定成功跳转地址 + String redirectUrl = + SecurityUtils.dealRedirectUrl(request, authorizationRequest.getRedirectUri()); + + // 微信Authorization Request URL + String authorizationRequestUri = + String.format(WechatConstants.AUTH_URL_FORMAT, + authorizationRequest.getClientId(), + SecurityUtils.encodeURL(redirectUrl), + OAuth2AuthorizationResponseType.CODE.getValue(), getScope(authorizationRequest), + authorizationRequest.getState()); + + return OAuth2AuthorizationRequest.from(authorizationRequest) + .authorizationRequestUri(authorizationRequestUri) + .build(); + } + + private static String getScope(OAuth2AuthorizationRequest authorizationRequest) { + return authorizationRequest.getScopes().stream().findFirst().orElse("snsapi_userinfo"); + } + + @Override + public OAuth2AccessTokenResponse getTokenResponse( + OAuth2AuthorizationCodeGrantRequest authorizationCodeGrantRequest) { + + // 调用WeChatAuthorizationCodeGrantRequestEntityConverter获取request + RequestEntity request = this.tokenConverter.convert(authorizationCodeGrantRequest); + + ResponseEntity response; + try { + // 执行request + response = StandardAuthorizationCodeTokenResponseClient.restOperations.exchange(request, + String.class); + } catch (RestClientException ex) { + String description = + "An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: "; + log.error(description, ex); + OAuth2Error oauth2Error = + new OAuth2Error( + StandardAuthorizationCodeTokenResponseClient.INVALID_TOKEN_RESPONSE_ERROR_CODE, + description + ex.getMessage(), null); + throw new OAuth2AuthorizationException(oauth2Error, ex); + } + + // 解析response + OAuth2AccessTokenResponse tokenResponse = + WeChatAccessTokenResponse.build(response.getBody()).toOAuth2AccessTokenResponse(authorizationCodeGrantRequest); + + if (CollectionUtils.isEmpty(tokenResponse.getAccessToken().getScopes())) { + tokenResponse = OAuth2AccessTokenResponse.withResponse(tokenResponse) + .scopes(authorizationCodeGrantRequest.getClientRegistration().getScopes()) + .build(); + } + + return tokenResponse; + + } + + + @Override + public Converter> getUserConvert() { + return userConverter; + } + + @Override + public OAuth2User dealUser(OAuth2UserRequest userRequest, String userJsonStr) { + WechatAuthUserInfoDTO wechatUserInfoDTO = null; + try { + // 编码转换 + userJsonStr = new String(userJsonStr.getBytes("ISO-8859-1"), "UTF-8"); + wechatUserInfoDTO = JsonUtils.toObject(userJsonStr, WechatAuthUserInfoDTO.class); + } catch (UnsupportedEncodingException e) { + log.error("An error occurred while attempting to encode userAttributes: " + e.getMessage()); + } + AuthDetailLoginDTO authDetailLoginDTO = AuthDetailMapMapper.INSTANCE.toDto(wechatUserInfoDTO); + Integer userType = MapUtils.getInteger(userRequest.getAdditionalParameters(), + SecurityConstants.LOGIN_USER_TYPE_KEY); + String registerCode = MapUtils.getString(userRequest.getAdditionalParameters(), + SecurityConstants.LOGIN_REGISTER_CODE_KEY); + String entrypoint = MapUtils.getString(userRequest.getAdditionalParameters(), + SecurityConstants.LOGIN_ENTRYPOINT_KEY); + authDetailLoginDTO + .setUserType(userType); + authDetailLoginDTO + .setAuthClientId(Long.valueOf(userRequest.getClientRegistration().getRegistrationId())); + authDetailLoginDTO.setAuthTypeCode(AuthTypeEnum.WECHAT.getCode()); + authDetailLoginDTO.setRegisterCode(registerCode); + authDetailLoginDTO.setEntrypoint(entrypoint); + UserDetailDTO userDetailDTO = userLoginService.findUserDetailDTO(authDetailLoginDTO); + return UserMapMapper.INSTANCE.dtoToDto(userDetailDTO); + } + + + +} diff --git a/src/main/java/com/newyetai/security/ssb/SsbAuthenticationFilter.java b/src/main/java/com/newyetai/security/ssb/SsbAuthenticationFilter.java new file mode 100644 index 0000000..a8728bb --- /dev/null +++ b/src/main/java/com/newyetai/security/ssb/SsbAuthenticationFilter.java @@ -0,0 +1,70 @@ +package com.newyetai.security.ssb; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.authentication.AuthenticationServiceException; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; + +import com.newyetai.common.util.JsonUtils; + +import lombok.extern.slf4j.Slf4j; + +/** + * 账号密码认证过滤器,指定请求组装token,调起认证 + * + * @author sr on 2021-06-21 + */ +@Slf4j +public class SsbAuthenticationFilter extends AbstractAuthenticationProcessingFilter { + + private boolean postOnly = true; + + public static final String REQUEST_METHOD = "GET"; + public static final String LOGIN_URI = "/h5/ssb_login_notify"; + public static final AntPathRequestMatcher requiresAuthenticationRequestMatcher = + new AntPathRequestMatcher(LOGIN_URI, REQUEST_METHOD); + + public static final String PARAM_PLATFORM = "platform"; + public static final String PARAM_ACCESS_TOKEN = "access_token"; + public static final String PARAM_CODE = "code"; + public static final String PARAM_STATE = "state"; + + public SsbAuthenticationFilter() { + super(requiresAuthenticationRequestMatcher); + } + + @Override + public Authentication attemptAuthentication(HttpServletRequest request, + HttpServletResponse response) throws AuthenticationException, IOException, ServletException { + + if (postOnly && !REQUEST_METHOD.equals(request.getMethod())) { + throw new AuthenticationServiceException( + "Authentication method not supported: " + request.getMethod()); + } + + String platform = request.getParameter(PARAM_PLATFORM); + String accessToken = request.getParameter(PARAM_ACCESS_TOKEN); + String code = request.getParameter(PARAM_CODE); + String state = request.getParameter(PARAM_STATE); + log.info("ssb login req params:{}", JsonUtils.toJsonString(request.getParameterMap())); + AbstractAuthenticationToken authRequest = new SsbAuthenticationToken( + SsbLoginDTO.builder().accessToken(accessToken).platform(platform).code(code).state(state).build(), accessToken); + + // Allow subclasses to set the "details" property + setDetails(request, authRequest); + + return this.getAuthenticationManager().authenticate(authRequest); + } + + protected void setDetails(HttpServletRequest request, AbstractAuthenticationToken authRequest) { + authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); + } +} diff --git a/src/main/java/com/newyetai/security/ssb/SsbAuthenticationProvider.java b/src/main/java/com/newyetai/security/ssb/SsbAuthenticationProvider.java new file mode 100644 index 0000000..8e8652f --- /dev/null +++ b/src/main/java/com/newyetai/security/ssb/SsbAuthenticationProvider.java @@ -0,0 +1,71 @@ +package com.newyetai.security.ssb; + +import java.util.HashSet; +import java.util.Set; + +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.common.validation.util.ValidateUtils; +import com.newyetai.security.dto.SecurityUserDTO; +import com.newyetai.security.expection.BadLoginException; +import com.newyetai.security.mapstruct.UserMapMapper; +import com.newyetai.usercenter.user.login.dto.LoginUsernamePasswordDTO; +import com.newyetai.usercenter.user.login.dto.UserDetailDTO; +import com.newyetai.usercenter.user.login.service.UserLoginService; + +import lombok.extern.slf4j.Slf4j; + +/** + * 账号密码认证provider,比对信息是否匹配 + * + * @author sr on 2021-06-21 + */ +@Slf4j +public class SsbAuthenticationProvider implements AuthenticationProvider { + + private UserLoginService userLoginService; + + public SsbAuthenticationProvider(UserLoginService userLoginService) { + this.userLoginService = userLoginService; + } + + @Override + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + SsbLoginDTO ssbLoginDTO = + (SsbLoginDTO) authentication.getPrincipal(); + log.info("ssb login req:{}", JsonUtils.toJsonString(ssbLoginDTO)); + String errMsg = ValidateUtils.validate(ssbLoginDTO); + Assert.isTrue(errMsg == null, new BadLoginException(errMsg)); + SecurityUserDTO loadedUser = null; + try { + UserDetailDTO userDetailDTO = this.userLoginService.loadUser(ssbLoginDTO); + loadedUser = UserMapMapper.INSTANCE.dtoToDto(userDetailDTO); + } catch (BadLoginException be) { + throw be; + } catch (Exception e) { + throw new BadLoginException(e.getMessage(), e); + } + + SsbAuthenticationToken result = + new SsbAuthenticationToken(loadedUser, listUserGrantedAuthorities(loadedUser)); + result.setDetails(authentication.getDetails()); + return result; + } + + @Override + public boolean supports(Class authentication) { + return (SsbAuthenticationToken.class.isAssignableFrom(authentication)); + } + + private Set listUserGrantedAuthorities(UserDetails userDetails) { + // 什么都不用做,访问资源鉴权的时会拿userDetail去缓存获取对应权限 + return new HashSet(); + } + +} diff --git a/src/main/java/com/newyetai/security/ssb/SsbAuthenticationToken.java b/src/main/java/com/newyetai/security/ssb/SsbAuthenticationToken.java new file mode 100644 index 0000000..f1c5024 --- /dev/null +++ b/src/main/java/com/newyetai/security/ssb/SsbAuthenticationToken.java @@ -0,0 +1,25 @@ +package com.newyetai.security.ssb; + +import java.util.Collection; + +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.GrantedAuthority; + + +/** + * 账号密码认证信息 + * @author sr on 2021-06-21 + */ +public class SsbAuthenticationToken extends UsernamePasswordAuthenticationToken { + + public SsbAuthenticationToken(Object principal, Object credentials) { + super(principal, credentials); + } + + public SsbAuthenticationToken(Object principal, Object credentials, + Collection authorities) { + super(principal, credentials, authorities); + } + +} diff --git a/src/main/java/com/newyetai/security/ssb/SsbLoginDTO.java b/src/main/java/com/newyetai/security/ssb/SsbLoginDTO.java new file mode 100644 index 0000000..55ee45f --- /dev/null +++ b/src/main/java/com/newyetai/security/ssb/SsbLoginDTO.java @@ -0,0 +1,34 @@ +package com.newyetai.security.ssb; + +import java.io.Serializable; + +import javax.validation.constraints.NotBlank; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class SsbLoginDTO implements Serializable { + + /** **/ + private static final long serialVersionUID = 6780283569028235063L; + /** 平台标识 + eshimin: 随申办 APP + weixinmini:微信小程序 + weixinmp:微信公众号 + alipaymini:支付宝小程序 + alipayfuwu:支付宝生活号 **/ +// @NotBlank(message = "平台标识不能为空") + private String platform; + /** 用户令牌,作为获取用户信息的入参 **/ + private String accessToken; + /** oauth code **/ + private String code; + private String state; + +} diff --git a/src/main/java/com/newyetai/security/temptoken/TokenAuthenticationFilter.java b/src/main/java/com/newyetai/security/temptoken/TokenAuthenticationFilter.java new file mode 100644 index 0000000..095f48c --- /dev/null +++ b/src/main/java/com/newyetai/security/temptoken/TokenAuthenticationFilter.java @@ -0,0 +1,100 @@ +package com.newyetai.security.temptoken; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.authentication.AuthenticationServiceException; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; + +import com.newyetai.security.expection.BadLoginException; +import com.newyetai.usercenter.constants.SecurityConstants; +import com.newyetai.usercenter.user.login.dto.LoginPhoneToken; +import com.newyetai.usercenter.user.login.dto.LoginUserToken; +import com.newyetai.usercenter.user.login.dto.TempTokenDTO; + +/** + * 临时token认证过滤器,指定请求组装token,调起认证 + * + * @author sr on 2020-06-04 + */ +public class TokenAuthenticationFilter extends AbstractAuthenticationProcessingFilter { + + + public static final String TYPE_KEY = "type"; + public static final String REQUEST_METHOD = "POST"; + + private static final AntPathRequestMatcher requiresAuthenticationRequestMatcher = + new AntPathRequestMatcher("/login_token_" + "{" + TYPE_KEY + "}", REQUEST_METHOD); + + private boolean postOnly = true; + + public TokenAuthenticationFilter() { + super(requiresAuthenticationRequestMatcher); + } + + @Override + public Authentication attemptAuthentication(HttpServletRequest request, + HttpServletResponse response) throws AuthenticationException, IOException, ServletException { + + if (postOnly && !REQUEST_METHOD.equals(request.getMethod())) { + throw new AuthenticationServiceException( + "Authentication method not supported: " + request.getMethod()); + } + + String type = this.resolveType(request); + String tempToken = request.getParameter(SecurityConstants.LOGIN_TEMP_TOKEN_KEY); + String entrypoint = request.getParameter(SecurityConstants.LOGIN_ENTRYPOINT_KEY); + TempTokenDTO tempTokenDTO = null; + if (TempTokenDTO.TYPE_PHONE.equals(type)) { + Long userId = null; + String userIdStr = request.getParameter(SecurityConstants.LOGIN_USER_ID_KEY); + if (StringUtils.isNotBlank(userIdStr)) { + try { + userId = Long.valueOf(userIdStr); + } catch (NumberFormatException e) { + throw new BadLoginException("用户id错误:" + userIdStr); + } + + } + tempTokenDTO = LoginPhoneToken.builder().tempToken(tempToken).entrypoint(entrypoint) + .userId(userId).build(); + } else if (TempTokenDTO.TYPE_USER.equals(type)) { + Long orgId = null; + String orgIdStr = request.getParameter(SecurityConstants.LOGIN_ORG_ID_KEY); + try { + orgId = Long.valueOf(orgIdStr); + } catch (NumberFormatException e) { + throw new BadLoginException("机构id错误:" + orgIdStr); + } + tempTokenDTO = LoginUserToken.builder().tempToken(tempToken).orgId(orgId).build(); + } else { + throw new BadLoginException("token认证类型有误"); + } + AbstractAuthenticationToken authRequest = new TokenAuthenticationToken(tempTokenDTO, tempToken); + + // Allow subclasses to set the "details" property + setDetails(request, authRequest); + + return this.getAuthenticationManager().authenticate(authRequest); + } + + protected void setDetails(HttpServletRequest request, AbstractAuthenticationToken authRequest) { + authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); + } + + private String resolveType(HttpServletRequest request) { + if (requiresAuthenticationRequestMatcher.matches(request)) { + return requiresAuthenticationRequestMatcher.extractUriTemplateVariables(request) + .get(TYPE_KEY); + } + return null; + } +} diff --git a/src/main/java/com/newyetai/security/temptoken/TokenAuthenticationProvider.java b/src/main/java/com/newyetai/security/temptoken/TokenAuthenticationProvider.java new file mode 100644 index 0000000..4f83830 --- /dev/null +++ b/src/main/java/com/newyetai/security/temptoken/TokenAuthenticationProvider.java @@ -0,0 +1,74 @@ +package com.newyetai.security.temptoken; + +import java.util.HashSet; +import java.util.Set; + +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.validation.util.ValidateUtils; +import com.newyetai.security.dto.SecurityUserDTO; +import com.newyetai.security.expection.BadLoginException; +import com.newyetai.security.mapstruct.UserMapMapper; +import com.newyetai.usercenter.user.login.dto.LoginPhoneToken; +import com.newyetai.usercenter.user.login.dto.LoginUserToken; +import com.newyetai.usercenter.user.login.dto.UserDetailDTO; +import com.newyetai.usercenter.user.login.service.UserLoginService; + +/** + * token认证provider,比对信息是否匹配 + * + * @author sr on 2020-06-04 + */ +public class TokenAuthenticationProvider implements AuthenticationProvider { + + private UserLoginService userLoginService; + + public TokenAuthenticationProvider(UserLoginService userLoginService) { + this.userLoginService = userLoginService; + } + + @Override + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + Object principal = authentication.getPrincipal(); + + String errMsg = ValidateUtils.validate(principal); + Assert.isTrue(errMsg == null, new BadLoginException(errMsg)); + SecurityUserDTO loadedUser = null; + try { + UserDetailDTO userDetailDTO = null; + if (principal instanceof LoginPhoneToken) { + userDetailDTO = userLoginService.loadUser((LoginPhoneToken) principal); + } else if (principal instanceof LoginUserToken) { + userDetailDTO = userLoginService.loadUser((LoginUserToken) principal); + }else { + throw new BadLoginException("token认证类型有误"); + } + loadedUser = UserMapMapper.INSTANCE.dtoToDto(userDetailDTO); + } catch (BadLoginException be) { + throw be; + } catch (Exception e) { + throw new BadLoginException(e.getMessage(), e); + } + + TokenAuthenticationToken result = + new TokenAuthenticationToken(loadedUser, listUserGrantedAuthorities(loadedUser)); + result.setDetails(authentication.getDetails()); + return result; + } + + @Override + public boolean supports(Class authentication) { + return (TokenAuthenticationToken.class.isAssignableFrom(authentication)); + } + + private Set listUserGrantedAuthorities(UserDetails userDetails) { + // 什么都不用做,访问资源鉴权的时会拿userDetail去缓存获取对应权限 + return new HashSet(); + } + +} diff --git a/src/main/java/com/newyetai/security/temptoken/TokenAuthenticationToken.java b/src/main/java/com/newyetai/security/temptoken/TokenAuthenticationToken.java new file mode 100644 index 0000000..65e54b8 --- /dev/null +++ b/src/main/java/com/newyetai/security/temptoken/TokenAuthenticationToken.java @@ -0,0 +1,24 @@ +package com.newyetai.security.temptoken; + +import java.util.Collection; + +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.GrantedAuthority; + +/** + * 临时token认证信息 + * + * @author sr on 2020-06-04 + */ +public class TokenAuthenticationToken extends UsernamePasswordAuthenticationToken { + + public TokenAuthenticationToken(Object principal, Object credentials) { + super(principal, credentials); + } + + public TokenAuthenticationToken(Object principal, Object credentials, + Collection authorities) { + super(principal, credentials, authorities); + } + +} diff --git a/src/main/java/com/newyetai/security/temptoken/dto/DuplMobileToken.java b/src/main/java/com/newyetai/security/temptoken/dto/DuplMobileToken.java new file mode 100644 index 0000000..501e7bc --- /dev/null +++ b/src/main/java/com/newyetai/security/temptoken/dto/DuplMobileToken.java @@ -0,0 +1,25 @@ +package com.newyetai.security.temptoken.dto; + +import java.util.List; + +import com.newyetai.usercenter.user.login.dto.PhoneToken; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@Data +@NoArgsConstructor +@SuperBuilder +@ApiModel(description = "多用户手机号token") +public class DuplMobileToken extends PhoneToken{ + + /** **/ + private static final long serialVersionUID = -4119001378908265360L; + + @ApiModelProperty("用户列表") + private List users; + +} diff --git a/src/main/java/com/newyetai/security/temptoken/dto/DuplUserToken.java b/src/main/java/com/newyetai/security/temptoken/dto/DuplUserToken.java new file mode 100644 index 0000000..16c52c4 --- /dev/null +++ b/src/main/java/com/newyetai/security/temptoken/dto/DuplUserToken.java @@ -0,0 +1,25 @@ +package com.newyetai.security.temptoken.dto; + +import java.util.List; + +import com.newyetai.usercenter.user.login.dto.UserToken; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@Data +@NoArgsConstructor +@SuperBuilder +@ApiModel(description = "多机构用户token") +public class DuplUserToken extends UserToken{ + + /** **/ + private static final long serialVersionUID = -374663184680420441L; + + @ApiModelProperty("机构列表") + private List orgs; + +} diff --git a/src/main/java/com/newyetai/security/temptoken/dto/PhoneTokenCreateDTO.java b/src/main/java/com/newyetai/security/temptoken/dto/PhoneTokenCreateDTO.java new file mode 100644 index 0000000..5437850 --- /dev/null +++ b/src/main/java/com/newyetai/security/temptoken/dto/PhoneTokenCreateDTO.java @@ -0,0 +1,20 @@ +package com.newyetai.security.temptoken.dto; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class PhoneTokenCreateDTO implements Serializable{ + + private Integer userType; + private String phone; + +} diff --git a/src/main/java/com/newyetai/security/temptoken/dto/UserTokenCreateDTO.java b/src/main/java/com/newyetai/security/temptoken/dto/UserTokenCreateDTO.java new file mode 100644 index 0000000..d84640f --- /dev/null +++ b/src/main/java/com/newyetai/security/temptoken/dto/UserTokenCreateDTO.java @@ -0,0 +1,19 @@ +package com.newyetai.security.temptoken.dto; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class UserTokenCreateDTO implements Serializable{ + + private Integer userType; + private Long userId; + +} diff --git a/src/main/java/com/newyetai/security/upassword/UpasswordAuthenticationFilter.java b/src/main/java/com/newyetai/security/upassword/UpasswordAuthenticationFilter.java new file mode 100644 index 0000000..d282b77 --- /dev/null +++ b/src/main/java/com/newyetai/security/upassword/UpasswordAuthenticationFilter.java @@ -0,0 +1,71 @@ +package com.newyetai.security.upassword; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.authentication.AuthenticationServiceException; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; + +import com.newyetai.security.expection.BadLoginException; +import com.newyetai.usercenter.constants.SecurityConstants; +import com.newyetai.usercenter.user.login.dto.LoginUsernamePasswordDTO; + +/** + * 账号密码认证过滤器,指定请求组装token,调起认证 + * + * @author sr on 2021-06-21 + */ +public class UpasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter { + + private boolean postOnly = true; + + public static final String REQUEST_METHOD = "POST"; + public static final AntPathRequestMatcher requiresAuthenticationRequestMatcher = + new AntPathRequestMatcher("/login", REQUEST_METHOD); + + public UpasswordAuthenticationFilter() { + super(requiresAuthenticationRequestMatcher); + } + + @Override + public Authentication attemptAuthentication(HttpServletRequest request, + HttpServletResponse response) throws AuthenticationException, IOException, ServletException { + + if (postOnly && !REQUEST_METHOD.equals(request.getMethod())) { + throw new AuthenticationServiceException( + "Authentication method not supported: " + request.getMethod()); + } + + String userTypeStr = request.getParameter(SecurityConstants.LOGIN_USER_TYPE_KEY); + Integer userType = null; + try { + userType = Integer.valueOf(userTypeStr); + } catch (NumberFormatException e) { + throw new BadLoginException("用户类型错误:" + userTypeStr); + } + + String username = request.getParameter(SecurityConstants.LOGIN_USERNAME_KEY); + String password = request.getParameter(SecurityConstants.LOGIN_PASSWORD_KEY); + username = username == null ? "" : username.trim(); + password = password == null ? "" : password.trim(); + + AbstractAuthenticationToken authRequest = new UpasswordAuthenticationToken( + LoginUsernamePasswordDTO.builder().username(username).password(password).userType(userType).build(), password); + + // Allow subclasses to set the "details" property + setDetails(request, authRequest); + + return this.getAuthenticationManager().authenticate(authRequest); + } + + protected void setDetails(HttpServletRequest request, AbstractAuthenticationToken authRequest) { + authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); + } +} diff --git a/src/main/java/com/newyetai/security/upassword/UpasswordAuthenticationProvider.java b/src/main/java/com/newyetai/security/upassword/UpasswordAuthenticationProvider.java new file mode 100644 index 0000000..30ffe5d --- /dev/null +++ b/src/main/java/com/newyetai/security/upassword/UpasswordAuthenticationProvider.java @@ -0,0 +1,66 @@ +package com.newyetai.security.upassword; + +import java.util.HashSet; +import java.util.Set; + +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.validation.util.ValidateUtils; +import com.newyetai.security.dto.SecurityUserDTO; +import com.newyetai.security.expection.BadLoginException; +import com.newyetai.security.mapstruct.UserMapMapper; +import com.newyetai.usercenter.user.login.dto.LoginUsernamePasswordDTO; +import com.newyetai.usercenter.user.login.dto.UserDetailDTO; +import com.newyetai.usercenter.user.login.service.UserLoginService; + +/** + * 账号密码认证provider,比对信息是否匹配 + * + * @author sr on 2021-06-21 + */ +public class UpasswordAuthenticationProvider implements AuthenticationProvider { + + private UserLoginService userLoginService; + + public UpasswordAuthenticationProvider(UserLoginService userLoginService) { + this.userLoginService = userLoginService; + } + + @Override + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + LoginUsernamePasswordDTO loginUsernamePasswordDTO = + (LoginUsernamePasswordDTO) authentication.getPrincipal(); + String errMsg = ValidateUtils.validate(loginUsernamePasswordDTO); + Assert.isTrue(errMsg == null, new BadLoginException(errMsg)); + SecurityUserDTO loadedUser = null; + try { + UserDetailDTO userDetailDTO = this.userLoginService.loadUser(loginUsernamePasswordDTO); + loadedUser = UserMapMapper.INSTANCE.dtoToDto(userDetailDTO); + } catch (BadLoginException be) { + throw be; + } catch (Exception e) { + throw new BadLoginException(e.getMessage(), e); + } + + UpasswordAuthenticationToken result = + new UpasswordAuthenticationToken(loadedUser, listUserGrantedAuthorities(loadedUser)); + result.setDetails(authentication.getDetails()); + return result; + } + + @Override + public boolean supports(Class authentication) { + return (UpasswordAuthenticationToken.class.isAssignableFrom(authentication)); + } + + private Set listUserGrantedAuthorities(UserDetails userDetails) { + // 什么都不用做,访问资源鉴权的时会拿userDetail去缓存获取对应权限 + return new HashSet(); + } + +} diff --git a/src/main/java/com/newyetai/security/upassword/UpasswordAuthenticationToken.java b/src/main/java/com/newyetai/security/upassword/UpasswordAuthenticationToken.java new file mode 100644 index 0000000..f86906a --- /dev/null +++ b/src/main/java/com/newyetai/security/upassword/UpasswordAuthenticationToken.java @@ -0,0 +1,25 @@ +package com.newyetai.security.upassword; + +import java.util.Collection; + +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.GrantedAuthority; + + +/** + * 账号密码认证信息 + * @author sr on 2021-06-21 + */ +public class UpasswordAuthenticationToken extends UsernamePasswordAuthenticationToken { + + public UpasswordAuthenticationToken(Object principal, Object credentials) { + super(principal, credentials); + } + + public UpasswordAuthenticationToken(Object principal, Object credentials, + Collection authorities) { + super(principal, credentials, authorities); + } + +} diff --git a/src/main/java/com/newyetai/security/util/HostContextHolder.java b/src/main/java/com/newyetai/security/util/HostContextHolder.java new file mode 100644 index 0000000..51a497e --- /dev/null +++ b/src/main/java/com/newyetai/security/util/HostContextHolder.java @@ -0,0 +1,35 @@ +package com.newyetai.security.util; + +/** + * request请求host上下文 + * @author sr on 2021-08-23 + */ +public class HostContextHolder { + + private static final ThreadLocal HOST = new ThreadLocal(); + + /** + * + * @author sr on 2021-08-18 + */ + public static void clearHost() { + HOST.remove(); + } + + /** + * @param host + * @author sr on 2021-08-18 + */ + public static void setHost(String host) { + HOST.set(host); + } + + /** + * @param host + * @author sr on 2021-08-18 + */ + public static String getHost() { + return HOST.get(); + } + +} diff --git a/src/main/java/com/newyetai/security/util/MockUtils.java b/src/main/java/com/newyetai/security/util/MockUtils.java new file mode 100644 index 0000000..89eaf57 --- /dev/null +++ b/src/main/java/com/newyetai/security/util/MockUtils.java @@ -0,0 +1,68 @@ +package com.newyetai.security.util; + +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.security.dto.SecurityUserDTO; +import com.newyetai.usercenter.constants.OrgConstants; +import com.newyetai.usercenter.constants.UserConstants; +import com.newyetai.usercenter.user.constant.UserTypeEnum; +import com.newyetai.usercenter.user.dto.UserDetailQueryDTO; + +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; + +/** + * @author sr on 2020-01-05 + */ +public class MockUtils { + + + /** + * 模拟登录机构用户,默认超级管理员/平台机构 + */ + public static void mockPlatUser() { + mockUser(UserConstants.SUPERIOR_USER_ID, OrgConstants.PLATFORM_ORG_ID,UserTypeEnum.ORG.getType()); + } + + /** + * 模拟登录用户 + * + * @param userId + * @param orgId(企业用户需要,个人不用可不传) + * @author sr on 2020-09-07 + */ + public static void mockUser(Long userId, Long orgId) { + mockUser(userId, orgId, null); + } + + /** + * 模拟登录用户(能拿到外部线程登录用户信息,则直接用外部的,不要自己定义固定值) + * 使用mockUser(userId,orgId), 不需要userType,userId已经有用户类型了 + * @param userId + * @param orgId 个人用户可为空 + * @param userType {@link UserTypeEnum} + * @author sr on 2020-09-07 + */ + @Deprecated + public static void mockUser(Long userId, Long orgId,Integer userType) { + Assert.notNull(userId, "无userId,无法mock.."); + UserDetailQueryDTO userDetailQueryDto = + UserDetailQueryDTO.builder().userId(userId).orgId(orgId).userType(userType).build(); + SecurityUserDTO securityUserDTO = UserLoginUtils.loadUserToMock(userDetailQueryDto); + SecurityContextHolder.getContext() + .setAuthentication(new UsernamePasswordAuthenticationToken( + securityUserDTO, null)); + UserContextHolder.setContext(securityUserDTO); + } + + /** + * + * @author sr on 2020-06-17 + */ + public static void clearUser() { + SecurityContextHolder.clearContext(); + UserContextHolder.clearContext(); + } + + +} diff --git a/src/main/java/com/newyetai/security/util/PasswordUtils.java b/src/main/java/com/newyetai/security/util/PasswordUtils.java new file mode 100644 index 0000000..5fecaf5 --- /dev/null +++ b/src/main/java/com/newyetai/security/util/PasswordUtils.java @@ -0,0 +1,25 @@ +package com.newyetai.security.util; + +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Component; + +@Component +public class PasswordUtils { + + private static PasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + + private PasswordUtils(PasswordEncoder passwordEncoder) { + PasswordUtils.passwordEncoder = passwordEncoder; + } + + public static String encode(String password) { + return passwordEncoder.encode(password); + } + + public static boolean match(String password, String encodedPassword) { + return passwordEncoder.matches(password, encodedPassword); + } + + +} diff --git a/src/main/java/com/newyetai/security/util/SecurityMockProvider.java b/src/main/java/com/newyetai/security/util/SecurityMockProvider.java new file mode 100644 index 0000000..3961cb7 --- /dev/null +++ b/src/main/java/com/newyetai/security/util/SecurityMockProvider.java @@ -0,0 +1,25 @@ +package com.newyetai.security.util; + +import org.springframework.stereotype.Service; + +import com.newyetai.common.service.IMockProvider; + +@Service +public class SecurityMockProvider implements IMockProvider{ + + @Override + public void mockPlatUser() { + MockUtils.mockPlatUser(); + } + + @Override + public void mockUser(Long userId, Long orgId) { + MockUtils.mockUser(userId, orgId); + } + + @Override + public void clearUser() { + MockUtils.clearUser(); + } + +} diff --git a/src/main/java/com/newyetai/security/util/SecurityPropertyUtils.java b/src/main/java/com/newyetai/security/util/SecurityPropertyUtils.java new file mode 100644 index 0000000..0cd6b3d --- /dev/null +++ b/src/main/java/com/newyetai/security/util/SecurityPropertyUtils.java @@ -0,0 +1,119 @@ +package com.newyetai.security.util; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.http.HttpMethod; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.util.matcher.RequestMatcher; + +import com.newyetai.common.util.EnvironmentUtils; +import com.newyetai.security.config.SecurityProperties; +import com.newyetai.usercenter.constants.SecurityConstants; + +/** + * @author sr on 2020-09-10 + */ +public abstract class SecurityPropertyUtils { + + private static SecurityProperties securityProperties; + + + private static List anonRequestMatchers; + private static RequestMatcher unacRequestMatcher = new AntPathRequestMatcher("/unac/**"); + private static RequestMatcher authedRequestMatcher = new AntPathRequestMatcher("/authed/**"); + + public static void setSecurityProperties(SecurityProperties securityProperties) { + SecurityPropertyUtils.securityProperties = securityProperties; + } + + public static SecurityProperties getProperties() { + return securityProperties; + } + + /** + * 根据匹配路径获取请求匹配对象 + * + * @param httpMethod + * @param antPatterns + * @return + * @author sr on 2020-09-10 + */ + public static List antMatchers(HttpMethod httpMethod, + String... antPatterns) { + String method = httpMethod == null ? null : httpMethod.toString(); + List matchers = new ArrayList<>(); + for (String pattern : antPatterns) { + matchers.add(new AntPathRequestMatcher(pattern, method)); + } + return matchers; + } + + /** + * 获取匿名配置匹配 + * + * @return + * @author sr on 2020-09-10 + */ + public static List getAnonRequestMatchers() { + if (anonRequestMatchers != null) { + return anonRequestMatchers; + } + + String anonymous = EnvironmentUtils.getProperty(SecurityConstants.PROP_KEY_SECURITY_ANONYMOUS); + if (StringUtils.isBlank(anonymous)) { + anonRequestMatchers = Collections.emptyList(); + return anonRequestMatchers; + } + anonRequestMatchers = antMatchers(null, anonymous.split(",")); + return anonRequestMatchers; + } + + /** + * 判断请求是否匿名请求 + * + * @param request + * @return + * @author sr on 2020-09-10 + */ + public static boolean isAnon(HttpServletRequest request) { + List matchers = getAnonRequestMatchers(); + if (matchers.isEmpty()) { + return false; + } + for (RequestMatcher matcher : matchers) { + if (matcher.matches(request)) { + return true; + } + } + return false; + } + + /** + * 判断请求是否未激活请求 + * + * @param request + * @return + * @author sr on 2021-06-29 + */ + public static boolean isUnac(HttpServletRequest request) { + return unacRequestMatcher.matches(request); + } + + /** + * 判断请求是否已实名请求 + * @param request + * @return + * @author sr on 2021-11-05 + */ + public static boolean isAuthed(HttpServletRequest request) { + return authedRequestMatcher.matches(request); + } + + + +} diff --git a/src/main/java/com/newyetai/security/util/SecurityUtils.java b/src/main/java/com/newyetai/security/util/SecurityUtils.java new file mode 100644 index 0000000..5a29dbe --- /dev/null +++ b/src/main/java/com/newyetai/security/util/SecurityUtils.java @@ -0,0 +1,146 @@ +package com.newyetai.security.util; + +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLDecoder; +import java.net.URLEncoder; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.lang3.StringUtils; + +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.util.EnvironmentUtils; +import com.newyetai.common.util.RequestUtils; +import com.newyetai.usercenter.constants.SecurityConstants; + +import cn.hutool.core.util.URLUtil; +import lombok.extern.slf4j.Slf4j; + +/** + * @author sr on 2020-06-15 + */ +@Slf4j +public class SecurityUtils { + + /** 代理域名 **/ + private static final String PROXY_DOMAIN = "proxy.niuyetai.cn"; + + /** 代理路径请求head-key **/ + public static final String PROXY_REQUEST_HEADER_KEY = "X-Proxy-Uri"; + + + public static String encodeURL(String url) { + try { + return URLEncoder.encode(url, "UTF-8"); + } catch (UnsupportedEncodingException e) { + log.info("encode失败:{}", e.getMessage()); + return null; + } + } + + public static String decodeURL(String url) { + try { + if(url.contains("%")) { + return URLDecoder.decode(url, "UTF-8"); + } + return url; + } catch (UnsupportedEncodingException e) { + log.info("encode失败:{}", e.getMessage()); + return null; + } + } + + /** + * 是否本地security调用 ;security.useLocal=false则关闭(调用户中心),其他都本地调用 + * + * @return + * @author sr on 2020-06-15 + */ + public static boolean useLocal() { + return !CommonConstants.FALSE_STR + .equals(EnvironmentUtils.getProperty(SecurityConstants.PROP_KEY_SECURITY_USELOCAL)); + } + + /** + * 处理代理路径 + * @param request + * @param uri + * @return + * @author sr on 2021-01-16 + */ + private static String dealProxy(HttpServletRequest request, String uri) { + String proxyUri = request.getHeader(PROXY_REQUEST_HEADER_KEY); + log.info("proxyUri {}", proxyUri); + // replace域名到代理域名 + if (StringUtils.isNotBlank(proxyUri) && uri.contains(PROXY_DOMAIN)) { + return uri.replace(PROXY_DOMAIN, PROXY_DOMAIN + proxyUri); + } + return uri; + } + + /** + * 指定成功跳转地址 + * + * @param request + * @param redirectUri + * @return + * @author sr on 2021-01-12 + */ + public static String dealRedirectUrl(HttpServletRequest request, final String redirectUri) { + String newRedirectUri = redirectUri; + String successToUrl = request.getParameter(SecurityConstants.SUCCESS_TO_URL); + if (StringUtils.isNotBlank(successToUrl)) { + newRedirectUri = + String.format(SecurityConstants.REDIRECT_URL_FORMAT, newRedirectUri, + encodeURL(successToUrl)); + } + newRedirectUri = dealProxy(request, newRedirectUri); + log.info("newRedirectUri:{}", newRedirectUri); + return newRedirectUri; + } + + public static String dealLoginUrl(HttpServletRequest request, String loginUri) { + String successToUrl = request.getParameter(SecurityConstants.SUCCESS_TO_URL); + // 指定成功跳转,但登陆地址未配置域名 + if (StringUtils.isNotBlank(successToUrl) + && loginUri.indexOf(RequestUtils.DOMAIN_SEPARATOR) < 0) { + String baseUrl = null; + try { + baseUrl = URLUtil.getHost(new URL(successToUrl)).toString(); + } catch (MalformedURLException e) { + log.error("successToUrl get domain error:{}", e.getMessage()); + return null; + } + loginUri = baseUrl + loginUri; + } + dealProxy(request, loginUri); + return loginUri; + } + + public static String dealSuccessUrl(HttpServletRequest request, String successUri, String token) { + if (successUri == null) { + return null; + } + String redirectSuccessToUrl = request.getParameter(SecurityConstants.SUCCESS_TO_URL); + log.debug("redirectSuccessToUrl:{}", redirectSuccessToUrl); + successUri = + StringUtils.isBlank(redirectSuccessToUrl) ? successUri : decodeURL(redirectSuccessToUrl); + if (successUri.indexOf(RequestUtils.DOMAIN_SEPARATOR) > 0) { + String requestBaseUrl = RequestUtils.getHttpDomain(request); + // 成功地址与当前地址域名不一致,跨域,拼接token + if (!successUri.startsWith(requestBaseUrl)) { + if (successUri.indexOf("?") > 0) { + successUri += "&" + SecurityConstants.TOKEN + "=" + token; + } else { + successUri += "?" + SecurityConstants.TOKEN + "=" + token; + } + } + } + dealProxy(request, successUri); + log.info("last redirectSuccessToUrl:{}", successUri); + return successUri; + } + +} diff --git a/src/main/java/com/newyetai/security/util/UserLoginUtils.java b/src/main/java/com/newyetai/security/util/UserLoginUtils.java new file mode 100644 index 0000000..cdedddc --- /dev/null +++ b/src/main/java/com/newyetai/security/util/UserLoginUtils.java @@ -0,0 +1,51 @@ +package com.newyetai.security.util; + +import org.springframework.stereotype.Component; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.security.dto.SecurityUserDTO; +import com.newyetai.security.mapstruct.UserMapMapper; +import com.newyetai.security.service.IUserSecurityService; +import com.newyetai.usercenter.user.dto.UserDetailQueryDTO; +import com.newyetai.usercenter.user.login.dto.UserDetailDTO; + +/** + * @author sr on 2020-06-15 + */ +@Component +public class UserLoginUtils { + + public static final String SPRING_SECURITY_FORM_ORG_ID_KEY = "orgId"; + + private static IUserSecurityService userService; + + private UserLoginUtils(IUserSecurityService userService) { + UserLoginUtils.userService = userService; + } + + /** + * 根据登录信息获取登录对象 + * + * @param userCloudService + * @param userService + * @param userDetailQueryDto + * @return + * @author sr on 2020-06-15 + */ + public static SecurityUserDTO loadUserToMock(UserDetailQueryDTO userDetailQueryDto) { + AlitaResult result = null; + result = + userService.findUserDetailDTOResult(userDetailQueryDto); + UserDetailDTO userDetailDTO = result.getData(); + Assert.isTrue(result.getSuccess(), "mock失败:" + result.getMsg()); + return UserMapMapper.INSTANCE.dtoToDto(userDetailDTO); + } + + public static AlitaResult findUserDetailDTOResult( + UserDetailQueryDTO userDetailQueryDto) { + return userService.findUserDetailDTOResult(userDetailQueryDto); + } + + +} diff --git a/src/main/java/com/newyetai/swagger/config/SwaggerConfig.java b/src/main/java/com/newyetai/swagger/config/SwaggerConfig.java new file mode 100644 index 0000000..64dd0f4 --- /dev/null +++ b/src/main/java/com/newyetai/swagger/config/SwaggerConfig.java @@ -0,0 +1,61 @@ +package com.newyetai.swagger.config; + +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.Contact; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +/** + * @author guhong + */ +@Configuration +@EnableSwagger2 +public class SwaggerConfig { + + @Value("${swagger.enable:false}") + private boolean swaggerEnable; + + /** 文档访问前缀 **/ + public static final String ACCESS_PREFIX = + "/swagger-resources/**,/swagger-ui.html**,/webjars/**,/v2/**"; + + public boolean isSwaggerEnable() { + return swaggerEnable; + } + + @Bean + public Docket docket() { + return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()) + // 设置是否开启swagger,生产环境关闭 + .enable(swaggerEnable).select() + // 当前包路径 + .apis(RequestHandlerSelectors.basePackage("com.newyetai")) + .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) + .paths(PathSelectors.any()).build(); + } + + /** + * 构建api文档的详细信息 + * @return + * @author sr on 2019-11-05 + */ + private ApiInfo apiInfo() { + return new ApiInfoBuilder() + // 页面标题 + .title("接口文档") + // 创建人 + .contact(new Contact("雷佳平", "", "")) + // 版本号 + .version("1.0") + // 描述 + .description("接口文档").build(); + } +} diff --git a/src/main/java/com/newyetai/tkmybatis/mybatis/MyMapper.java b/src/main/java/com/newyetai/tkmybatis/mybatis/MyMapper.java new file mode 100644 index 0000000..1543885 --- /dev/null +++ b/src/main/java/com/newyetai/tkmybatis/mybatis/MyMapper.java @@ -0,0 +1,227 @@ +package com.newyetai.tkmybatis.mybatis; + + +import java.util.Collection; +import java.util.Date; + +import org.apache.ibatis.annotations.Param; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.newyetai.common.entity.BaseEntity; +import com.newyetai.common.util.UserContextHolder; + +/** + * + * 定义自己的通用mapper + * + * @author guhong + * @date 2019/8/19 + */ +public interface MyMapper extends /*Mapper, ExistsMapper,*/BaseMapper { + + /** + * 设置新增属性值 + * @param entity + * @param operateUserId + * @author sr on 2019-11-05 + */ + default void setCreateProperty(T entity, Long operateUserId) { + entity.setCreateBy(operateUserId); + entity.setCreateTime(new Date()); + entity.setUpdateBy(null); + entity.setUpdateTime(null); + entity.setDeleted(false); + } + + /** + * 设置修改属性值 + * @param entity + * @param operateUserId + * @author sr on 2019-11-05 + */ + default void setUpdateProperty(T entity, Long operateUserId) { + entity.setUpdateBy(operateUserId); + entity.setUpdateTime(new Date()); + entity.setProxyBy(entity.getProxyBy()); + } + + /** + * 设置删除属性值 + * @param entity + * @param operateUserId + * @author sr on 2019-11-05 + */ + default void setDeleteProperty(T entity, Long operateUserId) { + setUpdateProperty(entity, operateUserId); + entity.setDeleted(true); + } + + + /** + * 新增 + * @param entity + * @param operateUserId 操作人 + * @author sr on 2019-10-12 + */ + default void saveEntity(T entity, Long operateUserId) { + setCreateProperty(entity, operateUserId); + insert(entity); + } + + /** + * 根据主键更新实体,null也会被更新 + * @param entity + * @param operateUserId 操作人 + * @return + * @author sr on 2019-10-12 + */ + default int updateEntity(T entity, Long operateUserId) { + setUpdateProperty(entity, operateUserId); + return alwaysUpdateSomeColumnById(entity); + } + + /** + * 根据主键更新实体,null不会被更新 + * @param entity + * @return + * @author sr on 2019-10-12 + */ + default int updateEntitySelective(T entity) { + return updateEntitySelective(entity, UserContextHolder.getLoginUserId()); + } + + /** + * 根据主键更新实体,null不会被更新 + * @param entity + * @return + * @author sr on 2019-10-12 + */ + default int updateEntitySelective(T entity, Long operateUserId) { + setUpdateProperty(entity, operateUserId); + // 创建人/时间不能修改 + entity.setCreateBy(null); + entity.setCreateTime(null); + return updateById(entity); + } + + + + /** + * 逻辑删除实体(实则根据主键更新实体,null不会更新) + * @param entity + * @param operateUserId + * @return + * @author sr on 2019-10-12 + */ + default int deleteEntity(T entity, Long operateUserId) { + setDeleteProperty(entity, operateUserId); + return updateById(entity); + } + + + /** + * 批量保存 + * @param entitys + * @param operateUserId + * @author sr on 2019-11-05 + */ + default void saveEntites(Collection entitys, Long operateUserId) { + entitys.forEach(entity -> saveEntity(entity, operateUserId)); + } + + /** + * 批量保存 + * @param entitys + * @param operateUserId + * @author sr on 2019-11-05 + */ + default void saveEntites(Collection entitys) { + this.saveEntites(entitys, UserContextHolder.getLoginUserId()); + } + + /** + * 批量修改(根据主键更新实体,null也会被更新) + * @param entitys + * @param operateUserId + * @author sr on 2019-11-05 + */ + default void updateEntites(Collection entitys, Long operateUserId) { + entitys.forEach(entity -> updateEntity(entity, operateUserId)); + } + + /** + * 批量删除(实则根据主键更新实体,null不会更新) + * @param entitys + * @param operateUserId + * @author sr on 2019-11-05 + */ + default void deleteEntites(Collection entitys, Long operateUserId) { + entitys.forEach(entity -> deleteEntity(entity, operateUserId)); + } + + /** + * 批量修改(根据主键更新实体,null不会被更新) + * @param entity + * @return + * @author sr on 2019-10-12 + */ + default void updateEntitysSelective(Collection entitys, Long operateUserId) { + entitys.forEach(entity -> updateEntitySelective(entity, operateUserId)); + } + + /** + * 根据id获取实体 + * @param id + * @return + * @author sr on 2019-11-05 + */ + default T getById(Long id) { + T entity = selectById(id); + return (entity == null || entity.getDeleted()) ? null : entity; + } + + + /** + * 判断是否存在相同属性其他实体(已设置deleted=0) + * @param record + * @return + * @author sr on 2019-12-09 + */ + boolean existsEntity(@Param(Constants.ENTITY)T record); + + + /** + * 新增(context取用户信息) + * @param entity + * @author sr on 2019-10-12 + */ + default void saveEntity(T entity) { + saveEntity(entity, UserContextHolder.getLoginUserId()); + } + + /** + * 根据主键更新实体,null也会被更新(context取用户信息) + * @param entity + * @return + * @author sr on 2019-10-12 + */ + default int updateEntity(T entity) { + return updateEntity(entity, UserContextHolder.getLoginUserId()); + } + + + /** + * 逻辑删除实体(实则根据主键更新实体,null不会更新,context取用户信息) + * @param entity + * @return + * @author sr on 2019-10-12 + */ + default int deleteEntity(T entity) { + return deleteEntity(entity, UserContextHolder.getLoginUserId()); + } + + int alwaysUpdateSomeColumnById(@Param(Constants.ENTITY)T entity); + +} diff --git a/src/main/java/com/newyetai/tkmybatis/pojo/Page.java b/src/main/java/com/newyetai/tkmybatis/pojo/Page.java new file mode 100644 index 0000000..89f1fc0 --- /dev/null +++ b/src/main/java/com/newyetai/tkmybatis/pojo/Page.java @@ -0,0 +1,78 @@ +package com.newyetai.tkmybatis.pojo; + +import com.newyetai.common.dto.IPage; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * 分页 + * + * @author guhong + * @date 2019/8/19 + */ +@Data +@AllArgsConstructor +@Builder +public class Page implements Serializable, IPage { + + /** **/ + private static final long serialVersionUID = -729078966440672920L; + + /** 第几页 **/ + private int pageNo; + /** 页宽 **/ + private int pageSize; + /** 一共的页数 **/ + private int pageCount; + /** 记录条数 **/ + private int totalCount; + /** 查询出来的对象实体 **/ + private List entityList; + + public Page() { + pageSize = 20; + pageNo = 1; + } + + public Page(int pageNo, int pageSize) { + super(); + this.pageNo = pageNo < 1 ? 1 : pageNo; + this.pageSize = pageSize < 1 ? 20 : pageSize; + } + + public void setTotalCount(int totalCount) { + pageCount = (int) Math.ceil((double) totalCount / pageSize); + this.totalCount = totalCount; + } + + public int getFirstEntityIndex() { + return (pageNo - 1) * pageSize; + } + + @Override + public Integer getPageNo() { + return pageNo; + } + + @Override + public Integer getPageSize() { + return pageSize; + } + + @Override + public void setPageResult(int totalCount, List results) { + this.entityList = results; + this.setTotalCount(totalCount); + } + + + @Override + public Boolean getNeedPage() { + return true; + } + +} diff --git a/src/main/java/com/newyetai/usercenter/annex/controller/UserAnnexController.java b/src/main/java/com/newyetai/usercenter/annex/controller/UserAnnexController.java new file mode 100644 index 0000000..b85c492 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/annex/controller/UserAnnexController.java @@ -0,0 +1,111 @@ +package com.newyetai.usercenter.annex.controller; + + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.newyetai.common.AlitaResult; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.annex.dto.UserAnnexCreateDTO; +import com.newyetai.usercenter.annex.dto.UserAnnexDTO; +import com.newyetai.usercenter.annex.dto.UserAnnexOperateDTO; +import com.newyetai.usercenter.annex.dto.UserAnnexPageQueryDTO; +import com.newyetai.usercenter.annex.entity.UserAnnex; +import com.newyetai.usercenter.annex.service.IUserAnnexService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.ibatis.annotations.Param; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +/** + *

+ * 用户附件表 前端控制器 + *

+ * + * @author Carlye + * @since 2021-01-12 + */ +@Api(tags = "用户附件") +@RestController +@RequestMapping("/annex") +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class UserAnnexController { + + private final IUserAnnexService userAnnexService; + + + /** + * 创建 + * + * @param userAnnexCreateDTO 用户附件创建dto + * @return {@link AlitaResult} + */ + @PostMapping("/create") + @ApiOperation("创建用户附件") + public AlitaResult create(@RequestBody UserAnnexCreateDTO userAnnexCreateDTO) { + return AlitaResult.success(userAnnexService.create(userAnnexCreateDTO)); + } + + /** + * 创建 + * + * @param userAnnexCreateDTO 用户附件创建dto + * @return {@link AlitaResult} + */ + @PostMapping("/modify") + @ApiOperation("更新用户附件") + public AlitaResult modify(@RequestBody UserAnnexOperateDTO userAnnexCreateDTO) { + return AlitaResult.success(userAnnexService.modify(userAnnexCreateDTO)); + } + + + /** + * 分页查询 + * + * @param queryDTO 查询dto + * @return {@link AlitaResult>} + */ + @GetMapping("/page") + @ApiOperation("分页查询") + public AlitaResult> page(UserAnnexPageQueryDTO queryDTO) { + userAnnexService.page(queryDTO); + return AlitaResult.success(queryDTO.getPageResult()); + } + + /** + * 查询单个 + * @param userId 用户ID + * @param annexType 附件类别 + * @return + */ + @GetMapping("/get/{userId}/{annexType}") + @ApiOperation("单个查询") + public AlitaResult get(@PathVariable("userId") Long userId, @PathVariable("annexType") Integer annexType) { + UserAnnexPageQueryDTO userAnnexPageQueryDTO = new UserAnnexPageQueryDTO(); + userAnnexPageQueryDTO.setUserId(userId); + userAnnexPageQueryDTO.setAnnexType(annexType); + userAnnexPageQueryDTO.setNeedPage(false); + List list = userAnnexService.page(userAnnexPageQueryDTO); + return AlitaResult.success(CollectionUtils.isEmpty(list)?null:list.get(0)); + } + + /** + * 查询单个 + * @param userId 用户ID + * @param annexType 附件类别 + * @return + */ + @DeleteMapping("/remove/{userId}/{annexType}") + @ApiOperation("删除附件") + public AlitaResult remove(@PathVariable("userId") Long userId, @PathVariable("annexType") Integer annexType) { + return AlitaResult.success(userAnnexService.update(Wrappers.lambdaUpdate() + .eq(UserAnnex::getUserId, userId) + .eq(UserAnnex::getAnnexType, annexType) + .eq(UserAnnex::getDeleted, false) + .set(UserAnnex::getDeleted, true))); + } + +} + diff --git a/src/main/java/com/newyetai/usercenter/annex/dao/UserAnnexDao.java b/src/main/java/com/newyetai/usercenter/annex/dao/UserAnnexDao.java new file mode 100644 index 0000000..aee8a9d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/annex/dao/UserAnnexDao.java @@ -0,0 +1,29 @@ +package com.newyetai.usercenter.annex.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.newyetai.usercenter.annex.dto.UserAnnexDTO; +import com.newyetai.usercenter.annex.dto.UserAnnexPageQueryDTO; +import com.newyetai.usercenter.annex.entity.UserAnnex; + +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 用户附件表 Mapper 接口 + *

+ * + * @author Carlye + * @since 2021-01-12 + */ +public interface UserAnnexDao extends BaseMapper { + + + /** + * 分页查询 + * + * @param userAnnexPageQueryDTO 用户附件页面查询dto + * @return {@link List} + */ + List page(@Param("param") UserAnnexPageQueryDTO userAnnexPageQueryDTO); +} diff --git a/src/main/java/com/newyetai/usercenter/annex/dto/UserAnnexCreateDTO.java b/src/main/java/com/newyetai/usercenter/annex/dto/UserAnnexCreateDTO.java new file mode 100644 index 0000000..6a713cf --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/annex/dto/UserAnnexCreateDTO.java @@ -0,0 +1,48 @@ +package com.newyetai.usercenter.annex.dto; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.common.validate.EnumValidator; +import com.newyetai.usercenter.annex.enums.AnnexTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; +import lombok.experimental.SuperBuilder; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +/** + *

+ * 用户附件实体 + *

+ * + * @author Carlye + * @since 2021-01-12 + */ +@ApiModel("用户附件创建DTO") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +public class UserAnnexCreateDTO extends BaseDTO { + + private static final long serialVersionUID = 6855183230684638997L; + + @ApiModelProperty("机构ID") + private Long orgId; + + @ApiModelProperty("用户ID") + private Long userId; + + @NotNull(message = "附件类型不能为空") + @EnumValidator(value = AnnexTypeEnum.class,message = "附件类型错误") + @ApiModelProperty("附件类型 1:身份证正面 2:身份证反面") + private Integer annexType; + + @NotEmpty(message = "fileCode不能为空") + @ApiModelProperty("附件fileCode") + private String annexFileCode; +} diff --git a/src/main/java/com/newyetai/usercenter/annex/dto/UserAnnexDTO.java b/src/main/java/com/newyetai/usercenter/annex/dto/UserAnnexDTO.java new file mode 100644 index 0000000..fa0ae5c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/annex/dto/UserAnnexDTO.java @@ -0,0 +1,40 @@ +package com.newyetai.usercenter.annex.dto; + +import com.newyetai.common.dto.BaseDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; +import lombok.experimental.SuperBuilder; + +/** + *

+ * 用户附件实体 + *

+ * + * @author Carlye + * @since 2021-01-12 + */ +@ApiModel("用户附件DTO") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +public class UserAnnexDTO extends BaseDTO { + + private static final long serialVersionUID = -1784620895307517063L; + + @ApiModelProperty("机构ID") + private Long orgId; + + @ApiModelProperty("用户ID") + private Long userId; + + @ApiModelProperty("附件类型 1:身份证正面 2:身份证反面") + private Integer annexType; + + @ApiModelProperty("附件fileCode") + private String annexFileCode; +} diff --git a/src/main/java/com/newyetai/usercenter/annex/dto/UserAnnexOperateDTO.java b/src/main/java/com/newyetai/usercenter/annex/dto/UserAnnexOperateDTO.java new file mode 100644 index 0000000..4fd26d7 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/annex/dto/UserAnnexOperateDTO.java @@ -0,0 +1,50 @@ +package com.newyetai.usercenter.annex.dto; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.common.validation.Update; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; +import lombok.experimental.SuperBuilder; + +/** + *

+ * 用户附件实体 + *

+ * + * @author Carlye + * @since 2021-01-12 + */ +@ApiModel("用户附件操作DTO") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +public class UserAnnexOperateDTO extends BaseDTO { + + private static final long serialVersionUID = 6855183230684638997L; + + @ApiModelProperty("机构ID") + private Long orgId; + + @NotNull(message = "用户ID不能为空", groups = {Update.class}) + @ApiModelProperty("用户ID") + private Long userId; + + @NotNull(message = "附件类型不能为空", groups = {Update.class}) + @ApiModelProperty("附件类型 1:身份证正面 2:身份证反面") + private Integer annexType; + + @NotEmpty(message = "fileCode不能为空", groups = {Update.class}) + @ApiModelProperty("附件fileCode") + private String annexFileCode; +} diff --git a/src/main/java/com/newyetai/usercenter/annex/dto/UserAnnexPageQueryDTO.java b/src/main/java/com/newyetai/usercenter/annex/dto/UserAnnexPageQueryDTO.java new file mode 100644 index 0000000..bdac369 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/annex/dto/UserAnnexPageQueryDTO.java @@ -0,0 +1,57 @@ +package com.newyetai.usercenter.annex.dto; + +import com.google.common.collect.Sets; +import com.newyetai.common.dto.PageQueryDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import java.util.Arrays; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +/** + *

+ * 用户附件实体 + *

+ * + * @author Carlye + * @since 2021-01-12 + */ +@ApiModel("用户附件查询DTO") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +public class UserAnnexPageQueryDTO extends PageQueryDTO { + + private static final long serialVersionUID = -1784620895307517063L; + + @ApiModelProperty("机构ID") + private Long orgId; + + @ApiModelProperty("用户ID") + private Long userId; + + @ApiModelProperty("附件类型 1:身份证正面 2:身份证反面") + private Integer annexType; + + @ApiModelProperty("附件fileCode") + private String annexFileCode; + + @ApiModelProperty("附件类型, ','分割") + private String annexTypeStr; + + private Set annexTypes; + + public Set getAnnexTypes() { + return Optional.ofNullable(getAnnexTypeStr()) + .map(str -> Arrays.stream(str.split(",")) + .collect(Collectors.toSet())) + .orElse(Sets.newHashSet()); + } +} diff --git a/src/main/java/com/newyetai/usercenter/annex/entity/UserAnnex.java b/src/main/java/com/newyetai/usercenter/annex/entity/UserAnnex.java new file mode 100644 index 0000000..a8bc308 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/annex/entity/UserAnnex.java @@ -0,0 +1,48 @@ +package com.newyetai.usercenter.annex.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; +import com.newyetai.usercenter.annex.enums.AnnexTypeEnum; +import lombok.*; +import lombok.experimental.Accessors; + +/** + *

+ * 用户附件表 + *

+ * + * @author Carlye + * @since 2021-01-12 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@TableName("xs_user_annex") +public class UserAnnex extends BaseEntity { + + private static final long serialVersionUID = -967369619441044008L; + /** + * 机构ID + */ + private Long orgId; + + /** + * 用户ID + */ + private Long userId; + + /** + * 附件类型 1:身份证正面 2:身份证反面 + */ + private AnnexTypeEnum annexType; + + /** + * 附件fileCode + */ + @TableField("annex_fileCode") + private String annexFileCode; +} diff --git a/src/main/java/com/newyetai/usercenter/annex/enums/AnnexTypeEnum.java b/src/main/java/com/newyetai/usercenter/annex/enums/AnnexTypeEnum.java new file mode 100644 index 0000000..959d9f0 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/annex/enums/AnnexTypeEnum.java @@ -0,0 +1,39 @@ +package com.newyetai.usercenter.annex.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.newyetai.mybatis.handle.BaseEnum; + +/** + * 附件类型的枚举 + * + * @author Carlye + * @date 2021/01/12 + */ +public enum AnnexTypeEnum implements BaseEnum { + IDCARD_FRONT(1, "身份证正面"), + + IDCARD_REVERSE(2, "身份证反面"); + + @EnumValue + private final Integer type; + + private final String desc; + + AnnexTypeEnum(Integer type, String desc) { + this.type = type; + this.desc = desc; + } + + public Integer getType() { + return type; + } + + public String getDesc() { + return desc; + } + + @Override + public Integer getValue() { + return type; + } +} diff --git a/src/main/java/com/newyetai/usercenter/annex/mapper/UserAnnexMapper.xml b/src/main/java/com/newyetai/usercenter/annex/mapper/UserAnnexMapper.xml new file mode 100644 index 0000000..386ee89 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/annex/mapper/UserAnnexMapper.xml @@ -0,0 +1,31 @@ + + + + + + + diff --git a/src/main/java/com/newyetai/usercenter/annex/mapstruct/UserAnnexMapMapper.java b/src/main/java/com/newyetai/usercenter/annex/mapstruct/UserAnnexMapMapper.java new file mode 100644 index 0000000..d35cc2f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/annex/mapstruct/UserAnnexMapMapper.java @@ -0,0 +1,38 @@ +package com.newyetai.usercenter.annex.mapstruct; + +import com.newyetai.common.util.EnumUtil; +import com.newyetai.usercenter.annex.dto.UserAnnexCreateDTO; +import com.newyetai.usercenter.annex.dto.UserAnnexDTO; +import com.newyetai.usercenter.annex.entity.UserAnnex; +import com.newyetai.usercenter.annex.enums.AnnexTypeEnum; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +import javax.validation.Valid; + + +/** + * 用户映射器附件地图 + * + * @author Carlye + * @date 2021/01/12 + */ +@Mapper +public interface UserAnnexMapMapper { + + UserAnnexMapMapper INSTANCE = Mappers.getMapper(UserAnnexMapMapper.class); + + UserAnnex exchange(@Valid UserAnnexCreateDTO userAnnex); + + @Mappings({ + @Mapping(target = "annexType", + source = "annexType.type") + }) + UserAnnexDTO exchange(UserAnnex userAnnex); + + default AnnexTypeEnum cover1(Integer type) { + return EnumUtil.resolve(AnnexTypeEnum::getType, type); + } +} diff --git a/src/main/java/com/newyetai/usercenter/annex/service/IUserAnnexService.java b/src/main/java/com/newyetai/usercenter/annex/service/IUserAnnexService.java new file mode 100644 index 0000000..d757ba4 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/annex/service/IUserAnnexService.java @@ -0,0 +1,49 @@ +package com.newyetai.usercenter.annex.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.newyetai.usercenter.annex.dto.UserAnnexCreateDTO; +import com.newyetai.usercenter.annex.dto.UserAnnexDTO; +import com.newyetai.usercenter.annex.dto.UserAnnexOperateDTO; +import com.newyetai.usercenter.annex.dto.UserAnnexPageQueryDTO; +import com.newyetai.usercenter.annex.entity.UserAnnex; +import org.springframework.validation.annotation.Validated; + +import javax.validation.Valid; +import javax.validation.groups.Default; +import java.util.List; + +/** + *

+ * 用户附件表 服务类 + *

+ * + * @author Carlye + * @since 2021-01-12 + */ +@Validated(Default.class) +public interface IUserAnnexService extends IService { + + /** + * 创建用户附件 + * + * @param userAnnexCreateDTO 用户附件创建dto + * @return {@link UserAnnexDTO} + * @throws RuntimeException 运行时异常 + */ + UserAnnexDTO create(@Valid UserAnnexCreateDTO userAnnexCreateDTO) throws RuntimeException; + + /** + * 用户附件分页查询 + * + * @param userAnnexPageQueryDTO 用户附件页面查询dto + * @return {@link List} + */ + List page(UserAnnexPageQueryDTO userAnnexPageQueryDTO); + + /** + * 修改用户福建 + * @param userAnnexCreateDTO 用户附件操作dto + * @return 是否成功 + */ + Boolean modify(UserAnnexOperateDTO userAnnexCreateDTO); +} diff --git a/src/main/java/com/newyetai/usercenter/annex/service/impl/UserAnnexServiceImpl.java b/src/main/java/com/newyetai/usercenter/annex/service/impl/UserAnnexServiceImpl.java new file mode 100644 index 0000000..06dcbfe --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/annex/service/impl/UserAnnexServiceImpl.java @@ -0,0 +1,87 @@ +package com.newyetai.usercenter.annex.service.impl; + +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.exception.util.ExceptionUtils; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.frame.redis.aop.annotation.AutoUnLock; +import com.newyetai.frame.redis.dto.LockDTO; +import com.newyetai.frame.redis.redisson.RedissonUtils; +import com.newyetai.usercenter.annex.dao.UserAnnexDao; +import com.newyetai.usercenter.annex.dto.UserAnnexCreateDTO; +import com.newyetai.usercenter.annex.dto.UserAnnexDTO; +import com.newyetai.usercenter.annex.dto.UserAnnexOperateDTO; +import com.newyetai.usercenter.annex.dto.UserAnnexPageQueryDTO; +import com.newyetai.usercenter.annex.entity.UserAnnex; +import com.newyetai.usercenter.annex.mapstruct.UserAnnexMapMapper; +import com.newyetai.usercenter.annex.service.IUserAnnexService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.validation.Valid; +import java.util.List; +import java.util.Optional; + + +/** + *

+ * 用户附件表 服务实现类 + *

+ * + * @author Carlye + * @since 2021-01-12 + */ +@Slf4j +@Service +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class UserAnnexServiceImpl extends ServiceImpl implements IUserAnnexService { + + @Override + @AutoUnLock + public UserAnnexDTO create(@Valid UserAnnexCreateDTO userAnnexCreateDTO) throws RuntimeException { + Long userId = Optional.ofNullable(userAnnexCreateDTO.getUserId()).orElse(UserContextHolder.getExistLoginUserId()); + Assert.isTrue(RedissonUtils.tryLockAutomatically(LockDTO.builder().methodName("userAnnexCreate").tryLockWaitTime(0L).arg(userId + "").arg(userAnnexCreateDTO.getAnnexType() + "").build()), + "用户附件正在处理中,请稍后再试哦!"); + userAnnexCreateDTO.setUserId(userId); + List userAnnexes = list(Wrappers.lambdaQuery().eq(UserAnnex::getUserId, userId).eq(UserAnnex::getAnnexType, userAnnexCreateDTO.getAnnexType()).eq(UserAnnex::getDeleted, false)); + if (CollectionUtils.isEmpty(userAnnexes)){ + UserAnnex userAnnex = UserAnnexMapMapper.INSTANCE.exchange(userAnnexCreateDTO); + Assert.isTrue(save(userAnnex), "新建用户附件异常"); + return UserAnnexMapMapper.INSTANCE.exchange(userAnnex); + }else if (userAnnexes.size() == 1){ + UserAnnex userAnnex = userAnnexes.get(0); + Assert.isTrue(update(Wrappers.lambdaUpdate().set(UserAnnex::getAnnexFileCode,userAnnexCreateDTO.getAnnexFileCode()).eq(UserAnnex::getId,userAnnex.getId())),"更新附件异常"); + userAnnex.setAnnexFileCode(userAnnexCreateDTO.getAnnexFileCode()); + return UserAnnexMapMapper.INSTANCE.exchange(userAnnex); + } + throw new RuntimeException("用户附件数据异常"); + } + + @Override + public List page(UserAnnexPageQueryDTO userAnnexPageQueryDTO) { + Long userId = Optional.ofNullable(userAnnexPageQueryDTO.getUserId()).orElse(UserContextHolder.getExistLoginUserId()); + userAnnexPageQueryDTO.setUserId(userId); + return getBaseMapper().page(userAnnexPageQueryDTO); + } + + @Override + public Boolean modify(UserAnnexOperateDTO userAnnexCreateDTO) { + LambdaUpdateWrapper lambdaUpdateWrapper = Wrappers.lambdaUpdate() + .eq(UserAnnex::getUserId, userAnnexCreateDTO.getUserId()) + .eq(UserAnnex::getAnnexType, userAnnexCreateDTO.getAnnexType()) + .eq(UserAnnex::getDeleted, false) + .set(UserAnnex::getAnnexFileCode, userAnnexCreateDTO.getAnnexFileCode()); + if(userAnnexCreateDTO.getOrgId() != null){ + lambdaUpdateWrapper.eq(UserAnnex::getOrgId, userAnnexCreateDTO.getOrgId()); + } + Assert.isTrue(update(lambdaUpdateWrapper), "修改用户附件失败"); + return Boolean.TRUE; + } +} diff --git a/src/main/java/com/newyetai/usercenter/auth/constant/AuthClientConstants.java b/src/main/java/com/newyetai/usercenter/auth/constant/AuthClientConstants.java new file mode 100644 index 0000000..0fbe8f5 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/constant/AuthClientConstants.java @@ -0,0 +1,8 @@ +package com.newyetai.usercenter.auth.constant; + +/** + * @author sr on 2021-05-24 + */ +public interface AuthClientConstants { + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/constant/AuthDetailConstants.java b/src/main/java/com/newyetai/usercenter/auth/constant/AuthDetailConstants.java new file mode 100644 index 0000000..9f66e52 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/constant/AuthDetailConstants.java @@ -0,0 +1,8 @@ +package com.newyetai.usercenter.auth.constant; + +/** + * @author sr on 2021-05-24 + */ +public interface AuthDetailConstants { + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/constant/AuthDetailEntrypointConstants.java b/src/main/java/com/newyetai/usercenter/auth/constant/AuthDetailEntrypointConstants.java new file mode 100644 index 0000000..207cd61 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/constant/AuthDetailEntrypointConstants.java @@ -0,0 +1,19 @@ +package com.newyetai.usercenter.auth.constant; + +/** + * @author sr on 2021-05-24 + */ +public interface AuthDetailEntrypointConstants { + + /** + * 招聘用户状态 1未报名 2已报名 3已邀约 4已面试 5待入职 6在职中 7已离职 + */ + Integer USER_JOB_STATUS_NOT_REGISTERED = 1; + Integer USER_JOB_STATUS_ALREADY_REGISTERED = 2; + Integer USER_JOB_STATUS_INVITED = 3; + Integer USER_JOB_STATUS_INTERVIEWED = 4; + Integer USER_JOB_STATUS_TO_BE_HIRED = 5; + Integer USER_JOB_STATUS_ON_THE_JOB = 6; + Integer USER_JOB_STATUS_RESIGNED = 7; + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/constant/AuthMainTypeEnum.java b/src/main/java/com/newyetai/usercenter/auth/constant/AuthMainTypeEnum.java new file mode 100644 index 0000000..e5c07a6 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/constant/AuthMainTypeEnum.java @@ -0,0 +1,40 @@ +package com.newyetai.usercenter.auth.constant; + +import java.util.Map; + +import com.google.common.collect.Maps; + +public enum AuthMainTypeEnum { + + /** 微信 **/ + WECHAT(1), + /** 支付宝 **/ + ALIPAY(2), + /** 字节 **/ + BYTE_DANCE(3), + /** 随申办 **/ + SSB(4), + ; + + private Integer type; + + private static Map typeMap = Maps.newHashMap(); + static { + for(AuthMainTypeEnum authTypeEnum : AuthMainTypeEnum.values()) { + typeMap.put(authTypeEnum.getType(), authTypeEnum); + } + } + + AuthMainTypeEnum(Integer type) { + this.type = type; + } + + public Integer getType() { + return type; + } + + public static AuthMainTypeEnum getByCode(Integer type) { + return typeMap.get(type); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/constant/AuthTypeEnum.java b/src/main/java/com/newyetai/usercenter/auth/constant/AuthTypeEnum.java new file mode 100644 index 0000000..11cd714 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/constant/AuthTypeEnum.java @@ -0,0 +1,55 @@ +package com.newyetai.usercenter.auth.constant; + +import java.util.Map; + +import com.google.common.collect.Maps; + +public enum AuthTypeEnum { + + /** 微信公众号 **/ + WECHAT(11, AuthMainTypeEnum.WECHAT.getType()), + /** 微信小程序 **/ + WECHAT_LITE(12, AuthMainTypeEnum.WECHAT.getType()), + /** 支付宝 **/ + ALIPAY(21, AuthMainTypeEnum.ALIPAY.getType()), + /** 支付宝小程序 **/ + ALIPAY_LITE(22, AuthMainTypeEnum.ALIPAY.getType()), + /** 字节跳动小程序 **/ + BYTE_DANCE_LITE(32, AuthMainTypeEnum.BYTE_DANCE.getType()), + /** 随申办app **/ + SSB_APP(41, AuthMainTypeEnum.SSB.getType()), + ; + + private Integer code; + + private Integer mainCode; + + private static Map AuthTypeMap = Maps.newHashMap(); + static { + for(AuthTypeEnum authTypeEnum : AuthTypeEnum.values()) { + AuthTypeMap.put(authTypeEnum.getCode(), authTypeEnum); + } + } + + AuthTypeEnum(Integer code, Integer mainCode) { + this.code = code; + this.mainCode = mainCode; + } + + public Integer getCode() { + return code; + } + + public Integer getMainCode() { + return mainCode; + } + + public static AuthTypeEnum getByCode(Integer code) { + return AuthTypeMap.get(code); + } + + public static Integer getAuthMainType(Integer code) { + return AuthTypeMap.get(code).getMainCode(); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/constant/LiteCodeConfigEnum.java b/src/main/java/com/newyetai/usercenter/auth/constant/LiteCodeConfigEnum.java new file mode 100644 index 0000000..a07cf7f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/constant/LiteCodeConfigEnum.java @@ -0,0 +1,30 @@ +package com.newyetai.usercenter.auth.constant; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.newyetai.mybatis.handle.BaseEnum; + +/** + * @description: + * @author: guixinman + * @create: 2023-04-07 11:47 + **/ +public enum LiteCodeConfigEnum { + + /**首页**/ + HOME(1), + /**岗位明细**/ + POSITION_DETAIL(2), + /**新招聘**/ + RECRUITNEW(3); + + private Integer type; + + LiteCodeConfigEnum(Integer type) { + this.type = type; + } + + public Integer getType() { + return type; + } + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/constant/LiteCodeConstant.java b/src/main/java/com/newyetai/usercenter/auth/constant/LiteCodeConstant.java new file mode 100644 index 0000000..bdfa7e2 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/constant/LiteCodeConstant.java @@ -0,0 +1,15 @@ +package com.newyetai.usercenter.auth.constant; + +/** + * 二维码 常量 + * + * @author Carlye + * @date 2022/03/29 + */ +public interface LiteCodeConstant { + + /** + * 来源 (PC端) + */ + Integer SOURCE_FROM_PC = 1; +} diff --git a/src/main/java/com/newyetai/usercenter/auth/controller/AuthClientController.java b/src/main/java/com/newyetai/usercenter/auth/controller/AuthClientController.java new file mode 100644 index 0000000..5589967 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/controller/AuthClientController.java @@ -0,0 +1,83 @@ +package com.newyetai.usercenter.auth.controller; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.dto.CasTokenDTO; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.auth.dto.AuthClientDTO; +import com.newyetai.usercenter.auth.dto.AuthClientOperateDTO; +import com.newyetai.usercenter.auth.dto.AuthClientQueryDTO; +import com.newyetai.usercenter.auth.dto.LitePhoneAuthDTO; +import com.newyetai.usercenter.auth.dto.LitePhoneLoginDTO; +import com.newyetai.usercenter.auth.service.AuthClientService; +import com.newyetai.usercenter.auth.service.impl.LitePhoneLoginProvider; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * @author sr on 2021-05-24 + */ +@RestController +@Api(tags = "授权客户端") +public class AuthClientController { + + @Autowired + private AuthClientService authClientService; + + @Autowired + private LitePhoneLoginProvider litePhoneLoginProvider; + + @PostMapping("auth_client/create") + @ApiOperation("创建") + public AlitaResult create(@RequestBody AuthClientOperateDTO authClientOperateDTO) { + return AlitaResult.success(authClientService.create(authClientOperateDTO)); + } + + @PutMapping("auth_client/modify") + @ApiOperation("修改") + public AlitaResult modify(@RequestBody AuthClientOperateDTO authClientOperateDTO) { + authClientService.modify(authClientOperateDTO); + return AlitaResult.success(true); + } + + @DeleteMapping("auth_client/remove/{id}") + @ApiOperation("删除") + public AlitaResult remove(@PathVariable Long id) { + authClientService.remove(id); + return AlitaResult.success(true); + } + + @GetMapping("auth_client/page") + @ApiOperation("分页查询") + public AlitaResult> page(AuthClientQueryDTO authClientQueryDTO) { + authClientService.page(authClientQueryDTO); + return AlitaResult.success(authClientQueryDTO.getPageResult()); + } + + + @ApiOperation("获取访问token") + @PostMapping("anon/auth_client/access_token") + public AlitaResult getAccessToken(@RequestBody AuthClientQueryDTO authClientQueryDTO) { + return AlitaResult.success(authClientService.getAccessToken(authClientQueryDTO)); + } + + @ApiOperation("获取ticket") + @PostMapping("anon/auth_client/ticket") + public AlitaResult getJsApiTicket(@RequestBody AuthClientQueryDTO authClientQueryDTO) { + return AlitaResult.success(authClientService.getJsApiTicket(authClientQueryDTO)); + } + + @ApiOperation("小程序登录(手机号)") + @PostMapping("anon/auth_client/login_lite") + public AlitaResult loginLite(@Validated @RequestBody LitePhoneLoginDTO loginPhoneLoginDTO) { + return AlitaResult.success(litePhoneLoginProvider.loginLite(loginPhoneLoginDTO)); + } + + @ApiOperation("获取小程序授权手机号") + @PostMapping("anon/auth_client/get_phone") + public AlitaResult getPhone(@Validated @RequestBody LitePhoneAuthDTO litePhoneAuthDTO) { + return AlitaResult.success(authClientService.getPhone(litePhoneAuthDTO)); + } +} diff --git a/src/main/java/com/newyetai/usercenter/auth/controller/AuthDetailController.java b/src/main/java/com/newyetai/usercenter/auth/controller/AuthDetailController.java new file mode 100644 index 0000000..204881f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/controller/AuthDetailController.java @@ -0,0 +1,44 @@ +package com.newyetai.usercenter.auth.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.newyetai.common.AlitaResult; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.auth.dto.AuthDetailDTO; +import com.newyetai.usercenter.auth.dto.AuthDetailQueryDTO; +import com.newyetai.usercenter.auth.service.AuthDetailService; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +/** + * @author sr on 2021-05-24 + */ +@RestController +@RequestMapping("auth_detail") +@Api(tags = "授权明细") +public class AuthDetailController { + + @Autowired + private AuthDetailService authDetailService; + + @DeleteMapping("/remove/{id}") + @ApiOperation("删除") + public AlitaResult remove(@PathVariable Long id){ + authDetailService.remove(id); + return AlitaResult.success(true); + } + + @GetMapping("/page") + @ApiOperation("分页查询") + public AlitaResult> page(AuthDetailQueryDTO authDetailQueryDTO){ + authDetailService.list(authDetailQueryDTO); + return AlitaResult.success(authDetailQueryDTO.getPageResult()); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/controller/AuthDetailEntrypointController.java b/src/main/java/com/newyetai/usercenter/auth/controller/AuthDetailEntrypointController.java new file mode 100644 index 0000000..7128d2d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/controller/AuthDetailEntrypointController.java @@ -0,0 +1,95 @@ +package com.newyetai.usercenter.auth.controller; + +import com.newyetai.common.AlitaResult; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.auth.dto.*; +import com.newyetai.usercenter.auth.service.AuthDetailEntrypointService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @author sr on 2022-01-06 + */ +@RestController +@Api(tags = "授权明细入口") +public class AuthDetailEntrypointController { + + @Autowired + private AuthDetailEntrypointService authDetailEntrypointService; + + @PostMapping("anon/auth_detail_entrypoint/create") + @ApiOperation("创建") + public AlitaResult create( + @Validated @RequestBody AuthCodeDTO authCodeDTO){ + return AlitaResult.success(authDetailEntrypointService.create(authCodeDTO)); + } + + @DeleteMapping("auth_detail_entrypoint/remove/{id}") + @ApiOperation("删除") + public AlitaResult remove(@PathVariable Long id){ + authDetailEntrypointService.remove(id); + return AlitaResult.success(true); + } + + @GetMapping("auth_detail_entrypoint/page") + @ApiOperation("分页查询") + public AlitaResult> page(AuthDetailEntrypointQueryDTO authDetailEntrypointQueryDTO){ + authDetailEntrypointService.page(authDetailEntrypointQueryDTO); + return AlitaResult.success(authDetailEntrypointQueryDTO.getPageResult()); + } + + @GetMapping("auth_detail_entrypoint/invite_info_page") + @ApiOperation("分页查询邀请信息") + public AlitaResult> inviteInfoPage(InviteInfoPageQueryDTO queryDTO){ + authDetailEntrypointService.inviteInfoPage(queryDTO); + return AlitaResult.success(queryDTO.getPageResult()); + } + @GetMapping("auth_detail_entrypoint/invite_info_statistic") + @ApiOperation("查询邀请信息-统计") + public AlitaResult inviteInfoStatistic(InviteInfoPageQueryDTO queryDTO){ + return AlitaResult.success(authDetailEntrypointService.inviteInfoStatistic(queryDTO)); + } + + @GetMapping("auth_detail_entrypoint/invite_info_detail/{entrypointId}") + @ApiOperation("查询邀请信息详情") + public AlitaResult inviteInfoDetail(@PathVariable("entrypointId") Long entrypointId){ + InviteInfoPageQueryDTO queryDTO = InviteInfoPageQueryDTO.builder().entrypointId(entrypointId).build(); + List inviteInfoDTOS = authDetailEntrypointService.inviteInfoPage(queryDTO); + if (CollectionUtils.isNotEmpty(inviteInfoDTOS)){ + return AlitaResult.success(inviteInfoDTOS.get(0)); + } + return AlitaResult.success(null); + } + + @GetMapping("auth_detail_entrypoint/pc_invite_info_page") + @ApiOperation("pc端分页查询邀请信息") + public AlitaResult> pcInviteInfoPage(PcInviteInfoPageQueryDTO queryDTO){ + authDetailEntrypointService.pcInviteInfoPage(queryDTO); + return AlitaResult.success(queryDTO.getPageResult()); + } + + @GetMapping("auth_detail_entrypoint/pc_invite_info_detail/{userId}") + @ApiOperation("单个邀请信息明细") + public AlitaResult getInviteInfoDetail(@PathVariable("userId") Long userId){ + return AlitaResult.success( + authDetailEntrypointService.getInviteInfoDetail(PcInviteInfoPageQueryDTO.builder().userId(userId).build())); + } + + @GetMapping("auth_detail_entrypoint/pc_invite_statistic") + @ApiOperation("邀请统计信息(pc)") + public AlitaResult pcInviteStatisticQuery(InviteStatisticQueryDTO queryDTO){ + return AlitaResult.success(authDetailEntrypointService.pcInviteStatisticQuery(queryDTO)); + } + + @GetMapping("auth_detail_entrypoint/invite_statistic") + @ApiOperation("邀请统计信息") + public AlitaResult inviteStatisticQuery(InviteStatisticQueryDTO queryDTO){ + return AlitaResult.success(authDetailEntrypointService.inviteStatisticQuery(queryDTO)); + } +} diff --git a/src/main/java/com/newyetai/usercenter/auth/controller/AuthSubscribeDetailController.java b/src/main/java/com/newyetai/usercenter/auth/controller/AuthSubscribeDetailController.java new file mode 100644 index 0000000..415b6cc --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/controller/AuthSubscribeDetailController.java @@ -0,0 +1,44 @@ +package com.newyetai.usercenter.auth.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.newyetai.common.AlitaResult; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.auth.dto.AuthSubscribeDetailDTO; +import com.newyetai.usercenter.auth.dto.AuthSubscribeDetailQueryDTO; +import com.newyetai.usercenter.auth.service.AuthSubscribeDetailService; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +/** + * @author sr on 2022-04-05 + */ +@RestController +@RequestMapping("auth_subscribe_detail") +@Api(tags = "授权订阅明细") +public class AuthSubscribeDetailController { + + @Autowired + private AuthSubscribeDetailService authSubscribeDetailService; + + @DeleteMapping("/remove/{id}") + @ApiOperation("删除") + public AlitaResult remove(@PathVariable Long id){ + authSubscribeDetailService.remove(id); + return AlitaResult.success(true); + } + + @GetMapping("/page") + @ApiOperation("分页查询") + public AlitaResult> page(AuthSubscribeDetailQueryDTO authSubscribeDetailQueryDTO){ + authSubscribeDetailService.page(authSubscribeDetailQueryDTO); + return AlitaResult.success(authSubscribeDetailQueryDTO.getPageResult()); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/controller/AuthTypeController.java b/src/main/java/com/newyetai/usercenter/auth/controller/AuthTypeController.java new file mode 100644 index 0000000..cc7fe65 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/controller/AuthTypeController.java @@ -0,0 +1,38 @@ +package com.newyetai.usercenter.auth.controller; + +import com.newyetai.common.AlitaResult; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.auth.dto.AuthTypeDTO; +import com.newyetai.usercenter.auth.dto.AuthTypeOperateDTO; +import com.newyetai.usercenter.auth.dto.AuthTypeQueryDTO; +import com.newyetai.usercenter.auth.service.AuthTypeService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +/** + * @author sr on 2021-05-24 + */ +@RestController +@RequestMapping("auth_type") +@Api(tags = "授权客户端类型") +public class AuthTypeController { + + @Autowired + private AuthTypeService authTypeService; + + @PostMapping("/create") + @ApiOperation("创建") + public AlitaResult create(@RequestBody AuthTypeOperateDTO typeOperateDTO) { + return AlitaResult.success(authTypeService.create(typeOperateDTO)); + } + + @GetMapping("/page") + @ApiOperation("分页查询") + public AlitaResult> page(AuthTypeQueryDTO queryDTO) { + authTypeService.list(queryDTO); + return AlitaResult.success(queryDTO.getPageResult()); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/controller/LiteCodeConfigController.java b/src/main/java/com/newyetai/usercenter/auth/controller/LiteCodeConfigController.java new file mode 100644 index 0000000..627ca05 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/controller/LiteCodeConfigController.java @@ -0,0 +1,66 @@ +package com.newyetai.usercenter.auth.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.validation.annotation.Validated; + +import com.newyetai.common.validation.Update; +import com.newyetai.common.AlitaResult; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.auth.dto.LiteCodeConfigQueryDTO; +import com.newyetai.usercenter.auth.service.LiteCodeConfigService; +import com.newyetai.usercenter.auth.dto.LiteCodeConfigDTO; +import com.newyetai.usercenter.auth.dto.LiteCodeConfigOperateDTO; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +/** + * @author sr on 2021-12-21 + */ +@RestController +@RequestMapping("lite_code_config") +@Api(tags = "小程序码配置") +public class LiteCodeConfigController { + + @Autowired + private LiteCodeConfigService liteCodeConfigService; + + @PostMapping("/create") + @ApiOperation("创建") + public AlitaResult create( + @Validated @RequestBody LiteCodeConfigOperateDTO liteCodeConfigOperateDTO){ + return AlitaResult.success(liteCodeConfigService.create(liteCodeConfigOperateDTO)); + } + + @PutMapping("/modify") + @ApiOperation("修改") + public AlitaResult modify( + @Validated(Update.class) @RequestBody LiteCodeConfigOperateDTO liteCodeConfigOperateDTO){ + liteCodeConfigService.modify(liteCodeConfigOperateDTO); + return AlitaResult.success(true); + } + + @DeleteMapping("/remove/{id}") + @ApiOperation("删除") + public AlitaResult remove(@PathVariable Long id){ + liteCodeConfigService.remove(id); + return AlitaResult.success(true); + } + + @GetMapping("/page") + @ApiOperation("分页查询") + public AlitaResult> page(LiteCodeConfigQueryDTO liteCodeConfigQueryDTO){ + liteCodeConfigService.list(liteCodeConfigQueryDTO); + return AlitaResult.success(liteCodeConfigQueryDTO.getPageResult()); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/controller/LiteCodeController.java b/src/main/java/com/newyetai/usercenter/auth/controller/LiteCodeController.java new file mode 100644 index 0000000..d88d3b5 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/controller/LiteCodeController.java @@ -0,0 +1,51 @@ +package com.newyetai.usercenter.auth.controller; + +import com.newyetai.usercenter.auth.dto.LiteCodeModifyDTO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import com.newyetai.common.AlitaResult; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.auth.dto.LiteCodeCreateDTO; +import com.newyetai.usercenter.auth.dto.LiteCodeDTO; +import com.newyetai.usercenter.auth.dto.LiteCodeQueryDTO; +import com.newyetai.usercenter.auth.service.LiteCodeService; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +/** + * @author sr on 2021-12-21 + */ +@RestController +@RequestMapping("lite_code") +@Api(tags = "小程序码") +public class LiteCodeController { + + @Autowired + private LiteCodeService liteCodeService; + + @PostMapping("/create") + @ApiOperation("创建") + public AlitaResult create( + @Validated @RequestBody LiteCodeCreateDTO liteCodeCreateDTO){ + return AlitaResult.success(liteCodeService.create(liteCodeCreateDTO)); + } + + @PutMapping("/modify") + @ApiOperation("修改") + public AlitaResult modify( + @Validated @RequestBody LiteCodeModifyDTO liteCodeModifyDTO){ + return AlitaResult.success(liteCodeService.modify(liteCodeModifyDTO)); + } + + @GetMapping("/page") + @ApiOperation("分页查询") + public AlitaResult> page(LiteCodeQueryDTO liteCodeQueryDTO){ + liteCodeService.page(liteCodeQueryDTO); + return AlitaResult.success(liteCodeQueryDTO.getPageResult()); + } + + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/dao/AuthClientMapper.java b/src/main/java/com/newyetai/usercenter/auth/dao/AuthClientMapper.java new file mode 100644 index 0000000..8f12162 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dao/AuthClientMapper.java @@ -0,0 +1,29 @@ +package com.newyetai.usercenter.auth.dao; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.usercenter.auth.dto.AuthClientDTO; +import com.newyetai.usercenter.auth.dto.AuthClientQueryDTO; +import com.newyetai.usercenter.auth.entity.AuthClient; + +/** + * 授权客户端 + * + * @author sr on 2021-05-24 + */ +public interface AuthClientMapper extends MyMapper { + + /** + * 查询 + * + * @param authClientQueryDTO + * @return + * @author sr on 2021-05-24 + */ + List listAuthClientDTO(@Param("param") AuthClientQueryDTO authClientQueryDTO); + + List list(@Param("param") AuthClientQueryDTO authClientQueryDTO); +} diff --git a/src/main/java/com/newyetai/usercenter/auth/dao/AuthDetailEntrypointMapper.java b/src/main/java/com/newyetai/usercenter/auth/dao/AuthDetailEntrypointMapper.java new file mode 100644 index 0000000..3f7d137 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dao/AuthDetailEntrypointMapper.java @@ -0,0 +1,58 @@ +package com.newyetai.usercenter.auth.dao; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.usercenter.auth.dto.*; +import com.newyetai.usercenter.auth.entity.AuthDetailEntrypoint; +import org.apache.ibatis.annotations.Param; + +import java.util.List; +import java.util.Set; + +/** + * 授权明细入口 + * + * @author sr on 2022-01-06 + */ +public interface AuthDetailEntrypointMapper extends MyMapper { + + /** + * 查询 + * + * @param authDetailEntrypointQueryDTO + * @return + * @author sr on 2022-01-06 + */ + List listAuthDetailEntrypointDTO(@Param("param") AuthDetailEntrypointQueryDTO authDetailEntrypointQueryDTO); + + /** + * 邀请信息 + * + * @param queryDTO 查询dto + * @param existLoginUserId 存在登录用户id + * @param existLoginOrgId 存在登录org id + * @return {@link List}<{@link InviteInfoDTO}> + */ + List inviteInfoPage(@Param("param") InviteInfoPageQueryDTO queryDTO, @Param("userId") Long existLoginUserId,@Param("orgId") Long existLoginOrgId); + /** + * PC端机构下所有的 邀请信息 + * + * @param queryDTO 查询dto + */ + List pcInviteInfoPage(@Param("param") PcInviteInfoPageQueryDTO queryDTO,@Param("orgId") Long existLoginOrgId); + + + List inviteStatisticQuery(@Param("param") InviteStatisticQueryDTO queryDTO, @Param("orgId") Long existLoginOrgId); + + /** + * 邀请数统计查询 + * + * @param queryDTO 查询dto + * @param existLoginOrgId 存在登录org id + * @return int + */ + int countInviteStatisticQuery(@Param("param") InviteStatisticQueryDTO queryDTO, @Param("orgId") Long existLoginOrgId); + + int inviteRegisterCount(@Param("param") InviteStatisticQueryDTO queryDTO, @Param("orgId") Long existLoginOrgId); + + List registrationList(@Param("userIds") Set userIds); +} diff --git a/src/main/java/com/newyetai/usercenter/auth/dao/AuthDetailMapper.java b/src/main/java/com/newyetai/usercenter/auth/dao/AuthDetailMapper.java new file mode 100644 index 0000000..98ddf3f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dao/AuthDetailMapper.java @@ -0,0 +1,28 @@ +package com.newyetai.usercenter.auth.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.usercenter.auth.dto.AuthDetailDTO; +import com.newyetai.usercenter.auth.dto.AuthDetailQueryDTO; +import com.newyetai.usercenter.auth.entity.AuthDetail; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 授权明细 + * + * @author sr on 2021-05-24 + */ +public interface AuthDetailMapper extends MyMapper { + + /** + * 查询 + * + * @param authDetailQueryDTO + * @return + * @author sr on 2021-05-24 + */ + List listAuthDetailDTO(@Param("param") AuthDetailQueryDTO authDetailQueryDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/dao/AuthSubscribeDetailMapper.java b/src/main/java/com/newyetai/usercenter/auth/dao/AuthSubscribeDetailMapper.java new file mode 100644 index 0000000..adb0194 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dao/AuthSubscribeDetailMapper.java @@ -0,0 +1,28 @@ +package com.newyetai.usercenter.auth.dao; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.newyetai.usercenter.auth.dto.AuthSubscribeDetailDTO; +import com.newyetai.usercenter.auth.dto.AuthSubscribeDetailQueryDTO; +import com.newyetai.usercenter.auth.entity.AuthSubscribeDetail; +import com.newyetai.tkmybatis.mybatis.MyMapper; + +/** + * 授权订阅明细 + * + * @author sr on 2022-04-05 + */ +public interface AuthSubscribeDetailMapper extends MyMapper { + + /** + * 查询 + * + * @param authSubscribeDetailQueryDTO + * @return + * @author sr on 2022-04-05 + */ + List listAuthSubscribeDetailDTO(@Param("param") AuthSubscribeDetailQueryDTO authSubscribeDetailQueryDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/dao/AuthTypeMapper.java b/src/main/java/com/newyetai/usercenter/auth/dao/AuthTypeMapper.java new file mode 100644 index 0000000..7ebd58c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dao/AuthTypeMapper.java @@ -0,0 +1,19 @@ +package com.newyetai.usercenter.auth.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.newyetai.usercenter.auth.dto.AuthTypeDTO; +import com.newyetai.usercenter.auth.dto.AuthTypeQueryDTO; +import com.newyetai.usercenter.auth.entity.AuthType; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 授权客户端 + * + * @author sr on 2021-05-24 + */ +public interface AuthTypeMapper extends BaseMapper { + + List list(@Param("param") AuthTypeQueryDTO queryDTO); +} diff --git a/src/main/java/com/newyetai/usercenter/auth/dao/LiteCodeConfigMapper.java b/src/main/java/com/newyetai/usercenter/auth/dao/LiteCodeConfigMapper.java new file mode 100644 index 0000000..10c6857 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dao/LiteCodeConfigMapper.java @@ -0,0 +1,28 @@ +package com.newyetai.usercenter.auth.dao; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.newyetai.usercenter.auth.dto.LiteCodeConfigDTO; +import com.newyetai.usercenter.auth.dto.LiteCodeConfigQueryDTO; +import com.newyetai.usercenter.auth.entity.LiteCodeConfig; +import com.newyetai.tkmybatis.mybatis.MyMapper; + +/** + * 小程序码配置 + * + * @author sr on 2021-12-21 + */ +public interface LiteCodeConfigMapper extends MyMapper { + + /** + * 查询 + * + * @param liteCodeConfigQueryDTO + * @return + * @author sr on 2021-12-21 + */ + List listLiteCodeConfigDTO(@Param("param") LiteCodeConfigQueryDTO liteCodeConfigQueryDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/dao/LiteCodeMapper.java b/src/main/java/com/newyetai/usercenter/auth/dao/LiteCodeMapper.java new file mode 100644 index 0000000..c6f53b2 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dao/LiteCodeMapper.java @@ -0,0 +1,28 @@ +package com.newyetai.usercenter.auth.dao; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.newyetai.usercenter.auth.dto.LiteCodeDTO; +import com.newyetai.usercenter.auth.dto.LiteCodeQueryDTO; +import com.newyetai.usercenter.auth.entity.LiteCode; +import com.newyetai.tkmybatis.mybatis.MyMapper; + +/** + * 小程序码 + * + * @author sr on 2021-12-21 + */ +public interface LiteCodeMapper extends MyMapper { + + /** + * 查询 + * + * @param liteCodeQueryDTO + * @return + * @author sr on 2021-12-21 + */ + List listLiteCodeDTO(@Param("param") LiteCodeQueryDTO liteCodeQueryDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/AuthClientDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/AuthClientDTO.java new file mode 100644 index 0000000..76d00fc --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/AuthClientDTO.java @@ -0,0 +1,39 @@ +package com.newyetai.usercenter.auth.dto; + +import com.newyetai.common.dto.BaseDTO; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2021-05-24 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@ApiModel(description = "授权客户端") +public class AuthClientDTO extends BaseDTO { + + /** **/ + private static final long serialVersionUID = 1L; + /** + * 授权类型名称 + */ + private String authTypeName; + /** + * 客户端名称 + */ + private String clientName; + /** 授权类型标识 */ + private Integer authTypeCode ; + /** 配置数据 */ + private String paramData ; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/AuthClientDataDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/AuthClientDataDTO.java new file mode 100644 index 0000000..e07c251 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/AuthClientDataDTO.java @@ -0,0 +1,32 @@ +package com.newyetai.usercenter.auth.dto; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "授权客户端配置数据信息") +public class AuthClientDataDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 285993673369713207L; + + @ApiModelProperty("授权客户端id") + private Long authClientId; + + @ApiModelProperty("授权类型标识") + private Integer authTypeCode ; + + @ApiModelProperty("第三方id") + private String clientId; + + @ApiModelProperty("第三方密钥") + private String clientSecret; + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/AuthClientOperateDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/AuthClientOperateDTO.java new file mode 100644 index 0000000..6b5f4dd --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/AuthClientOperateDTO.java @@ -0,0 +1,40 @@ +package com.newyetai.usercenter.auth.dto; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.SuperBuilder; + +import javax.validation.constraints.NotNull; + +/** + * @author sr on 2021-05-24 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +@ApiModel(description = "授权客户端操作") +public class AuthClientOperateDTO extends BaseDTO { + + /** + * + **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("授权类型标识") + @NotNull(message = "授权类型标识不能为空", groups = {Create.class, Update.class}) + private Integer authTypeCode; + @ApiModelProperty("授权应用名称") + @NotNull(message = "授权应用名称不能为空", groups = {Create.class, Update.class}) + private String clientName; + @ApiModelProperty("授权应用配置") + @NotNull(message = "授权应用配置不能为空", groups = {Create.class, Update.class}) + private String paramData; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/AuthClientQueryDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/AuthClientQueryDTO.java new file mode 100644 index 0000000..fd551ae --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/AuthClientQueryDTO.java @@ -0,0 +1,34 @@ +package com.newyetai.usercenter.auth.dto; + +import java.io.Serializable; + +import com.newyetai.common.dto.PageQueryDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2021-05-24 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "授权客户端查询条件") +public class AuthClientQueryDTO extends PageQueryDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + @ApiModelProperty("域名或ip") + private String domainOrIp; + @ApiModelProperty("授权类型标识") + private Integer authTypeCode ; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/AuthCodeDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/AuthCodeDTO.java new file mode 100644 index 0000000..5fc700a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/AuthCodeDTO.java @@ -0,0 +1,38 @@ +package com.newyetai.usercenter.auth.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2022-01-06 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "授权码信息") +public class AuthCodeDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 5013108110519909949L; + + @ApiModelProperty("授权类型标识") + @NotNull(message = "授权类型标识不能为空") + private Integer authTypeCode; + @ApiModelProperty("小程序授权码") + @NotBlank(message = "小程序授权码不能为空") + private String code; + @ApiModelProperty("请求域名或ip") + private String domainOrIp; + @ApiModelProperty("注册邀请码") + private String registerCode; + + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/AuthDetailBindDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/AuthDetailBindDTO.java new file mode 100644 index 0000000..d12c2ae --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/AuthDetailBindDTO.java @@ -0,0 +1,35 @@ +package com.newyetai.usercenter.auth.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotNull; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2021-05-24 + */ +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +@Data +@ApiModel(description = "授权明细(绑定)") +public class AuthDetailBindDTO extends AuthDetailCreateDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("用户类型") + @NotNull(message = "用户类型不能为空") + private Integer userType; + @ApiModelProperty("用户id") + @NotNull(message = "用户id不能为空") + private Long userId; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/AuthDetailCreateDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/AuthDetailCreateDTO.java new file mode 100644 index 0000000..3648962 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/AuthDetailCreateDTO.java @@ -0,0 +1,54 @@ +package com.newyetai.usercenter.auth.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2021-05-24 + */ +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +@Data +@ApiModel(description = "授权明细创建") +public class AuthDetailCreateDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @NotNull(message = "授权客户端id不能为空") + @ApiModelProperty("授权客户端id") + private Long authClientId ; + @NotNull(message = "授权类型不能为空") + @ApiModelProperty("授权类型标识") + private Integer authTypeCode ; + @ApiModelProperty("昵称") + private String nickname ; + @ApiModelProperty("头像") + private String avatar ; + @ApiModelProperty("性别") + private String gender ; + @ApiModelProperty("国家") + private String country ; + @ApiModelProperty("省份") + private String province ; + @ApiModelProperty("城市") + private String city ; + @ApiModelProperty("open_id") + private String openId ; + @NotBlank(message = "授权唯一id不能为空") + @ApiModelProperty("授权唯一id") + private String uniqueId ; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/AuthDetailDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/AuthDetailDTO.java new file mode 100644 index 0000000..048147b --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/AuthDetailDTO.java @@ -0,0 +1,50 @@ +package com.newyetai.usercenter.auth.dto; + +import com.newyetai.common.dto.BaseDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.SuperBuilder; + +import java.util.Date; + +/** + * @author sr on 2021-05-24 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@ApiModel(description = "授权明细") +public class AuthDetailDTO extends BaseDTO { + + private static final long serialVersionUID = -6031622340021565040L; + @ApiModelProperty("授权客户端id") + private Long authClientId; + @ApiModelProperty("授权应用名称") + private String authClientName; + @ApiModelProperty("授权类型标识") + private Integer authTypeCode; + @ApiModelProperty("授权类型名称") + private String authTypeName; + @ApiModelProperty("昵称") + private String nickname; + @ApiModelProperty("头像") + private String avatar; + @ApiModelProperty("性别") + private String gender; + @ApiModelProperty("国家") + private String country; + @ApiModelProperty("省份") + private String province; + @ApiModelProperty("城市") + private String city; + @ApiModelProperty("open_id") + private String openId; + @ApiModelProperty("授权唯一id") + private String uniqueId; + @ApiModelProperty("创建时间") + private Date createTime; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/AuthDetailEntrypointCreateDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/AuthDetailEntrypointCreateDTO.java new file mode 100644 index 0000000..f4f7570 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/AuthDetailEntrypointCreateDTO.java @@ -0,0 +1,39 @@ +package com.newyetai.usercenter.auth.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotBlank; + +import com.newyetai.common.dto.BaseOperateDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2022-01-06 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "授权明细入口操作") +public class AuthDetailEntrypointCreateDTO extends BaseOperateDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("授权类型标识") + private Integer authTypeCode; + @ApiModelProperty("授权码") + @NotBlank(message = "授权码不能为空") + private String code; + @ApiModelProperty("请求域名或ip") + private String domainOrIp; + @ApiModelProperty("注册邀请码") + private String registerCode; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/AuthDetailEntrypointCreateRes.java b/src/main/java/com/newyetai/usercenter/auth/dto/AuthDetailEntrypointCreateRes.java new file mode 100644 index 0000000..9d0012d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/AuthDetailEntrypointCreateRes.java @@ -0,0 +1,26 @@ +package com.newyetai.usercenter.auth.dto; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "授权明细入口操作结果") +public class AuthDetailEntrypointCreateRes implements Serializable{ + + /** **/ + private static final long serialVersionUID = 8730408984340728312L; + + @ApiModelProperty("是否订阅") + private Boolean subscribe; + + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/AuthDetailEntrypointDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/AuthDetailEntrypointDTO.java new file mode 100644 index 0000000..9519424 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/AuthDetailEntrypointDTO.java @@ -0,0 +1,35 @@ +package com.newyetai.usercenter.auth.dto; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.usercenter.annex.dto.UserAnnexCreateDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2022-01-06 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@ApiModel(description = "授权明细入口") +public class AuthDetailEntrypointDTO extends BaseDTO { + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("授权客户端id") + private Long authDetailId; + @ApiModelProperty("关联id(小程序码id)") + private Long unionId; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/AuthDetailEntrypointQueryDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/AuthDetailEntrypointQueryDTO.java new file mode 100644 index 0000000..0221a0d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/AuthDetailEntrypointQueryDTO.java @@ -0,0 +1,34 @@ +package com.newyetai.usercenter.auth.dto; + +import java.io.Serializable; + +import com.newyetai.common.dto.PageQueryDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2022-01-06 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "授权明细入口查询条件") +public class AuthDetailEntrypointQueryDTO extends PageQueryDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + @ApiModelProperty("授权客户端id") + private Long authDetailId; + @ApiModelProperty("关联id(小程序码id)") + private Long unionId; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/AuthDetailLoginDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/AuthDetailLoginDTO.java new file mode 100644 index 0000000..a1d984a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/AuthDetailLoginDTO.java @@ -0,0 +1,35 @@ +package com.newyetai.usercenter.auth.dto; + +import javax.validation.constraints.NotNull; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2021-05-24 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Data +@SuperBuilder +@ApiModel(description = "授权明细(登录)") +public class AuthDetailLoginDTO extends AuthDetailCreateDTO { + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("用户类型") + @NotNull(message = "用户类型不能为空") + private Integer userType; + @ApiModelProperty("注册邀请码") + private String registerCode; + @ApiModelProperty("入口点") + private String entrypoint; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/AuthDetailQueryDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/AuthDetailQueryDTO.java new file mode 100644 index 0000000..e22a84c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/AuthDetailQueryDTO.java @@ -0,0 +1,40 @@ +package com.newyetai.usercenter.auth.dto; + +import com.newyetai.common.dto.PageQueryDTO; +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 sr on 2021-05-24 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "授权明细查询条件") +public class AuthDetailQueryDTO extends PageQueryDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + @ApiModelProperty("授权客户端id") + private Long authClientId; + @ApiModelProperty("授权类型标识") + private Integer authTypeCode ; + @ApiModelProperty("open_id") + private String openId ; + @ApiModelProperty("用户id") + private Long userId; + @ApiModelProperty("授权唯一id") + private String uniqueId; + @ApiModelProperty("昵称") + private String nickname ; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/AuthSubscribeDetailCreateDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/AuthSubscribeDetailCreateDTO.java new file mode 100644 index 0000000..363e61b --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/AuthSubscribeDetailCreateDTO.java @@ -0,0 +1,41 @@ +package com.newyetai.usercenter.auth.dto; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import io.swagger.annotations.ApiModel; +import javax.validation.constraints.NotNull; +import com.newyetai.common.validation.Update; + +import com.newyetai.common.dto.BaseOperateDTO; + +/** + * @author sr on 2022-04-05 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "授权订阅明细操作") +public class AuthSubscribeDetailCreateDTO extends BaseOperateDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @NotNull(message = "id不能为空", groups = {Update.class}) + private Long id; + + @ApiModelProperty("授权客户端id") + @NotNull(message = "授权客户端id不能为空") + private Long authClientId ; + @NotNull(message = "openId不能为空") + private String openId ; + @NotNull(message = "uniqueId不能为空") + private String uniqueId ; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/AuthSubscribeDetailDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/AuthSubscribeDetailDTO.java new file mode 100644 index 0000000..07abd19 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/AuthSubscribeDetailDTO.java @@ -0,0 +1,37 @@ +package com.newyetai.usercenter.auth.dto; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.usercenter.annex.dto.UserAnnexCreateDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2022-04-05 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@ApiModel(description = "授权订阅明细") +public class AuthSubscribeDetailDTO extends BaseDTO { + + /** **/ + private static final long serialVersionUID = 1L; + + /** 授权客户端id */ + @ApiModelProperty("授权客户端id") + private Long authClientId ; + @ApiModelProperty("open_id") + private String openId ; + @ApiModelProperty("授权唯一id") + private String uniqueId ; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/AuthSubscribeDetailQueryDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/AuthSubscribeDetailQueryDTO.java new file mode 100644 index 0000000..54f7b2d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/AuthSubscribeDetailQueryDTO.java @@ -0,0 +1,35 @@ +package com.newyetai.usercenter.auth.dto; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import io.swagger.annotations.ApiModel; + +import com.newyetai.common.dto.PageQueryDTO; + +/** + * @author sr on 2022-04-05 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "授权订阅明细查询条件") +public class AuthSubscribeDetailQueryDTO extends PageQueryDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + /** 授权客户端id */ + @ApiModelProperty("授权客户端id") + private Long authClientId ; + @ApiModelProperty("授权唯一id") + private String uniqueId ; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/AuthTypeDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/AuthTypeDTO.java new file mode 100644 index 0000000..1d43898 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/AuthTypeDTO.java @@ -0,0 +1,32 @@ +package com.newyetai.usercenter.auth.dto; + +import com.newyetai.common.dto.BaseDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2021-05-24 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@ApiModel(description = "授权客户端类型") +public class AuthTypeDTO extends BaseDTO { + + /** + * + **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("授权大类:1微信,2支付宝") + private Integer authMainType; + @ApiModelProperty("授权类型标识") + private Integer authTypeCode; + @ApiModelProperty("名称") + private String name; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/AuthTypeOperateDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/AuthTypeOperateDTO.java new file mode 100644 index 0000000..1a30772 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/AuthTypeOperateDTO.java @@ -0,0 +1,36 @@ +package com.newyetai.usercenter.auth.dto; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.SuperBuilder; + +import javax.validation.constraints.NotNull; + +/** + * @author sr on 2021-05-24 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +@ApiModel(description = "授权客户端类型操作") +public class AuthTypeOperateDTO extends BaseDTO { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("授权大类:1微信,2支付宝") + @NotNull(message = "授权大类不能为空", groups = {Create.class, Update.class}) + private Integer authMainType; + @ApiModelProperty("授权类型标识") + @NotNull(message = "授权类型标识不能为空", groups = {Create.class, Update.class}) + private Integer authTypeCode; + @ApiModelProperty("名称") + @NotNull(message = "授权名称不能为空", groups = {Create.class, Update.class}) + private String name; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/AuthTypeQueryDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/AuthTypeQueryDTO.java new file mode 100644 index 0000000..3ef3116 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/AuthTypeQueryDTO.java @@ -0,0 +1,24 @@ +package com.newyetai.usercenter.auth.dto; + +import com.newyetai.common.dto.PageQueryDTO; +import io.swagger.annotations.ApiModel; +import lombok.*; + +import java.io.Serializable; + +/** + * @author sr on 2021-05-24 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +@Builder +@ApiModel(description = "授权客户端查询条件") +public class AuthTypeQueryDTO extends PageQueryDTO implements Serializable { + + /** + * + **/ + private static final long serialVersionUID = 1L; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/CodeToSessionDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/CodeToSessionDTO.java new file mode 100644 index 0000000..e15b371 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/CodeToSessionDTO.java @@ -0,0 +1,32 @@ +package com.newyetai.usercenter.auth.dto; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2022-01-06 + */ +@NoArgsConstructor +@AllArgsConstructor +@Builder +@Data +@ApiModel(description = "通用code换session对象") +public class CodeToSessionDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 6510677813408678455L; + + @ApiModelProperty("用户在当前小程序的 ID") + private String openId; + @ApiModelProperty("会话密钥") + private String unionId; + @ApiModelProperty("唯一标识符") + private String sessionKey; + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/InviteInfoDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/InviteInfoDTO.java new file mode 100644 index 0000000..df81ede --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/InviteInfoDTO.java @@ -0,0 +1,78 @@ +package com.newyetai.usercenter.auth.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import org.springframework.format.annotation.DateTimeFormat; + +import java.io.Serializable; +import java.util.Date; + +@NoArgsConstructor +@AllArgsConstructor +@Builder +@Data +@ApiModel(description = "邀请人信息") +public class InviteInfoDTO implements Serializable { + private static final long serialVersionUID = -5127886750745608146L; + + @ApiModelProperty("邀请记录ID") + private Long entrypointId; + + @ApiModelProperty("用户昵称") + private String userNickName; + + @ApiModelProperty("用户姓名") + private String userRealName; + + @ApiModelProperty("头像地址") + private String userAvatar; + + @ApiModelProperty("手机号") + private String userPhone; + + @ApiModelProperty("注册时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date userRegisterTime; + + @ApiModelProperty("用户ID") + private Long userId; + + @ApiModelProperty("简历-姓名") + private String resumePersonName; + + @ApiModelProperty("简历-身份证号") + private String resumeCardNo; + + @ApiModelProperty("简历 - 性别:0女 1男") + private Integer resumeSex; + + @ApiModelProperty("简历 - 年龄") + private Integer resumeAge; + + @ApiModelProperty("简历 - 文化程度:0学历不限、1初中、2高中、3专科、4本科、5硕士、6博士") + private Integer resumeEducation; + + @ApiModelProperty("简历 - 求职意向") + private String resumeJobIntention; + + @ApiModelProperty("简历 - 求职意向名称") + private String resumeJobIntentionName; + + @ApiModelProperty("简历 - 数据来源:1BOSS直聘、2猎聘...") + private Integer resumeSource; + + @ApiModelProperty("简历 - 简历附件") + private String resumeFileCode; + + @ApiModelProperty("简历 - 备注") + private String resumeRemark; + + @ApiModelProperty("简历 - 招聘负责人") + private Long resumePersonInCharge; + + @ApiModelProperty("当前用户的状态") + private Integer status; +} diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/InviteInfoPageQueryDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/InviteInfoPageQueryDTO.java new file mode 100644 index 0000000..978b15f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/InviteInfoPageQueryDTO.java @@ -0,0 +1,35 @@ +package com.newyetai.usercenter.auth.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.newyetai.common.dto.PageQueryDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +@Builder +@Data +@ApiModel(description = "邀请人信息 - 分页查询DTO") +public class InviteInfoPageQueryDTO extends PageQueryDTO { + + private static final long serialVersionUID = -7603359054944420315L; + @ApiModelProperty("二维码ID") + private Long lifeCodeId; + @ApiModelProperty("邀请记录ID") + private Long entrypointId; + + /** + * 查询类型 1: 需要查询在职人数 2:查今日邀请 + */ + private Integer queryType; + + @ApiModelProperty("开始时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date startTime; +} diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/InviteStatisticDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/InviteStatisticDTO.java new file mode 100644 index 0000000..c4bfe71 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/InviteStatisticDTO.java @@ -0,0 +1,19 @@ +package com.newyetai.usercenter.auth.dto; + +import io.swagger.annotations.ApiModel; +import lombok.*; + +import java.io.Serializable; + +@NoArgsConstructor +@AllArgsConstructor +@Builder +@Data +@ApiModel(description = "统计数据") +public class InviteStatisticDTO implements Serializable { + private static final long serialVersionUID = 366340705953671571L; + + private Long authDetailId; + + private Long userAuthId; +} diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/InviteStatisticInfoDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/InviteStatisticInfoDTO.java new file mode 100644 index 0000000..10a9128 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/InviteStatisticInfoDTO.java @@ -0,0 +1,51 @@ +package com.newyetai.usercenter.auth.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; +import java.util.Objects; + +@ApiModel("合伙人统计-查询DTO") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InviteStatisticInfoDTO implements Serializable { + + private static final long serialVersionUID = -5588108740516901862L; + + @ApiModelProperty("总邀请数量") + private Integer totalInviteNumber; + + @ApiModelProperty("今日邀请数量") + private Integer todayInviteNumber; + + @ApiModelProperty("在职数量") + private Integer onTheJobNumber; + + public Integer getTotalInviteNumber() { + if (Objects.isNull(totalInviteNumber)){ + totalInviteNumber = 0; + } + return totalInviteNumber; + } + + public Integer getTodayInviteNumber() { + if (Objects.isNull(todayInviteNumber)){ + todayInviteNumber = 0; + } + return todayInviteNumber; + } + + public Integer getOnTheJobNumber() { + if (Objects.isNull(onTheJobNumber)){ + onTheJobNumber = 0; + } + return onTheJobNumber; + } +} diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/InviteStatisticQueryDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/InviteStatisticQueryDTO.java new file mode 100644 index 0000000..368fd7e --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/InviteStatisticQueryDTO.java @@ -0,0 +1,44 @@ +package com.newyetai.usercenter.auth.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.format.annotation.DateTimeFormat; + +import java.io.Serializable; +import java.util.Date; + +@ApiModel("合伙人统计-查询DTO") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InviteStatisticQueryDTO implements Serializable { + + private static final long serialVersionUID = -5588108740516901862L; + + @ApiModelProperty("开始时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date startTime; + + @ApiModelProperty("结束时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date endTime; + + @ApiModelProperty("用户ID") + private Long userId; + + @ApiModelProperty("PC端调用默认pc") + private String clientType; + + /** + * 查询类型 1: 需要查询在职人数 + */ + private Integer queryType; +} diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/LiteCodeConfigDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/LiteCodeConfigDTO.java new file mode 100644 index 0000000..f1161fa --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/LiteCodeConfigDTO.java @@ -0,0 +1,42 @@ +package com.newyetai.usercenter.auth.dto; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.usercenter.annex.dto.UserAnnexCreateDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2021-12-21 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@ApiModel(description = "小程序码配置") +public class LiteCodeConfigDTO extends BaseDTO { + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("授权客户端id") + private Long authClientId; + @ApiModelProperty("小程序码业务类型") + private Integer bizType; + @ApiModelProperty("路径") + private String path; + @ApiModelProperty("参数键-逗号分隔") + private String paramKey; + @ApiModelProperty("内置环境参数键-逗号分隔") + private String envParamKey; + @ApiModelProperty("平台编码") + private Integer platformCode; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/LiteCodeConfigOperateDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/LiteCodeConfigOperateDTO.java new file mode 100644 index 0000000..ec7ea76 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/LiteCodeConfigOperateDTO.java @@ -0,0 +1,33 @@ +package com.newyetai.usercenter.auth.dto; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import io.swagger.annotations.ApiModel; +import javax.validation.constraints.NotNull; +import com.newyetai.common.validation.Update; + +import com.newyetai.common.dto.BaseOperateDTO; + +/** + * @author sr on 2021-12-21 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "小程序码配置操作") +public class LiteCodeConfigOperateDTO extends BaseOperateDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @NotNull(message = "id不能为空", groups = {Update.class}) + private Long id; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/LiteCodeConfigQueryDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/LiteCodeConfigQueryDTO.java new file mode 100644 index 0000000..0f53d86 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/LiteCodeConfigQueryDTO.java @@ -0,0 +1,34 @@ +package com.newyetai.usercenter.auth.dto; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import io.swagger.annotations.ApiModel; + +import com.newyetai.common.dto.PageQueryDTO; + +/** + * @author sr on 2021-12-21 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "小程序码配置查询条件") +public class LiteCodeConfigQueryDTO extends PageQueryDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + @ApiModelProperty("授权客户端id") + private Long authClientId; + @ApiModelProperty("小程序码业务类型") + private Integer bizType; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/LiteCodeCreateDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/LiteCodeCreateDTO.java new file mode 100644 index 0000000..f7286d0 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/LiteCodeCreateDTO.java @@ -0,0 +1,50 @@ +package com.newyetai.usercenter.auth.dto; + +import com.google.common.collect.Maps; +import com.newyetai.common.dto.BaseOperateDTO; +import com.newyetai.usercenter.auth.constant.AuthTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.Builder.Default; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.Map; + +/** + * @author sr on 2021-12-21 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "小程序码操作") +public class LiteCodeCreateDTO extends BaseOperateDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("小程序码业务类型") + @NotNull(message = "小程序码业务类型不能为空") + private Integer bizType; + @ApiModelProperty("名称") + @NotBlank(message = "名称不能为空") + private String name; + @ApiModelProperty("请求域名或ip") +// @NotBlank(message = "请求域名或ip不能为空") + private String domainOrIp; + @ApiModelProperty("授权类型:默认微信小程序") + @Default + private Integer authTypeCode = AuthTypeEnum.WECHAT_LITE.getCode(); + @ApiModelProperty("参数值") + @Default + private Map paramData = Maps.newHashMap(); + + /** + * 来源 + */ + private Integer sourceFrom; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/LiteCodeDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/LiteCodeDTO.java new file mode 100644 index 0000000..7fa758c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/LiteCodeDTO.java @@ -0,0 +1,49 @@ +package com.newyetai.usercenter.auth.dto; + +import com.newyetai.common.dto.BaseDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2021-12-21 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@ApiModel(description = "小程序码") +public class LiteCodeDTO extends BaseDTO { + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("小程序码配置id") + private Long liteCodeConfigId; + @ApiModelProperty("唯一码-uuid") + private String uniqueCode; + @ApiModelProperty("参数值(按参数键升序排列)(格式:**&**)") + private String paramValue; + @ApiModelProperty("query参数值(格式:**=**&**=**)") + private String queryValue; + @ApiModelProperty("小程序码文件编码") + private String fileCode; + @ApiModelProperty("小程序scheme码") + private String urlScheme; + @ApiModelProperty("名称") + private String name; + @ApiModelProperty("用户id") + private Long userId; + @ApiModelProperty("机构id") + private Long orgId; + @ApiModelProperty("平台编码") + private Integer platformCode; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/LiteCodeModifyDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/LiteCodeModifyDTO.java new file mode 100644 index 0000000..af6233a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/LiteCodeModifyDTO.java @@ -0,0 +1,36 @@ +package com.newyetai.usercenter.auth.dto; + +import com.newyetai.common.dto.BaseOperateDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +/** + * @description: 小程序码修改操作 + * @author: guixinman + * @create: 2023-02-20 16:08 + **/ +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "小程序码操作") +public class LiteCodeModifyDTO extends BaseOperateDTO implements Serializable { + + @ApiModelProperty("小程序码业务类型") + //@NotNull(message = "小程序码业务类型不能为空") + private Integer bizType; + + @NotNull(message = "id不能为空") + private Long id; + + + @NotBlank(message = "名称不能为空") + private String name; + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/LiteCodeQueryDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/LiteCodeQueryDTO.java new file mode 100644 index 0000000..dd6fec5 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/LiteCodeQueryDTO.java @@ -0,0 +1,43 @@ +package com.newyetai.usercenter.auth.dto; + +import com.newyetai.common.dto.PageQueryDTO; +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 sr on 2021-12-21 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "小程序码查询条件") +public class LiteCodeQueryDTO extends PageQueryDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + @ApiModelProperty("小程序码配置id") + private Long liteCodeConfigId; + @ApiModelProperty("参数值(按参数键升序排列)(格式:**&**)") + private String paramValue; + @ApiModelProperty("小程序码名称") + private String name; + @ApiModelProperty("小程序码名称(模糊匹配)") + private String nameLike; + @ApiModelProperty("用户id") + private Long userId; + @ApiModelProperty("机构id") + private Long orgId; + @ApiModelProperty("业务类型") + private Integer bizType; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/LitePhoneAuthDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/LitePhoneAuthDTO.java new file mode 100644 index 0000000..43e9950 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/LitePhoneAuthDTO.java @@ -0,0 +1,37 @@ +package com.newyetai.usercenter.auth.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotBlank; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2020-05-12 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "小程序手机号授权信息") +public class LitePhoneAuthDTO extends AuthCodeDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 2022092915168090246L; + + @ApiModelProperty("包括敏感数据在内的完整用户信息的加密数据") + @NotBlank(message = "加密数据不能为空") + private String encryptedData; + @ApiModelProperty("加密算法的初始向量") + @NotBlank(message = "加密向量不能为空") + private String iv; + @ApiModelProperty("获取手机号的code(微信小程序)") + private String phoneCode; + + @ApiModelProperty("手机号(加密信息换取的)") + private String phone; + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/LitePhoneLoginDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/LitePhoneLoginDTO.java new file mode 100644 index 0000000..919ac7a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/LitePhoneLoginDTO.java @@ -0,0 +1,32 @@ +package com.newyetai.usercenter.auth.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotNull; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2020-05-12 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "小程序登录") +public class LitePhoneLoginDTO extends LitePhoneAuthDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 2022092915168090246L; + + @ApiModelProperty("用户类型") + @NotNull(message = "用户类型不能为空") + private Integer userType; + @ApiModelProperty("入口点") + private String entrypoint; + + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/PcInviteInfoDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/PcInviteInfoDTO.java new file mode 100644 index 0000000..5478e2c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/PcInviteInfoDTO.java @@ -0,0 +1,66 @@ +package com.newyetai.usercenter.auth.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; +import java.util.Date; + +@NoArgsConstructor +@AllArgsConstructor +@Builder +@Data +@ApiModel(description = "邀请人信息") +public class PcInviteInfoDTO implements Serializable { + private static final long serialVersionUID = -5127886750745608146L; + + @ApiModelProperty("用户id") + private Long userId; + + @ApiModelProperty("姓名") + private String personName; + + @ApiModelProperty("昵称") + private String nickname; + + @ApiModelProperty("身份证号") + private String cardNo; + + @ApiModelProperty("性别:2女 1男 3 其它") + private String gender; + + @ApiModelProperty("年龄") + private Integer age; + + @ApiModelProperty("手机号") + private String phone; + + @ApiModelProperty("文化程度:0学历不限、1初中、2高中、3专科、4本科、5硕士、6博士") + private String education; + + @ApiModelProperty("求职意向") + private String jobIntention; + + @ApiModelProperty("邀请人id") + private String inviterId; + + @ApiModelProperty("邀请人名称") + private String inviterName; + + @ApiModelProperty("邀请时间") + private String inviterTime; + + @ApiModelProperty("注册时间") + private String registerTime; + + @ApiModelProperty("二维码名称") + private String liteName; + + @ApiModelProperty("备注") + private String remark; + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/PcInviteInfoPageQueryDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/PcInviteInfoPageQueryDTO.java new file mode 100644 index 0000000..cda38ba --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/PcInviteInfoPageQueryDTO.java @@ -0,0 +1,60 @@ +package com.newyetai.usercenter.auth.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.newyetai.common.dto.PageQueryDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +@Builder +@Data +@ApiModel(description = "PC端邀请人信息 - 分页查询DTO") +public class PcInviteInfoPageQueryDTO extends PageQueryDTO { + + private static final long serialVersionUID = -7603359054944420315L; + + @ApiModelProperty("用户id") + private Long userId; + + @ApiModelProperty("姓名") + private String personNameLike; + + @ApiModelProperty("昵称") + private String nicknameLike; + + @ApiModelProperty("性别:2女 1男 3 其它") + private Integer gender; + + @ApiModelProperty("年龄") + private Integer age; + + @ApiModelProperty("手机号") + private String phone; + + @ApiModelProperty("邀请人id") + private String inviterId; + + @ApiModelProperty("邀请时间开始") + private String inviterTimeStart; + @ApiModelProperty("邀请时间结束") + private String inviterTimeEnd; + + @ApiModelProperty("注册时间开始") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date registerTimeStart; + @ApiModelProperty("注册时间结束") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date registerTimeEnd; + + @ApiModelProperty("二维码名称") + private String liteNameLike; + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/PcInviteStatisticInfoDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/PcInviteStatisticInfoDTO.java new file mode 100644 index 0000000..142e52a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/PcInviteStatisticInfoDTO.java @@ -0,0 +1,51 @@ +package com.newyetai.usercenter.auth.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; +import java.util.Objects; + +@ApiModel("合伙人统计 - pc 查询DTO") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PcInviteStatisticInfoDTO implements Serializable { + + private static final long serialVersionUID = -5588108740516901862L; + + @ApiModelProperty("邀请数量") + private Integer inviteNumber; + + @ApiModelProperty("未注册数量") + private Integer unRegisterNumber; + + @ApiModelProperty("注册数量") + private Integer registerNumber; + + public Integer getInviteNumber() { + if (Objects.isNull(inviteNumber)) { + inviteNumber = 0; + } + return inviteNumber; + } + + public Integer getUnRegisterNumber() { + if (Objects.isNull(unRegisterNumber)) { + unRegisterNumber = 0; + } + return unRegisterNumber; + } + + public Integer getRegisterNumber() { + if (Objects.isNull(registerNumber)) { + registerNumber = 0; + } + return registerNumber; + } +} diff --git a/src/main/java/com/newyetai/usercenter/auth/dto/RegistrationInfoDTO.java b/src/main/java/com/newyetai/usercenter/auth/dto/RegistrationInfoDTO.java new file mode 100644 index 0000000..d4ab03b --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/dto/RegistrationInfoDTO.java @@ -0,0 +1,35 @@ +package com.newyetai.usercenter.auth.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class RegistrationInfoDTO implements Serializable { + private static final long serialVersionUID = -3240224698154801738L; + + /** + * 用户id + */ + private Long userId; + + /** + * 岗位ID + */ + private Long positionId; + + /** + * 状态 + */ + private Integer status; + + /** + * 终止 + */ + private Boolean termination; +} diff --git a/src/main/java/com/newyetai/usercenter/auth/entity/AuthClient.java b/src/main/java/com/newyetai/usercenter/auth/entity/AuthClient.java new file mode 100644 index 0000000..a1f36ad --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/entity/AuthClient.java @@ -0,0 +1,36 @@ +package com.newyetai.usercenter.auth.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 授权客户端 + * + * @author sr on 2021-05-24 + */ +@TableName("uc_auth_client") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +public class AuthClient extends BaseEntity { + + /** **/ + private static final long serialVersionUID = 1L; + /** + * 授权应用名称 + */ + private String clientName; + /** 授权类型标识 */ + private Integer authTypeCode ; + /** 配置数据 */ + private String paramData ; + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/entity/AuthDetail.java b/src/main/java/com/newyetai/usercenter/auth/entity/AuthDetail.java new file mode 100644 index 0000000..03bb8d3 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/entity/AuthDetail.java @@ -0,0 +1,49 @@ +package com.newyetai.usercenter.auth.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 授权明细 + * + * @author sr on 2021-05-24 + */ +@TableName("uc_auth_detail") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +public class AuthDetail extends BaseEntity { + + /** **/ + private static final long serialVersionUID = 1L; + + /** 授权客户端id */ + private Long authClientId ; + /** 授权类型标识 */ + private Integer authTypeCode ; + /** 昵称 */ + private String nickname ; + /** 头像 */ + private String avatar ; + /** 性别 */ + private String gender ; + /** 国家 */ + private String country ; + /** 省份 */ + private String province ; + /** 城市 */ + private String city ; + /** open_id */ + private String openId ; + /** 授权唯一id */ + private String uniqueId ; + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/entity/AuthDetailEntrypoint.java b/src/main/java/com/newyetai/usercenter/auth/entity/AuthDetailEntrypoint.java new file mode 100644 index 0000000..14828f7 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/entity/AuthDetailEntrypoint.java @@ -0,0 +1,33 @@ +package com.newyetai.usercenter.auth.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 授权明细入口 + * + * @author sr on 2022-01-06 + */ +@TableName("uc_auth_detail_entrypoint") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +public class AuthDetailEntrypoint extends BaseEntity { + + /** **/ + private static final long serialVersionUID = 1L; + + /** 授权客户端id **/ + private Long authDetailId; + /** 关联id(小程序码id) **/ + private Long unionId; + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/entity/AuthSubscribeDetail.java b/src/main/java/com/newyetai/usercenter/auth/entity/AuthSubscribeDetail.java new file mode 100644 index 0000000..5442d01 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/entity/AuthSubscribeDetail.java @@ -0,0 +1,35 @@ +package com.newyetai.usercenter.auth.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 授权订阅明细 + * + * @author sr on 2022-04-05 + */ +@TableName("uc_auth_subscribe_detail") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +public class AuthSubscribeDetail extends BaseEntity { + + /** **/ + private static final long serialVersionUID = 1L; + + /** 授权客户端id */ + private Long authClientId ; + /** open_id */ + private String openId ; + /** 授权唯一id */ + private String uniqueId ; + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/entity/AuthType.java b/src/main/java/com/newyetai/usercenter/auth/entity/AuthType.java new file mode 100644 index 0000000..74ae11b --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/entity/AuthType.java @@ -0,0 +1,34 @@ +package com.newyetai.usercenter.auth.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 授权类型 + * + * @author sr on 2021-05-24 + */ +@TableName("uc_auth_type") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +public class AuthType extends BaseEntity { + + /** + * 授权大类:1微信,2支付宝 + */ + private Integer authMainType; + /** 授权类型标识 */ + private Integer authTypeCode ; + /** 名称 */ + private String name ; + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/entity/LiteCode.java b/src/main/java/com/newyetai/usercenter/auth/entity/LiteCode.java new file mode 100644 index 0000000..7dd6219 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/entity/LiteCode.java @@ -0,0 +1,49 @@ +package com.newyetai.usercenter.auth.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 小程序码 + * + * @author sr on 2021-12-21 + */ +@TableName("uc_lite_code") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +public class LiteCode extends BaseEntity { + + /** **/ + private static final long serialVersionUID = 1L; + + /** 小程序码配置id **/ + private Long liteCodeConfigId; + /** 唯一码-uuid **/ + private String uniqueCode; + /** 参数值(按参数键升序排列)(格式:**&**) **/ + private String paramValue; + /** query参数值(格式:**=**&**=**) **/ + private String queryValue; + /** 小程序码文件编码 **/ + private String fileCode; + /** 小程序scheme码 **/ + private String urlScheme; + /** 名称 **/ + private String name; + /** 用户id **/ + private Long userId; + /** 机构id **/ + private Long orgId; + /** 平台编码 **/ + private Integer platformCode; + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/entity/LiteCodeConfig.java b/src/main/java/com/newyetai/usercenter/auth/entity/LiteCodeConfig.java new file mode 100644 index 0000000..fb83d57 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/entity/LiteCodeConfig.java @@ -0,0 +1,41 @@ +package com.newyetai.usercenter.auth.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 小程序码配置 + * + * @author sr on 2021-12-21 + */ +@TableName("uc_lite_code_config") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +public class LiteCodeConfig extends BaseEntity { + + /** **/ + private static final long serialVersionUID = 1L; + + /** 授权客户端id **/ + private Long authClientId; + /** 小程序码业务类型 **/ + private Integer bizType; + /** 路径 **/ + private String path; + /** 参数键-逗号分隔 **/ + private String paramKey; + /** 内置环境参数键-逗号分隔 **/ + private String envParamKey; + /** 平台编码 **/ + private Integer platformCode; + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/job/AuthJob.java b/src/main/java/com/newyetai/usercenter/auth/job/AuthJob.java new file mode 100644 index 0000000..43a6512 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/job/AuthJob.java @@ -0,0 +1,36 @@ +//package com.newyetai.usercenter.auth.job; +// +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.stereotype.Component; +// +//import com.newyetai.common.annotation.AlitaStopWatch; +//import com.newyetai.job.util.ReturnTUtils; +//import com.newyetai.security.util.MockUtils; +//import com.newyetai.usercenter.auth.service.AuthSubscribeDetailService; +//import com.newyetai.usercenter.common.constant.XxlJobHandlerConstants; +//import com.xxl.job.core.biz.model.ReturnT; +//import com.xxl.job.core.handler.annotation.XxlJob; +// +//import lombok.extern.slf4j.Slf4j; +// +//@Component +//@Slf4j +//public class AuthJob { +// +// @Autowired +// private AuthSubscribeDetailService authSubscribeDetailService; +// +// @XxlJob(XxlJobHandlerConstants.AUTH_SUBSCRIBE_USER_LIST) +// @AlitaStopWatch +// public ReturnT execute(String param) { +// try { +// MockUtils.mockPlatUser(); +// authSubscribeDetailService.loadAllClient(); +// return ReturnT.SUCCESS; +// }catch (Exception e) { +// return ReturnTUtils.error(e.getMessage()); +// } +// } +// +//} +// diff --git a/src/main/java/com/newyetai/usercenter/auth/mapper/AuthClientMapper.xml b/src/main/java/com/newyetai/usercenter/auth/mapper/AuthClientMapper.xml new file mode 100644 index 0000000..b82e373 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/mapper/AuthClientMapper.xml @@ -0,0 +1,42 @@ + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/auth/mapper/AuthDetailEntrypointMapper.xml b/src/main/java/com/newyetai/usercenter/auth/mapper/AuthDetailEntrypointMapper.xml new file mode 100644 index 0000000..ede067d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/mapper/AuthDetailEntrypointMapper.xml @@ -0,0 +1,245 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/auth/mapper/AuthDetailMapper.xml b/src/main/java/com/newyetai/usercenter/auth/mapper/AuthDetailMapper.xml new file mode 100644 index 0000000..de3ddd1 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/mapper/AuthDetailMapper.xml @@ -0,0 +1,48 @@ + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/auth/mapper/AuthSubscribeDetailMapper.xml b/src/main/java/com/newyetai/usercenter/auth/mapper/AuthSubscribeDetailMapper.xml new file mode 100644 index 0000000..e2e051f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/mapper/AuthSubscribeDetailMapper.xml @@ -0,0 +1,22 @@ + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/auth/mapper/AuthTypeMapper.xml b/src/main/java/com/newyetai/usercenter/auth/mapper/AuthTypeMapper.xml new file mode 100644 index 0000000..275ce05 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/mapper/AuthTypeMapper.xml @@ -0,0 +1,14 @@ + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/auth/mapper/LiteCodeConfigMapper.xml b/src/main/java/com/newyetai/usercenter/auth/mapper/LiteCodeConfigMapper.xml new file mode 100644 index 0000000..a169a4f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/mapper/LiteCodeConfigMapper.xml @@ -0,0 +1,23 @@ + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/auth/mapper/LiteCodeMapper.xml b/src/main/java/com/newyetai/usercenter/auth/mapper/LiteCodeMapper.xml new file mode 100644 index 0000000..ebb1326 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/mapper/LiteCodeMapper.xml @@ -0,0 +1,39 @@ + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/auth/mapstruct/AuthClientMapMapper.java b/src/main/java/com/newyetai/usercenter/auth/mapstruct/AuthClientMapMapper.java new file mode 100644 index 0000000..cd75014 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/mapstruct/AuthClientMapMapper.java @@ -0,0 +1,48 @@ +package com.newyetai.usercenter.auth.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.newyetai.sdk.bytedance.model.Code2SessionDataDTO; +import com.newyetai.sdk.wechat.model.Code2SessionDTO; +import com.newyetai.usercenter.auth.dto.AuthClientDTO; +import com.newyetai.usercenter.auth.dto.AuthClientOperateDTO; +import com.newyetai.usercenter.auth.dto.AuthTypeOperateDTO; +import com.newyetai.usercenter.auth.dto.CodeToSessionDTO; +import com.newyetai.usercenter.auth.entity.AuthClient; +import com.newyetai.usercenter.auth.entity.AuthType; + +/** + * @author sr on 2021-05-24 + */ +@Mapper +public interface AuthClientMapMapper { + + AuthClientMapMapper INSTANCE = + Mappers.getMapper(AuthClientMapMapper.class); + + /** + * dto to entity + * + * @param authClientDto + * @return + * @author sr on 2021-05-24 + */ + AuthClient toEntity( + AuthClientDTO authClientDto); + + + /** + * @param authClientOperateDTO + * @return + * @author sr on 2021-05-24 + */ + AuthClient toEntity(AuthClientOperateDTO authClientOperateDTO); + + AuthType exchange(AuthTypeOperateDTO operateDTO); + + CodeToSessionDTO to(Code2SessionDTO dto); + + CodeToSessionDTO to(Code2SessionDataDTO dto); + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/mapstruct/AuthDetailEntrypointMapMapper.java b/src/main/java/com/newyetai/usercenter/auth/mapstruct/AuthDetailEntrypointMapMapper.java new file mode 100644 index 0000000..75128d6 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/mapstruct/AuthDetailEntrypointMapMapper.java @@ -0,0 +1,29 @@ +package com.newyetai.usercenter.auth.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.newyetai.usercenter.auth.dto.AuthDetailEntrypointDTO; +import com.newyetai.usercenter.auth.entity.AuthDetailEntrypoint; + +/** + * @author sr on 2022-01-06 + */ +@Mapper +public interface AuthDetailEntrypointMapMapper { + + AuthDetailEntrypointMapMapper INSTANCE = + Mappers.getMapper(AuthDetailEntrypointMapMapper.class); + + /** + * dto to entity + * + * @param authDetailEntrypointDto + * @return + * @author sr on 2022-01-06 + */ + AuthDetailEntrypoint toEntity( + AuthDetailEntrypointDTO authDetailEntrypointDto); + + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/mapstruct/AuthDetailMapMapper.java b/src/main/java/com/newyetai/usercenter/auth/mapstruct/AuthDetailMapMapper.java new file mode 100644 index 0000000..a5b4ccd --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/mapstruct/AuthDetailMapMapper.java @@ -0,0 +1,36 @@ +package com.newyetai.usercenter.auth.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; + +import com.newyetai.usercenter.auth.dto.AuthDetailCreateDTO; +import com.newyetai.usercenter.auth.dto.AuthDetailLoginDTO; +import com.newyetai.usercenter.auth.dto.LitePhoneLoginDTO; +import com.newyetai.usercenter.auth.entity.AuthDetail; +import com.newyetai.usercenter.user.login.dto.LoginPhoneDTO; + +/** + * @author sr on 2021-05-24 + */ +@Mapper +public interface AuthDetailMapMapper { + + AuthDetailMapMapper INSTANCE = + Mappers.getMapper(AuthDetailMapMapper.class); + + /** + * dto to entity + * + * @param authDetailDto + * @return + * @author sr on 2021-05-24 + */ + AuthDetail toEntity(AuthDetailCreateDTO authDetailCreateDTO); + + @Mapping(target = "withoutCode", constant = "true") + LoginPhoneDTO to(LitePhoneLoginDTO litePhoneLoginDTO); + + AuthDetailLoginDTO toDto(LitePhoneLoginDTO loginPhoneLoginDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/mapstruct/AuthSubscribeDetailMapMapper.java b/src/main/java/com/newyetai/usercenter/auth/mapstruct/AuthSubscribeDetailMapMapper.java new file mode 100644 index 0000000..4f84a63 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/mapstruct/AuthSubscribeDetailMapMapper.java @@ -0,0 +1,37 @@ +package com.newyetai.usercenter.auth.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.newyetai.usercenter.auth.dto.AuthSubscribeDetailDTO; +import com.newyetai.usercenter.auth.entity.AuthSubscribeDetail; +import com.newyetai.usercenter.auth.dto.AuthSubscribeDetailCreateDTO; + +/** + * @author sr on 2022-04-05 + */ +@Mapper +public interface AuthSubscribeDetailMapMapper { + + AuthSubscribeDetailMapMapper INSTANCE = + Mappers.getMapper(AuthSubscribeDetailMapMapper.class); + + /** + * dto to entity + * + * @param authSubscribeDetailDto + * @return + * @author sr on 2022-04-05 + */ + AuthSubscribeDetail toEntity( + AuthSubscribeDetailDTO authSubscribeDetailDto); + + + /** + * @param authSubscribeDetailCreateDTO + * @return + * @author sr on 2022-04-05 + */ + AuthSubscribeDetail toEntity(AuthSubscribeDetailCreateDTO authSubscribeDetailCreateDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/mapstruct/LiteCodeConfigMapMapper.java b/src/main/java/com/newyetai/usercenter/auth/mapstruct/LiteCodeConfigMapMapper.java new file mode 100644 index 0000000..3085575 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/mapstruct/LiteCodeConfigMapMapper.java @@ -0,0 +1,37 @@ +package com.newyetai.usercenter.auth.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.newyetai.usercenter.auth.dto.LiteCodeConfigDTO; +import com.newyetai.usercenter.auth.entity.LiteCodeConfig; +import com.newyetai.usercenter.auth.dto.LiteCodeConfigOperateDTO; + +/** + * @author sr on 2021-12-21 + */ +@Mapper +public interface LiteCodeConfigMapMapper { + + LiteCodeConfigMapMapper INSTANCE = + Mappers.getMapper(LiteCodeConfigMapMapper.class); + + /** + * dto to entity + * + * @param liteCodeConfigDto + * @return + * @author sr on 2021-12-21 + */ + LiteCodeConfig toEntity( + LiteCodeConfigDTO liteCodeConfigDto); + + + /** + * @param liteCodeConfigOperateDTO + * @return + * @author sr on 2021-12-21 + */ + LiteCodeConfig toEntity(LiteCodeConfigOperateDTO liteCodeConfigOperateDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/mapstruct/LiteCodeMapMapper.java b/src/main/java/com/newyetai/usercenter/auth/mapstruct/LiteCodeMapMapper.java new file mode 100644 index 0000000..f942892 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/mapstruct/LiteCodeMapMapper.java @@ -0,0 +1,39 @@ +package com.newyetai.usercenter.auth.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.newyetai.usercenter.auth.dto.LiteCodeDTO; +import com.newyetai.usercenter.auth.entity.LiteCode; +import com.newyetai.usercenter.auth.dto.LiteCodeCreateDTO; + +/** + * @author sr on 2021-12-21 + */ +@Mapper +public interface LiteCodeMapMapper { + + LiteCodeMapMapper INSTANCE = + Mappers.getMapper(LiteCodeMapMapper.class); + + /** + * dto to entity + * + * @param liteCodeDto + * @return + * @author sr on 2021-12-21 + */ + LiteCode toEntity( + LiteCodeDTO liteCodeDto); + + + /** + * @param liteCodeOperateDTO + * @return + * @author sr on 2021-12-21 + */ + LiteCode toEntity(LiteCodeCreateDTO liteCodeOperateDTO); + + LiteCodeDTO toDto(LiteCode liteCode); + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/service/AuthClientService.java b/src/main/java/com/newyetai/usercenter/auth/service/AuthClientService.java new file mode 100644 index 0000000..321564f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/service/AuthClientService.java @@ -0,0 +1,191 @@ +package com.newyetai.usercenter.auth.service; + +import java.util.List; + +import javax.validation.Valid; + +import org.springframework.validation.annotation.Validated; + +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; +import com.newyetai.sdk.wechat.model.SubscibeMessageReq; +import com.newyetai.sdk.wechat.model.UnionDTO; +import com.newyetai.sdk.wechat.model.UrlSchemeReq; +import com.newyetai.sdk.wechat.model.WxacodeReq; +import com.newyetai.usercenter.auth.dto.AuthClientDTO; +import com.newyetai.usercenter.auth.dto.AuthClientDataDTO; +import com.newyetai.usercenter.auth.dto.AuthClientOperateDTO; +import com.newyetai.usercenter.auth.dto.AuthClientQueryDTO; +import com.newyetai.usercenter.auth.dto.CodeToSessionDTO; +import com.newyetai.usercenter.auth.dto.LitePhoneAuthDTO; +import com.newyetai.usercenter.auth.wechat.dto.WechatSignatureReqDTO; +import com.newyetai.usercenter.auth.wechat.dto.WechatSignatureResDTO; + +/** + * 授权客户端 + * + * @author sr on 2021-05-24 + */ +@Validated +public interface AuthClientService { + + /** + * 新增 + * + * @param authClientOperateDTO + * @return + * @author sr on 2021-05-24 + */ + @Validated(Create.class) + Long create(@Valid AuthClientOperateDTO authClientOperateDTO); + + /** + * 修改 + * + * @param authClientOperateDTO + * @author sr on 2021-05-24 + */ + @Validated(Update.class) + void modify(@Valid AuthClientOperateDTO authClientOperateDTO); + + /** + * 删除 + * + * @param id + * @author sr on 2021-05-24 + */ + void remove(Long id); + + /** + * 查询 + * + * @param authClientQueryDTO + * @return + * @author sr on 2021-05-24 + */ + List list(AuthClientQueryDTO authClientQueryDTO); + + /** + * 分页查询 + * @param authClientQueryDTO + * @author sr on 2022-01-04 + */ + void page(AuthClientQueryDTO authClientQueryDTO); + + /** + * 查询单个授权配置 + * @param authClientQueryDTO + * @return + * @author sr on 2021-06-24 + */ + AuthClientDTO findAuthClientDTO(AuthClientQueryDTO authClientQueryDTO); + + /** + * 查询单个授权配置数据对象 + * @param authClientQueryDTO + * @return + * @author sr on 2021-07-07 + */ + AuthClientDataDTO findClientData(AuthClientQueryDTO authClientQueryDTO); + + /** + * 获取授权配置数据对象 + * @param authClientDTO + * @return + * @author sr on 2022-04-06 + */ + AuthClientDataDTO toClientData(AuthClientDTO authClientDTO); + + + /** + * 获取accessToken + * + * @param clientRegistrationId + * @return + * @author sr on 2021-01-15 + */ + String getAccessToken(AuthClientQueryDTO authClientQueryDTO); + + /** + * 获取ticket + * + * @param clientRegistrationId + * @return + * @author sr on 2021-01-15 + */ + String getJsApiTicket(AuthClientQueryDTO authClientQueryDTO); + + /** + * 签名 + * + * @param wechatSignatureDTO + * @return + * @author sr on 2021-01-15 + */ + WechatSignatureResDTO signature(WechatSignatureReqDTO wechatSignatureDTO); + + /** + * 根据授权配置获取accessToken + * @param authClientDataDTO + * @return + * @author sr on 2021-12-24 + */ + String getAccessToken(AuthClientDataDTO authClientDataDTO); + + /** + * 获取小程序码 + * @param authClientDataDTO + * @param wxacodeRequestParam + * @return + * @author sr on 2021-12-24 + */ + byte[] getWxacode(AuthClientDataDTO authClientDataDTO, WxacodeReq wxacodeRequestParam); + + /** + * 获取小程序scheme码 + * @param authClientDataDTO + * @param urlSchemeRequestParam + * @return + * @author sr on 2021-12-24 + */ + String getUrlscheme(AuthClientDataDTO authClientDataDTO, + UrlSchemeReq urlSchemeRequestParam); + + /** + * 发送小程序订阅消息 + * @param authClientDataDTO + * @param subscibeMessageReq + * @author sr on 2022-01-04 + */ + void subscibeMessage(AuthClientDataDTO authClientDataDTO, SubscibeMessageReq subscibeMessageReq); + + /** + * code换session + * @param authClientDataDTO + * @param code + * @return + * @author sr on 2022-01-06 + */ + CodeToSessionDTO getCodeToSessionDTO(AuthClientDataDTO authClientDataDTO, String code); + + String getPhone(LitePhoneAuthDTO litePhoneAuthDTO); + + /** + * 订阅用户列表 + * @return openIds + * @author sr on 2022-04-05 + */ + List subscribeUser(AuthClientDataDTO authClientDataDTO); + + /** + * 批量openid换unionid + * @param authClientDataDTO + * @param openIds + * @return + * @author sr on 2022-04-05 + */ + List batchUnion(AuthClientDataDTO authClientDataDTO, List openIds); + + String getPhone(AuthClientDataDTO authClientDataDTO, String phoneCode); + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/service/AuthDetailEntrypointService.java b/src/main/java/com/newyetai/usercenter/auth/service/AuthDetailEntrypointService.java new file mode 100644 index 0000000..edc8f35 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/service/AuthDetailEntrypointService.java @@ -0,0 +1,97 @@ +package com.newyetai.usercenter.auth.service; + +import com.newyetai.usercenter.auth.dto.*; + +import com.newyetai.usercenter.auth.dto.AuthCodeDTO; +import com.newyetai.usercenter.auth.dto.AuthDetailEntrypointDTO; +import com.newyetai.usercenter.auth.dto.AuthDetailEntrypointQueryDTO; +import java.util.List; + +/** + * 授权明细入口 + * + * @author sr on 2022-01-06 + */ +public interface AuthDetailEntrypointService { + + /** + * 新增 + * + * @param authCodeDTO + * @return + * @author sr on 2022-01-06 + */ + AuthDetailEntrypointCreateRes create(AuthCodeDTO authCodeDTO); + + /** + * 删除 + * + * @param id + * @author sr on 2022-01-06 + */ + void remove(Long id); + + /** + * 查询 + * + * @param authDetailEntrypointQueryDTO + * @return + * @author sr on 2022-01-06 + */ + List list(AuthDetailEntrypointQueryDTO authDetailEntrypointQueryDTO); + + /** + * 分页查询 + * + * @param authDetailEntrypointQueryDTO + * @return + * @author sr on 2022-01-06 + */ + void page(AuthDetailEntrypointQueryDTO authDetailEntrypointQueryDTO); + + /** + * 单个查询 + * + * @param authDetailEntrypointQueryDTO + * @return + * @author sr on 2022-01-06 + */ + AuthDetailEntrypointDTO find(AuthDetailEntrypointQueryDTO authDetailEntrypointQueryDTO); + + /** + * 分页查询邀请人列表 + * 默认查询当前登录人 + * 只查询已注册的邀请人列表 + * + * @param queryDTO 查询dto + * @return {@link List}<{@link InviteInfoDTO}> + */ + List inviteInfoPage(InviteInfoPageQueryDTO queryDTO); + InviteStatisticInfoDTO inviteInfoStatistic(InviteInfoPageQueryDTO queryDTO); + + /** + * pc端查询邀请列表 + * @param queryDTO + * @return + */ + List pcInviteInfoPage(PcInviteInfoPageQueryDTO queryDTO); + + /** + * 请统计查询(pc) + * + * @param queryDTO 查询dto + * @return {@link InviteStatisticInfoDTO} + */ + PcInviteStatisticInfoDTO pcInviteStatisticQuery(InviteStatisticQueryDTO queryDTO); + + + /** + * 请统计查询 + * + * @param queryDTO 查询dto + * @return {@link InviteStatisticInfoDTO} + */ + InviteStatisticInfoDTO inviteStatisticQuery(InviteStatisticQueryDTO queryDTO); + + PcInviteInfoDTO getInviteInfoDetail(PcInviteInfoPageQueryDTO queryDTO); +} diff --git a/src/main/java/com/newyetai/usercenter/auth/service/AuthDetailService.java b/src/main/java/com/newyetai/usercenter/auth/service/AuthDetailService.java new file mode 100644 index 0000000..6d0812b --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/service/AuthDetailService.java @@ -0,0 +1,48 @@ +package com.newyetai.usercenter.auth.service; + +import java.util.List; + +import com.newyetai.usercenter.auth.dto.AuthDetailCreateDTO; +import com.newyetai.usercenter.auth.dto.AuthDetailDTO; +import com.newyetai.usercenter.auth.dto.AuthDetailQueryDTO; + +/** + * 授权明细 + * + * @author sr on 2021-05-24 + */ +public interface AuthDetailService { + + /** + * 创建(幂等) + * @param authDetailCreateDTO + * @return + * @author sr on 2022-01-06 + */ + Long create(AuthDetailCreateDTO authDetailCreateDTO); + + /** + * 删除 + * + * @param id + * @author sr on 2021-05-24 + */ + void remove(Long id); + + /** + * 查询 + * + * @param authDetailQueryDTO + * @return + * @author sr on 2021-05-24 + */ + List list(AuthDetailQueryDTO authDetailQueryDTO); + + /** + * 分页查询 + * @param authDetailQueryDTO + * @author sr on 2022-01-04 + */ + void page(AuthDetailQueryDTO authDetailQueryDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/service/AuthSubscribeDetailService.java b/src/main/java/com/newyetai/usercenter/auth/service/AuthSubscribeDetailService.java new file mode 100644 index 0000000..08c1fa2 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/service/AuthSubscribeDetailService.java @@ -0,0 +1,62 @@ +package com.newyetai.usercenter.auth.service; + +import java.util.List; + +import com.newyetai.usercenter.auth.dto.AuthSubscribeDetailQueryDTO; +import com.newyetai.usercenter.auth.dto.AuthSubscribeDetailCreateDTO; +import com.newyetai.usercenter.auth.dto.AuthSubscribeDetailDTO; + +/** + * 授权订阅明细 + * + * @author sr on 2022-04-05 + */ +public interface AuthSubscribeDetailService { + + /** + * 新增 + * + * @param authSubscribeDetailCreateDTO + * @return + * @author sr on 2022-04-05 + */ + void create(AuthSubscribeDetailCreateDTO authSubscribeDetailCreateDTO); + + /** + * 删除 + * + * @param id + * @author sr on 2022-04-05 + */ + void remove(Long id); + + /** + * 查询 + * + * @param authSubscribeDetailQueryDTO + * @return + * @author sr on 2022-04-05 + */ + List list(AuthSubscribeDetailQueryDTO authSubscribeDetailQueryDTO); + + /** + * 分页查询 + * + * @param authSubscribeDetailQueryDTO + * @return + * @author sr on 2022-04-05 + */ + void page(AuthSubscribeDetailQueryDTO authSubscribeDetailQueryDTO); + + /** + * 单个查询 + * + * @param authSubscribeDetailQueryDTO + * @return + * @author sr on 2022-04-05 + */ + AuthSubscribeDetailDTO find(AuthSubscribeDetailQueryDTO authSubscribeDetailQueryDTO); + + void loadAllClient(); + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/service/AuthTypeService.java b/src/main/java/com/newyetai/usercenter/auth/service/AuthTypeService.java new file mode 100644 index 0000000..7bac1e3 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/service/AuthTypeService.java @@ -0,0 +1,41 @@ +package com.newyetai.usercenter.auth.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.newyetai.common.validation.Create; +import com.newyetai.usercenter.auth.dto.AuthTypeDTO; +import com.newyetai.usercenter.auth.dto.AuthTypeOperateDTO; +import com.newyetai.usercenter.auth.dto.AuthTypeQueryDTO; +import com.newyetai.usercenter.auth.entity.AuthType; +import org.springframework.validation.annotation.Validated; + +import javax.validation.Valid; +import java.util.List; + +/** + * 授权客户端 + * + * @author sr on 2021-05-24 + */ +@Validated +public interface AuthTypeService extends IService { + + /** + * 新增 + * + * @param operateDTO + * @return + * @author sr on 2021-05-24 + */ + @Validated(Create.class) + Long create(@Valid AuthTypeOperateDTO operateDTO); + + /** + * 查询 + * + * @param queryDTO + * @return + * @author sr on 2021-05-24 + */ + List list(AuthTypeQueryDTO queryDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/service/LiteCodeConfigService.java b/src/main/java/com/newyetai/usercenter/auth/service/LiteCodeConfigService.java new file mode 100644 index 0000000..0fdc2dd --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/service/LiteCodeConfigService.java @@ -0,0 +1,68 @@ +package com.newyetai.usercenter.auth.service; + +import java.util.List; + +import com.newyetai.usercenter.auth.dto.LiteCodeConfigQueryDTO; +import com.newyetai.usercenter.auth.dto.LiteCodeConfigOperateDTO; +import com.newyetai.usercenter.auth.dto.LiteCodeConfigDTO; + +/** + * 小程序码配置 + * + * @author sr on 2021-12-21 + */ +public interface LiteCodeConfigService { + + /** + * 新增 + * + * @param liteCodeConfigOperateDTO + * @return + * @author sr on 2021-12-21 + */ + Long create(LiteCodeConfigOperateDTO liteCodeConfigOperateDTO); + + /** + * 修改 + * + * @param liteCodeConfigOperateDTO + * @author sr on 2021-12-21 + */ + void modify(LiteCodeConfigOperateDTO liteCodeConfigOperateDTO); + + /** + * 删除 + * + * @param id + * @author sr on 2021-12-21 + */ + void remove(Long id); + + /** + * 查询 + * + * @param liteCodeConfigQueryDTO + * @return + * @author sr on 2021-12-21 + */ + List list(LiteCodeConfigQueryDTO liteCodeConfigQueryDTO); + + /** + * 分页查询 + * + * @param liteCodeConfigQueryDTO + * @return + * @author sr on 2021-12-21 + */ + void page(LiteCodeConfigQueryDTO liteCodeConfigQueryDTO); + + /** + * 单个查询 + * + * @param liteCodeConfigQueryDTO + * @return + * @author sr on 2021-12-21 + */ + LiteCodeConfigDTO findOne(LiteCodeConfigQueryDTO liteCodeConfigQueryDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/service/LiteCodeService.java b/src/main/java/com/newyetai/usercenter/auth/service/LiteCodeService.java new file mode 100644 index 0000000..e0d3d51 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/service/LiteCodeService.java @@ -0,0 +1,54 @@ +package com.newyetai.usercenter.auth.service; + +import java.util.List; + +import com.newyetai.usercenter.auth.dto.LiteCodeModifyDTO; +import com.newyetai.usercenter.auth.dto.LiteCodeQueryDTO; +import com.newyetai.usercenter.auth.dto.LiteCodeCreateDTO; +import com.newyetai.usercenter.auth.dto.LiteCodeDTO; + +/** + * 小程序码 + * + * @author sr on 2021-12-21 + */ +public interface LiteCodeService { + + /** + * 新增 + * + * @param liteCodeCreateDTO + * @return + * @author sr on 2021-12-21 + */ + LiteCodeDTO create(LiteCodeCreateDTO liteCodeCreateDTO); + + /** + * 查询 + * + * @param liteCodeQueryDTO + * @return + * @author sr on 2021-12-21 + */ + List list(LiteCodeQueryDTO liteCodeQueryDTO); + + /** + * 分页查询 + * + * @param liteCodeQueryDTO + * @return + * @author sr on 2021-12-21 + */ + void page(LiteCodeQueryDTO liteCodeQueryDTO); + + /** + * 单个查询 + * + * @param liteCodeQueryDTO + * @return + * @author sr on 2021-12-21 + */ + LiteCodeDTO find(LiteCodeQueryDTO liteCodeQueryDTO); + + LiteCodeDTO modify(LiteCodeModifyDTO liteCodeModifyDTO); +} diff --git a/src/main/java/com/newyetai/usercenter/auth/service/impl/AuthClientServiceImpl.java b/src/main/java/com/newyetai/usercenter/auth/service/impl/AuthClientServiceImpl.java new file mode 100644 index 0000000..cb0f528 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/service/impl/AuthClientServiceImpl.java @@ -0,0 +1,308 @@ +package com.newyetai.usercenter.auth.service.impl; + +import java.util.List; + +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.google.common.collect.Lists; +import com.newyetai.common.AlitaResult; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.common.util.RandomUtils; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.frame.redis.util.RedisUtils; +import com.newyetai.sdk.bytedance.ByteDanceUtils; +import com.newyetai.sdk.bytedance.model.Code2SessionDataDTO; +import com.newyetai.sdk.bytedance.model.Code2SessionReqDTO; +import com.newyetai.sdk.common.dto.LiteUserPhoneDTO; +import com.newyetai.sdk.common.util.LiteEncryptor; +import com.newyetai.sdk.wechat.WechatClient; +import com.newyetai.sdk.wechat.model.AbstractAccessTokenReq; +import com.newyetai.sdk.wechat.model.AccessTokenDTO; +import com.newyetai.sdk.wechat.model.BaseWeChatDTO; +import com.newyetai.sdk.wechat.model.BatchUnionDTO; +import com.newyetai.sdk.wechat.model.BatchUnionReq; +import com.newyetai.sdk.wechat.model.BufferDTO; +import com.newyetai.sdk.wechat.model.Code2SessionDTO; +import com.newyetai.sdk.wechat.model.JsApiTicketDTO; +import com.newyetai.sdk.wechat.model.PhoneNumberDTO; +import com.newyetai.sdk.wechat.model.PhoneNumberReq; +import com.newyetai.sdk.wechat.model.SubscibeMessageReq; +import com.newyetai.sdk.wechat.model.SubscibeUserDTO; +import com.newyetai.sdk.wechat.model.SubscibeUserReq; +import com.newyetai.sdk.wechat.model.UnionDTO; +import com.newyetai.sdk.wechat.model.UnionUser; +import com.newyetai.sdk.wechat.model.UrlSchemeDTO; +import com.newyetai.sdk.wechat.model.UrlSchemeReq; +import com.newyetai.sdk.wechat.model.WxacodeReq; +import com.newyetai.usercenter.auth.constant.AuthTypeEnum; +import com.newyetai.usercenter.auth.dao.AuthClientMapper; +import com.newyetai.usercenter.auth.dto.AuthClientDTO; +import com.newyetai.usercenter.auth.dto.AuthClientDataDTO; +import com.newyetai.usercenter.auth.dto.AuthClientOperateDTO; +import com.newyetai.usercenter.auth.dto.AuthClientQueryDTO; +import com.newyetai.usercenter.auth.dto.CodeToSessionDTO; +import com.newyetai.usercenter.auth.dto.LitePhoneAuthDTO; +import com.newyetai.usercenter.auth.entity.AuthClient; +import com.newyetai.usercenter.auth.mapstruct.AuthClientMapMapper; +import com.newyetai.usercenter.auth.service.AuthClientService; +import com.newyetai.usercenter.auth.util.AuthClientUtils; +import com.newyetai.usercenter.auth.wechat.dto.WechatSignatureReqDTO; +import com.newyetai.usercenter.auth.wechat.dto.WechatSignatureResDTO; +import com.newyetai.usercenter.sys.util.DomainUtils; + +/** + * @author sr on 2021-05-24 + */ +@Service +public class AuthClientServiceImpl implements AuthClientService { + + @Autowired + private AuthClientMapper authClientMapper; + + @Override + public Long create(AuthClientOperateDTO authClientOperateDTO) { + AuthClient authClient = AuthClientMapMapper.INSTANCE.toEntity(authClientOperateDTO); + authClientMapper.saveEntity(authClient); + return authClient.getId(); + } + + @Override + public void modify(AuthClientOperateDTO authClientOperateDTO) { + AuthClient authClient = AuthClientMapMapper.INSTANCE.toEntity(authClientOperateDTO); + authClientMapper.updateEntitySelective(authClient); + } + + @Override + public void remove(Long id) { + authClientMapper.deleteEntity(AuthClient.builder().id(id).build(), + UserContextHolder.getLoginUserId()); + } + + @Override + public void page(AuthClientQueryDTO authClientQueryDTO) { + authClientMapper.list(authClientQueryDTO); + } + + @Override + public List list(AuthClientQueryDTO authClientQueryDTO) { + authClientQueryDTO.disablePage(); + return authClientMapper.list(authClientQueryDTO); + } + + @Override + public AuthClientDTO findAuthClientDTO(AuthClientQueryDTO authClientQueryDTO) { + authClientQueryDTO.disablePage(); + List authClientDTOs = authClientMapper.listAuthClientDTO(authClientQueryDTO); + Assert.isTrue(!authClientDTOs.isEmpty(), "未找到对应匹配的授权配置信息"); + Assert.isTrue(authClientDTOs.size() == 1, "找到多个匹配的授权配置信息"); + return authClientDTOs.get(0); + } + + @Override + public AuthClientDataDTO findClientData(AuthClientQueryDTO authClientQueryDTO) { + AuthClientDTO authClientDTO = findAuthClientDTO(authClientQueryDTO); + return toClientData(authClientDTO); + } + + @Override + public AuthClientDataDTO toClientData(AuthClientDTO authClientDTO) { + String paramDataStr = authClientDTO.getParamData(); + Assert.isTrue(StringUtils.isNotBlank(paramDataStr), "授权客户端缺少第三方配置"); + AuthClientDataDTO authClientDataDTO = JsonUtils.toObject(paramDataStr, AuthClientDataDTO.class); + authClientDataDTO.setAuthClientId(authClientDTO.getId()); + authClientDataDTO.setAuthTypeCode(authClientDTO.getAuthTypeCode()); + return authClientDataDTO; + } + + @Override + public String getAccessToken(AuthClientQueryDTO authClientQueryDTO) { + AuthClientDataDTO authClientDataDTO = this.findClientData(authClientQueryDTO); + return this.getAccessToken(authClientDataDTO); + } + + @Override + public String getAccessToken(AuthClientDataDTO authClientDataDTO) { + Long authClientId = authClientDataDTO.getAuthClientId(); + String redisKey = AuthClientUtils.getRedisAccessTokenKey(authClientId); + String token = (String) RedisUtils.get(redisKey); + if (StringUtils.isNotBlank(token)) { + return token; + } + WechatClient client = + new WechatClient(authClientDataDTO.getClientId(), authClientDataDTO.getClientSecret()); + + AlitaResult tokenResult = client.getAccessToken(); + Assert.isTrue(tokenResult.getSuccess(), "微信token获取失败:" + tokenResult.getMsg()); + token = tokenResult.getData().getAccessToken(); + RedisUtils.add(redisKey, token, AuthClientUtils.DEFAULT_EXPIRE_TIME); + return token; + } + + @Override + public String getJsApiTicket(AuthClientQueryDTO authClientQueryDTO) { + AuthClientDataDTO authClientDataDTO = this.findClientData(authClientQueryDTO); + return this.getJsApiTicket(authClientDataDTO); + } + + private String getJsApiTicket(AuthClientDataDTO authClientDataDTO) { + Long authClientId = authClientDataDTO.getAuthClientId(); + String redisKey = AuthClientUtils.getRedisAccessTokenKey(authClientId); + // 判断缓存是否存在,不存在调接口 + String ticket = (String) RedisUtils.get(redisKey); + if (StringUtils.isNotBlank(ticket)) { + return ticket; + } + String accessToken = this.getAccessToken(authClientDataDTO); + AlitaResult ticketResult = WechatClient.getJsApiTicket(accessToken); + Assert.isTrue(ticketResult.getSuccess(), "微信ticket获取失败:" + ticketResult.getMsg()); + ticket = ticketResult.getData().getTicket(); + RedisUtils.add(redisKey, ticket, AuthClientUtils.DEFAULT_EXPIRE_TIME); + return ticket; + } + + @Override + public WechatSignatureResDTO signature(WechatSignatureReqDTO wechatSignatureDTO) { + AuthClientDataDTO authClientDataDTO = this.findClientData(wechatSignatureDTO); + // 当前时间戳 + String timestamp = String.valueOf(System.currentTimeMillis() / 1000); + // 数据字符串 + String nonceStr = RandomUtils.generateUUID().substring(0, 16); + // ticket + String ticket = this.getJsApiTicket(authClientDataDTO); + String str = String.format("jsapi_ticket=%s&noncestr=%s×tamp=%s&url=%s", ticket, nonceStr, + timestamp, wechatSignatureDTO.getUrl()); + // 签名 + String signature = DigestUtils.sha1Hex(str); + return WechatSignatureResDTO.builder().nonceStr(nonceStr).timestamp(timestamp) + .signature(signature).appId(authClientDataDTO.getClientId()).build(); + } + + /** + * 处理accessToken + * @param authClientDataDTO + * @param param + * @author sr on 2021-12-24 + */ + private void dealAccessToken(AuthClientDataDTO authClientDataDTO, Object param) { + if (param instanceof AbstractAccessTokenReq) { + AbstractAccessTokenReq req = (AbstractAccessTokenReq) param; + String accessToken = req.getAccessToken(); + if (StringUtils.isBlank(accessToken)) { + Assert.notNull(authClientDataDTO, "授权客户端配置为空"); + req.setAccessToken(getAccessToken(authClientDataDTO)); + } + } + } + + @Override + public byte[] getWxacode(AuthClientDataDTO authClientDataDTO, WxacodeReq wxacodeRequestParam) { + dealAccessToken(authClientDataDTO, wxacodeRequestParam); + AlitaResult wxacodeResult = WechatClient.getWxacode(wxacodeRequestParam); + Assert.isTrue(wxacodeResult.getSuccess(), "获取微信小程序码失败:" + wxacodeResult.getMsg()); + return wxacodeResult.getData().getBuffer(); + } + + @Override + public String getUrlscheme(AuthClientDataDTO authClientDataDTO, UrlSchemeReq urlSchemeRequestParam) { + dealAccessToken(authClientDataDTO, urlSchemeRequestParam); + AlitaResult urlSchemeResult = WechatClient.getUrlscheme(urlSchemeRequestParam); + Assert.isTrue(urlSchemeResult.getSuccess(), "获取微信小程序scheme码失败:" + urlSchemeResult.getMsg()); + return urlSchemeResult.getData().getOpenlink(); + } + + @Override + public void subscibeMessage(AuthClientDataDTO authClientDataDTO, SubscibeMessageReq subscibeMessageReq) { + dealAccessToken(authClientDataDTO, subscibeMessageReq); + AlitaResult subscibeMessagResult = WechatClient.subscibeMessage(subscibeMessageReq); + Assert.isTrue(subscibeMessagResult.getSuccess(), "发送微信小程序订阅消息失败:" + subscibeMessagResult.getMsg()); + } + + @Override + public CodeToSessionDTO getCodeToSessionDTO(AuthClientDataDTO authClientDataDTO, String code) { + Integer authTypeCode = authClientDataDTO.getAuthTypeCode(); + String clientId = authClientDataDTO.getClientId(); + String clientSecret = authClientDataDTO.getClientSecret(); + + if (AuthTypeEnum.WECHAT_LITE.getCode().equals(authTypeCode)) { + WechatClient client = + new WechatClient(clientId, clientSecret); + AlitaResult sessionResult = client.code2Session(code); + Assert.isTrue(sessionResult.getSuccess(), "获取小程序用户信息失败:" + sessionResult.getMsg()); + return AuthClientMapMapper.INSTANCE.to(sessionResult.getData()); + } else if (AuthTypeEnum.BYTE_DANCE_LITE.getCode().equals(authTypeCode)) { + AlitaResult sessionResult = ByteDanceUtils + .execute(Code2SessionReqDTO.builder().appId(clientId).secret(clientSecret) + .code(code).build()); + Assert.isTrue(sessionResult.getSuccess(), "获取小程序用户信息失败:" + sessionResult.getMsg()); + return AuthClientMapMapper.INSTANCE.to(sessionResult.getData()); + } else { + throw new BusinessException("授权类型有误"); + } + } + + @Override + public String getPhone(LitePhoneAuthDTO litePhoneAuthDTO) { + String domainOrIp = DomainUtils.getOrDefault(litePhoneAuthDTO.getDomainOrIp()); + Integer authTypeCode = litePhoneAuthDTO.getAuthTypeCode(); + AuthClientDataDTO authClientDataDTO = this + .findClientData(AuthClientQueryDTO.builder().domainOrIp(domainOrIp) + .authTypeCode(authTypeCode).build()); + String phoneCode = litePhoneAuthDTO.getPhoneCode(); + String phone = null; + if (AuthTypeEnum.WECHAT_LITE.getCode().equals(authTypeCode) + && StringUtils.isNotBlank(phoneCode)) { + phone = this.getPhone(authClientDataDTO, phoneCode); + } else { + CodeToSessionDTO codeToSessionDTO = + this.getCodeToSessionDTO(authClientDataDTO, litePhoneAuthDTO.getCode()); + LiteUserPhoneDTO liteUserPhoneDTO = LiteEncryptor.decrypt(litePhoneAuthDTO.getEncryptedData(), + litePhoneAuthDTO.getIv(), codeToSessionDTO.getSessionKey(), LiteUserPhoneDTO.class); + phone = liteUserPhoneDTO.getPhoneNumber(); + } + return phone; + } + + @Override + public List subscribeUser(AuthClientDataDTO authClientDataDTO) { + String accessToken = getAccessToken(authClientDataDTO); + AlitaResult result = + WechatClient.getSubscibeUser(SubscibeUserReq.builder().accessToken(accessToken).build()); + Assert.isTrue(result.getSuccess(), "获取订阅用户列表失败:" + result.getMsg()); + // TODO 待关注人数超1w时,修复分页 + return result.getData().getData().getOpenId(); + } + + @Override + public List batchUnion(AuthClientDataDTO authClientDataDTO, List openIds) { + String accessToken = getAccessToken(authClientDataDTO); + List partUser = Lists.newArrayListWithExpectedSize(100); + int totalSize = openIds.size(); + List totalUnionDTO = Lists.newArrayListWithExpectedSize(totalSize); + for (int i = 0; i< totalSize; i++) { + partUser.add(UnionUser.builder().openId(openIds.get(i)).build()); + if (i % 99 == 0 || i == totalSize -1) { + // 整百/最后一个 + AlitaResult batchUnionResult = WechatClient.batchUnion(BatchUnionReq.builder().accessToken(accessToken).users(partUser).build()); + Assert.isTrue(batchUnionResult.getSuccess(), "获取订阅用户unionid失败:" + batchUnionResult.getMsg()); + totalUnionDTO.addAll(batchUnionResult.getData().getUserInfoList()); + partUser = Lists.newArrayListWithExpectedSize(100); + } + } + return totalUnionDTO; + } + + @Override + public String getPhone(AuthClientDataDTO authClientDataDTO, String phoneCode) { + AlitaResult phoneResult = WechatClient.phoneNumber(PhoneNumberReq.builder() + .accessToken(getAccessToken(authClientDataDTO)).code(phoneCode).build()); + Assert.isTrue(phoneResult.getSuccess(), "获取授权手机号失败:" + phoneResult.getMsg()); + return phoneResult.getData().getPhoneInfo().getPhoneNumber(); + } + + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/service/impl/AuthDetailEntrypointServiceImpl.java b/src/main/java/com/newyetai/usercenter/auth/service/impl/AuthDetailEntrypointServiceImpl.java new file mode 100644 index 0000000..14d84d4 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/service/impl/AuthDetailEntrypointServiceImpl.java @@ -0,0 +1,328 @@ +package com.newyetai.usercenter.auth.service.impl; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.ZoneId; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.google.common.collect.Maps; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.IdcardUtils; +import com.newyetai.common.util.ListUtil; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.usercenter.auth.constant.AuthDetailEntrypointConstants; +import com.newyetai.usercenter.auth.constant.AuthTypeEnum; +import com.newyetai.usercenter.auth.dao.AuthDetailEntrypointMapper; +import com.newyetai.usercenter.auth.dao.AuthSubscribeDetailMapper; +import com.newyetai.usercenter.auth.dto.AuthClientDataDTO; +import com.newyetai.usercenter.auth.dto.AuthClientQueryDTO; +import com.newyetai.usercenter.auth.dto.AuthCodeDTO; +import com.newyetai.usercenter.auth.dto.AuthDetailCreateDTO; +import com.newyetai.usercenter.auth.dto.AuthDetailEntrypointCreateRes; +import com.newyetai.usercenter.auth.dto.AuthDetailEntrypointDTO; +import com.newyetai.usercenter.auth.dto.AuthDetailEntrypointQueryDTO; +import com.newyetai.usercenter.auth.dto.CodeToSessionDTO; +import com.newyetai.usercenter.auth.dto.InviteInfoDTO; +import com.newyetai.usercenter.auth.dto.InviteInfoPageQueryDTO; +import com.newyetai.usercenter.auth.dto.InviteStatisticDTO; +import com.newyetai.usercenter.auth.dto.InviteStatisticInfoDTO; +import com.newyetai.usercenter.auth.dto.InviteStatisticQueryDTO; +import com.newyetai.usercenter.auth.dto.PcInviteInfoDTO; +import com.newyetai.usercenter.auth.dto.PcInviteInfoPageQueryDTO; +import com.newyetai.usercenter.auth.dto.PcInviteStatisticInfoDTO; +import com.newyetai.usercenter.auth.dto.RegistrationInfoDTO; +import com.newyetai.usercenter.auth.entity.AuthDetailEntrypoint; +import com.newyetai.usercenter.auth.entity.AuthSubscribeDetail; +import com.newyetai.usercenter.auth.service.AuthClientService; +import com.newyetai.usercenter.auth.service.AuthDetailEntrypointService; +import com.newyetai.usercenter.auth.service.AuthDetailService; +import com.newyetai.usercenter.sys.util.DomainUtils; +import com.newyetai.usercenter.user.constant.UserTypeEnum; +import com.newyetai.usercenter.user.dao.UserMapper; +import com.newyetai.usercenter.user.dto.UserAuthQueryDTO; +import com.newyetai.usercenter.user.dto.UserRegisterCodeInfoDTO; +import com.newyetai.usercenter.user.login.dto.UserDetailDTO; +import com.newyetai.usercenter.user.service.UserRegisterService; + +import cn.hutool.core.date.DateUtil; + +/** + * @author sr on 2022-01-06 + */ +@Service +public class AuthDetailEntrypointServiceImpl implements AuthDetailEntrypointService { + + @Autowired + private AuthDetailEntrypointMapper authDetailEntrypointMapper; + + @Autowired + private AuthClientService authClientService; + + @Autowired + private AuthDetailService authDetailService; + + @Autowired + private UserRegisterService userRegisterService; + + @Autowired + private UserMapper userMapper; + + @Autowired + private AuthSubscribeDetailMapper authSubscribeDetailMapper; + + @Override + @Transactional + public AuthDetailEntrypointCreateRes create(AuthCodeDTO authCodeDTO) { + String domainOrIp = DomainUtils.getOrDefault(authCodeDTO.getDomainOrIp()); + Integer authTypeCode = authCodeDTO.getAuthTypeCode(); + AuthClientDataDTO authClientDataDTO = authClientService + .findClientData(AuthClientQueryDTO.builder().domainOrIp(domainOrIp) + .authTypeCode(authTypeCode).build()); + CodeToSessionDTO codeToSessionDTO = + authClientService.getCodeToSessionDTO(authClientDataDTO, authCodeDTO.getCode()); + String authUnionId = codeToSessionDTO.getUnionId(); + // 是否关注公众号 + boolean subscribe = authSubscribeDetailMapper + .existsEntity(AuthSubscribeDetail.builder().uniqueId(authUnionId).build()); + AuthDetailEntrypointCreateRes createRes = AuthDetailEntrypointCreateRes.builder().subscribe(subscribe).build(); + // 判断授权用户是否已注册用户 + UserAuthQueryDTO userAuthQueryDTO = (UserAuthQueryDTO) UserAuthQueryDTO.builder() + .authMainType(AuthTypeEnum.getAuthMainType(authTypeCode)) + .uniqueId(authUnionId) + .userType(UserTypeEnum.PERSON.getType()) + .build() + .disablePage(); + List userDetailDTOs = + userMapper.listAuthUserDetailDTO(userAuthQueryDTO); + if(!userDetailDTOs.isEmpty()) { + return createRes; + } + // 获取创建授权信息 + long authDetailId = authDetailService.create(AuthDetailCreateDTO.builder() + .authClientId(authClientDataDTO.getAuthClientId()).authTypeCode(authTypeCode) + .openId(codeToSessionDTO.getOpenId()).uniqueId(authUnionId).build()); + String registerCode = authCodeDTO.getRegisterCode(); + Long unionId = null; + if (StringUtils.isNotBlank(registerCode)) { + UserRegisterCodeInfoDTO infoDto = userRegisterService.analyRegisterCode(registerCode); + if (infoDto != null) { + unionId = infoDto.getUnionId(); + } + } + // 是否已存在 + AuthDetailEntrypointDTO authDetailEntrypointDTO = find( + AuthDetailEntrypointQueryDTO.builder().authDetailId(authDetailId).unionId(unionId).build()); + if (authDetailEntrypointDTO != null) { + return createRes; + } + AuthDetailEntrypoint authDetailEntrypoint = + AuthDetailEntrypoint.builder().authDetailId(authDetailId).unionId(unionId).build(); + authDetailEntrypointMapper.saveEntity(authDetailEntrypoint); + return createRes; + } + + @Override + @Transactional + public void remove(Long id) { + authDetailEntrypointMapper.deleteEntity(AuthDetailEntrypoint.builder().id(id).build(), + UserContextHolder.getLoginUserId()); + } + + @Override + public List list( + AuthDetailEntrypointQueryDTO authDetailEntrypointQueryDTO) { + authDetailEntrypointQueryDTO.disablePage(); + return authDetailEntrypointMapper.listAuthDetailEntrypointDTO(authDetailEntrypointQueryDTO); + } + + @Override + public void page(AuthDetailEntrypointQueryDTO authDetailEntrypointQueryDTO) { + authDetailEntrypointMapper.listAuthDetailEntrypointDTO(authDetailEntrypointQueryDTO); + } + + @Override + public AuthDetailEntrypointDTO find(AuthDetailEntrypointQueryDTO authDetailEntrypointQueryDTO) { + List authDetailEntrypointDTOs = + this.list(authDetailEntrypointQueryDTO); + return authDetailEntrypointDTOs.isEmpty() ? null : ListUtil.first(authDetailEntrypointDTOs); + } + + @Override + public List inviteInfoPage(InviteInfoPageQueryDTO queryDTO) { + if (queryDTO.getQueryType() != null && queryDTO.getQueryType() == 2) { + queryDTO.setStartTime(DateUtil.beginOfDay(DateUtil.date())); + }else { + queryDTO.setStartTime(null); + } + List inviteInfoDTOS = authDetailEntrypointMapper.inviteInfoPage(queryDTO, UserContextHolder.getExistLoginUserId() + , UserContextHolder.getExistLoginOrgId()); + if (CollectionUtils.isNotEmpty(inviteInfoDTOS)){ + Set userIds = inviteInfoDTOS.stream().map(InviteInfoDTO::getUserId).collect(Collectors.toSet()); + List registrationInfoDTOS = authDetailEntrypointMapper.registrationList(userIds); + Map statusMap = statusMap(registrationInfoDTOS); + return inviteInfoDTOS.stream().peek(inviteInfoDTO -> { + inviteInfoDTO.setStatus(statusMap.get(inviteInfoDTO.getUserId())); + }).collect(Collectors.toList()); + } + return inviteInfoDTOS; + } + + @Override + public InviteStatisticInfoDTO inviteInfoStatistic(InviteInfoPageQueryDTO queryDTO) { + + InviteStatisticInfoDTO infoDTO = new InviteStatisticInfoDTO(); + + queryDTO.setStartTime(null); + queryDTO.setQueryType(null); + infoDTO.setTotalInviteNumber(authDetailEntrypointMapper.inviteInfoPage(queryDTO, UserContextHolder.getExistLoginUserId() + , UserContextHolder.getExistLoginOrgId()).size()); + + queryDTO.setStartTime(DateUtil.beginOfDay(DateUtil.date())); + infoDTO.setTodayInviteNumber(authDetailEntrypointMapper.inviteInfoPage(queryDTO, UserContextHolder.getExistLoginUserId() + , UserContextHolder.getExistLoginOrgId()).size()); + + queryDTO.setStartTime(null); + queryDTO.setQueryType(1); + infoDTO.setOnTheJobNumber(authDetailEntrypointMapper.inviteInfoPage(queryDTO, UserContextHolder.getExistLoginUserId() + , UserContextHolder.getExistLoginOrgId()).size()); + return infoDTO; + } + + /** + * 状态图hh + * + * @param registrationInfoDTOS 注册信息dto + * @return {@link Map}<{@link Long}, {@link Integer}> + */ + private Map statusMap(List registrationInfoDTOS){ + Map statusMap = Maps.newHashMap(); + if (CollectionUtils.isEmpty(registrationInfoDTOS)){ + return statusMap; + } + for (RegistrationInfoDTO registrationInfoDTO : registrationInfoDTOS) { + Long userId = registrationInfoDTO.getUserId(); + Integer status = registrationInfoDTO.getStatus(); + Boolean termination = registrationInfoDTO.getTermination(); + Integer existStatus = statusMap.get(userId); + Integer newStatus = mergeStatus(status, termination); + if (Objects.isNull(existStatus)){ + statusMap.put(userId,newStatus); + }else { + if (AuthDetailEntrypointConstants.USER_JOB_STATUS_RESIGNED.equals(existStatus)){ + statusMap.put(userId,newStatus); + }else { + if (!(AuthDetailEntrypointConstants.USER_JOB_STATUS_RESIGNED.equals(newStatus) || Objects.isNull(newStatus))){ + if (newStatus > existStatus){ + statusMap.put(userId,newStatus); + } + } + } + } + } + return statusMap; + } + + /** + * 合并状态 + * + * @param originStatus 起源地位 + * @param termination 终止 + * @return {@link Integer} + */ + private Integer mergeStatus(Integer originStatus,Boolean termination){ + if (AuthDetailEntrypointConstants.USER_JOB_STATUS_ON_THE_JOB.equals(originStatus)){ + // 在职中 + return AuthDetailEntrypointConstants.USER_JOB_STATUS_ON_THE_JOB; + }else if (AuthDetailEntrypointConstants.USER_JOB_STATUS_ALREADY_REGISTERED.equals(originStatus) + || AuthDetailEntrypointConstants.USER_JOB_STATUS_INVITED.equals(originStatus) + || AuthDetailEntrypointConstants.USER_JOB_STATUS_INTERVIEWED.equals(originStatus) + || AuthDetailEntrypointConstants.USER_JOB_STATUS_TO_BE_HIRED.equals(originStatus) + ){ + // 已报名 + return AuthDetailEntrypointConstants.USER_JOB_STATUS_ALREADY_REGISTERED; + }else if (!Boolean.TRUE.equals(termination) || AuthDetailEntrypointConstants.USER_JOB_STATUS_NOT_REGISTERED.equals(originStatus)){ + // 未报名 + return AuthDetailEntrypointConstants.USER_JOB_STATUS_NOT_REGISTERED; + }else if (AuthDetailEntrypointConstants.USER_JOB_STATUS_RESIGNED.equals(originStatus)){ + // 已离职 + return AuthDetailEntrypointConstants.USER_JOB_STATUS_RESIGNED; + } + return null; + } + + @Override + public List pcInviteInfoPage(PcInviteInfoPageQueryDTO queryDTO) { + List result = authDetailEntrypointMapper.pcInviteInfoPage(queryDTO, UserContextHolder.getExistLoginOrgId()); + result.stream().forEach(exportDTO -> { + // 解析身份证性别、年龄 + if(StringUtils.isNotBlank(exportDTO.getCardNo())){ + exportDTO.setGender(IdcardUtils.judgeGender(exportDTO.getCardNo())); + exportDTO.setAge(IdcardUtils.getAgeByIDNumber(exportDTO.getCardNo())); + } + }); + return result; + } + + @Override + public PcInviteInfoDTO getInviteInfoDetail(PcInviteInfoPageQueryDTO queryDTO){ + List result = this.pcInviteInfoPage(queryDTO); + Assert.isTrue(result.size() == 1, "邀请人信息不唯一"); + return result.get(0); + } + + @Override + public PcInviteStatisticInfoDTO pcInviteStatisticQuery(InviteStatisticQueryDTO queryDTO) { + // PC端调用去除查询条件 + if(!"pc".equals(queryDTO.getClientType())){ + queryDTO.setUserId(UserContextHolder.getExistLoginUserId()); + if (Objects.isNull(queryDTO.getStartTime()) && Objects.isNull(queryDTO.getEndTime())) { + //日期转换 + ZoneId zone = ZoneId.systemDefault(); + Date startTime = Date.from(LocalDateTime.of(LocalDate.now(), LocalTime.MIN).atZone(zone).toInstant()); + Date endTime = Date.from(LocalDateTime.now().atZone(zone).toInstant()); + queryDTO.setStartTime(startTime); + queryDTO.setEndTime(endTime); + } + } + PcInviteStatisticInfoDTO infoDTO = new PcInviteStatisticInfoDTO(); + //查询邀请数 未注册数 + List inviteStatisticDTOS = authDetailEntrypointMapper.inviteStatisticQuery(queryDTO, UserContextHolder.getExistLoginOrgId()); + if (CollectionUtils.isNotEmpty(inviteStatisticDTOS)){ + for (InviteStatisticDTO inviteStatisticDTO : inviteStatisticDTOS) { + infoDTO.setInviteNumber(infoDTO.getInviteNumber() + 1); + if (Objects.isNull(inviteStatisticDTO.getUserAuthId())){ + infoDTO.setUnRegisterNumber(infoDTO.getUnRegisterNumber() + 1); + } + } + } + //查询注册数 + int count = authDetailEntrypointMapper.inviteRegisterCount(queryDTO, UserContextHolder.getExistLoginOrgId()); + infoDTO.setRegisterNumber(count); + return infoDTO; + } + + @Override + public InviteStatisticInfoDTO inviteStatisticQuery(InviteStatisticQueryDTO queryDTO) { + queryDTO.setUserId(UserContextHolder.getExistLoginUserId()); + InviteStatisticInfoDTO infoDTO = new InviteStatisticInfoDTO(); + infoDTO.setTotalInviteNumber(authDetailEntrypointMapper.countInviteStatisticQuery(queryDTO,UserContextHolder.getExistLoginOrgId())); + queryDTO.setStartTime(DateUtil.beginOfDay(DateUtil.date())); + infoDTO.setTodayInviteNumber(authDetailEntrypointMapper.countInviteStatisticQuery(queryDTO,UserContextHolder.getExistLoginOrgId())); + queryDTO.setStartTime(null); + queryDTO.setQueryType(1); + infoDTO.setOnTheJobNumber(authDetailEntrypointMapper.countInviteStatisticQuery(queryDTO,UserContextHolder.getExistLoginOrgId())); + return infoDTO; + } +} diff --git a/src/main/java/com/newyetai/usercenter/auth/service/impl/AuthDetailServiceImpl.java b/src/main/java/com/newyetai/usercenter/auth/service/impl/AuthDetailServiceImpl.java new file mode 100644 index 0000000..9535566 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/service/impl/AuthDetailServiceImpl.java @@ -0,0 +1,91 @@ +package com.newyetai.usercenter.auth.service.impl; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.frame.redis.dto.LockDTO; +import com.newyetai.frame.redis.redisson.RedissonUtils; +import com.newyetai.usercenter.auth.constant.AuthTypeEnum; +import com.newyetai.usercenter.auth.dao.AuthDetailMapper; +import com.newyetai.usercenter.auth.dto.AuthDetailCreateDTO; +import com.newyetai.usercenter.auth.dto.AuthDetailDTO; +import com.newyetai.usercenter.auth.dto.AuthDetailQueryDTO; +import com.newyetai.usercenter.auth.entity.AuthDetail; +import com.newyetai.usercenter.auth.mapstruct.AuthDetailMapMapper; +import com.newyetai.usercenter.auth.service.AuthDetailService; + +/** + * @author sr on 2021-05-24 + */ +@Service +public class AuthDetailServiceImpl implements AuthDetailService { + + private static final String AUTH_DETAIL_LOCK_NAME = "auth:detail"; + + @Autowired + private AuthDetailMapper authDetailMapper; + + private LockDTO getAuthDetailLockDTO(String openId) { + Assert.notBlank(openId, "第三方授权信息id不能为空"); + return LockDTO.builder().methodName(AUTH_DETAIL_LOCK_NAME).tryLockWaitTime(0L) + .arg(AUTH_DETAIL_LOCK_NAME) + .build(); + } + + @Override + @Transactional + public Long create(AuthDetailCreateDTO authDetailCreateDTO) { + Integer authTypeCode = authDetailCreateDTO.getAuthTypeCode(); + String openId = authDetailCreateDTO.getOpenId(); + // TODO 暂只支持微信公众号+小程序|字节小程序 + if (AuthTypeEnum.WECHAT.getCode().equals(authTypeCode) + || AuthTypeEnum.WECHAT_LITE.getCode().equals(authTypeCode) + || AuthTypeEnum.BYTE_DANCE_LITE.getCode().equals(authTypeCode)) { + // 上锁 + LockDTO lockDTO = getAuthDetailLockDTO(openId); + try { + Assert.isTrue(RedissonUtils.tryLock(lockDTO), "该授权信息正在被操作"); + List authDetailDTOs = + authDetailMapper.listAuthDetailDTO((AuthDetailQueryDTO) AuthDetailQueryDTO.builder() + .authTypeCode(authTypeCode).openId(openId).build().disablePage()); + int num = authDetailDTOs.size(); + Assert.isTrue(num <= 1, openId + "授权信息异常,请联系管理员"); + if (num == 0) { + // 无则创建 + AuthDetail authDetail = AuthDetailMapMapper.INSTANCE.toEntity(authDetailCreateDTO); + authDetailMapper.saveEntity(authDetail); + return authDetail.getId(); + } else { + return authDetailDTOs.get(0).getId(); + } + } finally { + RedissonUtils.unlock(lockDTO); + } + } else { + throw new BusinessException("暂不支持该类型授权信息"); + } + + } + + @Override + public void remove(Long id) { + + } + + @Override + public List list(AuthDetailQueryDTO authDetailQueryDTO) { + authDetailQueryDTO.disablePage(); + return authDetailMapper.listAuthDetailDTO(authDetailQueryDTO); + } + + @Override + public void page(AuthDetailQueryDTO authDetailQueryDTO) { + authDetailMapper.listAuthDetailDTO(authDetailQueryDTO); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/service/impl/AuthSubscribeDetailServiceImpl.java b/src/main/java/com/newyetai/usercenter/auth/service/impl/AuthSubscribeDetailServiceImpl.java new file mode 100644 index 0000000..ea09ba7 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/service/impl/AuthSubscribeDetailServiceImpl.java @@ -0,0 +1,94 @@ +package com.newyetai.usercenter.auth.service.impl; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.common.util.ListUtil; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.sdk.wechat.model.UnionDTO; +import com.newyetai.usercenter.auth.constant.AuthTypeEnum; +import com.newyetai.usercenter.auth.dao.AuthSubscribeDetailMapper; +import com.newyetai.usercenter.auth.dto.AuthClientDTO; +import com.newyetai.usercenter.auth.dto.AuthClientDataDTO; +import com.newyetai.usercenter.auth.dto.AuthClientQueryDTO; +import com.newyetai.usercenter.auth.dto.AuthSubscribeDetailCreateDTO; +import com.newyetai.usercenter.auth.dto.AuthSubscribeDetailDTO; +import com.newyetai.usercenter.auth.dto.AuthSubscribeDetailQueryDTO; +import com.newyetai.usercenter.auth.entity.AuthSubscribeDetail; +import com.newyetai.usercenter.auth.mapstruct.AuthSubscribeDetailMapMapper; +import com.newyetai.usercenter.auth.service.AuthClientService; +import com.newyetai.usercenter.auth.service.AuthSubscribeDetailService; + +/** + * @author sr on 2022-04-05 + */ +@Service +public class AuthSubscribeDetailServiceImpl implements AuthSubscribeDetailService { + + @Autowired + private AuthSubscribeDetailMapper authSubscribeDetailMapper; + + @Autowired + private AuthClientService authClientService; + + @Override + @Transactional + public void create(AuthSubscribeDetailCreateDTO createDto) { + Long authClientId = createDto.getAuthClientId(); + String openId = createDto.getOpenId(); + boolean exist = authSubscribeDetailMapper + .existsEntity(AuthSubscribeDetail.builder().authClientId(authClientId).openId(openId).build()); + if (exist) { + return; + } + authSubscribeDetailMapper.saveEntity(AuthSubscribeDetailMapMapper.INSTANCE.toEntity(createDto)); + } + + @Override + @Transactional + public void remove(Long id) { + authSubscribeDetailMapper.deleteEntity(AuthSubscribeDetail.builder().id(id).build(), + UserContextHolder.getLoginUserId()); + } + + @Override + public List list(AuthSubscribeDetailQueryDTO authSubscribeDetailQueryDTO) { + authSubscribeDetailQueryDTO.disablePage(); + return authSubscribeDetailMapper.listAuthSubscribeDetailDTO(authSubscribeDetailQueryDTO); + } + + @Override + public void page(AuthSubscribeDetailQueryDTO authSubscribeDetailQueryDTO) { + authSubscribeDetailMapper.listAuthSubscribeDetailDTO(authSubscribeDetailQueryDTO); + } + + @Override + public AuthSubscribeDetailDTO find(AuthSubscribeDetailQueryDTO authSubscribeDetailQueryDTO) { + List authSubscribeDetailDTOs = this.list(authSubscribeDetailQueryDTO); + return authSubscribeDetailDTOs.isEmpty() ? null : ListUtil.first(authSubscribeDetailDTOs); + } + + @Override + public void loadAllClient() { + List authClients = authClientService + .list(AuthClientQueryDTO.builder().authTypeCode(AuthTypeEnum.WECHAT.getCode()).build()); + if (authClients.isEmpty()) { + return ; + } + authClients.forEach(client -> { + // 获取订阅列表 + AuthClientDataDTO authClientDataDTO = authClientService.toClientData(client); + List openIds = authClientService.subscribeUser(authClientDataDTO); + List unionDtos = authClientService.batchUnion(authClientDataDTO, openIds); + unionDtos.stream().filter(d -> d.getSubscribe().equals(1)).forEach( + dto -> create(AuthSubscribeDetailCreateDTO.builder() + .authClientId(client.getId()) + .openId(dto.getOpenId()) + .uniqueId(dto.getUnionId()).build())); + }); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/service/impl/AuthTypeServiceImpl.java b/src/main/java/com/newyetai/usercenter/auth/service/impl/AuthTypeServiceImpl.java new file mode 100644 index 0000000..6bca174 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/service/impl/AuthTypeServiceImpl.java @@ -0,0 +1,39 @@ +package com.newyetai.usercenter.auth.service.impl; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.usercenter.auth.dao.AuthTypeMapper; +import com.newyetai.usercenter.auth.dto.AuthTypeDTO; +import com.newyetai.usercenter.auth.dto.AuthTypeOperateDTO; +import com.newyetai.usercenter.auth.dto.AuthTypeQueryDTO; +import com.newyetai.usercenter.auth.entity.AuthType; +import com.newyetai.usercenter.auth.mapstruct.AuthClientMapMapper; +import com.newyetai.usercenter.auth.service.AuthTypeService; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author sr on 2021-05-24 + */ +@Service +public class AuthTypeServiceImpl extends ServiceImpl implements AuthTypeService { + + + @Override + public Long create(AuthTypeOperateDTO operateDTO) { + AuthType authType = AuthClientMapMapper.INSTANCE.exchange(operateDTO); + Assert.isTrue(count(Wrappers.lambdaQuery() + .eq(AuthType::getDeleted,false) + .eq(AuthType::getAuthTypeCode,authType.getAuthTypeCode()) + ) == 0,"授权类型标识重复"); + save(authType); + return authType.getId(); + } + + @Override + public List list(AuthTypeQueryDTO queryDTO) { + return getBaseMapper().list(queryDTO); + } +} diff --git a/src/main/java/com/newyetai/usercenter/auth/service/impl/LiteCodeConfigServiceImpl.java b/src/main/java/com/newyetai/usercenter/auth/service/impl/LiteCodeConfigServiceImpl.java new file mode 100644 index 0000000..09bc64c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/service/impl/LiteCodeConfigServiceImpl.java @@ -0,0 +1,67 @@ +package com.newyetai.usercenter.auth.service.impl; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.usercenter.auth.dao.LiteCodeConfigMapper; +import com.newyetai.usercenter.auth.service.LiteCodeConfigService; +import com.newyetai.usercenter.auth.dto.LiteCodeConfigQueryDTO; +import com.newyetai.usercenter.auth.dto.LiteCodeConfigDTO; +import com.newyetai.usercenter.auth.dto.LiteCodeConfigOperateDTO; +import com.newyetai.usercenter.auth.entity.LiteCodeConfig; + +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.ListUtil; + +/** + * @author sr on 2021-12-21 + */ +@Service +public class LiteCodeConfigServiceImpl implements LiteCodeConfigService { + + @Autowired + private LiteCodeConfigMapper liteCodeConfigMapper; + + @Override + @Transactional + public Long create(LiteCodeConfigOperateDTO liteCodeConfigOperateDTO) { + // TODO Auto-generated method stub + return null; + } + + @Override + @Transactional + public void modify(LiteCodeConfigOperateDTO liteCodeConfigOperateDTO) { + // TODO Auto-generated method stub + + } + + @Override + @Transactional + public void remove(Long id) { + liteCodeConfigMapper.deleteEntity(LiteCodeConfig.builder().id(id).build(), + UserContextHolder.getLoginUserId()); + } + + @Override + public List list(LiteCodeConfigQueryDTO liteCodeConfigQueryDTO) { + liteCodeConfigQueryDTO.disablePage(); + return liteCodeConfigMapper.listLiteCodeConfigDTO(liteCodeConfigQueryDTO); + } + + @Override + public void page(LiteCodeConfigQueryDTO liteCodeConfigQueryDTO) { + liteCodeConfigMapper.listLiteCodeConfigDTO(liteCodeConfigQueryDTO); + } + + @Override + public LiteCodeConfigDTO findOne(LiteCodeConfigQueryDTO liteCodeConfigQueryDTO) { + List liteCodeConfigDTOs = this.list(liteCodeConfigQueryDTO); + Assert.isTrue(liteCodeConfigDTOs.size() == 1, "未找到唯一匹配小程序码配置"); + return ListUtil.first(liteCodeConfigDTOs); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/service/impl/LiteCodeServiceImpl.java b/src/main/java/com/newyetai/usercenter/auth/service/impl/LiteCodeServiceImpl.java new file mode 100644 index 0000000..5fbe1a7 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/service/impl/LiteCodeServiceImpl.java @@ -0,0 +1,181 @@ +package com.newyetai.usercenter.auth.service.impl; + +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.ListUtil; +import com.newyetai.common.util.RandomUtils; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.component.file.service.FileService; +import com.newyetai.frame.redis.aop.annotation.AutoUnLock; +import com.newyetai.frame.redis.dto.LockDTO; +import com.newyetai.frame.redis.redisson.RedissonUtils; +import com.newyetai.sdk.wechat.model.JumpWxa; +import com.newyetai.sdk.wechat.model.UrlSchemeReq; +import com.newyetai.sdk.wechat.model.WxacodeReq; +import com.newyetai.usercenter.auth.constant.AuthTypeEnum; +import com.newyetai.usercenter.auth.constant.LiteCodeConstant; +import com.newyetai.usercenter.auth.dao.LiteCodeMapper; +import com.newyetai.usercenter.auth.dto.*; +import com.newyetai.usercenter.auth.entity.LiteCode; +import com.newyetai.usercenter.auth.mapstruct.LiteCodeMapMapper; +import com.newyetai.usercenter.auth.service.AuthClientService; +import com.newyetai.usercenter.auth.service.LiteCodeConfigService; +import com.newyetai.usercenter.auth.service.LiteCodeService; +import com.newyetai.usercenter.auth.util.AuthClientUtils; +import com.newyetai.usercenter.auth.util.LiteCodeUtils; +import com.newyetai.usercenter.sys.dao.DomainMapper; +import com.newyetai.usercenter.sys.dto.DomainDTO; +import com.newyetai.usercenter.sys.dto.DomainQueryDTO; +import com.newyetai.usercenter.sys.util.DomainUtils; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; + +/** + * @author sr on 2021-12-21 + */ +@Service +public class LiteCodeServiceImpl implements LiteCodeService { + + /** 小程序码文件名称 **/ + public static final String CODE_FILE_NAME = "wxacode.png"; + private static final String LOCK_NAME = "lite:code"; + + @Autowired + private LiteCodeMapper liteCodeMapper; + + @Autowired + private AuthClientService authClientService; + + @Autowired + private LiteCodeConfigService liteCodeConfigService; + + @Autowired + private FileService fileService; + + @Autowired + private DomainMapper domainMapper; + + public static LockDTO getLockDTO(Long liteCodeConfigId, String name, String paramValue, Long userId, + Long orgId) { + Assert.isTrue(liteCodeConfigId != null && StringUtils.isNotBlank(name), "小程序码配置不能为空"); + return LockDTO.builder().methodName(LOCK_NAME).tryLockWaitTime(0L) + .arg(liteCodeConfigId.toString()) + .arg(name) + .arg(paramValue) + .arg(Optional.ofNullable(userId).orElse(0L).toString()) + .arg(Optional.ofNullable(orgId).orElse(0L).toString()) + .build(); + } + + + @Override + @Transactional + @AutoUnLock + public LiteCodeDTO create(LiteCodeCreateDTO liteCodeCreateDTO) { + String domainOrIp = DomainUtils.getOrDefault(liteCodeCreateDTO.getDomainOrIp()); + + //只有PC端的才需要这个校验 + if (Objects.nonNull(liteCodeCreateDTO.getSourceFrom()) + && LiteCodeConstant.SOURCE_FROM_PC.equals(liteCodeCreateDTO.getSourceFrom())){ + List domainDTOS = domainMapper.listDomainDTO(DomainQueryDTO.builder() + .orgId(UserContextHolder.getExistLoginOrgId()) + .domainOrIp(domainOrIp) + .build()); + Assert.isTrue(CollectionUtils.size(domainDTOS) == 1,"当前域名无法生成邀请二维码,请登录机构绑定域名操作"); + } + + Integer authTypeCode = liteCodeCreateDTO.getAuthTypeCode(); + Assert.isTrue(AuthTypeEnum.WECHAT_LITE.getCode().equals(authTypeCode), "暂只处理微信小程序码"); + AuthClientDataDTO authClientDataDTO = authClientService + .findClientData(AuthClientQueryDTO.builder().domainOrIp(domainOrIp) + .authTypeCode(authTypeCode).build()); + // 查询小程序码配置 + LiteCodeConfigDTO liteCodeConfigDTO = liteCodeConfigService.findOne( + LiteCodeConfigQueryDTO.builder().authClientId(authClientDataDTO.getAuthClientId()) + .bizType(liteCodeCreateDTO.getBizType()).build()); + Long liteCodeConfigId = liteCodeConfigDTO.getId(); + Map paramData = liteCodeCreateDTO.getParamData(); + String paramValue = LiteCodeUtils.buildParamValue(liteCodeConfigDTO, paramData); + + Long userId = MapUtils.getLong(paramData, LiteCodeUtils.USER_ID_KEY); + Long orgId = MapUtils.getLong(paramData, LiteCodeUtils.ORG_ID_KEY); + String name = liteCodeCreateDTO.getName(); + LiteCodeQueryDTO liteCodeQueryDTO = + LiteCodeQueryDTO.builder().liteCodeConfigId(liteCodeConfigId).name(name) + .paramValue(paramValue).userId(userId).orgId(orgId).build(); + LiteCodeDTO liteCodeDTO = find(liteCodeQueryDTO); + if (liteCodeDTO != null) { + return liteCodeDTO; + } + // 上锁 + LockDTO lockDTO = getLockDTO(liteCodeConfigId, name, paramValue, userId, orgId); + Assert.isTrue(RedissonUtils.tryLockAutomatically(lockDTO), "小程序码正在被生成"); + liteCodeDTO = find(liteCodeQueryDTO); + if (liteCodeDTO != null) { + return liteCodeDTO; + } + LiteCode liteCode = LiteCode.builder().liteCodeConfigId(liteCodeConfigId) + .uniqueCode(RandomUtils.generateUUID()).paramValue(paramValue).name(name) + .userId(userId) + .orgId(orgId) + .platformCode(liteCodeConfigDTO.getPlatformCode()) + .build(); + liteCodeMapper.saveEntity(liteCode); + Long liteCodeId = liteCode.getId(); + String queryValue = LiteCodeUtils.buildQueryValue(liteCodeId, liteCodeConfigDTO, paramData); + + String fileCode = null; + String path = liteCodeConfigDTO.getPath(); + // 小程序码 + WxacodeReq wxacodeRequestParam = WxacodeReq.builder() + .path(path + CommonConstants.QUESTION + queryValue).build(); + fileCode = fileService + .upload(CODE_FILE_NAME, + AuthClientUtils.getService().getWxacode(authClientDataDTO, wxacodeRequestParam)) + .getFileCode(); + // 小程序scheme码 + UrlSchemeReq urlSchemeRequestParam = + UrlSchemeReq.builder() + .jumpWxa( + JumpWxa.builder().path(path).query(queryValue) + .envVersion(LiteCodeUtils.getEnvVersion()).build()) + .build(); + String urlScheme = AuthClientUtils.getService().getUrlscheme(authClientDataDTO, urlSchemeRequestParam); + liteCode.setQueryValue(queryValue); + liteCode.setFileCode(fileCode); + liteCode.setUrlScheme(urlScheme); + liteCodeMapper.updateEntity(liteCode); + return LiteCodeMapMapper.INSTANCE.toDto(liteCode); + } + + @Override + public List list(LiteCodeQueryDTO liteCodeQueryDTO) { + liteCodeQueryDTO.disablePage(); + return liteCodeMapper.listLiteCodeDTO(liteCodeQueryDTO); + } + + @Override + public void page(LiteCodeQueryDTO liteCodeQueryDTO) { + liteCodeMapper.listLiteCodeDTO(liteCodeQueryDTO); + } + + @Override + public LiteCodeDTO find(LiteCodeQueryDTO liteCodeQueryDTO) { + List liteCodeDTOs = this.list(liteCodeQueryDTO); + return liteCodeDTOs.isEmpty() ? null : ListUtil.first(liteCodeDTOs); + } + + @Override + public LiteCodeDTO modify(LiteCodeModifyDTO liteCodeModifyDTO) { + liteCodeMapper.updateEntitySelective( + LiteCode.builder().id(liteCodeModifyDTO.getId()).name(liteCodeModifyDTO.getName()).build()); + return this.find(LiteCodeQueryDTO.builder().id(liteCodeModifyDTO.getId()).build()); + } +} diff --git a/src/main/java/com/newyetai/usercenter/auth/service/impl/LitePhoneLoginProvider.java b/src/main/java/com/newyetai/usercenter/auth/service/impl/LitePhoneLoginProvider.java new file mode 100644 index 0000000..a27c961 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/service/impl/LitePhoneLoginProvider.java @@ -0,0 +1,122 @@ +package com.newyetai.usercenter.auth.service.impl; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.newyetai.common.dto.CasTokenDTO; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.DevopsException; +import com.newyetai.common.exception.WithResultException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.sdk.common.dto.LiteUserPhoneDTO; +import com.newyetai.sdk.common.util.LiteEncryptor; +import com.newyetai.sdk.robot.util.RobotUtils; +import com.newyetai.security.expection.BadLoginException; +import com.newyetai.security.jwt.JwtTokenUtils; +import com.newyetai.security.mapstruct.UserMapMapper; +import com.newyetai.security.util.HostContextHolder; +import com.newyetai.usercenter.auth.constant.AuthTypeEnum; +import com.newyetai.usercenter.auth.dto.AuthClientDataDTO; +import com.newyetai.usercenter.auth.dto.AuthClientQueryDTO; +import com.newyetai.usercenter.auth.dto.AuthDetailBindDTO; +import com.newyetai.usercenter.auth.dto.CodeToSessionDTO; +import com.newyetai.usercenter.auth.dto.LitePhoneLoginDTO; +import com.newyetai.usercenter.auth.mapstruct.AuthDetailMapMapper; +import com.newyetai.usercenter.auth.service.AuthClientService; +import com.newyetai.usercenter.sys.util.DomainUtils; +import com.newyetai.usercenter.user.login.dto.LoginPhoneDTO; +import com.newyetai.usercenter.user.login.dto.UserDetailDTO; +import com.newyetai.usercenter.user.login.service.UserLoginService; +import com.newyetai.usercenter.user.service.UserService; + +import lombok.extern.slf4j.Slf4j; + + +/** + * 小程序登录提供者 + * @author sr on 2022-01-04 + */ +@Service +@Slf4j +public class LitePhoneLoginProvider { + + @Autowired + private AuthClientService authClientService; + + @Autowired + private UserLoginService userLoginService; + + @Autowired + private UserService userService; + + public CasTokenDTO loginLite(LitePhoneLoginDTO litePhoneLoginDTO) { + Assert.notNull(litePhoneLoginDTO.getAuthTypeCode(), "授权类型不能为空"); + AuthDetailBindDTO authDetailBindDTO = this.toAuthDetailDTO(litePhoneLoginDTO); + LoginPhoneDTO loginPhoneDTO = AuthDetailMapMapper.INSTANCE.to(litePhoneLoginDTO); + try { + UserDetailDTO userDetailDTO = userLoginService.loadUser(loginPhoneDTO); + String token = JwtTokenUtils.generateToken(UserMapMapper.INSTANCE.dtoToDto(userDetailDTO)); + // 指定用户id + authDetailBindDTO.setUserId(userDetailDTO.getId()); + if (StringUtils.isBlank(authDetailBindDTO.getUniqueId())) { + log.debug(authDetailBindDTO.getAuthClientId() + "-小程序未挂载开放平台"); + // RobotUtils.sendDevops(authDetailBindDTO.getAuthClientId() + "-小程序未挂载开放平台"); + } else { + try { + userService.bindUserAuth(authDetailBindDTO); + } catch (Exception e) { + // 现在都没看,也就没必要发了 + /*RobotUtils.sendDevops("微信小程序登录绑定授权信息失败:authClientId=" + authDetailBindDTO.getAuthClientId() + + ",unionId=" + authDetailBindDTO.getUniqueId() + + ",openId=" + authDetailBindDTO.getOpenId());*/ + log.info("auth login bind error:{},clientId:{},openId:{},unionId:{}", e.getMessage(), + authDetailBindDTO.getAuthClientId(), authDetailBindDTO.getOpenId(), + authDetailBindDTO.getUniqueId()); + } + } + return CasTokenDTO.builder().token(token).register(userDetailDTO.getRegister()).build(); + } catch (BadLoginException be) { + throw new WithResultException(be.getResult(), be); + } catch (BusinessException be) { + throw be; + } catch (Exception e) { + throw new BusinessException(e.getMessage(), e); + } + } + + /** + * 获取授权绑定对象 + * 手机号,openId,unionId等 + * @param litePhoneLoginDTO + * @return + * @author sr on 2022-03-15 + */ + private AuthDetailBindDTO toAuthDetailDTO(LitePhoneLoginDTO litePhoneLoginDTO) { + Integer authTypeCode = litePhoneLoginDTO.getAuthTypeCode(); + AuthClientDataDTO authClientDataDTO = authClientService + .findClientData(AuthClientQueryDTO.builder() + .domainOrIp(DomainUtils.getOrDefault(litePhoneLoginDTO.getDomainOrIp())) + .authTypeCode(authTypeCode).build()); + CodeToSessionDTO codeToSessionDTO = + authClientService.getCodeToSessionDTO(authClientDataDTO, litePhoneLoginDTO.getCode()); + String phoneCode = litePhoneLoginDTO.getPhoneCode(); + String phone = null; + if (AuthTypeEnum.WECHAT_LITE.getCode().equals(authTypeCode) + && StringUtils.isNotBlank(phoneCode)) { + phone = authClientService.getPhone(authClientDataDTO, phoneCode); + } else { + LiteUserPhoneDTO liteUserPhoneDTO = LiteEncryptor.decrypt(litePhoneLoginDTO.getEncryptedData(), + litePhoneLoginDTO.getIv(), codeToSessionDTO.getSessionKey(), LiteUserPhoneDTO.class); + phone = liteUserPhoneDTO.getPhoneNumber(); + } + + litePhoneLoginDTO.setPhone(phone); + return AuthDetailBindDTO.builder().authClientId(authClientDataDTO.getAuthClientId()) + .userType(litePhoneLoginDTO.getUserType()) + .authTypeCode(authTypeCode) + .openId(codeToSessionDTO.getOpenId()) + .uniqueId(codeToSessionDTO.getUnionId()).build(); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/util/AuthClientUtils.java b/src/main/java/com/newyetai/usercenter/auth/util/AuthClientUtils.java new file mode 100644 index 0000000..cbc4e55 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/util/AuthClientUtils.java @@ -0,0 +1,56 @@ +package com.newyetai.usercenter.auth.util; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.newyetai.common.exception.util.Assert; +import com.newyetai.usercenter.auth.service.AuthClientService; + +/** + * @author sr on 2021-01-15 + */ +@Component +public class AuthClientUtils { + + public static final String REDIS_KEY_WX_ACCESS_TOKEN_PREFIX = "uc:auth:accesstoken:"; + public static final String REDIS_KEY_WX_JSAPI_TICKET_PREFIX = "uc:auth:jsapiticket:"; + + private static AuthClientService authClientService; + + /** redis key默认过期时间 **/ + public static final Long DEFAULT_EXPIRE_TIME = 6000L; + + @Autowired + public void setWechatUtils(AuthClientService authClientService) { + AuthClientUtils.authClientService = authClientService; + } + + /** + * 获取缓存accesstoken的键 + * + * @param authClientId + * @return + * @author sr on 2021-01-15 + */ + public static String getRedisAccessTokenKey(Long authClientId) { + return REDIS_KEY_WX_ACCESS_TOKEN_PREFIX + authClientId; + } + + /** + * 获取缓存jsapiticket的键 + * + * @param authClientId + * @return + * @author sr on 2021-01-15 + */ + public static String getRedisJsApiTicketKey(Long authClientId) { + return REDIS_KEY_WX_JSAPI_TICKET_PREFIX + authClientId; + } + + public static AuthClientService getService() { + Assert.notNull(authClientService, "无法获取acessToken,请检查配置"); + return authClientService; + } + + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/util/AuthDetailUtils.java b/src/main/java/com/newyetai/usercenter/auth/util/AuthDetailUtils.java new file mode 100644 index 0000000..21da733 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/util/AuthDetailUtils.java @@ -0,0 +1,8 @@ +package com.newyetai.usercenter.auth.util; + +/** + * @author sr on 2021-05-24 + */ +public class AuthDetailUtils { + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/util/LiteCodeUtils.java b/src/main/java/com/newyetai/usercenter/auth/util/LiteCodeUtils.java new file mode 100644 index 0000000..8bc1e11 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/util/LiteCodeUtils.java @@ -0,0 +1,151 @@ +package com.newyetai.usercenter.auth.util; + +import java.util.Arrays; +import java.util.Map; + +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.StringUtils; + +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.constant.ProjectProfileEnum; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.EnvironmentUtils; +import com.newyetai.common.util.SpringContextHolder; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.usercenter.auth.dto.LiteCodeConfigDTO; +import com.newyetai.usercenter.dto.IUserDetail; +import com.newyetai.usercenter.user.constant.UserTypeEnum; +import com.newyetai.usercenter.user.dto.UserRegisterCodeInfoDTO; +import com.newyetai.usercenter.user.service.UserRegisterService; + +/** + * @author sr on 2021-12-21 + */ +public class LiteCodeUtils { + + /** 内置环境参数键:注册码 **/ + public static final String REGISTER_CODE_KEY = "registerCode"; + + public static final String USER_ID_KEY = "userId"; + public static final String USER_TYPE_KEY = "userType"; + public static final String ORG_ID_KEY = "orgId"; + public static final String PLATFORM_CODE_KEY = "platformCode"; + + private static UserRegisterService userRegisterService; + + /** + * 构建参数值(按参数键升序排列)(格式:**&**) + * @param paramData + * @return + * @author sr on 2021-12-21 + */ + public static String buildParamValue(LiteCodeConfigDTO liteCodeConfigDTO, Map paramData) { + String paramKey = liteCodeConfigDTO.getParamKey(); + dealEnv(liteCodeConfigDTO, paramData); + if (StringUtils.isBlank(paramKey)) { + return null; + } + String[] paramKeyArray = paramKey.split(CommonConstants.AND); + // 排序 + Arrays.sort(paramKeyArray); + StringBuilder paramstr = new StringBuilder(); + for (String key : paramKeyArray) { + Object paramValue = paramData.get(key); + Assert.notNull(paramValue, "获取小程序码参数不全"); + paramstr.append(key).append(CommonConstants.EQUAL).append(paramValue.toString()) + .append(CommonConstants.AND); + } + return paramstr.toString(); + } + + public static UserRegisterService getUserRegisterService() { + if (userRegisterService == null) { + userRegisterService = SpringContextHolder.getBean(UserRegisterService.class); + } + return userRegisterService; + } + + public static void dealEnv(LiteCodeConfigDTO liteCodeConfigDTO, + Map paramData) { + String envParamKey = liteCodeConfigDTO.getEnvParamKey(); + if (StringUtils.isBlank(envParamKey)) { + return ; + } + String[] envParamKeyArray = envParamKey.split(CommonConstants.AND); + for (String envKey : envParamKeyArray) { + if (REGISTER_CODE_KEY.equals(envKey)) { + Long userId = MapUtils.getLong(paramData, USER_ID_KEY); + Long orgId = MapUtils.getLong(paramData, ORG_ID_KEY); + paramData.put(PLATFORM_CODE_KEY, liteCodeConfigDTO.getPlatformCode()); + if (userId != null) { + if (orgId != null) { + paramData.put(USER_TYPE_KEY, UserTypeEnum.ORG.getType()); + } else { + paramData.put(USER_TYPE_KEY, UserTypeEnum.PERSON.getType()); + } + } else { + IUserDetail userDetail = UserContextHolder.getExistLoginUser(); + paramData.put(USER_ID_KEY, userDetail.getId()); + paramData.put(USER_TYPE_KEY, userDetail.getType()); + paramData.put(ORG_ID_KEY, userDetail.getOrgId()); + } + } + } + } + + /** + * 组装query值 + * @param paramKey + * @param envParamKey + * @param paramData + * @return + * @author sr on 2021-12-22 + */ + public static String buildQueryValue(Long liteCodeId, LiteCodeConfigDTO liteCodeConfigDTO, + Map paramData) { + String paramKey = liteCodeConfigDTO.getParamKey(); + String envParamKey = liteCodeConfigDTO.getEnvParamKey(); + StringBuilder paramBuilder = new StringBuilder(); + if (StringUtils.isNotBlank(paramKey)) { + String[] paramKeyArray = paramKey.split(CommonConstants.AND); + for (String key : paramKeyArray) { + paramBuilder.append(key).append(CommonConstants.EQUAL) + .append(MapUtils.getString(paramData, key)).append(CommonConstants.AND); + } + } + if (StringUtils.isBlank(envParamKey)) { + return paramBuilder.toString(); + } + String[] envParamKeyArray = envParamKey.split(CommonConstants.AND); + for (String envKey : envParamKeyArray) { + if (REGISTER_CODE_KEY.equals(envKey)) { + Integer inviterType = MapUtils.getInteger(paramData, USER_TYPE_KEY); + Long inviterId = MapUtils.getLong(paramData, USER_ID_KEY); + Long inviterOrgId = MapUtils.getLong(paramData, ORG_ID_KEY); + Integer platformCode = MapUtils.getInteger(paramData, PLATFORM_CODE_KEY); + String registerCode = getUserRegisterService() + .getCode(UserRegisterCodeInfoDTO.builder().inviterId(inviterId).inviterType(inviterType) + .inviterOrgId(inviterOrgId).platformCode(platformCode).unionId(liteCodeId).build()); + paramBuilder.append(envKey).append(CommonConstants.EQUAL) + .append(registerCode).append(CommonConstants.AND); + } + } + int length = paramBuilder.length(); + return length > 0 ? paramBuilder.substring(0, length - 1) : null; + } + + + /** + * 获取小程序版本 + * @return + * @author sr on 2021-12-22 + */ + public static String getEnvVersion() { + String profile = EnvironmentUtils.getProfile(); + if (ProjectProfileEnum.UAT.getValue().equals(profile)) { + return "trial"; + } + return "release"; + } + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/wechat/controller/UcWechatController.java b/src/main/java/com/newyetai/usercenter/auth/wechat/controller/UcWechatController.java new file mode 100644 index 0000000..62027fc --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/wechat/controller/UcWechatController.java @@ -0,0 +1,58 @@ +package com.newyetai.usercenter.auth.wechat.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.dto.CasTokenDTO; +import com.newyetai.usercenter.auth.service.AuthClientService; +import com.newyetai.usercenter.auth.wechat.dto.WechatLiteLoginDTO; +import com.newyetai.usercenter.auth.wechat.dto.WechatLiteSubMsgDTO; +import com.newyetai.usercenter.auth.wechat.dto.WechatSignatureReqDTO; +import com.newyetai.usercenter.auth.wechat.dto.WechatSignatureResDTO; +import com.newyetai.usercenter.auth.wechat.service.WechatService; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +@RestController +@Api(tags = "微信操作") +public class UcWechatController { + + @Autowired + private WechatService wechatService; + + @Autowired + private AuthClientService authClientService; + + @ApiOperation("获取signature") + @PostMapping("anon/wechat/signature") + public AlitaResult signature(@Validated @RequestBody WechatSignatureReqDTO wechatSignatureDTO){ + return AlitaResult.success(authClientService.signature(wechatSignatureDTO)); + } + + @ApiOperation("小程序登录(授权信息)") + @PostMapping("anon/wechat/login_lite") + public AlitaResult loginLite(@Validated @RequestBody WechatLiteLoginDTO wechatLiteLoginDTO) { + return AlitaResult.success(wechatService.loginLite(wechatLiteLoginDTO)); + } + + @ApiOperation("绑定小程序") + @PostMapping("unac/wechat/bind_lite") + public AlitaResult bindLite(@Validated @RequestBody WechatLiteLoginDTO wechatLiteLoginDTO) { + wechatService.bindLite(wechatLiteLoginDTO); + return AlitaResult.success(); + } + + @ApiOperation("发送小程序订阅消息") + @PostMapping("wechat/send_lite_sub_msg") + public AlitaResult sendLiteSubMsg(@Validated @RequestBody WechatLiteSubMsgDTO wechatLiteSubMsgDTO) { + wechatService.sendLiteSubMsg(wechatLiteSubMsgDTO); + return AlitaResult.success(); + } + + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/wechat/dto/BaseWeChatDTO.java b/src/main/java/com/newyetai/usercenter/auth/wechat/dto/BaseWeChatDTO.java new file mode 100644 index 0000000..8c342fb --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/wechat/dto/BaseWeChatDTO.java @@ -0,0 +1,23 @@ +package com.newyetai.usercenter.auth.wechat.dto; + +import lombok.Data; + +import java.io.Serializable; + +/** + * @author leijiaping + */ +@Data +public class BaseWeChatDTO implements Serializable { + + /** + * 错误编码 + */ + private String errcode; + + /** + * 错误信息 + */ + private String errmsg; + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/wechat/dto/WechatAuthUserInfoDTO.java b/src/main/java/com/newyetai/usercenter/auth/wechat/dto/WechatAuthUserInfoDTO.java new file mode 100644 index 0000000..fbced9c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/wechat/dto/WechatAuthUserInfoDTO.java @@ -0,0 +1,71 @@ +package com.newyetai.usercenter.auth.wechat.dto; + +import java.io.Serializable; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2020-05-12 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +@AllArgsConstructor +public class WechatAuthUserInfoDTO extends BaseWeChatDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 2022092915168090246L; + + /** + * 用户的唯一标识 + */ + @JsonProperty("openid") + private String openId; + + /** + * 用户昵称 + */ + private String nickname; + + /** + * 用户的性别,值为1时是男性,值为2时是女性,值为0时是未知 + */ + private Integer sex; + + /** + * 用户个人资料填写的省份 + */ + private String province; + + /** + * 普通用户个人资料填写的城市 + */ + private String city; + + /** + * 国家,如中国为CN + */ + private String country; + + /** + * 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。 + */ + private String headimgurl; + + /** + * 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段 + */ + private String unionid; + + private String encryptedData; + + private String iv; + + + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/wechat/dto/WechatLiteAccessTokenDTO.java b/src/main/java/com/newyetai/usercenter/auth/wechat/dto/WechatLiteAccessTokenDTO.java new file mode 100644 index 0000000..283c4af --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/wechat/dto/WechatLiteAccessTokenDTO.java @@ -0,0 +1,31 @@ +package com.newyetai.usercenter.auth.wechat.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * @author leijiaping + */ +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +public class WechatLiteAccessTokenDTO extends BaseWeChatDTO implements Serializable { + + /** + * 授权用户唯一标识 + */ + private String openid; + + /** + * 当且仅当该网站应用已获得该用户的userinfo授权时,才会出现该字段 + */ + private String unionid; + + + private String session_key; +} diff --git a/src/main/java/com/newyetai/usercenter/auth/wechat/dto/WechatLiteCodeReqDTO.java b/src/main/java/com/newyetai/usercenter/auth/wechat/dto/WechatLiteCodeReqDTO.java new file mode 100644 index 0000000..3ba12fc --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/wechat/dto/WechatLiteCodeReqDTO.java @@ -0,0 +1,31 @@ +package com.newyetai.usercenter.auth.wechat.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotBlank; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class WechatLiteCodeReqDTO implements Serializable{ + + @ApiModelProperty("请求域名或ip") + @NotBlank(message = "请求域名或ip不能为空") + private String domainOrIp; + @ApiModelProperty("唯一标识") + @NotBlank(message = "唯一标识") + private String uniqueCode; + @ApiModelProperty("小程序路径") + @NotBlank(message = "小程序路径不能为空") + private String path; + @ApiModelProperty("小程序路径参数") +// @NotBlank(message = "小程序路径参数不能为空") + private String query; + @ApiModelProperty("码类型:1小程序码,2.urlscheme") + private Integer type; +} diff --git a/src/main/java/com/newyetai/usercenter/auth/wechat/dto/WechatLiteLoginDTO.java b/src/main/java/com/newyetai/usercenter/auth/wechat/dto/WechatLiteLoginDTO.java new file mode 100644 index 0000000..cd23aaa --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/wechat/dto/WechatLiteLoginDTO.java @@ -0,0 +1,37 @@ +package com.newyetai.usercenter.auth.wechat.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2020-05-12 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "小程序登录") +public class WechatLiteLoginDTO extends WechatAuthUserInfoDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 2022092915168090246L; + @ApiModelProperty("小程序授权码") + @NotBlank(message = "小程序授权码不能为空") + private String code; + @ApiModelProperty("用户类型") + @NotNull(message = "用户类型不能为空") + private Integer userType; + @ApiModelProperty("请求域名或ip") + private String domainOrIp; + + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/wechat/dto/WechatLiteSubMsgDTO.java b/src/main/java/com/newyetai/usercenter/auth/wechat/dto/WechatLiteSubMsgDTO.java new file mode 100644 index 0000000..135460b --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/wechat/dto/WechatLiteSubMsgDTO.java @@ -0,0 +1,43 @@ +package com.newyetai.usercenter.auth.wechat.dto; + +import java.io.Serializable; +import java.util.Map; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import com.google.common.collect.Maps; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2022-01-04 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "小程序消息") +@Builder +public class WechatLiteSubMsgDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 2022092915168090246L; + @ApiModelProperty("请求域名或ip") + private String domainOrIp; + @ApiModelProperty("用户id") + @NotNull(message = "用户id不能为空") + private Long userId; + @ApiModelProperty("微信订阅消息模版id") + @NotBlank(message = "微信订阅消息模版id不能为空") + private String templateId; + @ApiModelProperty("消息参数") + private Map paramData = Maps.newHashMap(); + @ApiModelProperty("点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar") + private String page; + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/wechat/dto/WechatSignatureReqDTO.java b/src/main/java/com/newyetai/usercenter/auth/wechat/dto/WechatSignatureReqDTO.java new file mode 100644 index 0000000..3492251 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/wechat/dto/WechatSignatureReqDTO.java @@ -0,0 +1,26 @@ +package com.newyetai.usercenter.auth.wechat.dto; + +import javax.validation.constraints.NotBlank; + +import com.newyetai.usercenter.auth.dto.AuthClientQueryDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "微信签名链接") +public class WechatSignatureReqDTO extends AuthClientQueryDTO{ + + /** **/ + private static final long serialVersionUID = -1042268580628180555L; + + @ApiModelProperty("链接") + @NotBlank(message = "链接不能为空") + private String url; + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/wechat/dto/WechatSignatureResDTO.java b/src/main/java/com/newyetai/usercenter/auth/wechat/dto/WechatSignatureResDTO.java new file mode 100644 index 0000000..251fc82 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/wechat/dto/WechatSignatureResDTO.java @@ -0,0 +1,26 @@ +package com.newyetai.usercenter.auth.wechat.dto; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "微信签名链接返回") +public class WechatSignatureResDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = -1042268580628180555L; + + private String nonceStr; + private String timestamp; + private String signature; + private String appId; + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/wechat/mapstruct/WechatMapMapper.java b/src/main/java/com/newyetai/usercenter/auth/wechat/mapstruct/WechatMapMapper.java new file mode 100644 index 0000000..b47ed7f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/wechat/mapstruct/WechatMapMapper.java @@ -0,0 +1,39 @@ +package com.newyetai.usercenter.auth.wechat.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +import com.newyetai.usercenter.auth.dto.AuthDetailBindDTO; +import com.newyetai.usercenter.auth.dto.AuthDetailLoginDTO; +import com.newyetai.usercenter.auth.wechat.dto.WechatLiteLoginDTO; +import com.newyetai.usercenter.user.login.dto.LoginPhoneDTO; + +/** + * @author sr on 2021-11-23 + */ +@Mapper +public interface WechatMapMapper { + + WechatMapMapper INSTANCE = + Mappers.getMapper(WechatMapMapper.class); + + @Mapping(target = "withoutCode", constant = "true") + LoginPhoneDTO toDto(AuthDetailLoginDTO authDetailLoginDTO); + + @Mappings(value = { + @Mapping(target = "avatar", source = "headimgurl"), + @Mapping(target = "gender", source = "sex"), + @Mapping(target = "uniqueId", source = "unionid"), + }) + AuthDetailLoginDTO toLoginDto(WechatLiteLoginDTO wechatLiteLoginDTO); + + @Mappings(value = { + @Mapping(target = "avatar", source = "headimgurl"), + @Mapping(target = "gender", source = "sex"), + @Mapping(target = "uniqueId", source = "unionid"), + }) + AuthDetailBindDTO toBindDto(WechatLiteLoginDTO wechatLiteLoginDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/wechat/service/WechatService.java b/src/main/java/com/newyetai/usercenter/auth/wechat/service/WechatService.java new file mode 100644 index 0000000..0fd4188 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/wechat/service/WechatService.java @@ -0,0 +1,34 @@ +package com.newyetai.usercenter.auth.wechat.service; + +import com.newyetai.common.dto.CasTokenDTO; +import com.newyetai.usercenter.auth.wechat.dto.WechatLiteLoginDTO; +import com.newyetai.usercenter.auth.wechat.dto.WechatLiteSubMsgDTO; + +/** + * @author sr on 2021-01-15 + */ +public interface WechatService { + + /** + * 小程序登录 + * @param wechatLiteLoginDTO + * @return + * @author sr on 2021-07-09 + */ + CasTokenDTO loginLite(WechatLiteLoginDTO wechatLiteLoginDTO); + + /** + * 绑定微信小程序 + * @param wechatLiteLoginDTO + * @author sr on 2021-08-23 + */ + void bindLite(WechatLiteLoginDTO wechatLiteLoginDTO); + + /** + * 小程序订阅消息 + * @param wechatLiteSubMsgDTO + * @author sr on 2022-01-04 + */ + void sendLiteSubMsg(WechatLiteSubMsgDTO wechatLiteSubMsgDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/auth/wechat/service/impl/WechatServiceImpl.java b/src/main/java/com/newyetai/usercenter/auth/wechat/service/impl/WechatServiceImpl.java new file mode 100644 index 0000000..c0e33b5 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/auth/wechat/service/impl/WechatServiceImpl.java @@ -0,0 +1,122 @@ +package com.newyetai.usercenter.auth.wechat.service.impl; + +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.newyetai.common.dto.CasTokenDTO; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.DevopsException; +import com.newyetai.common.exception.WithResultException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.ListUtil; +import com.newyetai.sdk.wechat.model.SubscibeMessageReq; +import com.newyetai.sdk.wechat.util.MessageParamUtils; +import com.newyetai.security.expection.BadLoginException; +import com.newyetai.security.jwt.JwtTokenUtils; +import com.newyetai.security.mapstruct.UserMapMapper; +import com.newyetai.security.util.HostContextHolder; +import com.newyetai.usercenter.auth.constant.AuthTypeEnum; +import com.newyetai.usercenter.auth.dto.AuthClientDataDTO; +import com.newyetai.usercenter.auth.dto.AuthClientQueryDTO; +import com.newyetai.usercenter.auth.dto.AuthDetailBindDTO; +import com.newyetai.usercenter.auth.dto.AuthDetailCreateDTO; +import com.newyetai.usercenter.auth.dto.AuthDetailDTO; +import com.newyetai.usercenter.auth.dto.AuthDetailLoginDTO; +import com.newyetai.usercenter.auth.dto.AuthDetailQueryDTO; +import com.newyetai.usercenter.auth.dto.CodeToSessionDTO; +import com.newyetai.usercenter.auth.service.AuthClientService; +import com.newyetai.usercenter.auth.service.AuthDetailService; +import com.newyetai.usercenter.auth.util.AuthClientUtils; +import com.newyetai.usercenter.auth.util.LiteCodeUtils; +import com.newyetai.usercenter.auth.wechat.dto.WechatLiteLoginDTO; +import com.newyetai.usercenter.auth.wechat.dto.WechatLiteSubMsgDTO; +import com.newyetai.usercenter.auth.wechat.mapstruct.WechatMapMapper; +import com.newyetai.usercenter.auth.wechat.service.WechatService; +import com.newyetai.usercenter.sys.util.DomainUtils; +import com.newyetai.usercenter.user.login.dto.UserDetailDTO; +import com.newyetai.usercenter.user.login.service.UserLoginService; +import com.newyetai.usercenter.user.service.UserService; + +import lombok.extern.slf4j.Slf4j; + +@Service +@Slf4j +public class WechatServiceImpl implements WechatService { + + @Autowired + private AuthClientService authClientService; + + @Autowired + private UserLoginService userLoginService; + + @Autowired + private UserService userService; + + @Autowired + private AuthDetailService authDetailService; + + @Override + public CasTokenDTO loginLite(WechatLiteLoginDTO wechatLiteLoginDTO) { + try { + AuthDetailLoginDTO authDetailLoginDTO = WechatMapMapper.INSTANCE.toLoginDto(wechatLiteLoginDTO); + analyCode(wechatLiteLoginDTO, authDetailLoginDTO); + UserDetailDTO userDetailDTO = userLoginService.findUserDetailDTO(authDetailLoginDTO); + String token = JwtTokenUtils.generateToken(UserMapMapper.INSTANCE.dtoToDto(userDetailDTO)); + return CasTokenDTO.builder().token(token).register(userDetailDTO.getRegister()).build(); + } catch (BadLoginException be) { + log.info("silence login:{}", be.getMessage()); + } catch (Exception e) { + log.info("silence login:{}", e.getMessage()); + } + return new CasTokenDTO(); + } + + private void analyCode(WechatLiteLoginDTO wechatLiteLoginDTO, AuthDetailCreateDTO authDetailCreateDTO) { + AuthClientDataDTO authClientDataDTO = authClientService + .findClientData(AuthClientQueryDTO.builder() + .domainOrIp(DomainUtils.getOrDefault(wechatLiteLoginDTO.getDomainOrIp())) + .authTypeCode(AuthTypeEnum.WECHAT_LITE.getCode()).build()); + CodeToSessionDTO codeToSessionDTO = + authClientService.getCodeToSessionDTO(authClientDataDTO, wechatLiteLoginDTO.getCode()); + authDetailCreateDTO.setUniqueId(codeToSessionDTO.getUnionId()); + authDetailCreateDTO.setOpenId(codeToSessionDTO.getOpenId()); + authDetailCreateDTO.setAuthClientId(authClientDataDTO.getAuthClientId()); + authDetailCreateDTO.setAuthTypeCode(AuthTypeEnum.WECHAT_LITE.getCode()); + log.debug("code2SessionDTO:{},", codeToSessionDTO); + } + + @Override + public void bindLite(WechatLiteLoginDTO wechatLiteLoginDTO) { + AuthDetailBindDTO authDetailBindDTO = WechatMapMapper.INSTANCE.toBindDto(wechatLiteLoginDTO); + analyCode(wechatLiteLoginDTO, authDetailBindDTO); + Assert.isTrue(StringUtils.isNotBlank(authDetailBindDTO.getUniqueId()), + //new DevopsException(authDetailBindDTO.getAuthClientId() + "-小程序未挂载开放平台") + authDetailBindDTO.getAuthClientId() + "-小程序未挂载开放平台" + ); + userService.bindUserAuth(authDetailBindDTO); + } + + @Override + public void sendLiteSubMsg(WechatLiteSubMsgDTO wechatLiteMsgDTO) { + String domainOrIp = DomainUtils.getOrDefault(wechatLiteMsgDTO.getDomainOrIp()); + AuthClientDataDTO authClientDataDTO = authClientService + .findClientData(AuthClientQueryDTO.builder().domainOrIp(domainOrIp) + .authTypeCode(AuthTypeEnum.WECHAT_LITE.getCode()).build()); + List authDetails = authDetailService + .list(AuthDetailQueryDTO.builder().authClientId(authClientDataDTO.getAuthClientId()) + .userId(wechatLiteMsgDTO.getUserId()).build()); + Assert.isTrue(authDetails.size() == 1, "未找到唯一匹配的用户授权信息"); + SubscibeMessageReq subscibeMessageReq = SubscibeMessageReq.builder() + .touser(ListUtil.first(authDetails).getOpenId()) + .templateId(wechatLiteMsgDTO.getTemplateId()) + .data(MessageParamUtils.dealData(wechatLiteMsgDTO.getParamData())) + .page(wechatLiteMsgDTO.getPage()) + .miniprogramState(LiteCodeUtils.getEnvVersion()) + .build(); + AuthClientUtils.getService().subscibeMessage(authClientDataDTO, subscibeMessageReq); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/authority/constants/PermissionConstants.java b/src/main/java/com/newyetai/usercenter/authority/constants/PermissionConstants.java new file mode 100644 index 0000000..19b7483 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/authority/constants/PermissionConstants.java @@ -0,0 +1,16 @@ +package com.newyetai.usercenter.authority.constants; + +/** + * 角色权限常量类 + * @author sr on 2019-10-16 + */ +public class PermissionConstants { + + /** 资源类型: 菜单**/ + public static final String RESOURCE_TYPE_URL = "1"; + /** 资源类型: 组件 **/ + public static final String RESOURCE_TYPE_COMPONENT = "2"; + /** 资源类型: 接口 **/ + public static final String RESOURCE_TYPE_INTERFACE = "3"; + +} diff --git a/src/main/java/com/newyetai/usercenter/authority/controller/UcPermissionController.java b/src/main/java/com/newyetai/usercenter/authority/controller/UcPermissionController.java new file mode 100644 index 0000000..9dd0d50 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/authority/controller/UcPermissionController.java @@ -0,0 +1,33 @@ +package com.newyetai.usercenter.authority.controller; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.newyetai.common.AlitaResult; +import com.newyetai.usercenter.authority.dto.PermissionQueryDTO; +import com.newyetai.usercenter.authority.dto.UrlPermissionDTO; +import com.newyetai.usercenter.authority.service.UcPermissionService; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +@Api(tags = "角色权限操作") +@RestController +@RequestMapping("/permission") +public class UcPermissionController { + + @Autowired + private UcPermissionService ucPermissionService; + + @ApiOperation("查询角色权限分配菜单接口") + @GetMapping("/list_url") + public AlitaResult> listUrl(PermissionQueryDTO permissionQueryDTO) { + return ucPermissionService.listUrl(permissionQueryDTO); + + } + +} diff --git a/src/main/java/com/newyetai/usercenter/authority/controller/UcRoleController.java b/src/main/java/com/newyetai/usercenter/authority/controller/UcRoleController.java new file mode 100644 index 0000000..607072a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/authority/controller/UcRoleController.java @@ -0,0 +1,178 @@ +package com.newyetai.usercenter.authority.controller; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.common.validation.Check; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.authority.dto.*; +import com.newyetai.usercenter.authority.service.UcRoleAllocationService; +import com.newyetai.usercenter.authority.service.UcRoleService; +import com.newyetai.usercenter.cache.SecurityCacheUtils; +import com.newyetai.usercenter.dto.*; +import com.newyetai.usercenter.query.RoleQuery; +import com.newyetai.usercenter.resource.service.UcUrlService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Objects; + +/** + * 角色操作 + * + * @author sr on 2019-11-05 + */ +@Api(tags = "角色操作") +@RestController +@RequestMapping("/role") +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class UcRoleController { + + private final UcRoleService roleService; + + private final UcRoleAllocationService ucRoleAllocationService; + + private final UcUrlService urlService; + + @ApiOperation("创建普通机构角色") + @PostMapping("/create") + public AlitaResult createOrgRole(@Validated(Create.class) @RequestBody RoleDTO roleDTO) { + roleService.createOrgRole(UserContextHolder.getExistLoginOrgId(), roleDTO); + return AlitaResult.success(roleDTO); + } + + @ApiOperation("修改普通机构角色") + @PostMapping("/update") + public AlitaResult updateOrgRole(@Validated(Update.class) @RequestBody RoleDTO roleDTO) { + roleService.updateOrgRole(UserContextHolder.getExistLoginOrgId(), roleDTO); + return AlitaResult.success(roleDTO); + } + + @ApiOperation("删除普通机构角色") + @DeleteMapping("/delete/{id}") + public AlitaResult deleteOrgRole(@PathVariable("id") Long roleId) { + roleService.deleteOrgRole(UserContextHolder.getExistLoginOrgId(), roleId); + return AlitaResult.success(true); + } + + @ApiOperation("获取普通机构角色列表") + @GetMapping("/list") + public AlitaResult> query(Page page, RoleDTO roleDTO) { + roleService.queryOrgRole(UserContextHolder.getExistLoginOrgId(), roleDTO, page); + return AlitaResult.success(page); + } + + @ApiOperation("获取机构招聘负责人角色列表") + @GetMapping("/listPersonCharge") + public AlitaResult> queryByPersonCharge(Long orgId) { + return AlitaResult.success(roleService.queryOrgRole(orgId)); + } + + @ApiOperation("获取机构角色列表") + @PostMapping("/page") + public AlitaResult> page(@RequestBody RoleQuery query) { + query.setOrgId(UserContextHolder.getExistLoginOrgId()); + roleService.queryPlatformAdminRoleList(query); + return AlitaResult.success(query.getPageResult()); + } + + @ApiOperation("根据用户ID查询可分配的角色列表") + @PostMapping("/page_allocation_role_list") + public AlitaResult queryAllocationRoleList(@RequestBody RoleQuery query) { + if (Objects.isNull(query.getOrgId())){ + query.setOrgId(UserContextHolder.getExistLoginOrgId()); + } + return roleService.queryUserAllocationRoleList(query); + } + + @ApiOperation("获取普通机构角色已选分配权限") + @GetMapping("/check_key/list") + public AlitaResult> queryCheckedKeys() { + List checkedKeysByRoleIds = roleService + .findCheckedKeysByRoleIds(UserContextHolder.getExistLoginOrgId()); + return AlitaResult.success(checkedKeysByRoleIds); + } + + @ApiOperation("角色权限分配") + @PostMapping("/url_allocation") + public AlitaResult roleUrlAllocation( + @RequestBody PermissionOperateDTO permissionOptionDTO) { + //保存菜单 + roleService.roleUrlAllocation(permissionOptionDTO, UserContextHolder.getExistLoginOrgId()); + //清理已删除菜单下相关接口/组件 + roleService.cleanRoleComponentAndInterface(); + // 刷新缓存 + SecurityCacheUtils.flushAll(); + return AlitaResult.success(Boolean.TRUE); + } + + @ApiOperation("用户分配角色") + @PostMapping("/user_allocation_role") + public AlitaResult userAllocationRole(@RequestBody AllocationRoleDTO allocationRoleDTO) { + return roleService.userAllocationRole(allocationRoleDTO, UserContextHolder.getLoginUserId()); + } + + @ApiOperation("角色分配用户") + @PostMapping("/role_allocation_user") + public AlitaResult roleAllocationUser(@RequestBody AllocationRoleUserDTO dto) { + roleService.roleAllocationUser(dto); + return AlitaResult.success(Boolean.TRUE); + } + + @ApiOperation("分配角色删除用户") + @PostMapping("/remove_allocation_role") + public AlitaResult removelocationRole(@RequestBody AllocationRoleUserDTO allocationRoleDTO) { + roleService.removelocationRole(allocationRoleDTO); + return AlitaResult.success(Boolean.TRUE); + } + + @ApiOperation("角色是否启用") + @PostMapping("/enable") + public AlitaResult roleEnable(@RequestBody RoleDTO roleDTO) { + return roleService.roleEnable(roleDTO.getId(), roleDTO.getEnabled(), UserContextHolder.getExistLoginUserId()); + } + + @ApiOperation("查询指定机构下用户业务角色(已分配/未分配)列表") + @GetMapping("/getBusinessRoles/{orgId}/{userId}") + public AlitaResult> getBusinessRoles(@PathVariable("orgId") Long orgId, @PathVariable("userId") Long userId) { + return AlitaResult.success(ucRoleAllocationService.getBusinessRoles(orgId, userId)); + } + + + @ApiOperation("指定用户角色分配(新分配/取消分配)") + @PostMapping("/allocateBusinessRoles/{orgId}/{userId}") + public AlitaResult allocateBusinessRoles(@PathVariable("orgId") Long orgId, @PathVariable("userId") Long userId, @RequestBody UserAllocateRoleDTO userAllocateRoleDTO) { + ucRoleAllocationService.allocateBusinessRoles(orgId, userId, userAllocateRoleDTO, UserContextHolder.getExistLoginUserId()); + return AlitaResult.success(); + } + + @ApiOperation("获取角色菜单下相关组件/接口列表") + @GetMapping("/get_url_resources") + public AlitaResult> getAllResourceList(@Validated(Check.class) + PermissionPageQueryDTO permissionPageQueryDTO) { + permissionPageQueryDTO.setOrgId(UserContextHolder.getExistLoginOrgId()); + urlService.queryAllResourceList(permissionPageQueryDTO); + return AlitaResult.success(permissionPageQueryDTO.getPageResult()); + } + + @ApiOperation("保存角色对应菜单下组件/接口列表") + @PostMapping("/save_url_resources") + public AlitaResult saveUrlResourcesOperateDTO( + @Validated(Create.class) @RequestBody PermissionResourcesDTO permissionResourcesDTO) { + urlService.saveUrlResourcesOperateDTO(permissionResourcesDTO); + SecurityCacheUtils.flushAll(); + return AlitaResult.success(Boolean.TRUE); + } + + @ApiOperation("查询指定机构、指定用户、指定平台的已分配角色列表") + @GetMapping("/getAllocatedBusinessRoles") + public AlitaResult> getAllocatedBusinessRoles(@Validated AllocatedBusinessRoleQueryDTO queryDTO) { + return AlitaResult.success(ucRoleAllocationService.getAllocatedBusinessRoles(queryDTO)); + } +} diff --git a/src/main/java/com/newyetai/usercenter/authority/dao/UcPermissionMapper.java b/src/main/java/com/newyetai/usercenter/authority/dao/UcPermissionMapper.java new file mode 100644 index 0000000..d358011 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/authority/dao/UcPermissionMapper.java @@ -0,0 +1,108 @@ +package com.newyetai.usercenter.authority.dao; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.usercenter.authority.dto.*; +import com.newyetai.usercenter.authority.entity.Permission; +import com.newyetai.usercenter.dto.CheckKeyDTO; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; +import org.apache.ibatis.annotations.Update; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * 权限mapper + * @author sr on 2019-10-07 + */ +@Component(UcPermissionMapper.BEAN_ID) +public interface UcPermissionMapper extends MyMapper { + + String BEAN_ID = "security.permissionMapper"; + + /** + * 查询所有组件权限 + * + * @return + * @author sr on 2019-10-17 + */ + List findComponent(@Param("param") PermissionQueryDTO permissionQueryDTO); + + /** + * 查询所有菜单权限 + * + * @return + * @author sr on 2019-10-17 + */ + List findUrl(@Param("param") PermissionQueryDTO permissionQueryDTO); + + /** + * 查询指定角色指定类型拥有权限的资源id列表 + * @param roleId + * @param resourceType + * @return + * @author sr on 2019-10-17 + */ + @Select("select distinct p.resource_id from xs_permission p, xs_url r " + + "where p.role_id = #{roleId} and p.resource_type = #{resourceType} and p.deleted = 0 " + + "and p.resource_id = r.id and r.deleted=0 order by p.resource_id") + Set findResourceIdByRoleId(Long roleId, Integer resourceType); + + @Select("select distinct p.resource_id from xs_permission p, xs_url r " + + "where p.role_id = #{roleId} and p.resource_type = #{resourceType} and p.deleted = 0 " + + "and p.resource_id = r.id order by p.resource_id") + Set selectResourceIdByRoleId(Long roleId, String resourceType); + + /** + * 查询指定角色拥有权限的所有资源id+type + * @param roleIds + * @return + * @author sr on 2019-10-17 + */ + List> listResourceIdTypeByRoleId(List roleIds); + + + /** + * 查询指定用户拥有的权限列表 + * @param roleId + * @return + * @author sr on 2019-10-17 + */ + @Select("select * from xs_permission where role_id = #{roleId} and deleted = 0 ") + List findByRoleId(Long roleId); + + + /** + * 查询指定角色的checkedKeys + * @param roleIds + * @return + */ + List findCheckedKeysByRoleIds(@Param("roleIds") Set roleIds); + + /** + * 逻辑删除角色分配资源 + * + * @param roleId + * @param resourceId + * @return + */ + @Update("update xs_permission set deleted = 1, update_by = #{operateUserId} where role_id = #{roleId} and resource_id = #{resourceId}") + int deletePermissionByRoleIdAndResourceId(Long operateUserId, Long roleId, Long resourceId); + + /** + * 逻辑删除角色分配资源 + * + * @param roleId + * @return + */ + @Update("update xs_permission set deleted = 1, update_by = #{operateUserId} where role_id = #{roleId}") + int deletePermissionByRoleId(Long operateUserId, Long roleId); + + List urlComponentList( + @Param("param") PermissionPageQueryDTO permissionPageQueryDTO); + + List urlInterfaceList( + @Param("param") PermissionPageQueryDTO permissionPageQueryDTO); +} diff --git a/src/main/java/com/newyetai/usercenter/authority/dao/UcRoleAllocationMapper.java b/src/main/java/com/newyetai/usercenter/authority/dao/UcRoleAllocationMapper.java new file mode 100644 index 0000000..0627e8c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/authority/dao/UcRoleAllocationMapper.java @@ -0,0 +1,101 @@ +package com.newyetai.usercenter.authority.dao; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.usercenter.authority.dto.RoleAllocationDTO; +import com.newyetai.usercenter.authority.entity.RoleAllocation; +import com.newyetai.usercenter.dto.AllocatedBusinessRoleQueryDTO; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; +import org.apache.ibatis.annotations.Update; + +import java.util.List; +import java.util.Set; +import com.newyetai.usercenter.dto.RoleDTO; + +/** + * @author Jerry.li + * @description 角色分配 + * @date 2020/3/24 + */ +@Mapper +public interface UcRoleAllocationMapper extends MyMapper { + + /** + * 查询角色分配列表 + * @param allocationType + * @param allocationId + * @return + */ + List selectAllocationList(@Param("allocationType") String allocationType, @Param("allocationId") Long allocationId); + + /** + * 查询角色ID列表 + * @param allocationType + * @param allocationId + * @return + */ + Set selectRoleIds(@Param("allocationType") String allocationType, @Param("allocationId") Long allocationId); + + /** + * 批量删除角色 + * @param allocationType + * @param allocationId + * @param deleteRoleIds + * @param operateUserId + */ + void deleteByRoleIds(@Param("allocationType") String allocationType, @Param("allocationId") Long allocationId, @Param("roleIds") List deleteRoleIds, @Param("operateUserId") Long operateUserId); + + /** + * 根据账号查询角色分配列表 + * @param username + * @return + */ + List selectAllocationListByUsername(String username); + + /** + * 查询指定分配类型id的分配列表 + * @param allocationType + * @param allocationId + * @return + * @author sr on 2019-10-17 + */ + @Select("select * from xs_role_allocation where allocation_type = #{allocationType} and allocation_id = #{allocationId} and deleted = 0 ") + List findByAllocationId(@Param("allocationType") String allocationType, @Param("allocationId") Long allocationId); + + /** + * 查询指定分配类型id的分配角色id列表 + * @param allocationType + * @param allocationId + * @return + * @author sr on 2019-10-17 + */ + @Select("select distinct role_id from xs_role_allocation where allocation_type = #{allocationType} and allocation_id = #{allocationId} and deleted = 0 ") + Set findRoleIds(@Param("allocationType") String allocationType, @Param("allocationId") Long allocationId); + + /** + * 查询指定用户的角色分配列表 + * @param userId + * @return + * @author sr on 2021-08-05 + */ + List findByUserId(Long userId); + + /** + * 取消用户已分配的角色 + * @param operateUserId + * @param roleId + * @param userId + * @return + */ + @Update("update xs_role_allocation set deleted = 1, update_by = #{operateUserId} where role_id = #{roleId} and allocation_id = #{userId} and deleted = 0") + int deleteUserAllocatedRole(Long operateUserId, Long roleId, Long userId); + /** + * @description: 查询指定机构、指定用户、指定平台的已分配角色 + * @return: + * @author: guixinman + * @param: + */ + List getAllocatedBusinessRoles(@Param("param") AllocatedBusinessRoleQueryDTO queryDTO); +} diff --git a/src/main/java/com/newyetai/usercenter/authority/dao/UcRoleMapper.java b/src/main/java/com/newyetai/usercenter/authority/dao/UcRoleMapper.java new file mode 100644 index 0000000..17e4fc6 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/authority/dao/UcRoleMapper.java @@ -0,0 +1,144 @@ +package com.newyetai.usercenter.authority.dao; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.authority.entity.Role; +import com.newyetai.usercenter.dto.RoleDTO; +import com.newyetai.usercenter.query.RoleQuery; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; +import java.util.Set; + +/** + * @author Jerry.li + * @description 角色 + * @date 2020/3/24 + */ +@Mapper +public interface UcRoleMapper extends MyMapper { + + /** + * 根据角色类型查询角色ID + * @param roleType + * @return + */ + @Select("select id from xs_role where type = #{roleType} and deleted = 0 ") + Long selectRoleIdByRoleType(String roleType); + + /** + * + * @param orgId + * @param roleDTO + * @return + */ + List selectOrgRoleList(@Param("orgId") Long orgId, @Param("param") RoleDTO roleDTO); + + /** + * 查询指定机构的角色列表 + * @param orgId + * @param roleDTO + * @param page + * @return + * @author sr on 2019-10-14 + */ + List queryOrgRoles(@Param("orgId")Long orgId, @Param("param") RoleDTO roleDTO, Page page); + + /** + * 查询指定机构的角色列表 + * @param orgId + * @return + * @author sr on 2019-10-14 + */ + @Select("select * from xs_role where org_id = #{orgId} and deleted = 0") + List queryOrgRoleList(@Param("orgId")Long orgId); + + /** + * 校验指定机构下是否存在对应角色类型角色 + * @param orgId + * @param roleId + * @param roleType + * @return + * @author sr on 2019-10-17 + */ + @Select("select count(*) from xs_role where org_id = #{orgId} and id = #{roleId} and type = #{roleType} and deleted = 0") + int existRole(@Param("orgId") Long orgId, @Param("roleId") Long roleId, @Param("roleType") String roleType); + + /** + * 查询机构下角色id列表 + * @param orgId + * @param roleDTO + * @return + * @author sr on 2019-10-17 + */ + Set queryOrgRoleIds(@Param("orgId")Long orgId, @Param("param") RoleDTO roleDTO); + + /** + * 根据类型查询角色id(内置的系统角色) + * @param roleType + * @return + * @author sr on 2019-10-19 + */ + @Select("select id from xs_role where type = #{roleType} and deleted = 0 ") + Long queryRoleId(String roleType); + + /** + * 校验角色名是否存在 + * @param orgId + * @param roleName + * @param roleId 为空则判断所有角色(新增),不为空代表判断除该角色id之外的角色(修改) + * @return + * @author sr on 2019-11-18 + */ + int existRoleName(@Param("orgId") Long orgId, @Param("roleName") String roleName, @Param("roleId") Long roleId); + + /** + * 分页查询平台级角色列表 + * @param page + * @return + */ + List selectPlatformAdminRoleList(@Param("param") RoleQuery roleQuery); + + /** + * 查询用户已分配的角色ID + * @param query + * @return + */ + List selectAllocatedRoleIdListByUserId(RoleQuery query); + + /** + * 查询平台用户可分配的角色列表 + */ + List selectPlatformUserUnallocatedRoleList(RoleQuery query); + + /** + * 查询机构用户可分配的角色列表 + * + * @param query + * @return + */ + List selectOrgUserUnallocatedRoleList(RoleQuery query); + + /** + * 获取所有不能删除的销售角色 + * + * @return {@link Set} + */ + Set getSellerRoleCanNotBeDeleted(@Param("userId") Long userId); + + /** + * 清理已删除菜单的组件 + * @param loginUserId + */ + void cleanRoleComponent(Long loginUserId); + + /** + * 清理已删除菜单的接口 + * @param loginUserId + */ + void cleanRoleInterface(Long loginUserId); + + +} diff --git a/src/main/java/com/newyetai/usercenter/authority/dto/ComponentPermissionDTO.java b/src/main/java/com/newyetai/usercenter/authority/dto/ComponentPermissionDTO.java new file mode 100644 index 0000000..ce24cdf --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/authority/dto/ComponentPermissionDTO.java @@ -0,0 +1,50 @@ +package com.newyetai.usercenter.authority.dto; + +import org.apache.commons.lang3.StringUtils; + +import com.newyetai.security.access.provider.IConfigAttribute; + +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2020-09-07 + */ +@Data +@NoArgsConstructor +public class ComponentPermissionDTO implements IConfigAttribute { + + /** **/ + private static final long serialVersionUID = -451031464850427393L; + + /** 角色ID **/ + private Long roleId; + + /** 资源类型:1菜单3接口 **/ + private String resourceType; + + /** 资源ID **/ + private Long resourceId; + + /** 权限鉴别属性,默认格式:ROLE_{roleId} **/ + private String attribute; + + @Override + /** + * 权限鉴别属性,默认格式:ROLE_{roleId} + * + * @return attribute + */ + public String getAttribute() { + if (StringUtils.isBlank(attribute)) { + return "ROLE_" + roleId; + } + return attribute; + } + + @Override + public Long getKey() { + return resourceId; + } + +} diff --git a/src/main/java/com/newyetai/usercenter/authority/dto/PermissionDTO.java b/src/main/java/com/newyetai/usercenter/authority/dto/PermissionDTO.java new file mode 100644 index 0000000..5d8293c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/authority/dto/PermissionDTO.java @@ -0,0 +1,66 @@ +package com.newyetai.usercenter.authority.dto; + +import javax.validation.constraints.NotNull; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 权限信息 + * + * @author on 2019-11-05 + */ +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public class PermissionDTO extends BaseDTO { + + private static final long serialVersionUID = -8945833162881931804L; + + @ApiModelProperty("角色ID") + private Long roleId; + + @ApiModelProperty("资源类型:1菜单2组件3接口") + private String resourceType; + + @ApiModelProperty("资源ID,如菜单和组件,以及用户定义的资源") + private Long resourceId; + + @ApiModelProperty("所属菜单ID") + private Long urlId; + + @ApiModelProperty("机构ID") + private Long orgId; + + @ApiModelProperty("权限鉴别属性,默认格式:ROLE_{roleId},可以扩展") + private String attribute; + + @ApiModelProperty("组件/接口名称") + private String name; + + @ApiModelProperty("接口地址") + private String link; + + @ApiModelProperty("组件编码") + private String code; + + @ApiModelProperty("描述") + private String description; + + @ApiModelProperty("平台编码") + private Integer platformCode; + + @ApiModelProperty("是否授权") + @NotNull(message = "是否选中标识不能为空", groups = { + Create.class, Update.class}) + private Boolean selected; + +} diff --git a/src/main/java/com/newyetai/usercenter/authority/dto/PermissionOperateDTO.java b/src/main/java/com/newyetai/usercenter/authority/dto/PermissionOperateDTO.java new file mode 100644 index 0000000..13f8015 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/authority/dto/PermissionOperateDTO.java @@ -0,0 +1,53 @@ +package com.newyetai.usercenter.authority.dto; + +import java.io.Serializable; +import java.util.List; + +import javax.validation.constraints.NotNull; + +import com.newyetai.common.validation.Update; +import com.newyetai.usercenter.resource.dto.UrlDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 角色权限 + * + * @author sr on 2019-11-05 + */ +@ApiModel("角色权限") +@Data +@NoArgsConstructor +@AllArgsConstructor +public class PermissionOperateDTO implements Serializable { + + /** + * + **/ + private static final long serialVersionUID = 4898248691495623567L; + + @ApiModelProperty("角色id") + @NotNull(message = "角色id不能为空", groups = {Update.class}) + private Long roleId; + + /** + * 平台编码 + */ + private Integer platformCode; + + @ApiModelProperty("资源树") + List urlDTOs; + + @ApiModelProperty("分配资源id(type_id)") + List resourceIds; + + @ApiModelProperty("已分配的资源列表") + List resourceIdList; + + + +} diff --git a/src/main/java/com/newyetai/usercenter/authority/dto/PermissionPageQueryDTO.java b/src/main/java/com/newyetai/usercenter/authority/dto/PermissionPageQueryDTO.java new file mode 100644 index 0000000..39c17e0 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/authority/dto/PermissionPageQueryDTO.java @@ -0,0 +1,47 @@ +package com.newyetai.usercenter.authority.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotNull; + +import com.newyetai.common.dto.PageQueryDTO; +import com.newyetai.common.validation.Check; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author yzq + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class PermissionPageQueryDTO extends PageQueryDTO implements Serializable { + + @ApiModelProperty("应用编码 1.业务系统 2.运营中台 3.用户中心 4.支付系统 5.在线培训 6.转发器 7.风控 8.网关 9.发号器 10.基础框架") + @NotNull(message = "平台编码不能为空", groups = {Check.class}) + private Integer platformCode; + + @ApiModelProperty("角色ID") + @NotNull(message = "角色不能为空", groups = {Check.class}) + private Long roleId; + + @ApiModelProperty("机构ID") + private Long orgId; + + @ApiModelProperty("资源类型:1菜单 2组件 3接口") + @NotNull(message = "资源类型不能为空", groups = {Check.class}) + private String resourceType; + + @ApiModelProperty("父菜单Id") + @NotNull(message = "父菜单id不能为空s", groups = {Check.class}) + private Long urlId; + + @ApiModelProperty("是否已授权 1.已授权 2.未授权 ") + private Boolean selected; + +} diff --git a/src/main/java/com/newyetai/usercenter/authority/dto/PermissionQueryDTO.java b/src/main/java/com/newyetai/usercenter/authority/dto/PermissionQueryDTO.java new file mode 100644 index 0000000..b3b5897 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/authority/dto/PermissionQueryDTO.java @@ -0,0 +1,27 @@ +package com.newyetai.usercenter.authority.dto; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2020-09-07 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class PermissionQueryDTO implements Serializable { + + /** **/ + private static final long serialVersionUID = -3670302869701791296L; + + /** 应用 **/ + private Integer systemCode; + /** 机构id **/ + private Long orgId; + +} diff --git a/src/main/java/com/newyetai/usercenter/authority/dto/PermissionResourcesDTO.java b/src/main/java/com/newyetai/usercenter/authority/dto/PermissionResourcesDTO.java new file mode 100644 index 0000000..f9dc9c9 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/authority/dto/PermissionResourcesDTO.java @@ -0,0 +1,24 @@ +package com.newyetai.usercenter.authority.dto; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; + + +/** + * @author yzhq + */ +@ApiModel("角色资源保存DTO") +@Data +@NoArgsConstructor +@AllArgsConstructor +public class PermissionResourcesDTO extends PermissionPageQueryDTO implements Serializable { + + private List PermissionDTOList; + +} + diff --git a/src/main/java/com/newyetai/usercenter/authority/dto/RoleAllocationDTO.java b/src/main/java/com/newyetai/usercenter/authority/dto/RoleAllocationDTO.java new file mode 100644 index 0000000..1b00c25 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/authority/dto/RoleAllocationDTO.java @@ -0,0 +1,51 @@ +package com.newyetai.usercenter.authority.dto; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.usercenter.constants.SecurityConstants; +import lombok.*; +import lombok.experimental.SuperBuilder; + +import org.springframework.security.core.GrantedAuthority; + +/** + * 角色分配表 + * + * @author on 2019-11-05 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@SuperBuilder +public class RoleAllocationDTO extends BaseDTO implements GrantedAuthority { + + /** + * + */ + private static final long serialVersionUID = 1L; + + /** + * 角色id + */ + private Long roleId; + + /** + * 角色具体分配类型对应的id + */ + private Long allocationId; + + /** + * 角色分配类型:1个人2部门3组 + */ + private String allocationType; + + @Override + public String getAuthority() { + if (roleId != null && roleId != 0L) { + return SecurityConstants.ROLE_PERMISSION_PREFIX + roleId; + } + return null; + } + +} diff --git a/src/main/java/com/newyetai/usercenter/authority/dto/UrlPermissionDTO.java b/src/main/java/com/newyetai/usercenter/authority/dto/UrlPermissionDTO.java new file mode 100644 index 0000000..89092c1 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/authority/dto/UrlPermissionDTO.java @@ -0,0 +1,57 @@ +package com.newyetai.usercenter.authority.dto; + +import org.apache.commons.lang3.StringUtils; + +import com.newyetai.security.access.provider.IUrlConfigAttribute; + +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2020-09-07 + */ +@Data +@NoArgsConstructor +public class UrlPermissionDTO implements IUrlConfigAttribute{ + + private static final long serialVersionUID = 9030470489046670169L; + + /** 角色ID **/ + private Long roleId; + + /** 资源类型:1菜单3接口 **/ + private String resourceType; + + /** 资源ID **/ + private Long resourceId; + + /** 权限鉴别属性,默认格式:ROLE_{roleId} **/ + private String attribute; + + /** 链接 **/ + private String link; + + @Override + /** + * 权限鉴别属性,默认格式:ROLE_{roleId} + * + * @return attribute + */ + public String getAttribute() { + if (StringUtils.isBlank(attribute)) { + return "ROLE_" + roleId; + } + return attribute; + } + + @Override + public Long getKey() { + return resourceId; + } + + @Override + public String getUrl() { + return link; + } + +} diff --git a/src/main/java/com/newyetai/usercenter/authority/entity/Permission.java b/src/main/java/com/newyetai/usercenter/authority/entity/Permission.java new file mode 100644 index 0000000..c5c1bf5 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/authority/entity/Permission.java @@ -0,0 +1,80 @@ +package com.newyetai.usercenter.authority.entity; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.data.annotation.Transient; +import org.springframework.security.access.ConfigAttribute; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * 权限信息 + * + * @author on 2019-11-05 + */ +@TableName("xs_permission") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@EqualsAndHashCode(callSuper = true) +public class Permission extends BaseEntity implements ConfigAttribute { + + private static final long serialVersionUID = 1L; + + /** + * 角色ID + **/ + private Long roleId; + + /** + * 资源类型:1菜单2组件 + **/ + private String resourceType; + + /** + * 资源ID,如菜单和组件,以及用户定义的资源 + **/ + private Long resourceId; + + /** + * 权限鉴别属性,默认格式:ROLE_{roleId},可以扩展 + **/ + private String attribute; + + /** + * 机构ID + */ + private Long orgId; + + /** + * 平台编码 + */ + private Integer platformCode; + + /** + * 菜单地址,为收集菜单权限 + **/ + @Transient + private String resourceLink; + + @Override + /** + * 权限鉴别属性,默认格式:ROLE_{roleId} + * + * @return attribute + */ + public String getAttribute() { + if (StringUtils.isBlank(attribute)) { + return "ROLE_" + roleId; + } + return attribute; + } + +} diff --git a/src/main/java/com/newyetai/usercenter/authority/entity/Role.java b/src/main/java/com/newyetai/usercenter/authority/entity/Role.java new file mode 100644 index 0000000..5cf5129 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/authority/entity/Role.java @@ -0,0 +1,66 @@ +package com.newyetai.usercenter.authority.entity; + +import java.io.Serializable; +import java.util.Date; + +import org.springframework.data.annotation.Transient; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author Jerry.li + * @description 角色 + * @date 2020/3/24 + */ +@Data +@TableName("xs_role") +@AllArgsConstructor +@NoArgsConstructor +public class Role extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 4976697243964672402L; + + /** 机构id **/ + private Long orgId; + + /** 名称 **/ + private String name; + + /** 类型:0业务角色、1系统角色-渠道代理商、2系统角色-普通机构 **/ + private String type; + + /** 是否启用 **/ + private Boolean enabled; + + /** 描述 **/ + private String description; + + /** 标准角色类型:见role_standard_type **/ + private String standardType; + + /** + * 所属平台 + */ + private Integer platformCode; + + @Builder + public Role(Long id, Boolean deleted, Long createBy, Date createTime, Long updateBy, + Date updateTime, Long proxyBy, Long orgId, String name, String type, Boolean enabled, + String description, String standardType, Integer platformCode) { + super(id, deleted, createBy, createTime, updateBy, updateTime, proxyBy); + this.orgId = orgId; + this.name = name; + this.type = type; + this.enabled = enabled; + this.description = description; + this.standardType = standardType; + this.platformCode = platformCode; + } + +} diff --git a/src/main/java/com/newyetai/usercenter/authority/entity/RoleAllocation.java b/src/main/java/com/newyetai/usercenter/authority/entity/RoleAllocation.java new file mode 100644 index 0000000..67aca88 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/authority/entity/RoleAllocation.java @@ -0,0 +1,48 @@ +package com.newyetai.usercenter.authority.entity; + +import java.io.Serializable; + +import org.springframework.data.annotation.Transient; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author Jerry.li + * @description 角色分配 + * @date 2020/3/24 + */ +@TableName("xs_role_allocation") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public class RoleAllocation extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 5399518985159547780L; + + /** 机构id **/ + @Transient + private Long orgId; + + /** + * 角色id + */ + private Long roleId; + + /** + * 角色具体分配类型对应的id + */ + private Long allocationId; + + /** + * 角色分配类型:1-个人 2-部门 3-组 + */ + private String allocationType; + +} diff --git a/src/main/java/com/newyetai/usercenter/authority/mapper/UcPermissionMapper.xml b/src/main/java/com/newyetai/usercenter/authority/mapper/UcPermissionMapper.xml new file mode 100644 index 0000000..874b17b --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/authority/mapper/UcPermissionMapper.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + diff --git a/src/main/java/com/newyetai/usercenter/authority/mapper/UcRoleAllocationMapper.xml b/src/main/java/com/newyetai/usercenter/authority/mapper/UcRoleAllocationMapper.xml new file mode 100644 index 0000000..a8f9688 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/authority/mapper/UcRoleAllocationMapper.xml @@ -0,0 +1,85 @@ + + + + + + + + + + + + update + xs_role_allocation + set + deleted = 1, + update_by = #{operateUserId}, + update_time = now() + where + allocation_type = #{allocationType} + and allocation_id = #{allocationId} + and deleted = 0 + and role_id in + + #{roleId} + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/authority/mapper/UcRoleMapper.xml b/src/main/java/com/newyetai/usercenter/authority/mapper/UcRoleMapper.xml new file mode 100644 index 0000000..5aa17ca --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/authority/mapper/UcRoleMapper.xml @@ -0,0 +1,181 @@ + + + + + FROM xs_role + + org_id = #{orgId} and deleted = 0 + + + AND name like #{nameLike} + + + and enabled = #{param.enabled} + + + and type = #{param.type} + + + and standard_type = #{param.standardType} + + + order by id desc + + + -- 菜单已删除,组件还存在 + UPDATE + xs_permission xp + LEFT JOIN xs_component xc ON + xp.resource_id = xc.id + AND xc.deleted = 0 + LEFT JOIN xs_permission xp2 ON + xp2.resource_id = xc.url_id + AND xp2.role_id = xp.role_id + AND xp2.deleted = 0 + SET xp.deleted =1,xp.update_by = #{loginUserId}, xp.update_time = now() + WHERE + xp.deleted = 0 + AND xp2.id IS null + AND xp.resource_type = 2 + + + + -- 菜单已删除,接口还存在 + UPDATE + xs_permission xp + LEFT JOIN xs_url xc ON + xp.resource_id = xc.id + AND xc.type = 2 + AND xc.deleted = 0 + LEFT JOIN xs_permission xp2 ON + xp2.resource_id = xc.parent_id + AND xp2.role_id = xp.role_id + AND xp2.deleted = 0 + SET xp.deleted =1,xp.update_by = #{loginUserId} , xp.update_time = now() + WHERE + xp.deleted = 0 + AND xp2.id IS NULL + AND xp.resource_type = 3 + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/com/newyetai/usercenter/authority/service/UcPermissionService.java b/src/main/java/com/newyetai/usercenter/authority/service/UcPermissionService.java new file mode 100644 index 0000000..0a0b313 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/authority/service/UcPermissionService.java @@ -0,0 +1,36 @@ +package com.newyetai.usercenter.authority.service; + + +import java.util.List; +import java.util.Map; + +import com.newyetai.security.service.IPermissionSecurityService; +import com.newyetai.usercenter.authority.dto.ComponentPermissionDTO; +import com.newyetai.usercenter.authority.dto.PermissionQueryDTO; + +/** + * @author chenyun + * @description + * @date 2020/9/3 17:52 + */ +public interface UcPermissionService extends IPermissionSecurityService { + + /** + * 查询角色下所有组件 + * + * @return + */ + List listComponent(PermissionQueryDTO permissionQueryDTO); + + /** + * 查询指定角色拥有权限的所有资源id+type + * + * @param roleIds + * @return + * @author sr on 2020-09-07 + */ + List> listResourceIdTypeByRoleId(List roleIds); + + + +} diff --git a/src/main/java/com/newyetai/usercenter/authority/service/UcRoleAllocationService.java b/src/main/java/com/newyetai/usercenter/authority/service/UcRoleAllocationService.java new file mode 100644 index 0000000..4366376 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/authority/service/UcRoleAllocationService.java @@ -0,0 +1,48 @@ +package com.newyetai.usercenter.authority.service; + +import com.newyetai.security.service.IRoleAllocationSecurityService; +import com.newyetai.usercenter.dto.AllocatedBusinessRoleQueryDTO; +import com.newyetai.usercenter.dto.AllocationDTO; +import com.newyetai.usercenter.dto.RoleDTO; +import com.newyetai.usercenter.dto.UserAllocateRoleDTO; + +import java.util.List; + +/** + * 角色分配 + * + * @author sr on 2019-10-17 + */ +public interface UcRoleAllocationService extends IRoleAllocationSecurityService{ + + /** + * 查询指定机构下用户业务角色(已分配/未分配)列表 + * + * @param orgId + * @param userId + * @return + * @author sr on 2019-10-17 + */ + AllocationDTO getBusinessRoles(Long orgId, Long userId); + + /** + * @description: 查询指定机构、指定用户、指定平台的已分配角色 + * @return: + * @author: guixinman + * @param: + */ + List getAllocatedBusinessRoles(AllocatedBusinessRoleQueryDTO queryDTO); + + /** + * 指定用户角色分配(新分配/取消分配) + * + * @param orgId + * @param userId + * @param userAllocateRoleDTO + * @param operateUserId + * @author sr on 2019-10-17 + */ + void allocateBusinessRoles(Long orgId, Long userId, UserAllocateRoleDTO userAllocateRoleDTO, + Long operateUserId); + +} diff --git a/src/main/java/com/newyetai/usercenter/authority/service/UcRoleService.java b/src/main/java/com/newyetai/usercenter/authority/service/UcRoleService.java new file mode 100644 index 0000000..77a4175 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/authority/service/UcRoleService.java @@ -0,0 +1,133 @@ +package com.newyetai.usercenter.authority.service; + +import com.newyetai.common.AlitaResult; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.authority.dto.PermissionOperateDTO; +import com.newyetai.usercenter.dto.AllocationRoleDTO; +import com.newyetai.usercenter.dto.AllocationRoleUserDTO; +import com.newyetai.usercenter.dto.CheckKeyDTO; +import com.newyetai.usercenter.dto.RoleDTO; +import com.newyetai.usercenter.query.RoleQuery; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; + +import javax.validation.constraints.NotNull; +import javax.validation.groups.Default; +import java.util.List; + +/** + * @author Jerry.li + * @description 角色服务类 + * @date 2020/3/26 + */ +@Validated(Default.class) +public interface UcRoleService { + + /** + * 创建普通机构角色(type=0) + * + * @param orgId 机构id 不能为空 + * @param roleDTO + * @return + * @author sr on 2019-10-14 + */ + void createOrgRole(Long orgId, RoleDTO roleDTO); + + /** + * 修改普通机构角色(type=0) + * + * @param orgId 机构id 不能为空 + * @param roleDTO + * @author sr on 2019-10-14 + */ + void updateOrgRole(@NotNull Long orgId, @NotNull RoleDTO roleDTO); + + /** + * 删除普通机构角色(type=0) + * + * @param orgId 机构id 不能为空 + * @param roleId + * @author sr on 2019-10-14 + */ + void deleteOrgRole(Long orgId, Long roleId); + + /** + * 获取普通机构角色列表(type=0) + * + * @param orgId 机构id 不能为空 + * @param roleDTO + * @param page + * @author sr on 2019-10-14 + */ + void queryOrgRole(Long orgId, RoleDTO roleDTO, Page page); + + /** + * 获取标准角色为招聘负责人的列表 + * + */ + List queryOrgRole(Long orgId); + + /** + * 获取当前登录机构下角色的权限数据 + * + * @param orgId + * @return + */ + List findCheckedKeysByRoleIds(Long orgId); + + /** + * 分页查询平台管理员的角色列表 + * @param page + * @param query + */ + void queryPlatformAdminRoleList(RoleQuery query); + + /** + * 角色资源分配 + * @param permissionDTO + * @param operateUserId + */ + void roleUrlAllocation(PermissionOperateDTO permissionDTO, Long operateUserId); + + /** + * 用户分配角色 + * @param allocationRoleDTO + * @param operateUserId + * @return + */ + AlitaResult userAllocationRole(AllocationRoleDTO allocationRoleDTO, Long operateUserId); + + /** + * 角色分配用户 + * @param dto + * @return + */ + AlitaResult roleAllocationUser(AllocationRoleUserDTO dto); + + + /** + * 分配角色删除用户 + * @param allocationRoleDTO + */ + void removelocationRole(AllocationRoleUserDTO allocationRoleDTO); + + /** + * 角色启用 + * @param roleId + * @param enable + * @param operateUserId + * @return + */ + AlitaResult roleEnable(Long roleId, Boolean enable, Long operateUserId); + + /** + * 根据用户ID查询可分配的角色列表 + * @param query + */ + AlitaResult queryUserAllocationRoleList(RoleQuery query); + + /** + * 清理已已删除菜单下的组件和接口 + */ + void cleanRoleComponentAndInterface(); +} diff --git a/src/main/java/com/newyetai/usercenter/authority/service/impl/ResourceSecurityServiceImpl.java b/src/main/java/com/newyetai/usercenter/authority/service/impl/ResourceSecurityServiceImpl.java new file mode 100644 index 0000000..ac99f32 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/authority/service/impl/ResourceSecurityServiceImpl.java @@ -0,0 +1,189 @@ +package com.newyetai.usercenter.authority.service.impl; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import com.newyetai.common.constant.SystemCodeEnum; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.security.decision.manager.SecurityDecisionManager; +import com.newyetai.security.dto.SecurityUserDTO; +import com.newyetai.security.service.IResourceSecurityService; +import com.newyetai.usercenter.authority.constants.PermissionConstants; +import com.newyetai.usercenter.authority.dao.UcRoleMapper; +import com.newyetai.usercenter.authority.dto.PermissionQueryDTO; +import com.newyetai.usercenter.authority.service.UcPermissionService; +import com.newyetai.usercenter.constants.OrgConstants; +import com.newyetai.usercenter.constants.SecurityConstants; +import com.newyetai.usercenter.constants.UrlConstants; +import com.newyetai.usercenter.dto.IUserDetail; +import com.newyetai.usercenter.query.RoleQuery; +import com.newyetai.usercenter.resource.dao.UcComponentMapper; +import com.newyetai.usercenter.resource.dao.UcUrlMapper; +import com.newyetai.usercenter.resource.dto.ComponentDTO; +import com.newyetai.usercenter.resource.dto.UrlDTO; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Service +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +@Slf4j +public class ResourceSecurityServiceImpl implements IResourceSecurityService { + + private final UcUrlMapper ucUrlMapper; + + private final UcComponentMapper ucComponentMapper; + + private final SecurityDecisionManager securityDecisionManager; + + private final UcPermissionService ucPermissionService; + + private final UcRoleMapper ucRoleMapper; + + @Override + @Transactional(rollbackFor = RuntimeException.class) + @Cacheable(cacheNames = SecurityConstants.CacheName.RESOURCE_TREE_CACHE_KEY, + key = SecurityConstants.CACHE_KEY_ORG_SYSTEM_USER) + public List listResource(Integer systemCode, IUserDetail iUserDetail) { + return listResource(systemCode, iUserDetail, null); + } + + @Override + @Cacheable(cacheNames = SecurityConstants.CacheName.RESOURCE_TREE_CACHE_KEY, + key = SecurityConstants.CACHE_KEY_ORG_SYSTEM_USER_ROLE) + public List listResource(Integer systemCode, IUserDetail iUserDetail, Long roleId) { + // 当前登录人资源 + // 角色id不为空,已选角色资源列表 + Set urlIds = Sets.newHashSet(); + Set componentIds = Sets.newHashSet(); + if (roleId != null) { + distinctResource(roleId, urlIds, componentIds); + } + boolean isManager = UserContextHolder.isAdministrator(iUserDetail); + Long orgId = iUserDetail.getOrgId(); + Assert.notNull(orgId, "暂只支持查询企业用户资源列表,个人用户待处理"); + // 查询机构拥有资源 + List urls = this.listUrlDTO(systemCode, orgId); + Map urlMap = urls.stream() + .collect(Collectors.toMap(UrlDTO::getId, url -> url)); + List urlDTOs = Lists.newArrayList(); + PermissionQueryDTO permissionQueryDTO = + PermissionQueryDTO.builder().orgId(orgId).systemCode(systemCode).build(); + // 保证菜单顺序 + urls.stream().forEach(url -> { + // 决策权限 + if (!isManager && !securityDecisionManager.decide((SecurityUserDTO)iUserDetail, url, permissionQueryDTO)) { + return; + } + Long urlId = url.getId(); + UrlDTO uDto = urlMap.get(urlId); + + // 顶级菜单 + if (UrlConstants.URL_TOP_PARENT_ID.equals(url.getParentId())) { + urlDTOs.add(uDto); + return; + } + // 找父url,然后把自己加入其子集合 + UrlDTO pDto = urlMap.get(url.getParentId()); + if (pDto == null) { + log.error("️**************菜单数据异常,需修复数据*****************"); + return; + } + pDto.getChildren().add(uDto); + // 判断roleId是否拥有权限 + if (roleId != null && urlIds.contains(urlId)) { + uDto.setSelected(true); + } + }); + + // 将组件加入树中 + List components = this.listComponentDTO(systemCode, orgId); + components.stream().forEach(component -> { + // 决策权限 + if (!isManager && !securityDecisionManager.decide(component, permissionQueryDTO)) { + return; + } + UrlDTO url = urlMap.get(component.getUrlId()); + if (url == null) { + return; + } + url.getComponents().add(component); + + // 判断roleId是否拥有权限 + if (roleId != null && componentIds.contains(component.getId())) { + component.setSelected(true); + } + }); + return urlDTOs; + } + + /** + * 分类角色拥有的资源id(菜单/组件), + * + * @param roleId + * @param urlIds + * @param componentIds + * @author sr on 2019-10-16 + */ + private void distinctResource(Long roleId, Set urlIds, Set componentIds) { + List allocatedRoleIdList = Lists.newLinkedList(); + allocatedRoleIdList.add(roleId); + if (roleId == null) { + //当前登录人 + Long loginUserId = UserContextHolder.getLoginUserId(); + //查询当前用户已分配的角色 + RoleQuery roleQuery = RoleQuery.builder().userId(loginUserId).build(); + allocatedRoleIdList = ucRoleMapper.selectAllocatedRoleIdListByUserId(roleQuery); + } + if (CollectionUtils.isNotEmpty(allocatedRoleIdList)) { + List> resources = + ucPermissionService.listResourceIdTypeByRoleId(allocatedRoleIdList); + resources.forEach(resource -> { + if (PermissionConstants.RESOURCE_TYPE_URL + .equals(MapUtils.getString(resource, SecurityConstants.MAP_KEY_RESOURCE_TYPE))) { + urlIds.add(MapUtils.getLong(resource, SecurityConstants.MAP_KEY_RESOURCE_ID)); + return; + } + if (PermissionConstants.RESOURCE_TYPE_COMPONENT + .equals(MapUtils.getString(resource, SecurityConstants.MAP_KEY_RESOURCE_TYPE))) { + componentIds.add(MapUtils.getLong(resource, SecurityConstants.MAP_KEY_RESOURCE_ID)); + return; + } + }); + } + } + + @Override + public List listUrlDTO(Integer systemCode, Long orgId) { + Assert.notNull( + Arrays.stream(SystemCodeEnum.values()).filter(code -> code.getCode().equals(systemCode)) + .findFirst().orElse(null), + "应用不存在"); + return ucUrlMapper.listUrlDTO(systemCode, + OrgConstants.PLATFORM_ORG_ID.equals(orgId) ? null : orgId); + } + + @Override + public List listComponentDTO(Integer systemCode, Long orgId) { + Assert.notNull( + Arrays.stream(SystemCodeEnum.values()).filter(code -> code.getCode().equals(systemCode)) + .findFirst().orElse(null), + "应用不存在"); + return ucComponentMapper.listComponentDTO(systemCode, + OrgConstants.PLATFORM_ORG_ID.equals(orgId) ? null : orgId); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/authority/service/impl/UcPermissionServiceImpl.java b/src/main/java/com/newyetai/usercenter/authority/service/impl/UcPermissionServiceImpl.java new file mode 100644 index 0000000..4ab5cc1 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/authority/service/impl/UcPermissionServiceImpl.java @@ -0,0 +1,38 @@ +package com.newyetai.usercenter.authority.service.impl; + +import java.util.List; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.newyetai.common.AlitaResult; +import com.newyetai.usercenter.authority.dao.UcPermissionMapper; +import com.newyetai.usercenter.authority.dto.ComponentPermissionDTO; +import com.newyetai.usercenter.authority.dto.PermissionQueryDTO; +import com.newyetai.usercenter.authority.dto.UrlPermissionDTO; +import com.newyetai.usercenter.authority.service.UcPermissionService; + +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class UcPermissionServiceImpl implements UcPermissionService { + + private final UcPermissionMapper ucPermissionMapper; + + @Override + public List listComponent(PermissionQueryDTO permissionQueryDTO) { + return ucPermissionMapper.findComponent(permissionQueryDTO); + } + + @Override + public AlitaResult> listUrl(PermissionQueryDTO permissionQueryDTO) { + return AlitaResult.success(ucPermissionMapper.findUrl(permissionQueryDTO)); + } + + @Override + public List> listResourceIdTypeByRoleId(List roleIds) { + return ucPermissionMapper.listResourceIdTypeByRoleId(roleIds); + } +} diff --git a/src/main/java/com/newyetai/usercenter/authority/service/impl/UcRoleAllocationServiceImpl.java b/src/main/java/com/newyetai/usercenter/authority/service/impl/UcRoleAllocationServiceImpl.java new file mode 100644 index 0000000..edf89cf --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/authority/service/impl/UcRoleAllocationServiceImpl.java @@ -0,0 +1,117 @@ +package com.newyetai.usercenter.authority.service.impl; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import org.apache.commons.collections.CollectionUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.google.common.collect.Lists; +import com.newyetai.common.AlitaResult; +import com.newyetai.common.exception.util.ExceptionUtils; +import com.newyetai.usercenter.authority.dao.UcRoleAllocationMapper; +import com.newyetai.usercenter.authority.dao.UcRoleMapper; +import com.newyetai.usercenter.authority.dto.RoleAllocationDTO; +import com.newyetai.usercenter.authority.entity.RoleAllocation; +import com.newyetai.usercenter.authority.service.UcRoleAllocationService; +import com.newyetai.usercenter.constants.SecurityConstants; +import com.newyetai.usercenter.constants.SecurityExceptionMsg; +import com.newyetai.usercenter.dto.AllocatedBusinessRoleQueryDTO; +import com.newyetai.usercenter.dto.AllocationDTO; +import com.newyetai.usercenter.dto.RoleDTO; +import com.newyetai.usercenter.dto.UserAllocateRoleDTO; +import com.newyetai.usercenter.user.service.OrgUserService; +import com.newyetai.usercenter.utils.RoleUtils; + +import lombok.RequiredArgsConstructor; + +/** + * 角色分配 + * + * @author sr on 2019-10-17 + */ +@Service +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class UcRoleAllocationServiceImpl implements UcRoleAllocationService { + + private final UcRoleMapper ucRoleMapper; + + private final OrgUserService orgUserService; + + private final UcRoleAllocationMapper ucRoleAllocationMapper; + + @Override + @Transactional(rollbackFor = RuntimeException.class) + public AllocationDTO getBusinessRoles(Long orgId, Long userId) { + // 校验机构下是否存在用户 + ExceptionUtils.throwBusinessException(orgUserService.existOrgUser(orgId, userId), + SecurityExceptionMsg.ORG_USER_NOT_EXIST); + // 查询用户已经分配的角色id + Set roleIds = + ucRoleAllocationMapper.findRoleIds(SecurityConstants.ALLOCATION_TYPE_USER, userId); + // 查询机构下的角色(启用/业务角色)列表 + List roleDTOs = + ucRoleMapper.queryOrgRoles(orgId, RoleUtils.getBusinessRoleDTO(), null); + Map> roleDTOMap = roleDTOs.stream() + .collect(Collectors.partitioningBy(roleDTO -> roleIds.contains(roleDTO.getId()))); + return new AllocationDTO<>(roleDTOMap.get(true), roleDTOMap.get(false)); + } + + @Override + public List getAllocatedBusinessRoles(AllocatedBusinessRoleQueryDTO queryDTO) { + // 校验机构下是否存在用户 + ExceptionUtils.throwBusinessException(orgUserService.existOrgUser(queryDTO.getOrgId(), queryDTO.getAllocationId()), + SecurityExceptionMsg.ORG_USER_NOT_EXIST); + return ucRoleAllocationMapper.getAllocatedBusinessRoles(queryDTO); + } + + @Override + @Transactional(rollbackFor = RuntimeException.class) + public void allocateBusinessRoles(Long orgId, Long userId, + UserAllocateRoleDTO userAllocateRoleDTO, + Long operateUserId) { + // 校验机构下是否存在用户 + ExceptionUtils.throwBusinessException(orgUserService.existOrgUser(orgId, userId), + SecurityExceptionMsg.ORG_USER_NOT_EXIST); + boolean allocated = Boolean.TRUE.equals(userAllocateRoleDTO.getAllocated()); + // 查询机构下的角色(启用/业务角色)id列表 + Set orgRoleIds = ucRoleMapper.queryOrgRoleIds(orgId, RoleUtils.getBusinessRoleDTO()); + // 过滤掉不在范围的id + List roleAllocations = allocated ? Lists.newArrayList() : null; + List deleteRoleIds = allocated ? null : Lists.newArrayList(); + + // 查询用户已经分配的角色id + Set allocationRoleIds = + ucRoleAllocationMapper.findRoleIds(SecurityConstants.ALLOCATION_TYPE_USER, userId); + + userAllocateRoleDTO.getRoleIds().stream().filter(roleId -> orgRoleIds.contains(roleId)) + .forEach(roleId -> { + if (allocated && !allocationRoleIds.contains(roleId)) { + roleAllocations + .add(RoleAllocation.builder().orgId(orgId).roleId(roleId).allocationId(userId) + .allocationType(SecurityConstants.ALLOCATION_TYPE_USER).build()); + } else if ((!allocated && allocationRoleIds.contains(roleId))) { + deleteRoleIds.add(roleId); + } + }); + if (allocated) { + ExceptionUtils.throwBusinessException(CollectionUtils.isEmpty(roleAllocations), + SecurityExceptionMsg.ALLOCATE_ROLES_EMPTY); + ucRoleAllocationMapper.saveEntites(roleAllocations, operateUserId); + } else { + ExceptionUtils.throwBusinessException(CollectionUtils.isEmpty(deleteRoleIds), + SecurityExceptionMsg.UNALLOCATE_ROLES_EMPTY); + ucRoleAllocationMapper.deleteByRoleIds(SecurityConstants.ALLOCATION_TYPE_USER, userId, + deleteRoleIds, operateUserId); + } + } + + @Override + public AlitaResult> findByUserId(Long userId) { + return AlitaResult.success(ucRoleAllocationMapper.findByUserId(userId)); + } +} diff --git a/src/main/java/com/newyetai/usercenter/authority/service/impl/UcRoleServiceImpl.java b/src/main/java/com/newyetai/usercenter/authority/service/impl/UcRoleServiceImpl.java new file mode 100644 index 0000000..18cdb07 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/authority/service/impl/UcRoleServiceImpl.java @@ -0,0 +1,381 @@ +package com.newyetai.usercenter.authority.service.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.authority.dao.UcPermissionMapper; +import com.newyetai.usercenter.authority.dao.UcRoleAllocationMapper; +import com.newyetai.usercenter.authority.dao.UcRoleMapper; +import com.newyetai.usercenter.authority.dto.PermissionOperateDTO; +import com.newyetai.usercenter.authority.entity.Permission; +import com.newyetai.usercenter.authority.entity.Role; +import com.newyetai.usercenter.authority.entity.RoleAllocation; +import com.newyetai.usercenter.authority.service.UcRoleService; +import com.newyetai.usercenter.cache.SecurityCacheUtils; +import com.newyetai.usercenter.constants.RoleConstants; +import com.newyetai.usercenter.constants.SecurityConstants; +import com.newyetai.usercenter.constants.SecurityExceptionMsg; +import com.newyetai.usercenter.dto.AllocationRoleDTO; +import com.newyetai.usercenter.dto.AllocationRoleUserDTO; +import com.newyetai.usercenter.dto.CheckKeyDTO; +import com.newyetai.usercenter.dto.RoleDTO; +import com.newyetai.usercenter.enums.ResourceType; +import com.newyetai.usercenter.query.RoleQuery; +import com.newyetai.usercenter.resource.dao.UcUrlMapper; +import com.newyetai.usercenter.utils.RoleUtils; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @author Jerry.li + * @description 角色服务 + * @date 2020/3/26 + */ +@Slf4j +@Service +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +// TODO 目前只有本地引用,需提供cloud调用,然后放开注释 +// @ConditionalOnProperty(name = SecurityConstants.PROP_KEY_SECURITY_USELOCAL, havingValue = "true", +// matchIfMissing = true) +public class UcRoleServiceImpl implements UcRoleService { + + private final UcUrlMapper ucUrlMapper; + + private final UcRoleMapper ucRoleMapper; + + private final UcPermissionMapper ucPermissionMapper; + + private final UcRoleAllocationMapper ucRoleAllocationMapper; + + @Override + @Transactional(rollbackFor = RuntimeException.class) + public void createOrgRole(Long orgId, RoleDTO roleDTO) { + // 校验机构下角色名称 + Assert.isTrue( + ucRoleMapper.existRoleName(orgId, roleDTO.getName(), null) == 0, + SecurityExceptionMsg.ROLE_NAME_EXIST); + if (StringUtils.isBlank(roleDTO.getStandardType())) { + roleDTO.setStandardType(RoleConstants.STANDARD_ROLE_TYPE_ELSE); + } + Role role = RoleUtils.toCreateRole(orgId, roleDTO, RoleConstants.ROLE_TYPE_BUSINESS); + + ucRoleMapper.saveEntity(role, UserContextHolder.getExistLoginUserId()); + + roleDTO.setId(role.getId()); + roleDTO.setCreateTime(role.getCreateTime()); + // 刷新缓存 + SecurityCacheUtils.flushAll(); + } + + @Override + @Transactional(rollbackFor = RuntimeException.class) + public void updateOrgRole(Long orgId, RoleDTO roleDTO) { + Role byId = ucRoleMapper.getById(roleDTO.getId()); + Assert.isTrue(byId != null && orgId.equals(byId.getOrgId()), "角色信息不存在"); + + if (!StringUtils.equals(roleDTO.getName(), byId.getName())) { + // 校验机构下角色名称 + Assert.isTrue( + ucRoleMapper.existRoleName(orgId, roleDTO.getName(), roleDTO.getId()) == 0, + SecurityExceptionMsg.ROLE_NAME_EXIST); + } + + if (StringUtils.isBlank(roleDTO.getStandardType())) { + roleDTO.setStandardType(RoleConstants.STANDARD_ROLE_TYPE_ELSE); + } + + Assert.isTrue( + ucRoleMapper.updateEntitySelective( + RoleUtils.toUpdateRole(roleDTO), UserContextHolder.getExistLoginUserId()) + == 1, + SecurityExceptionMsg.UPDATE_NOT_EXIST); + // 刷新缓存 + SecurityCacheUtils.flushAll(); + } + + @Override + @Transactional(rollbackFor = RuntimeException.class) + public void deleteOrgRole(Long orgId, Long roleId) { + Assert.isTrue( + ucRoleMapper.deleteEntity( + Role.builder().id(roleId).build(), UserContextHolder.getExistLoginUserId()) + == 1, + SecurityExceptionMsg.UPDATE_NOT_EXIST); + // 刷新缓存 + SecurityCacheUtils.flushAll(); + } + + @Override + @Transactional(rollbackFor = RuntimeException.class) + public void queryOrgRole(Long orgId, RoleDTO roleDTO, Page page) { + roleDTO.setType(RoleConstants.ROLE_TYPE_BUSINESS); + ucRoleMapper.queryOrgRoles(orgId, roleDTO, page); + } + + @Override + public List queryOrgRole(Long orgId) { + RoleDTO roleDTO = RoleDTO.builder().standardType(RoleConstants.STANDARD_ROLE_TYPE_PERSONCHARGE).build(); + return ucRoleMapper.queryOrgRoles(orgId, roleDTO, null); + } + + @Override + public List findCheckedKeysByRoleIds(Long orgId) { + List roleDTOS = ucRoleMapper.queryOrgRoleList(orgId); + List rs = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(roleDTOS)) { + Set roleIds = roleDTOS.stream().map(RoleDTO::getId).collect(Collectors.toSet()); + rs = ucPermissionMapper.findCheckedKeysByRoleIds(roleIds); + } + return rs; + } + + @Override + public void queryPlatformAdminRoleList(RoleQuery query) { + ucRoleMapper.selectPlatformAdminRoleList(query); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void roleUrlAllocation( + PermissionOperateDTO permissionDTO, Long operateUserId) { + Long roleId = permissionDTO.getRoleId(); + String attribute = "ROLE_" + roleId; + //本次所有选择的菜单 + List selectedIdList = permissionDTO.getResourceIdList(); + if(CollectionUtils.isEmpty(selectedIdList)){ + // 取消之前全部分配资源列表并退出 + ucPermissionMapper.deletePermissionByRoleId(operateUserId, roleId); + return; + } + // 查询出该角色已分配的资源ID列表 + Set oldResourceIdSet = + ucPermissionMapper.selectResourceIdByRoleId(roleId, + RoleConstants.ROLE_TYPE_BUSINESS); + //过滤出需要删除的(原本已存在,不在本次所选菜单中) + Set removeIdList= + oldResourceIdSet.stream().filter(resourceId ->!selectedIdList.contains(resourceId)).collect(Collectors.toSet()); + //过滤出新增的 + selectedIdList.removeAll(oldResourceIdSet); + // 本次新增 + if (CollectionUtils.isNotEmpty(selectedIdList)) { + // 查询出父级菜单ID + Set parentIds = ucUrlMapper.selectParentIdByResourceIds(selectedIdList); + parentIds.addAll(selectedIdList); + log.info("-------本次新增资源ID:{}", parentIds.toString()); + parentIds.forEach( + resourceId -> { + Permission permission = + Permission.builder() + .roleId(roleId) + .resourceId(resourceId) + .attribute(attribute) + .platformCode(permissionDTO.getPlatformCode()) + .orgId(UserContextHolder.getLoginOrgId()) + .resourceType(ResourceType.RESOURCE_MENU_TYPE.getType()) + .build(); + ucPermissionMapper.saveEntity(permission, operateUserId); + }); + } + if(CollectionUtils.isNotEmpty(removeIdList)){ + this.removeResource(removeIdList,roleId,UserContextHolder.getLoginUserId()); + } + } + + /** + * 检查分配角色 + * + * @param oldRoles 旧的角色 + * @param newRoles 新角色 + * @param cannotDeletedRoles 不能删除角色 + */ + private void checkAllocationRole(List oldRoles, List newRoles, Set cannotDeletedRoles) { + Assert.isTrue(!(CollectionUtils.containsAny(oldRoles, cannotDeletedRoles) && !CollectionUtils.containsAny(newRoles, cannotDeletedRoles)), + "当前操作包含的销售角色不是无关联状态"); + } + + @Override + public AlitaResult userAllocationRole( + AllocationRoleDTO allocationRoleDTO, Long operateUserId) { + Long userId = allocationRoleDTO.getUserId(); + // 查询用户已分配的角色ID + RoleQuery query = RoleQuery.builder() + .userId(userId) + .platformCode(allocationRoleDTO.getPlatformCode()) + .build(); + List allocatedRoleIdList = ucRoleMapper.selectAllocatedRoleIdListByUserId(query); + + // 本次分配 + List tempRoleIdList = allocationRoleDTO.getAllocatedRoleIdList(); + + checkAllocationRole(allocatedRoleIdList, tempRoleIdList, ucRoleMapper.getSellerRoleCanNotBeDeleted(userId)); + + if (CollectionUtils.isEmpty(tempRoleIdList)) { + // 取消已分配的全部权限 + removeAllocatedRole(allocatedRoleIdList, userId, operateUserId); + return AlitaResult.success(true); + } + + // 筛选出本次取消和新分配的角色ID + if (CollectionUtils.isNotEmpty(allocatedRoleIdList)) { + List cancelAllocationRoleIdList = new ArrayList<>(); + allocatedRoleIdList.forEach( + oldRoleId -> { + if (!tempRoleIdList.contains(oldRoleId)) { + cancelAllocationRoleIdList.add(oldRoleId); + } + }); + + removeAllocatedRole(cancelAllocationRoleIdList, userId, operateUserId); + // 过滤掉本次取消的角色ID + allocatedRoleIdList.removeAll(cancelAllocationRoleIdList); + // 过滤已分配有效的角色ID + tempRoleIdList.removeAll(allocatedRoleIdList); + } + + // 本次新增 + if (CollectionUtils.isNotEmpty(tempRoleIdList)) { + tempRoleIdList.forEach( + roleId -> { + RoleAllocation allocation = + RoleAllocation.builder() + .roleId(roleId) + .allocationId(userId) + .createBy(operateUserId) + .allocationType(SecurityConstants.ALLOCATION_TYPE_USER) // TODO: 其他类型待确认 + .build(); + ucRoleAllocationMapper.saveEntity(allocation, operateUserId); + }); + } + // 刷新缓存 + SecurityCacheUtils.flushAll(); + return AlitaResult.success(true); + } + + + @Override + public AlitaResult roleAllocationUser(AllocationRoleUserDTO dto ) { + for (Long userId : dto.getUserIds()) { + // 查询用户已分配的角色ID + RoleQuery query = RoleQuery.builder() + .userId(userId) + .platformCode(dto.getPlatformCode()) + .build(); + List allocatedRoleIdList = ucRoleMapper.selectAllocatedRoleIdListByUserId(query); + // 已分配过则跳过 + if(allocatedRoleIdList.contains(dto.getRoleId())){ + continue; + } + // 检查分配角色 + checkAllocationRole(allocatedRoleIdList, Arrays.asList(dto.getRoleId()), ucRoleMapper.getSellerRoleCanNotBeDeleted(userId)); + // 本次新增 + RoleAllocation allocation = + RoleAllocation.builder() + .roleId(dto.getRoleId()) + .allocationId(userId) + .allocationType(SecurityConstants.ALLOCATION_TYPE_USER) // TODO: 其他类型待确认 + .build(); + ucRoleAllocationMapper.saveEntity(allocation); + } + // 刷新缓存 + SecurityCacheUtils.flushAll(); + return AlitaResult.success(true); + } + + + @Override + public void removelocationRole(AllocationRoleUserDTO allocationRoleDTO) { + // 取消已分配的权限 + allocationRoleDTO.getUserIds().stream().forEach( userId -> { + removeAllocatedRole(Arrays.asList(allocationRoleDTO.getRoleId()), userId, UserContextHolder.getExistLoginOrgId()); + }); + SecurityCacheUtils.flushAll(); + } + + @Override + public AlitaResult roleEnable(Long roleId, Boolean enable, Long operateUserId) { + Role role = Role.builder().id(roleId).enabled(enable).build(); + int count = ucRoleMapper.updateEntitySelective(role, operateUserId); + // 刷新缓存 + SecurityCacheUtils.flushAll(); + return AlitaResult.success(count > 0); + } + + @Override + public AlitaResult queryUserAllocationRoleList(RoleQuery query) { + Long userId = query.getUserId(); + AllocationRoleDTO allocationRoleDTO = new AllocationRoleDTO(); + // 查询已分配的角色ID + List allocatedRoleIdList = ucRoleMapper.selectAllocatedRoleIdListByUserId(query); + allocationRoleDTO.setAllocatedRoleIdList(allocatedRoleIdList); + + // 查询用户对应的机构信息 +// OrganizeDTO organizeDTO = ucOrgMapper.selectOrgInfoByUserId(userId); +// ExceptionUtils.throwBusinessException(organizeDTO == null, SecurityExceptionMsg.ORG_NOT_EXIST); + + List roleDTOList = ucRoleMapper.selectPlatformUserUnallocatedRoleList(query); + allocationRoleDTO.setUnallocatedRoleList(roleDTOList); + return AlitaResult.success(allocationRoleDTO); + } + + @Override + public void + cleanRoleComponentAndInterface() { + ucRoleMapper.cleanRoleComponent(UserContextHolder.getLoginUserId()); + ucRoleMapper.cleanRoleInterface(UserContextHolder.getLoginUserId()); + } + + /** + * 移除已分配的资源 + * + * @param resourceIdSet + * @param roleId + * @param operateUserId + */ + private void removeResource(Set resourceIdSet, Long roleId, Long operateUserId) { + resourceIdSet.forEach( + resourceId -> { + log.info( + "-------本次取消的资源分配信息roleId:{}, resourceId: {}, operateUserId:{}", + roleId, + resourceId, + operateUserId); + ucPermissionMapper.deletePermissionByRoleIdAndResourceId( + operateUserId, roleId, resourceId); + }); + } + + /** + * 取消已分配的角色 + * + * @param roleIdList + * @param userId + * @param operateUserId + */ + private void removeAllocatedRole(List roleIdList, Long userId, Long operateUserId) { + if (CollectionUtils.isNotEmpty(roleIdList)) { + roleIdList.forEach( + roleId -> { + log.info( + "-------本次取消的角色分配roleId:{}, userId: {}, operateUserId:{}", + roleId, + userId, + operateUserId); + ucRoleAllocationMapper.deleteUserAllocatedRole(operateUserId, roleId, userId); + }); + } + } +} diff --git a/src/main/java/com/newyetai/usercenter/cache/CacheConfig.java b/src/main/java/com/newyetai/usercenter/cache/CacheConfig.java new file mode 100644 index 0000000..d47fe11 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/cache/CacheConfig.java @@ -0,0 +1,14 @@ +package com.newyetai.usercenter.cache; + +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Configuration; + +/** + * 缓存配置类 + * @author sr on 2019-09-11 + */ +@Configuration +@EnableCaching +public class CacheConfig { + +} diff --git a/src/main/java/com/newyetai/usercenter/cache/SecurityCacheAllEvict.java b/src/main/java/com/newyetai/usercenter/cache/SecurityCacheAllEvict.java new file mode 100644 index 0000000..c2f477f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/cache/SecurityCacheAllEvict.java @@ -0,0 +1,32 @@ +package com.newyetai.usercenter.cache; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Caching; + +import com.newyetai.usercenter.constants.SecurityConstants; + +/** + * 清除所有security缓存 + * + * @author on 2019-11-05 + */ +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Inherited +@Caching(evict = { + @CacheEvict(cacheNames = { + SecurityConstants.CacheName.RESOURCE_TREE_CACHE_KEY, + SecurityConstants.CacheName.USER_GRANTED_AUTHORITY_CACHE_KEY, + SecurityConstants.CacheName.URL_FILTER_ATTRIBUTE_MAP_CACHE_KEY, + SecurityConstants.CacheName.URL_ATTRIBUTE_MAP_CACHE_KEY, + SecurityConstants.CacheName.COMPONENT_ATTRIBUTE_MAP_CACHE_KEY + }, allEntries = true) +}) +public @interface SecurityCacheAllEvict { + +} diff --git a/src/main/java/com/newyetai/usercenter/cache/SecurityCacheEvict.java b/src/main/java/com/newyetai/usercenter/cache/SecurityCacheEvict.java new file mode 100644 index 0000000..d29f97a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/cache/SecurityCacheEvict.java @@ -0,0 +1,40 @@ +package com.newyetai.usercenter.cache; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Caching; + +import com.newyetai.usercenter.constants.SecurityConstants; + +/** + * 清除缓存 + * + * @author on 2019-11-05 + */ +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Inherited +@Caching(evict = { + @CacheEvict(cacheNames = SecurityConstants.CacheName.RESOURCE_TREE_CACHE_KEY, + key = SecurityCacheEvict.SYSTEM_ORG_ALL), + @CacheEvict(cacheNames = SecurityConstants.CacheName.USER_GRANTED_AUTHORITY_CACHE_KEY, + key = SecurityCacheEvict.ORG_ALL), + @CacheEvict(cacheNames = SecurityConstants.CacheName.URL_FILTER_ATTRIBUTE_MAP_CACHE_KEY, + key = SecurityCacheEvict.SYSTEM_ALL), + @CacheEvict(cacheNames = SecurityConstants.CacheName.URL_ATTRIBUTE_MAP_CACHE_KEY, + key = SecurityCacheEvict.SYSTEM_ORG), + @CacheEvict(cacheNames = SecurityConstants.CacheName.COMPONENT_ATTRIBUTE_MAP_CACHE_KEY, + key = SecurityCacheEvict.SYSTEM_ORG), +}) +public @interface SecurityCacheEvict { + + String SYSTEM_ORG = "#systemCode + ':' + #orgId"; + String SYSTEM_ORG_ALL = "#systemCode + ':' + #orgId + '*'"; + String SYSTEM_ALL = "#systemCode + '*'"; + String ORG_ALL = "#orgId + '*'"; + +} diff --git a/src/main/java/com/newyetai/usercenter/cache/SecurityCacheService.java b/src/main/java/com/newyetai/usercenter/cache/SecurityCacheService.java new file mode 100644 index 0000000..6ce2b5c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/cache/SecurityCacheService.java @@ -0,0 +1,17 @@ +package com.newyetai.usercenter.cache; + +import org.springframework.stereotype.Service; + +@Service +public class SecurityCacheService { + + @SecurityCacheEvict + public void evictSystemOrg(Integer systemCode, Long orgId) { + // do nothing... + } + + @SecurityCacheAllEvict + public void evictAll() { + // do nothing... + } +} diff --git a/src/main/java/com/newyetai/usercenter/cache/SecurityCacheUtils.java b/src/main/java/com/newyetai/usercenter/cache/SecurityCacheUtils.java new file mode 100644 index 0000000..2f0c77e --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/cache/SecurityCacheUtils.java @@ -0,0 +1,67 @@ +package com.newyetai.usercenter.cache; + +import java.util.Set; + +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import com.google.common.collect.Sets; +import com.newyetai.common.util.EnvironmentUtils; +import com.newyetai.common.util.UserContextHolder; + +/** + * security缓存工具类 + * + * @author sr on 2020-09-15 + */ +@Component +public class SecurityCacheUtils { + + private static SecurityCacheService securityCacheService; + + SecurityCacheUtils(SecurityCacheService securityCacheService) { + SecurityCacheUtils.securityCacheService = securityCacheService; + } + + /** + * 清除当前系统机构级缓存 + * + * @author sr on 2020-09-15 + */ + public static void flushCurrentSystemOrg() { + flushSystemOrg(null, UserContextHolder.getLoginOrgId()); + } + + /** + * 清除系统机构级缓存 + * + * @param systemCode + * @param orgId + * @author sr on 2020-09-15 + */ + public static void flushSystemOrg(Integer systemCode, Long orgId) { + flushSystemOrgs(systemCode, Sets.newHashSet(orgId)); + } + + + public static void flushSystemOrgs(Integer systemCode, Set orgIds) { + if (CollectionUtils.isEmpty(orgIds)) { + return; + } + if (systemCode == null) { + systemCode = EnvironmentUtils.getSystemCode(); + } + for (Long orgId : orgIds) { + securityCacheService.evictSystemOrg(systemCode, orgId); + } + } + + /** + * 清除所有缓存 + * @author sr on 2020-09-15 + */ + public static void flushAll() { + securityCacheService.evictAll(); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/common/constant/CodeTypeEnum.java b/src/main/java/com/newyetai/usercenter/common/constant/CodeTypeEnum.java new file mode 100644 index 0000000..aaaf972 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/common/constant/CodeTypeEnum.java @@ -0,0 +1,24 @@ +package com.newyetai.usercenter.common.constant; + +import com.newyetai.codegenerator.pojo.CodeParam; + +/** + * 编码类型 + * @author sr on 2019-12-06 + */ +public enum CodeTypeEnum { + + ORG(CodeParam.builder().type("O").build()), + + ; + private CodeParam codeParam; + + private CodeTypeEnum(CodeParam codeParam) { + this.codeParam = codeParam; + } + + public CodeParam getCodeParam() { + return this.codeParam; + } + +} diff --git a/src/main/java/com/newyetai/usercenter/common/constant/XxlJobHandlerConstants.java b/src/main/java/com/newyetai/usercenter/common/constant/XxlJobHandlerConstants.java new file mode 100644 index 0000000..94ecf77 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/common/constant/XxlJobHandlerConstants.java @@ -0,0 +1,24 @@ +package com.newyetai.usercenter.common.constant; + +/** + * 任务调度常量类 + * + * @author sr on 2020-11-25 + */ +public interface XxlJobHandlerConstants { + + /** + * 统计机构最近登录时间 HCY + **/ + String STATISTIC_ORG_LAST_LOGIN_TIME = "statisticOrgLastLoginTimeHandler"; + + /** + * 授权订阅用户列表 + **/ + String AUTH_SUBSCRIBE_USER_LIST = "authSubscribeUserListHandler"; + /** + * 用户注销通知工作 + */ + String USER_CANCEL_NOTIFY_JOB = "userCancelNotifyHandler"; + +} diff --git a/src/main/java/com/newyetai/usercenter/common/controller/SlickParamController.java b/src/main/java/com/newyetai/usercenter/common/controller/SlickParamController.java new file mode 100644 index 0000000..1a1bd8e --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/common/controller/SlickParamController.java @@ -0,0 +1,55 @@ +package com.newyetai.usercenter.common.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.newyetai.common.AlitaResult; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.common.dto.SlickParamCreateDTO; +import com.newyetai.usercenter.common.dto.SlickParamDTO; +import com.newyetai.usercenter.common.dto.SlickParamQueryDTO; +import com.newyetai.usercenter.common.service.SlickParamService; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +/** + * @author sr on 2022-01-11 + */ +@RestController +@RequestMapping("slick_param") +@Api(tags = "圆滑的参数") +public class SlickParamController { + + @Autowired + private SlickParamService slickParamService; + + @PostMapping("/create") + @ApiOperation("创建") + public AlitaResult create( + @Validated @RequestBody SlickParamCreateDTO slickParamCreateDTO){ + return AlitaResult.success(slickParamService.create(slickParamCreateDTO)); + } + + @DeleteMapping("/remove/{id}") + @ApiOperation("删除") + public AlitaResult remove(@PathVariable Long id){ + slickParamService.remove(id); + return AlitaResult.success(true); + } + + @GetMapping("/page") + @ApiOperation("分页查询") + public AlitaResult> page(SlickParamQueryDTO slickParamQueryDTO){ + slickParamService.page(slickParamQueryDTO); + return AlitaResult.success(slickParamQueryDTO.getPageResult()); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/common/controller/SmsController.java b/src/main/java/com/newyetai/usercenter/common/controller/SmsController.java new file mode 100644 index 0000000..afca97f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/common/controller/SmsController.java @@ -0,0 +1,48 @@ +package com.newyetai.usercenter.common.controller; + +import com.newyetai.common.AlitaResult; +import com.newyetai.usercenter.user.phone.dto.PhoneCodeDTO; +import com.newyetai.usercenter.user.phone.dto.PhoneCodeSmsDTO; +import com.newyetai.usercenter.user.phone.dto.SmsSimpleSendDTO; +import com.newyetai.usercenter.user.phone.provider.simple.ISimpleSms; +import com.newyetai.usercenter.user.phone.util.PhoneCodeUtils; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author sr on 2022-09-26 + */ +@RestController +@Api(tags = "短信") +public class SmsController { + + @Autowired + private ISimpleSms simpleSms; + + @PostMapping("sms/send/simple/async") + @ApiOperation("发送短信") + public AlitaResult simpleSms(@Validated @RequestBody SmsSimpleSendDTO sendDTO) { + simpleSms.sendAsync(sendDTO); + return AlitaResult.success(); + } + + @PostMapping("anon/sms/send") + @ApiOperation("获取验证码-不同类型") + public AlitaResult sms(@Validated @RequestBody PhoneCodeSmsDTO phoneCodeSmsDTO) { + PhoneCodeUtils.send(phoneCodeSmsDTO); + return AlitaResult.success(); + } + + @PostMapping("sms/match") + @ApiOperation("获取验证码-匹配验证") + public AlitaResult match(@Validated @RequestBody PhoneCodeDTO phoneCodeDTO) { + PhoneCodeUtils.matchBiz(phoneCodeDTO); + return AlitaResult.success(); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/common/dao/SlickParamMapper.java b/src/main/java/com/newyetai/usercenter/common/dao/SlickParamMapper.java new file mode 100644 index 0000000..eb079ac --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/common/dao/SlickParamMapper.java @@ -0,0 +1,28 @@ +package com.newyetai.usercenter.common.dao; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.newyetai.usercenter.common.dto.SlickParamDTO; +import com.newyetai.usercenter.common.dto.SlickParamQueryDTO; +import com.newyetai.usercenter.common.entity.SlickParam; +import com.newyetai.tkmybatis.mybatis.MyMapper; + +/** + * 圆滑的参数 + * + * @author sr on 2022-01-11 + */ +public interface SlickParamMapper extends MyMapper { + + /** + * 查询 + * + * @param slickParamQueryDTO + * @return + * @author sr on 2022-01-11 + */ + List listSlickParamDTO(@Param("param") SlickParamQueryDTO slickParamQueryDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/common/dto/SlickParamCreateDTO.java b/src/main/java/com/newyetai/usercenter/common/dto/SlickParamCreateDTO.java new file mode 100644 index 0000000..6678ba1 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/common/dto/SlickParamCreateDTO.java @@ -0,0 +1,34 @@ +package com.newyetai.usercenter.common.dto; + +import java.io.Serializable; +import java.util.Map; + +import javax.validation.constraints.NotNull; + +import com.newyetai.common.dto.BaseOperateDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2022-01-11 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "圆滑的参数创建") +public class SlickParamCreateDTO extends BaseOperateDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("参数属性") + @NotNull(message = "参数属性不能为空") + private Object paramData; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/common/dto/SlickParamDTO.java b/src/main/java/com/newyetai/usercenter/common/dto/SlickParamDTO.java new file mode 100644 index 0000000..1bb00cb --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/common/dto/SlickParamDTO.java @@ -0,0 +1,37 @@ +package com.newyetai.usercenter.common.dto; + +import com.newyetai.common.dto.BaseDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2022-01-11 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@ApiModel(description = "圆滑的参数") +public class SlickParamDTO extends BaseDTO { + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("唯一码-uuid") + private String uniqueCode; + @ApiModelProperty("query升序值(格式:**=**&**=**)") + private String queryValue; + @ApiModelProperty("json数据") + private String paramData; + @ApiModelProperty("哈希值") + private Integer hashCode; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/common/dto/SlickParamQueryDTO.java b/src/main/java/com/newyetai/usercenter/common/dto/SlickParamQueryDTO.java new file mode 100644 index 0000000..0dfc6ac --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/common/dto/SlickParamQueryDTO.java @@ -0,0 +1,35 @@ +package com.newyetai.usercenter.common.dto; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import io.swagger.annotations.ApiModel; + +import com.newyetai.common.dto.PageQueryDTO; + +/** + * @author sr on 2022-01-11 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "圆滑的参数查询条件") +public class SlickParamQueryDTO extends PageQueryDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + @ApiModelProperty("唯一码-uuid") + private String uniqueCode; + @ApiModelProperty("query升序值(格式:**=**&**=**)") + private String queryValue; + @ApiModelProperty("哈希值") + private Integer hashCode; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/common/entity/SlickParam.java b/src/main/java/com/newyetai/usercenter/common/entity/SlickParam.java new file mode 100644 index 0000000..2982b53 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/common/entity/SlickParam.java @@ -0,0 +1,37 @@ +package com.newyetai.usercenter.common.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 圆滑的参数 + * + * @author sr on 2022-01-11 + */ +@TableName("uc_slick_param") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +public class SlickParam extends BaseEntity { + + /** **/ + private static final long serialVersionUID = 1L; + + /** 唯一码-uuid **/ + private String uniqueCode; + /** query升序值(格式:**=**&**=**) **/ + private String queryValue; + /** json数据 **/ + private String paramData; + /** 哈希值 **/ + private Integer hashCode; + +} diff --git a/src/main/java/com/newyetai/usercenter/common/mapper/SlickParamMapper.xml b/src/main/java/com/newyetai/usercenter/common/mapper/SlickParamMapper.xml new file mode 100644 index 0000000..50d7390 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/common/mapper/SlickParamMapper.xml @@ -0,0 +1,25 @@ + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/common/mapstruct/SlickParamMapMapper.java b/src/main/java/com/newyetai/usercenter/common/mapstruct/SlickParamMapMapper.java new file mode 100644 index 0000000..2fb0112 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/common/mapstruct/SlickParamMapMapper.java @@ -0,0 +1,30 @@ +package com.newyetai.usercenter.common.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.newyetai.usercenter.common.dto.SlickParamDTO; +import com.newyetai.usercenter.common.entity.SlickParam; + +/** + * @author sr on 2022-01-11 + */ +@Mapper +public interface SlickParamMapMapper { + + SlickParamMapMapper INSTANCE = + Mappers.getMapper(SlickParamMapMapper.class); + + /** + * dto to entity + * + * @param slickParamDto + * @return + * @author sr on 2022-01-11 + */ + SlickParam toEntity( + SlickParamDTO slickParamDto); + + SlickParamDTO toDto(SlickParam slickParam); + +} diff --git a/src/main/java/com/newyetai/usercenter/common/mq/constant/UcMqConstants.java b/src/main/java/com/newyetai/usercenter/common/mq/constant/UcMqConstants.java new file mode 100644 index 0000000..d6f19a9 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/common/mq/constant/UcMqConstants.java @@ -0,0 +1,36 @@ +package com.newyetai.usercenter.common.mq.constant; + +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.constant.SystemCodeEnum; + +/** + * mq常量类(routingkey) + * @author sr on 2021-01-05 + */ +public interface UcMqConstants { + + /** 用户中心系统mq前缀 **/ + String MQ_PREFIX = SystemCodeEnum.ALITA_USER_CENTER.getName() + CommonConstants.POINT; + + /** 站内信(websocket消费) **/ + String ROUTING_KEY_SITE_NOTICE = UcMqConstants.MQ_PREFIX + "site_notice"; + + /** + * 阶梯费率单子创建 + */ + String LADDER_RATE_ORDER_NOTICE = UcMqConstants.MQ_PREFIX + "ladder_rate_order_notice"; + + + /** 企业产品能力开通 **/ + String ROUTING_KEY_UNION_PROD_ABILITY_CREATE = UcMqConstants.MQ_PREFIX + "prod_ability_create"; + + /** 修改手机号 **/ + String CHANGE_PHONE = UcMqConstants.MQ_PREFIX + "change_phone"; + + /** 修改手机号 关联简历 **/ + String CHANGE_PHONE_RESUME = UcMqConstants.MQ_PREFIX + "change_phone_resume"; + + /** 用户活动记录处理 **/ + String ROUTING_KEY_USER_ACTIVITY_RECORD_DEAL = UcMqConstants.MQ_PREFIX + "user_activity_record_deal"; + +} diff --git a/src/main/java/com/newyetai/usercenter/common/mybatis/MyBatisConfig.java b/src/main/java/com/newyetai/usercenter/common/mybatis/MyBatisConfig.java new file mode 100644 index 0000000..4139c94 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/common/mybatis/MyBatisConfig.java @@ -0,0 +1,24 @@ +package com.newyetai.usercenter.common.mybatis; + +import com.newyetai.mybatis.handle.BaseEnumTypeHandler; +import org.apache.ibatis.session.SqlSessionFactory; +import org.apache.ibatis.type.TypeHandlerRegistry; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; + +/** + * @description: + * @author: chenyun.huang + * @create: 2020-04-13 14:53 + **/ +@Configuration +public class MyBatisConfig { + + @Autowired + public void myInterceptor(SqlSessionFactory sqlSessionFactory) { + // 取得类型转换注册器 + TypeHandlerRegistry typeHandlerRegistry = sqlSessionFactory.getConfiguration().getTypeHandlerRegistry(); + // 注册默认枚举转换器 + typeHandlerRegistry.setDefaultEnumTypeHandler(BaseEnumTypeHandler.class); + } +} diff --git a/src/main/java/com/newyetai/usercenter/common/service/SlickParamService.java b/src/main/java/com/newyetai/usercenter/common/service/SlickParamService.java new file mode 100644 index 0000000..9ecfb84 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/common/service/SlickParamService.java @@ -0,0 +1,70 @@ +package com.newyetai.usercenter.common.service; + +import java.util.List; + +import com.newyetai.usercenter.common.dto.SlickParamQueryDTO; +import com.newyetai.usercenter.common.dto.SlickParamCreateDTO; +import com.newyetai.usercenter.common.dto.SlickParamDTO; + +/** + * 圆滑的参数 + * + * @author sr on 2022-01-11 + */ +public interface SlickParamService { + + /** + * 新增 + * + * @param slickParamCreateDTO + * @return + * @author sr on 2022-01-11 + */ + SlickParamDTO create(SlickParamCreateDTO slickParamCreateDTO); + + /** + * 删除 + * + * @param id + * @author sr on 2022-01-11 + */ + void remove(Long id); + + /** + * 查询 + * + * @param slickParamQueryDTO + * @return + * @author sr on 2022-01-11 + */ + List list(SlickParamQueryDTO slickParamQueryDTO); + + /** + * 分页查询 + * + * @param slickParamQueryDTO + * @return + * @author sr on 2022-01-11 + */ + void page(SlickParamQueryDTO slickParamQueryDTO); + + /** + * 单个查询 + * + * @param slickParamQueryDTO + * @return + * @author sr on 2022-01-11 + */ + SlickParamDTO find(SlickParamQueryDTO slickParamQueryDTO); + + /** + * 转换参数对象 + * @param + * @param uniqueCode + * @param clazz + * @return + * @author sr on 2022-01-11 + */ + T parseCode(String uniqueCode, Class clazz); + +} diff --git a/src/main/java/com/newyetai/usercenter/common/service/impl/SlickParamServiceImpl.java b/src/main/java/com/newyetai/usercenter/common/service/impl/SlickParamServiceImpl.java new file mode 100644 index 0000000..7c7cd7f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/common/service/impl/SlickParamServiceImpl.java @@ -0,0 +1,89 @@ +package com.newyetai.usercenter.common.service.impl; + +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.common.util.ListUtil; +import com.newyetai.common.util.RandomUtils; +import com.newyetai.common.util.StrUtils; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.usercenter.common.dao.SlickParamMapper; +import com.newyetai.usercenter.common.dto.SlickParamCreateDTO; +import com.newyetai.usercenter.common.dto.SlickParamDTO; +import com.newyetai.usercenter.common.dto.SlickParamQueryDTO; +import com.newyetai.usercenter.common.entity.SlickParam; +import com.newyetai.usercenter.common.mapstruct.SlickParamMapMapper; +import com.newyetai.usercenter.common.service.SlickParamService; + +/** + * @author sr on 2022-01-11 + */ +@Service +public class SlickParamServiceImpl implements SlickParamService { + + @Autowired + private SlickParamMapper slickParamMapper; + + @Override + @Transactional + public SlickParamDTO create(SlickParamCreateDTO slickParamCreateDTO) { + Object paramData = slickParamCreateDTO.getParamData(); + String queryValue = StrUtils.buildAscQueryValue(paramData); + Assert.notNull(queryValue, "无有效参数"); + Integer hashCode = queryValue.hashCode(); + SlickParamQueryDTO slickParamQueryDTO = + SlickParamQueryDTO.builder().queryValue(queryValue).hashCode(hashCode).build(); + SlickParamDTO slickParamDTO = find(slickParamQueryDTO); + if (slickParamDTO != null) { + return slickParamDTO; + } + SlickParam slickParam = SlickParam.builder().queryValue(queryValue) + .paramData(JsonUtils.toJsonString(paramData)).hashCode(hashCode) + .uniqueCode(RandomUtils.generateUUID()).build(); + slickParamMapper.saveEntity(slickParam); + return SlickParamMapMapper.INSTANCE.toDto(slickParam); + } + + + @Override + @Transactional + public void remove(Long id) { + slickParamMapper.deleteEntity(SlickParam.builder().id(id).build(), + UserContextHolder.getLoginUserId()); + } + + @Override + public List list(SlickParamQueryDTO slickParamQueryDTO) { + slickParamQueryDTO.disablePage(); + return slickParamMapper.listSlickParamDTO(slickParamQueryDTO); + } + + @Override + public void page(SlickParamQueryDTO slickParamQueryDTO) { + slickParamMapper.listSlickParamDTO(slickParamQueryDTO); + } + + @Override + public SlickParamDTO find(SlickParamQueryDTO slickParamQueryDTO) { + List slickParamDTOs = this.list(slickParamQueryDTO); + return slickParamDTOs.isEmpty() ? null : ListUtil.first(slickParamDTOs); + } + + + @Override + public T parseCode(String uniqueCode, Class clazz) { + if (StringUtils.isBlank(uniqueCode)) { + return null; + } + SlickParamDTO slickParamDTO = find(SlickParamQueryDTO.builder().uniqueCode(uniqueCode).build()); + Assert.notNull(slickParamDTO, "无效码"); + return JsonUtils.toObject(slickParamDTO.getParamData(), clazz); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/common/threadPools/AsyncExecutorConfig.java b/src/main/java/com/newyetai/usercenter/common/threadPools/AsyncExecutorConfig.java new file mode 100644 index 0000000..114fed2 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/common/threadPools/AsyncExecutorConfig.java @@ -0,0 +1,50 @@ +package com.newyetai.usercenter.common.threadPools; + + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +import java.util.concurrent.Executor; +import java.util.concurrent.ThreadPoolExecutor; + + +/** + * 外部方法线程池配置 + * + * @author on 2019-11-05 + */ +@Configuration +@EnableAsync +public class AsyncExecutorConfig { + + @Value("${async-executor.core_pool_size:10}") + private int corePoolSize; + @Value("${async-executor.max_pool_size:50}") + private int maxPoolSize; + @Value("${async-executor.queue-capacity:1000}") + private int queueCapacity; + @Value("${async-executor.name-prefix:async-}") + private String namePrefix; + + + @Bean("asyncExecutor") + public Executor asyncExecutor() { + ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); + taskExecutor.setCorePoolSize(corePoolSize);// 线程池核心线程数 + taskExecutor.setMaxPoolSize(maxPoolSize);// 线程池最大线程数 + taskExecutor.setQueueCapacity(queueCapacity);// 缓冲队列 + taskExecutor.setThreadNamePrefix(namePrefix);// 线程名称前缀 + taskExecutor.setKeepAliveSeconds(60);// 线程空闲后的最大存活时间 + // rejection-policy:当pool已经达到max size的时候,如何处理新任务 + // CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行 + // 对拒绝task的处理策略 + taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); + // 执行初始化 + taskExecutor.initialize(); + return taskExecutor; + } + +} diff --git a/src/main/java/com/newyetai/usercenter/common/validate/ValidatorConf.java b/src/main/java/com/newyetai/usercenter/common/validate/ValidatorConf.java new file mode 100644 index 0000000..fb35443 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/common/validate/ValidatorConf.java @@ -0,0 +1,24 @@ +package com.newyetai.usercenter.common.validate; + +import org.hibernate.validator.HibernateValidator; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.validation.Validation; +import javax.validation.Validator; + +/** + * @description: 参数校验配置 + * @author: chenyun.huang + * @create: 2020-04-11 10:09 + **/ +@Configuration +public class ValidatorConf { + @Bean + public Validator validator() { + return Validation.byProvider(HibernateValidator.class) + .configure() + .failFast(true) + .buildValidatorFactory().getValidator(); + } +} diff --git a/src/main/java/com/newyetai/usercenter/constants/CacheConstants.java b/src/main/java/com/newyetai/usercenter/constants/CacheConstants.java new file mode 100644 index 0000000..e1ff975 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/constants/CacheConstants.java @@ -0,0 +1,16 @@ +package com.newyetai.usercenter.constants; + +public interface CacheConstants { + + String DISTRICT_TREE_ALL_KEY = "districtTreeAll"; + + String DISTRICT_TREE_PROVINCE_KEY = "districtTreeProvince"; + //省级 + String DISTRICT_PROVINCE_LIST_KEY = "districtProvinceList"; + //城市 + String DISTRICT_CITY_MAP_KEY = "districtCityMap"; + //区、县 + String DISTRICT_COUNTY_MAP_KEY = "districtCountyMap"; + //街道 + String DISTRICT_STREET_MAP_KEY = "districtStreetMap"; +} diff --git a/src/main/java/com/newyetai/usercenter/constants/CompanyConstants.java b/src/main/java/com/newyetai/usercenter/constants/CompanyConstants.java new file mode 100644 index 0000000..384c564 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/constants/CompanyConstants.java @@ -0,0 +1,33 @@ +package com.newyetai.usercenter.constants; + +/** + * 企业常量类 + * + * @author sr on 2019-10-19 + */ +public class CompanyConstants { + + /** 关联分类:产品 **/ + public static final String UNION_TYPE_PROD = "1"; + /** 关联分类:机构 **/ + public static final String UNION_TYPE_ORG = "2"; + + /** + * 未认证:1 + */ + public static final String STATUS_NOT_CERTIFIED = "1"; + /** + * 已认证:2 + */ + public static final String STATUS_CERTIFIED = "2"; + /** + * 已注销:3 + */ + public static final String STATUS_CANCELED = "3"; + + + /** -----异常信息----- **/ + public static final String COMPANY_ID_NULL = "企业id为空"; + /** -----异常信息----- **/ + +} diff --git a/src/main/java/com/newyetai/usercenter/constants/DomainSettingTypeEnum.java b/src/main/java/com/newyetai/usercenter/constants/DomainSettingTypeEnum.java new file mode 100644 index 0000000..d5b8969 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/constants/DomainSettingTypeEnum.java @@ -0,0 +1,30 @@ +package com.newyetai.usercenter.constants; + +/** + * 域名配置类型枚举 + * @author sr on 2021-08-18 + */ +public enum DomainSettingTypeEnum { + + /** 轮播图 **/ + CAROUSEL(1), + /** banner图 **/ + BANNER(2), + /** 个人端入口 **/ + MC_ENTRYPOINT(3), + /** 短信配置 **/ + SMS(4), + /** 微信消息模板 **/ + MESSAGE_TEMPLATE(12); + + DomainSettingTypeEnum(Integer type) { + this.type = type; + } + + private Integer type; + + public Integer getType() { + return type; + } + +} diff --git a/src/main/java/com/newyetai/usercenter/constants/OrgConstants.java b/src/main/java/com/newyetai/usercenter/constants/OrgConstants.java new file mode 100644 index 0000000..b4f8d56 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/constants/OrgConstants.java @@ -0,0 +1,15 @@ +package com.newyetai.usercenter.constants; + +/** + * 机构相关常量 + */ +public class OrgConstants { + + private OrgConstants() {} + + /** + * 平台机构id + **/ + public static final Long PLATFORM_ORG_ID = 1L; + +} diff --git a/src/main/java/com/newyetai/usercenter/constants/RoleConstants.java b/src/main/java/com/newyetai/usercenter/constants/RoleConstants.java new file mode 100644 index 0000000..b434b86 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/constants/RoleConstants.java @@ -0,0 +1,30 @@ +package com.newyetai.usercenter.constants; + +/** + * 角色常量类 + * @author sr on 2019-10-11 + */ +public interface RoleConstants { + + /** 角色类型:业务角色(机构内) **/ + String ROLE_TYPE_BUSINESS = "1"; + + /** 标准角色类型:其他 **/ + String STANDARD_ROLE_TYPE_ELSE = "1"; + /** 标准角色类型:销售 **/ + String STANDARD_ROLE_TYPE_SALE = "2"; + /** 标准角色类型:财务 **/ + String STANDARD_ROLE_TYPE_FINANCE = "3"; + /** 标准角色类型:法务 **/ + String STANDARD_ROLE_TYPE_LEGAL = "4"; + /** 标准角色类型:运维 **/ + String STANDARD_ROLE_TYPE_OPS = "5"; + /** 标准角色类型:运营 **/ + String STANDARD_ROLE_TYPE_OPERATION = "6"; + /** 标准角色类型:招聘负责人 **/ + String STANDARD_ROLE_TYPE_PERSONCHARGE = "7"; + + /** 角色类型:制单 **/ + String PREPARED_BY = "7"; + +} diff --git a/src/main/java/com/newyetai/usercenter/constants/SecurityConstants.java b/src/main/java/com/newyetai/usercenter/constants/SecurityConstants.java new file mode 100644 index 0000000..456b216 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/constants/SecurityConstants.java @@ -0,0 +1,93 @@ +package com.newyetai.usercenter.constants; + +/** + * 权限常量类 + * @author sr on 2019-10-07 + */ +public interface SecurityConstants { + + /** 通用权限鉴别属性前缀 **/ + String ROLE_PERMISSION_PREFIX = "ROLE_"; + + /** 角色分配类型:个人 **/ + String ALLOCATION_TYPE_USER = "1"; + + /** 缓存key:方法名 **/ + String CACHE_KEY_METHOD = "#root.methodName"; + /** 缓存key:方法参数-账号 **/ + String CACHE_KEY_PERMISSION_ORG_SYSTEM = "#permissionQueryDTO.systemCode + ':' + #permissionQueryDTO.orgId"; + String CACHE_KEY_SYSTEM = "#systemCode"; + String CACHE_KEY_ORG_USER = "#userDetails.orgId + ':' + #userDetails.id"; + String CACHE_KEY_ORG_SYSTEM_USER = "#systemCode + ':' + #iUserDetail.orgId + ':' + #iUserDetail.id"; + String CACHE_KEY_ORG_SYSTEM_USER_ROLE = CACHE_KEY_ORG_SYSTEM_USER + " + ':' + #roleId"; + + public interface CacheName { + + /** 所有组件权限缓存关键字:id-attributes orgId_systemCode **/ + String COMPONENT_ATTRIBUTE_MAP_CACHE_KEY = "componentAttributeMap"; + + /** 所有菜单权限缓存关键字:id-attributes orgId_systemCode **/ + String URL_ATTRIBUTE_MAP_CACHE_KEY = "urlAttributeMap"; + + /** 所有菜单(访问)权限缓存关键字:link-attributes orgId_systemCode **/ + String URL_FILTER_ATTRIBUTE_MAP_CACHE_KEY = "urlFilterAttributeMap"; + + /** 资源树(包含菜单和组件)orgId_systemCode_userId(_roleId) **/ + String RESOURCE_TREE_CACHE_KEY = "resourceTree"; + + /** 用户已经授权角色 orgId_userId **/ + String USER_GRANTED_AUTHORITY_CACHE_KEY = "userGrantedAuthority"; + + + } + + /** map-key:资源id **/ + String MAP_KEY_RESOURCE_ID = "resourceId"; + /** map-key:资源类型 **/ + String MAP_KEY_RESOURCE_TYPE = "resourceType"; + + /** 属性配置键:是否启用jwt **/ + String PROP_KEY_JWT_ENBALE = "security.jwt.enable"; + /** 属性配置键:jwt过期时间 **/ + String PROP_KEY_JWT_EXPIRATION = "security.jwt.expiration"; + /** 属性配置键:jwt密钥 **/ + String PROP_KEY_JWT_SECRET = "security.jwt.secret"; + + /** 属性配置键:security是否本地调用 **/ + String PROP_KEY_SECURITY_USELOCAL = "security.useLocal"; + /** 属性配置键:security匿名访问路径 **/ + String PROP_KEY_SECURITY_ANONYMOUS = "security.anonymous"; + + String PROP_KEY_SECURITY_OAUTH2_USEDB = "security.oauth2.usedb"; + + /** 指定登陆完成跳转地址 **/ + String REDIRECT_URL_FORMAT = "%s?success_to=%s"; + /** 指定成功跳转地址 **/ + String SUCCESS_TO_URL = "success_to"; + /** token **/ + String TOKEN = "token"; + + /** 登录参数:手机号 **/ + String LOGIN_PHONE_KEY = "phone"; + /** 登录参数:手机号验证码 **/ + String LOGIN_CODE_KEY = "code"; + /** 登录参数:用户类型 **/ + String LOGIN_USER_TYPE_KEY = "userType"; + /** 登录参数:用户id **/ + String LOGIN_USER_ID_KEY = "userId"; + /** 登录参数:用户名 **/ + String LOGIN_USERNAME_KEY = "username"; + /** 登录参数:密码 **/ + String LOGIN_PASSWORD_KEY = "password"; + /** 登录参数:注册邀请码 **/ + String LOGIN_REGISTER_CODE_KEY = "registerCode"; + /** 登录参数:入口来源 **/ + String LOGIN_ENTRYPOINT_KEY = "entrypoint"; + /** 登录参数:临时token **/ + String LOGIN_TEMP_TOKEN_KEY = "tempToken"; + /** 登录参数:机构id **/ + String LOGIN_ORG_ID_KEY = "orgId"; + + + +} diff --git a/src/main/java/com/newyetai/usercenter/constants/SecurityExceptionMsg.java b/src/main/java/com/newyetai/usercenter/constants/SecurityExceptionMsg.java new file mode 100644 index 0000000..d489bef --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/constants/SecurityExceptionMsg.java @@ -0,0 +1,26 @@ +package com.newyetai.usercenter.constants; + +/** + * 权限相关异常信息 + * @author sr on 2019-10-14 + */ +public class SecurityExceptionMsg { + + public static final String UPDATE_NOT_EXIST = "未找到对应数据"; + public static final String USERNAME_EXIST = "账号已存在"; + public static final String ORG_USER_NOT_EXIST = "机构下不存在对应用户"; + public static final String USER_NOT_EXIST = "用户不存在"; + public static final String USER_OLD_PASSWORD_ERROR = "用户原密码错误"; + public static final String ORG_ROLE_NOT_EXIST = "未找到对应角色"; + public static final String NOT_SUPERIOR_LOGIN = "只有平台管理员能访问"; + public static final String NOT_PLATFORM_LOGIN = "无权限访问(platform only)"; + public static final String URL_NOT_EXIST = "未找到对应菜单"; + public static final String COMPONENT_NOT_EXIST = "未找到对应组件"; + public static final String UNALLOCATE_ROLES_EMPTY = "请选择有效角色取消授权"; + public static final String ALLOCATE_ROLES_EMPTY = "请选择有效角色授权"; + public static final String ORG_NOT_EXIST = "未找到对应有效机构"; + public static final String ORG_TYPE_ERROR = "机构类型错误"; + public static final String ROLE_NAME_EXIST = "角色名称已存在"; + public static final String ORG_NAME_EXIST = "企业名称已存在"; + +} diff --git a/src/main/java/com/newyetai/usercenter/constants/SecurityValidateConstants.java b/src/main/java/com/newyetai/usercenter/constants/SecurityValidateConstants.java new file mode 100644 index 0000000..4e78d55 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/constants/SecurityValidateConstants.java @@ -0,0 +1,46 @@ +package com.newyetai.usercenter.constants; + +/** + * 权限模块校验信息常量 + * + * @author sr on 2019-10-11 + */ +public class SecurityValidateConstants { + + public static final String PLATFORM_CODE_EMPTY = "平台编码不能为空"; + public static final String ROLE_ID_EMPTY = "角色不能为空"; + public static final String RESOURCE_TYPE_EMPTY = "资源类型不能为空"; + + public static final String USER_NAME_EMPTY = "账号不能为空"; + public static final String USER_NAME_SIZE = "账号长度不符(3-5)"; + public static final String USER_ID_NULL = "用户id不能为空"; + public static final String USER_OLD_PASSWORD_EMPTY = "原密码不能为空"; + public static final String USER_NEW_PASSWORD_EMPTY = "新密码不能为空"; + + + public static final String ROLE_NAME_EMPTY = "角色名称不能为空"; + public static final String ROLE_ID_NULL = "角色id不能为空"; + public static final String ROLE_ALLOCATE_OPERATE_TYPE = "操作类型不能为空(授权true/取消false)"; + + + public static final String URL_ID_NULL = "菜单id不能为空"; + public static final String URL_NAME_EMPTY = "菜单名称不能为空"; + public static final String URL_LINK_EMPTY = "菜单地址不能为空"; + public static final String URL_PARENT_ID_NULL = "父菜单id不能为空"; + + public static final String COMPONENT_ID_NULL = "组件id不能为空"; + public static final String COMPONENT_URL_ID_NULL = "组件所属菜单id不能为空"; + public static final String COMPONENT_CODE_EMPTY = "组件不能为空"; + + + public static final String RESOURCE_ID_NULL = "资源id不能为空"; + public static final String RESOURCE_TYPE_NULL = "资源类型不能为空"; + + public static final String PERMISSION_PACKAGE_ID_NULL = "权限包ID不能为空"; + public static final String PERMISSION_PACKAGE_NAME_NULL = "权限包名称不能为空"; + public static final String PERMISSION_PACKAGE_TYPE_NULL = "权限包类型不能为空"; + public static final String PERMISSION_ORG_ID_NULL = "分配机构ID不能为空"; + public static final String PERMISSION_COMPANY_ID_NULL = "分配企业ID不能为空"; + public static final String PERMISSION_SELECTED_FLAG_NULL = "是否选中标识不能为空"; + +} diff --git a/src/main/java/com/newyetai/usercenter/constants/UrlConstants.java b/src/main/java/com/newyetai/usercenter/constants/UrlConstants.java new file mode 100644 index 0000000..538de8a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/constants/UrlConstants.java @@ -0,0 +1,12 @@ +package com.newyetai.usercenter.constants; + +/** + * 菜单常量 + * @author sr on 2019-10-15 + */ +public class UrlConstants { + + /** 顶级菜单父id **/ + public static final Long URL_TOP_PARENT_ID = 0L; + +} diff --git a/src/main/java/com/newyetai/usercenter/constants/UserCenterValidateConstants.java b/src/main/java/com/newyetai/usercenter/constants/UserCenterValidateConstants.java new file mode 100644 index 0000000..fc4a1e2 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/constants/UserCenterValidateConstants.java @@ -0,0 +1,19 @@ +package com.newyetai.usercenter.constants; + +/** + * @author Jerry.li + * @description 用户中心验证常量类 + * @date 2020/3/24 + */ +public class UserCenterValidateConstants { + + private UserCenterValidateConstants() { + } + + public static final String ORG_ID_NULL = "机构ID不能为空"; + public static final String COMPANY_RATE_NULL = "服务费率不能为空"; + public static final String ORG_NAME_NULL = "机构名称不能为空"; + public static final String ORG_TYPE_NULL = "机构类型不能为空"; + public static final String COMPANY_RATE_OUT_RANGE = "费率超出范围(0-1)"; + +} diff --git a/src/main/java/com/newyetai/usercenter/constants/UserConstants.java b/src/main/java/com/newyetai/usercenter/constants/UserConstants.java new file mode 100644 index 0000000..a0797c1 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/constants/UserConstants.java @@ -0,0 +1,39 @@ +package com.newyetai.usercenter.constants; + +/** + * 用户常量类 + * + * @author sr on 2019-10-10 + */ +public class UserConstants { + + /** + * 用户默认密码 + **/ + public static final String DEFAULT_PASSWORD = "123456"; + + /** + * 机构管理员后缀 + **/ + public static final String ORG_MANAGER_USERNAME_SUFFIX = "admin"; + + /** + * 超管用户id + **/ + public static final Long SUPERIOR_USER_ID = 1L; + + + /** + * 查询类型 + */ + public static class queryType { + + /** + * 页面查询的用户列表,包含类型 平台管理员、企业管理员、企业用户 + */ + public static final String USER_INFO = "userInfo"; + } + + + +} diff --git a/src/main/java/com/newyetai/usercenter/controller/UcDictionaryController.java b/src/main/java/com/newyetai/usercenter/controller/UcDictionaryController.java new file mode 100644 index 0000000..e220119 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/controller/UcDictionaryController.java @@ -0,0 +1,67 @@ +package com.newyetai.usercenter.controller; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.util.TreeHelper; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.component.dict.dto.DictDTO; +import com.newyetai.component.dict.dto.DictDetailDTO; +import com.newyetai.component.dict.dto.DictDetailQueryDTO; +import com.newyetai.component.dict.dto.DictQueryDTO; +import com.newyetai.component.dict.service.DictDetailService; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.service.UcDictionaryService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + * @author: Jerry.li + * @description: 数据字典 + * @create: 2020-06-18 14:39 + **/ +@Api(tags = "数据字典") +@RestController +@RequestMapping(value = "/dict") +public class UcDictionaryController { + + @Autowired + private UcDictionaryService ucDictionaryService; + + @Autowired + private DictDetailService dictDetailService; + + @ApiOperation("编辑字典数据") + @PostMapping("/edit_dict") + public AlitaResult editDict(@RequestBody DictDTO dictDTO) { + return ucDictionaryService.editDictionary(dictDTO, UserContextHolder.getExistLoginUserId()); + } + + @ApiOperation("编辑字典详情数据") + @PostMapping("/edit_dict_detail") + public AlitaResult editDictDetail(@RequestBody DictDetailDTO detailDTO) { + return ucDictionaryService + .editDictionaryDetail(detailDTO, UserContextHolder.getExistLoginUserId()); + } + + @ApiOperation("分页查询数据字典列表") + @PostMapping("/page_dict_list") + public AlitaResult> pageQueryDictionaryList(@RequestBody DictQueryDTO query) { + ucDictionaryService.pageDictionaryList(query); + return AlitaResult.success(query.getPageResult()); + } + + @ApiOperation("根据ID获取字典详情列表") + @PostMapping("/get_dict_detail_list") + public AlitaResult> getDictDetailList(@RequestBody DictDetailQueryDTO dictDetailQueryDTO) { + dictDetailQueryDTO.disablePage(); + List details = ucDictionaryService.getDictDetailList(dictDetailQueryDTO); + return AlitaResult.success(TreeHelper.buildTree(null, details)); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/controller/UcRoleStandardTypeController.java b/src/main/java/com/newyetai/usercenter/controller/UcRoleStandardTypeController.java new file mode 100644 index 0000000..407f90c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/controller/UcRoleStandardTypeController.java @@ -0,0 +1,47 @@ +package com.newyetai.usercenter.controller; + +import com.baomidou.mybatisplus.extension.api.R; +import com.newyetai.common.AlitaResult; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.constants.SecurityConstants; +import com.newyetai.usercenter.dto.RoleStandardTypeDTO; +import com.newyetai.usercenter.entity.RoleStandardType; +import com.newyetai.usercenter.enums.SmsScenesEnum; +import com.newyetai.usercenter.query.RoleStandardTypeQuery; +import com.newyetai.usercenter.service.UcRoleStandardTypeService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @Author dylanyuan + * @Date 2021/2/19 4:15 下午 + * @Version 1.0 + */ +@Api(tags = "标准角色管理") +@RestController +@RequestMapping(value = "/role_standard_type") +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +@ConditionalOnProperty(name = SecurityConstants.PROP_KEY_SECURITY_USELOCAL, havingValue = "true", + matchIfMissing = true) +public class UcRoleStandardTypeController { + + private final UcRoleStandardTypeService ucRoleStandardTypeService; + + @ApiOperation("分页查询") + @GetMapping("/page") + public AlitaResult> page(RoleStandardTypeQuery query) { + ucRoleStandardTypeService.page(query); + return AlitaResult.success(query.getPageResult()); + } + + + +} diff --git a/src/main/java/com/newyetai/usercenter/dao/XsRoleStandardTypeMapper.java b/src/main/java/com/newyetai/usercenter/dao/XsRoleStandardTypeMapper.java new file mode 100644 index 0000000..680cc43 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/dao/XsRoleStandardTypeMapper.java @@ -0,0 +1,18 @@ +package com.newyetai.usercenter.dao; + +import java.util.List; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.newyetai.usercenter.dto.RoleStandardTypeDTO; +import com.newyetai.usercenter.entity.RoleStandardType; +import com.newyetai.usercenter.query.RoleStandardTypeQuery; + +/** + * @Author dylanyuan + * @Date 2021/2/19 2:09 下午 + * @Version 1.0 + */ +public interface XsRoleStandardTypeMapper extends BaseMapper { + + List page(RoleStandardTypeQuery query); +} diff --git a/src/main/java/com/newyetai/usercenter/district/constants/DistrictConstants.java b/src/main/java/com/newyetai/usercenter/district/constants/DistrictConstants.java new file mode 100644 index 0000000..66f47fe --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/district/constants/DistrictConstants.java @@ -0,0 +1,29 @@ +package com.newyetai.usercenter.district.constants; + +/** + * @author czy + * @date 2021-07-08 + */ +public interface DistrictConstants { + + Long DEFAULT_DISTRICT_ID = 0l; + + String CACHE_KEY_DISTRICT_ID = "#districtId"; + + interface CacheNames { + + /** 省 **/ + String DISTRICT_PROVINCE = "district:province"; + + /** 市 **/ + String DISTRICT_CITY = "district:city"; + + /** 区 **/ + String DISTRICT_AREA = "district:area"; + + /** 街 **/ + String DISTRICT_STREET = "district:street"; + + } + +} diff --git a/src/main/java/com/newyetai/usercenter/district/controller/DistrictController.java b/src/main/java/com/newyetai/usercenter/district/controller/DistrictController.java new file mode 100644 index 0000000..0a830e9 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/district/controller/DistrictController.java @@ -0,0 +1,61 @@ +package com.newyetai.usercenter.district.controller; + + +import com.newyetai.common.AlitaResult; +import com.newyetai.usercenter.district.constants.DistrictConstants; +import com.newyetai.usercenter.district.dto.DistrictDTO; +import com.newyetai.usercenter.district.dto.DistrictTreeQueryDTO; +import com.newyetai.usercenter.district.entity.District; +import com.newyetai.usercenter.district.service.IDistrictService; + +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + *

+ * 省份城市 前端控制器 + *

+ * + * @author Carlye + * @since 2021-01-25 + */ +@RestController +@RequestMapping("/anon/district") +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class DistrictController { + + private final IDistrictService districtService; + + @GetMapping("/tree") + @ApiOperation("创建用户附件") + public AlitaResult> tree(DistrictTreeQueryDTO queryDTO) { + return AlitaResult.success(districtService.treeList(queryDTO)); + } + + @GetMapping("/list") + @ApiOperation("获取指定Id下的城市列表(不传就默认查省列表)") + public AlitaResult> loadDataById(@RequestParam(value = "districtId", required = false) Long districtId) { + if (districtId == null) { + districtId = DistrictConstants.DEFAULT_DISTRICT_ID; + } + return AlitaResult.success(districtService.queryListById(districtId)); + } + + @GetMapping("/all") + @ApiOperation("获取全部") + public AlitaResult> all(@RequestParam(value = "level") Integer level) { + return AlitaResult.success(districtService.all(level)); + } + + +} + diff --git a/src/main/java/com/newyetai/usercenter/district/dao/DistrictMapper.java b/src/main/java/com/newyetai/usercenter/district/dao/DistrictMapper.java new file mode 100644 index 0000000..b287411 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/district/dao/DistrictMapper.java @@ -0,0 +1,23 @@ +package com.newyetai.usercenter.district.dao; + +import com.newyetai.usercenter.district.dto.DistrictDTO; +import com.newyetai.usercenter.district.entity.District; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 省份城市 Mapper 接口 + *

+ * + * @author Carlye + * @since 2021-01-25 + */ +public interface DistrictMapper extends BaseMapper { + + List queryById(Long districtId); + + String queryNameByCode(@Param("codes") List codes); + +} diff --git a/src/main/java/com/newyetai/usercenter/district/dto/DistrictDTO.java b/src/main/java/com/newyetai/usercenter/district/dto/DistrictDTO.java new file mode 100644 index 0000000..5df212b --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/district/dto/DistrictDTO.java @@ -0,0 +1,80 @@ +package com.newyetai.usercenter.district.dto; + +import com.google.common.collect.Lists; +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.common.util.TreeNode; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; +import lombok.experimental.SuperBuilder; + +import java.util.List; +import java.util.Objects; + +/** + *

+ * 省份城市 + *

+ * + * @author Carlye + * @since 2021-01-25 + */ +@ApiModel("省份城市树形DTO") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +public class DistrictDTO extends BaseDTO implements TreeNode { + + private static final long serialVersionUID = -3042079366109391854L; + + @ApiModelProperty("城市名称") + private String name; + + @ApiModelProperty("上级城市ID") + private Long parentId; + + @ApiModelProperty("首字母") + private String initial; + + @ApiModelProperty("简拼") + private String initials; + + @ApiModelProperty("全拼") + private String pinyin; + + @ApiModelProperty("特别行政区") + private String extra; + + @ApiModelProperty("后缀") + private String suffix; + + @ApiModelProperty("城市编码") + private String code; + + @ApiModelProperty("区域编码") + private String areaCode; + + @ApiModelProperty("排序") + private Integer districtOrder; + + private Integer level; + + @ApiModelProperty("下级") + private List childrenSet; + + public List getChildrenSet() { + if (Objects.isNull(this.childrenSet)) { + this.childrenSet = Lists.newArrayList(); + } + return this.childrenSet; + } + + @Override + public void addChildren(DistrictDTO node) { + getChildrenSet().add(node); + } +} diff --git a/src/main/java/com/newyetai/usercenter/district/dto/DistrictTreeQueryDTO.java b/src/main/java/com/newyetai/usercenter/district/dto/DistrictTreeQueryDTO.java new file mode 100644 index 0000000..6286258 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/district/dto/DistrictTreeQueryDTO.java @@ -0,0 +1,31 @@ +package com.newyetai.usercenter.district.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + *

+ * 省份城市 + *

+ * + * @author Carlye + * @since 2021-01-25 + */ +@ApiModel("省份城市树形查询DTO") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class DistrictTreeQueryDTO { + + private static final long serialVersionUID = -3042079366109391854L; + + + @ApiModelProperty("省份编码") + private String code; + +} diff --git a/src/main/java/com/newyetai/usercenter/district/entity/District.java b/src/main/java/com/newyetai/usercenter/district/entity/District.java new file mode 100644 index 0000000..d9425a4 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/district/entity/District.java @@ -0,0 +1,56 @@ +package com.newyetai.usercenter.district.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; +import lombok.*; +import lombok.experimental.Accessors; + +/** + * 省份城市 + * + * @author Carlye + * @since 2021-01-25 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@TableName("xs_district") +public class District extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** 城市名称 */ + private String name; + + /** 上级城市ID */ + private Long parentId; + + /** 首字母 */ + private String initial; + + /** 简拼 */ + private String initials; + + /** 全拼 */ + private String pinyin; + + /** 特别行政区 */ + private String extra; + + /** 后缀 */ + private String suffix; + + /** 城市编码 */ + private String code; + + /** 区域编码 */ + private String areaCode; + + /** 排序 */ + private Integer districtOrder; + + private Integer level; +} diff --git a/src/main/java/com/newyetai/usercenter/district/mapper/DistrictMapper.xml b/src/main/java/com/newyetai/usercenter/district/mapper/DistrictMapper.xml new file mode 100644 index 0000000..95158ee --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/district/mapper/DistrictMapper.xml @@ -0,0 +1,30 @@ + + + + + + + + + diff --git a/src/main/java/com/newyetai/usercenter/district/mapstruct/DistrictMapMapper.java b/src/main/java/com/newyetai/usercenter/district/mapstruct/DistrictMapMapper.java new file mode 100644 index 0000000..119ccda --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/district/mapstruct/DistrictMapMapper.java @@ -0,0 +1,24 @@ +package com.newyetai.usercenter.district.mapstruct; + +import com.newyetai.usercenter.district.dto.DistrictDTO; +import com.newyetai.usercenter.district.entity.District; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + + +/** + * 用户映射器附件地图 + * + * @author Carlye + * @date 2021/01/12 + */ +@Mapper +public interface DistrictMapMapper { + + DistrictMapMapper INSTANCE = Mappers.getMapper(DistrictMapMapper.class); + + DistrictDTO exchange(District district); + + DistrictDTO exchange(DistrictDTO districtDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/district/service/IDistrictService.java b/src/main/java/com/newyetai/usercenter/district/service/IDistrictService.java new file mode 100644 index 0000000..2e59b8f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/district/service/IDistrictService.java @@ -0,0 +1,28 @@ +package com.newyetai.usercenter.district.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.newyetai.usercenter.district.dto.DistrictDTO; +import com.newyetai.usercenter.district.dto.DistrictTreeQueryDTO; +import com.newyetai.usercenter.district.entity.District; + +import java.util.List; + +/** + * 省份城市 服务类 + * + * @author Carlye + * @since 2021-01-25 + */ +public interface IDistrictService extends IService { + + /** + * 树列表 + * + * @return {@link List} + */ + List treeList(DistrictTreeQueryDTO queryDTO); + + List queryListById(Long districtId); + + List all(Integer level); +} diff --git a/src/main/java/com/newyetai/usercenter/district/service/impl/DistrictServiceImpl.java b/src/main/java/com/newyetai/usercenter/district/service/impl/DistrictServiceImpl.java new file mode 100644 index 0000000..8a4b62e --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/district/service/impl/DistrictServiceImpl.java @@ -0,0 +1,138 @@ +package com.newyetai.usercenter.district.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; + +import com.google.common.collect.Lists; + +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.TreeHelper; +import com.newyetai.frame.redis.aop.annotation.AutoUnLock; +import com.newyetai.frame.redis.dto.LockDTO; +import com.newyetai.frame.redis.redisson.RedissonUtils; +import com.newyetai.usercenter.constants.CacheConstants; +import com.newyetai.usercenter.district.constants.DistrictConstants; +import com.newyetai.usercenter.district.dao.DistrictMapper; +import com.newyetai.usercenter.district.dto.DistrictDTO; +import com.newyetai.usercenter.district.dto.DistrictTreeQueryDTO; +import com.newyetai.usercenter.district.entity.District; +import com.newyetai.usercenter.district.mapstruct.DistrictMapMapper; +import com.newyetai.usercenter.district.service.IDistrictService; + +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.http.impl.client.HttpClients; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; + +/** + * 省份城市 服务实现类 + * + * @author Carlye + * @since 2021-01-25 + */ +@Slf4j +@Service +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class DistrictServiceImpl extends ServiceImpl + implements IDistrictService { + + private final RedisTemplate redisTemplate; + + private final DistrictMapper districtMapper; + + @Override + @AutoUnLock + public List treeList(DistrictTreeQueryDTO queryDTO) { + List range = redisTemplate.opsForList().range(CacheConstants.DISTRICT_TREE_PROVINCE_KEY, 0, -1); + if (CollectionUtils.isEmpty(range)) { + Assert.isTrue(RedissonUtils.tryLockAutomatically(LockDTO.builder().methodName("treeList").build()), "正在初始化数据,请稍后再试"); + List range2 = redisTemplate.opsForList().range(CacheConstants.DISTRICT_TREE_PROVINCE_KEY, 0, -1); + if (CollectionUtils.isEmpty(range2)) { + @SuppressWarnings("unchecked") + List allDistricts = + list(Wrappers.lambdaQuery() + .eq(District::getDeleted, false) + .orderByAsc(District::getParentId, District::getDistrictOrder, + District::getId)); + if (CollectionUtils.isEmpty(allDistricts)) { + List districtDTOS = Lists.newArrayList(new DistrictDTO()); + redisTemplate.opsForList() + .leftPush(CacheConstants.DISTRICT_TREE_PROVINCE_KEY, districtDTOS); + redisTemplate.expire(CacheConstants.DISTRICT_TREE_PROVINCE_KEY, 5, TimeUnit.MINUTES); + return districtDTOS; + } + //省市区 + List allDistrictDTOS = allDistricts.stream() + .map(DistrictMapMapper.INSTANCE::exchange).collect(Collectors.toList()); + + List districtDTOS = TreeHelper.buildTree(0L, allDistrictDTOS); + //区-街道 + List suffix = Lists.newArrayList(); + districtDTOS.forEach(districtDTO -> recursiveDistrictDTO(districtDTO, suffix)); + for (DistrictDTO districtDTO : suffix) { + String key = String + .join(":", CacheConstants.DISTRICT_TREE_ALL_KEY, districtDTO.getCode()); + redisTemplate.delete(key); + redisTemplate.opsForList().rightPushAll(key, districtDTO.getChildrenSet()); + redisTemplate.expire(key, 1, TimeUnit.DAYS); + } + redisTemplate.delete(CacheConstants.DISTRICT_TREE_PROVINCE_KEY); + redisTemplate.opsForList() + .rightPushAll(CacheConstants.DISTRICT_TREE_PROVINCE_KEY, districtDTOS); + redisTemplate.expire(CacheConstants.DISTRICT_TREE_PROVINCE_KEY, 1, TimeUnit.DAYS); + range = districtDTOS; + } + } + String code = queryDTO.getCode(); + if (StringUtils.isNotEmpty(code)) { + String key = String.join(":", CacheConstants.DISTRICT_TREE_ALL_KEY, code); + return redisTemplate.opsForList().range(key, 0, -1); + } + return range; + } + + + private static final Integer TAG = 4; + + private void recursiveDistrictDTO(DistrictDTO districtDTO, + List suffix) { + int length = districtDTO.getCode().length(); + if (length < TAG) { + for (DistrictDTO child : districtDTO.getChildrenSet()) { + recursiveDistrictDTO(child, suffix); + } + } + if (length == TAG) { + suffix.add(DistrictMapMapper.INSTANCE.exchange(districtDTO)); + districtDTO.setChildrenSet(null); + } + } + + @Override + @Cacheable(cacheNames = DistrictConstants.CacheNames.DISTRICT_PROVINCE, + key = DistrictConstants.CACHE_KEY_DISTRICT_ID) + public List queryListById(Long districtId) { + List districtDTOS = districtMapper.queryById(districtId); + return districtDTOS; + } + + @Override + public List all(Integer level) { + List districts = districtMapper.selectList(new LambdaQueryWrapper() + .eq(District::getLevel, level) + .eq(District::getDeleted, false) + .orderByAsc(District::getCode)); + return districts; + } +} diff --git a/src/main/java/com/newyetai/usercenter/dto/AllocatedBusinessRoleQueryDTO.java b/src/main/java/com/newyetai/usercenter/dto/AllocatedBusinessRoleQueryDTO.java new file mode 100644 index 0000000..af6aed0 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/dto/AllocatedBusinessRoleQueryDTO.java @@ -0,0 +1,70 @@ +package com.newyetai.usercenter.dto; + +import com.newyetai.common.constant.SystemCodeEnum; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.usercenter.constants.RoleConstants; +import com.newyetai.usercenter.constants.SecurityConstants; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.List; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @description: 已分配业务角色DTO + * @author: guixinman + * @create: 2023-10-31 18:20 + **/ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class AllocatedBusinessRoleQueryDTO implements Serializable { + + @NotNull(message = "orgId不能为null") + private Long orgId; + + /** + * 所属平台 + **/ + @NotNull(message = "platformCode不能为null") + private Integer platformCode; + + /** + * 角色具体分配类型对应的id + **/ + @NotNull(message = "allocationId不能为null") + private Long allocationId; + + /** + * 角色分配类型:1个人2部门3组 + **/ + @Builder.Default + private String allocationType = SecurityConstants.ALLOCATION_TYPE_USER; + + /** + * 类型 + **/ + @Builder.Default + private String type = RoleConstants.ROLE_TYPE_BUSINESS; + + @ApiModelProperty("标准角色类型:见role_standard_type") + private List standardTypes; + + /** + * 是否启用 + **/ + @Builder.Default + private Boolean enabled = Boolean.TRUE; + +} + + diff --git a/src/main/java/com/newyetai/usercenter/dto/AllocationDTO.java b/src/main/java/com/newyetai/usercenter/dto/AllocationDTO.java new file mode 100644 index 0000000..fcbd835 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/dto/AllocationDTO.java @@ -0,0 +1,30 @@ +package com.newyetai.usercenter.dto; + +import java.io.Serializable; +import java.util.List; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2019-10-17 + */ +@ApiModel("用户角色分配") +@Data +@NoArgsConstructor +@AllArgsConstructor +public class AllocationDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 8761125972738825343L; + + @ApiModelProperty("已分配") + private List allocated; + + @ApiModelProperty("未分配") + private List unallocated; + +} diff --git a/src/main/java/com/newyetai/usercenter/dto/AllocationRoleDTO.java b/src/main/java/com/newyetai/usercenter/dto/AllocationRoleDTO.java new file mode 100644 index 0000000..db5ba87 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/dto/AllocationRoleDTO.java @@ -0,0 +1,38 @@ +package com.newyetai.usercenter.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; + +/** + * @author: Jerry.li + * @description: 可分配角色 + * @create: 2020-06-17 17:48 + **/ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class AllocationRoleDTO implements Serializable { + + /** + * 用户ID + */ + private Long userId; + + /** + * 可分配的角色列表 + */ + private List unallocatedRoleList; + + /** + * 已分配的角色ID列表 + */ + private List allocatedRoleIdList; + + @ApiModelProperty("所属平台") + private Integer platformCode; +} diff --git a/src/main/java/com/newyetai/usercenter/dto/AllocationRoleUserDTO.java b/src/main/java/com/newyetai/usercenter/dto/AllocationRoleUserDTO.java new file mode 100644 index 0000000..96939a9 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/dto/AllocationRoleUserDTO.java @@ -0,0 +1,25 @@ +package com.newyetai.usercenter.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class AllocationRoleUserDTO implements Serializable { + + @ApiModelProperty("用户ID") + private List userIds; + + @ApiModelProperty("所属平台") + private Integer platformCode; + + @ApiModelProperty("角色ID") + private Long roleId; + +} diff --git a/src/main/java/com/newyetai/usercenter/dto/CaptchaDTO.java b/src/main/java/com/newyetai/usercenter/dto/CaptchaDTO.java new file mode 100644 index 0000000..3935f73 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/dto/CaptchaDTO.java @@ -0,0 +1,30 @@ +package com.newyetai.usercenter.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotBlank; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2020-08-11 + */ +@ApiModel("防水墙验证信息") +@Data +@NoArgsConstructor +public class CaptchaDTO implements Serializable { + + /** **/ + private static final long serialVersionUID = 4760648640763876418L; + + @ApiModelProperty("前端回调函数返回的用户验证票据") + @NotBlank(message = "防水墙验证票据不能为空") + private String ticket; + @ApiModelProperty("前端回调函数返回的随机字符串") + @NotBlank(message = "防水墙随机字符串不能为空") + private String randstr; + +} diff --git a/src/main/java/com/newyetai/usercenter/dto/CheckKeyDTO.java b/src/main/java/com/newyetai/usercenter/dto/CheckKeyDTO.java new file mode 100644 index 0000000..b4dd8f6 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/dto/CheckKeyDTO.java @@ -0,0 +1,25 @@ +package com.newyetai.usercenter.dto; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@ApiModel("角色权限树已选数据") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class CheckKeyDTO { + + /** + * 角色Id + */ + private Long roleId; + + /** + * 已勾选的菜单Id + */ + private String checkedKeys; +} diff --git a/src/main/java/com/newyetai/usercenter/dto/DomainSettingOperateDTO.java b/src/main/java/com/newyetai/usercenter/dto/DomainSettingOperateDTO.java new file mode 100644 index 0000000..5cca146 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/dto/DomainSettingOperateDTO.java @@ -0,0 +1,44 @@ +package com.newyetai.usercenter.dto; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.SuperBuilder; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(value = "域名配置-请求DTO", description = "域名配置-请求DTO") +@SuperBuilder +public class DomainSettingOperateDTO extends BaseDTO { + + + private static final long serialVersionUID = 5671785716204667479L; + @ApiModelProperty("域名ID") + @NotNull(message = "域名ID不能为空", groups = {Create.class}) + private Long domainId; + /** + * 类型 + */ + @ApiModelProperty("类型") + @NotNull(message = "类型不能为空", groups = {Create.class, Update.class}) + private Integer type; + + @ApiModelProperty("描述") + private String remark; + + /** + * 配置数据 + */ + @ApiModelProperty("配置数据") + @NotEmpty(message = "配置数据不能为空", groups = {Create.class, Update.class}) + private String data; + +} diff --git a/src/main/java/com/newyetai/usercenter/dto/DomainSettingReqDTO.java b/src/main/java/com/newyetai/usercenter/dto/DomainSettingReqDTO.java new file mode 100644 index 0000000..8775eb1 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/dto/DomainSettingReqDTO.java @@ -0,0 +1,31 @@ +package com.newyetai.usercenter.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import java.io.Serializable; +import java.util.Objects; +import java.util.Set; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(value = "域名配置-请求DTO", description = "域名配置-请求DTO") +@Builder +public class DomainSettingReqDTO implements Serializable { + private static final long serialVersionUID = -8208703257479920916L; + @ApiModelProperty("域名或IP") +// @NotNull(message = "域名或IP不能为空") + private String domainOrIp; + @ApiModelProperty("域名ID") + private Long domainId; + @ApiModelProperty("类型集合") + @Singular + private Set types; + + @Override + public String toString() { + return String.join("_", "domain_setting", Objects.nonNull(domainId) ? Long.toString(domainId) : ""); + } +} diff --git a/src/main/java/com/newyetai/usercenter/dto/DomainSettingResDTO.java b/src/main/java/com/newyetai/usercenter/dto/DomainSettingResDTO.java new file mode 100644 index 0000000..58a57a2 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/dto/DomainSettingResDTO.java @@ -0,0 +1,30 @@ +package com.newyetai.usercenter.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.Date; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(value = "域名配置-响应DTO",description = "域名配置-响应DTO") +public class DomainSettingResDTO implements Serializable { + private static final long serialVersionUID = 4501680475900802319L; + @ApiModelProperty("id") + private Long id; + @ApiModelProperty("类型集合") + private Integer type; + @ApiModelProperty("配置备注") + private String remark; + @ApiModelProperty("配置数据") + private String data; + @ApiModelProperty("创建时间") + private Date createTime; + @ApiModelProperty("修改时间") + private Date updateTime; +} diff --git a/src/main/java/com/newyetai/usercenter/dto/IUserDetail.java b/src/main/java/com/newyetai/usercenter/dto/IUserDetail.java new file mode 100644 index 0000000..117adfe --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/dto/IUserDetail.java @@ -0,0 +1,38 @@ +package com.newyetai.usercenter.dto; + +public interface IUserDetail { + + /** 用户id **/ + Long getId(); + + /** 是否超管 **/ + Boolean getSupeiror(); + + /** 类型 **/ + Integer getType(); + + /** 当前操作机构 **/ + Long getOrgId(); + + /** 当前操作机构名称 **/ + String getOrgName(); + + /** 当前操作机构类型 **/ + String getOrgType(); + + /** 是否机构管理员 **/ + Boolean getAdministrator(); + + /** 用户名 **/ + String getUsername(); + + /** 标签 **/ + String getTag(); + + /** 状态 */ + Integer getStatus(); + + /** 手机号绑定状态 */ + Boolean getPhoneBinding(); + +} diff --git a/src/main/java/com/newyetai/usercenter/dto/MenuResourceDTO.java b/src/main/java/com/newyetai/usercenter/dto/MenuResourceDTO.java new file mode 100644 index 0000000..ec52f82 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/dto/MenuResourceDTO.java @@ -0,0 +1,38 @@ +package com.newyetai.usercenter.dto; + +import com.newyetai.usercenter.resource.dto.ComponentDTO; +import com.newyetai.usercenter.resource.dto.UrlDTO; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; +import java.util.Set; + +/** + * @author: Jerry.li + * @description: 菜单资源 + * @create: 2020-07-10 15:13 + **/ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class MenuResourceDTO implements Serializable { + + /** + * 用户资源列表 + */ + private List resourceList; + + /** + * 组件列表 + */ + private List componentList; + + private Set urlIds; + private Set componentIds; + +} diff --git a/src/main/java/com/newyetai/usercenter/dto/OrgAdminDTO.java b/src/main/java/com/newyetai/usercenter/dto/OrgAdminDTO.java new file mode 100644 index 0000000..cf09c6c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/dto/OrgAdminDTO.java @@ -0,0 +1,73 @@ +package com.newyetai.usercenter.dto; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.common.validation.Update; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +/** + * @author: Jerry.li + * @description: 机构管理员 + * @create: 2020-06-15 17:16 + * @create: 2020-06-17 12:00 + **/ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class OrgAdminDTO extends BaseDTO implements Serializable { + /** + * 用户中文名 + */ + @NotNull(groups = {Update.class}, message = "用户中文名不能为空") + private String chineseName; + /** + * 帐号 + */ + @NotNull(groups = {Update.class}, message = "登录账号不能为空") + private String username; + /** + * 手机号码 + */ + @NotNull(groups = {Update.class}, message = "手机号不能为空") + private String phone; + /** + * 邮箱 + */ + private String email; + /** + * 是否启用 + */ + private Boolean enabled; + /** + * 手机号绑定状态 + */ + private Boolean phoneBinding; + /** + * 机构ID: 更新和修改时必填 + */ + private Long orgId; + /** + * 机构名称 + */ + private String orgName; + + /** + * 类型 + */ + private String type; + + /** + * 用户状态 + */ + private Integer userStatus; + + /** + * 是否管理员 + */ + private Boolean administrator; + +} diff --git a/src/main/java/com/newyetai/usercenter/dto/OrgLoginTimeDTO.java b/src/main/java/com/newyetai/usercenter/dto/OrgLoginTimeDTO.java new file mode 100644 index 0000000..003262e --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/dto/OrgLoginTimeDTO.java @@ -0,0 +1,32 @@ +package com.newyetai.usercenter.dto; + +import java.io.Serializable; +import java.util.Date; + +import org.springframework.format.annotation.DateTimeFormat; + +import com.newyetai.common.util.JsonUtils; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class OrgLoginTimeDTO implements Serializable { + private static final long serialVersionUID = 7457935915892036131L; + + private Long orgId; + + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date requestTime; + + @Override + public String toString() { + return JsonUtils.toJsonString(this); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/dto/OrgTreeDTO.java b/src/main/java/com/newyetai/usercenter/dto/OrgTreeDTO.java new file mode 100644 index 0000000..d7675ab --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/dto/OrgTreeDTO.java @@ -0,0 +1,45 @@ +package com.newyetai.usercenter.dto; + +import com.google.common.collect.Lists; +import com.newyetai.common.util.TreeNode; +import java.io.Serializable; +import java.util.List; +import java.util.Objects; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + + +/** + * org树dto + * + * @author Carlye + * @date 2021/02/22 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class OrgTreeDTO implements Serializable, TreeNode { + + private static final long serialVersionUID = 8410087864668609131L; + + private Long id; + + private Long parentId; + + private List childrenSet; + + public List getChildrenSet() { + if (Objects.isNull(this.childrenSet)) { + this.childrenSet = Lists.newArrayList(); + } + return this.childrenSet; + } + + @Override + public void addChildren(OrgTreeDTO node) { + getChildrenSet().add(node); + } +} diff --git a/src/main/java/com/newyetai/usercenter/dto/OrgUserEditDTO.java b/src/main/java/com/newyetai/usercenter/dto/OrgUserEditDTO.java new file mode 100644 index 0000000..971b8ba --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/dto/OrgUserEditDTO.java @@ -0,0 +1,58 @@ +package com.newyetai.usercenter.dto; + +import javax.validation.constraints.NotNull; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.common.dto.BaseOperateDTO; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * yzq + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@SuperBuilder +public class OrgUserEditDTO extends BaseDTO{ + + private static final long serialVersionUID = -9143944005872387841L; + + + /** + * 昵称 + */ + private String chineseName; + /** + * 帐号 + */ + @NotNull(groups = {Create.class}, message = "中文名不能为空") + private String username; + + /** + * 手机号码 + */ + @NotNull(groups = {Update.class,Create.class}, message = "手机号码不能为空") + private String phone; + + /** + * 手机号验证码 + */ + private String code; + /** + * 邮箱 + */ + private String email; + + /** + * 是否启用 + */ + private Boolean enabled; + +} diff --git a/src/main/java/com/newyetai/usercenter/dto/PaymentCodeDTO.java b/src/main/java/com/newyetai/usercenter/dto/PaymentCodeDTO.java new file mode 100644 index 0000000..a839276 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/dto/PaymentCodeDTO.java @@ -0,0 +1,29 @@ +package com.newyetai.usercenter.dto; + +import com.newyetai.common.validation.Create; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +/** + * @description: 创建支付密码DTO + * @author: chenyun.huang + * @create: 2020-04-11 11:18 + **/ +@Data +public class PaymentCodeDTO implements Serializable { + private static final long serialVersionUID = -2177790509082680961L; + + /** + * 用户ID + */ + @NotNull(message = "用户ID不能为空", groups = {Create.class}) + private Long userId; + + /** + * 支付密码 + */ + @NotNull(message = "支付密码不能为空", groups = {Create.class}) + private String paymentCode; +} diff --git a/src/main/java/com/newyetai/usercenter/dto/ResetPasswordByPhoneDTO.java b/src/main/java/com/newyetai/usercenter/dto/ResetPasswordByPhoneDTO.java new file mode 100644 index 0000000..c3123ba --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/dto/ResetPasswordByPhoneDTO.java @@ -0,0 +1,43 @@ +package com.newyetai.usercenter.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotEmpty; + +import com.newyetai.common.dto.BaseOperateDTO; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author chenyun + * @description 重置密码DTO + * @date 2020/8/26 17:54 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ResetPasswordByPhoneDTO extends BaseOperateDTO implements Serializable { + private static final long serialVersionUID = 8505258030368487025L; + + /** + * 验证码 + */ + @NotEmpty(message = "短信验证码不能为空") + private String phoneCode; + + /** + * 新密码 + */ + @NotEmpty(message = "新密码不能为空") + private String newPassword; + + /** + * 确认密码 + */ + @NotEmpty(message = "确认新密码不能为空") + private String confirmPassword; +} diff --git a/src/main/java/com/newyetai/usercenter/dto/Resource.java b/src/main/java/com/newyetai/usercenter/dto/Resource.java new file mode 100644 index 0000000..e8fb3ad --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/dto/Resource.java @@ -0,0 +1,24 @@ +package com.newyetai.usercenter.dto; + +import org.springframework.security.access.ConfigAttribute; + +import java.io.Serializable; +import java.util.List; + +/** + * 支持授权的资源接口 + * + * @author on 2019-11-05 + */ +public interface Resource extends Serializable { + + Long getId(); + + /** + * 提供资源对于的权限信息 + * + * @return 权限信息 + */ + List getAttributes(); + +} diff --git a/src/main/java/com/newyetai/usercenter/dto/ResourceDTO.java b/src/main/java/com/newyetai/usercenter/dto/ResourceDTO.java new file mode 100644 index 0000000..301abc9 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/dto/ResourceDTO.java @@ -0,0 +1,35 @@ +package com.newyetai.usercenter.dto; + +import com.newyetai.common.validation.Delete; +import com.newyetai.common.validation.Update; +import com.newyetai.usercenter.constants.SecurityValidateConstants; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +/** + * 资源父dto + * @author sr on 2019-10-17 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class ResourceDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = -1196257535328529826L; + + @ApiModelProperty("资源id") + @NotNull(message = SecurityValidateConstants.RESOURCE_ID_NULL, groups = {Update.class, Delete.class}) + private Long id; + + @ApiModelProperty("是否授权") + private Boolean selected; + +} diff --git a/src/main/java/com/newyetai/usercenter/dto/RoleDTO.java b/src/main/java/com/newyetai/usercenter/dto/RoleDTO.java new file mode 100644 index 0000000..189a387 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/dto/RoleDTO.java @@ -0,0 +1,77 @@ +package com.newyetai.usercenter.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; +import com.newyetai.usercenter.constants.SecurityValidateConstants; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import java.io.Serializable; +import java.util.Date; + +/** + * 角色 + * + * @author sr on 2019-11-05 + */ +@ApiModel("角色") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class RoleDTO implements Serializable { + + /** **/ + private static final long serialVersionUID = -1148469623294607563L; + + @ApiModelProperty("角色id") + @NotNull(message = SecurityValidateConstants.ROLE_ID_NULL, groups = {Update.class}) + private Long id; + + @ApiModelProperty("名称") + @NotBlank(message = SecurityValidateConstants.ROLE_NAME_EMPTY, groups = {Create.class}) + @Size(max = 128) + private String name; + + /** 类型 **/ + @JsonIgnore + private String type; + + @ApiModelProperty("是否启用") + private Boolean enabled; + + @ApiModelProperty("描述") + @Size(max = 64, groups = {Create.class, Update.class}) + private String description; + + @ApiModelProperty("标准角色类型:见role_standard_type") + private String standardType; + + @ApiModelProperty("标准角色名称") + private String standardRoleName; + + @ApiModelProperty("所属平台") + private Integer platformCode; + + @ApiModelProperty("创建时间") + @DateTimeFormat( + pattern = "yyyy-MM-dd HH:mm:ss" + ) + @JsonFormat( + shape = JsonFormat.Shape.STRING, + pattern = "yyyy-MM-dd HH:mm:ss", + timezone = "GMT+8" + ) + private Date createTime; + +} diff --git a/src/main/java/com/newyetai/usercenter/dto/RoleQueryDTO.java b/src/main/java/com/newyetai/usercenter/dto/RoleQueryDTO.java new file mode 100644 index 0000000..a0b9ea1 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/dto/RoleQueryDTO.java @@ -0,0 +1,17 @@ +package com.newyetai.usercenter.dto; + +import com.newyetai.common.dto.PageQueryDTO; + +import lombok.Data; + +@Data +public class RoleQueryDTO extends PageQueryDTO{ + + /** **/ + private static final long serialVersionUID = 2970842314451422682L; + + private String type; + private String name; + private Boolean enabled; + +} diff --git a/src/main/java/com/newyetai/usercenter/dto/RoleStandardTypeDTO.java b/src/main/java/com/newyetai/usercenter/dto/RoleStandardTypeDTO.java new file mode 100644 index 0000000..6a74d9c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/dto/RoleStandardTypeDTO.java @@ -0,0 +1,41 @@ +package com.newyetai.usercenter.dto; + +import java.io.Serializable; +import java.util.Date; + +import com.newyetai.common.dto.BaseOperateDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author dylanyuan + */ +@ApiModel("标准角色") +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class RoleStandardTypeDTO extends BaseOperateDTO implements Serializable { + + private static final long serialVersionUID = 3433337468933511136L; + + @ApiModelProperty("编码") + private String roleCode; + + @ApiModelProperty("名称") + private String name; + + @ApiModelProperty("平台编码") + private String platformCode; + + @ApiModelProperty("顺序") + private Integer typeOrder; + +} diff --git a/src/main/java/com/newyetai/usercenter/dto/SecurityCodeRequestDTO.java b/src/main/java/com/newyetai/usercenter/dto/SecurityCodeRequestDTO.java new file mode 100644 index 0000000..19e4a67 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/dto/SecurityCodeRequestDTO.java @@ -0,0 +1,41 @@ +package com.newyetai.usercenter.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotEmpty; +import java.io.Serializable; + +/** + * @author chenyun + * @description 安全码DTO + * @date 2020/8/27 15:32 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class SecurityCodeRequestDTO implements Serializable { + + private static final long serialVersionUID = 9212030527588925234L; + + /** + * 短信验证码 + */ + @NotEmpty(message = "短信验证码不能为空") + private String phoneCode; + + /** + * 安全码 + */ + @NotEmpty(message = "安全码不能为空") + private String securityCode; + + /** + * 确认安全码 + */ + @NotEmpty(message = "确认安全码不能为空") + private String confirmSecurityCode; +} diff --git a/src/main/java/com/newyetai/usercenter/dto/SuperResetPasswordDTO.java b/src/main/java/com/newyetai/usercenter/dto/SuperResetPasswordDTO.java new file mode 100644 index 0000000..975faef --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/dto/SuperResetPasswordDTO.java @@ -0,0 +1,49 @@ +package com.newyetai.usercenter.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import com.newyetai.common.dto.BaseOperateDTO; +import com.newyetai.common.validation.annotation.Expression; +import com.newyetai.common.validation.constants.ValidProviderEnum; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author chenyun + * @description 重置密码DTO + * @date 2020/7/27 10:55 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class SuperResetPasswordDTO extends BaseOperateDTO implements Serializable { + private static final long serialVersionUID = 8505258030368487025L; + + /** + * 用户ID + */ + @NotNull(message = "用户id不能为空") + private Long userId; + + /** + * 新密码 + */ + @ApiModelProperty("密码") + @Expression(type = ValidProviderEnum.PASSWORD, message = "密码格式不正确") + private String newPassword; + + /** + * 确认密码 + */ + @ApiModelProperty("二次确认密码") + @NotBlank(message = "二次确认密码不能为空") + private String confirmPassword; +} diff --git a/src/main/java/com/newyetai/usercenter/dto/UserAllocateRoleDTO.java b/src/main/java/com/newyetai/usercenter/dto/UserAllocateRoleDTO.java new file mode 100644 index 0000000..b9043a9 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/dto/UserAllocateRoleDTO.java @@ -0,0 +1,32 @@ +package com.newyetai.usercenter.dto; + +import java.util.List; + +import javax.validation.constraints.NotNull; + +import com.newyetai.usercenter.constants.SecurityValidateConstants; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2019-10-17 + */ +@ApiModel("用户分配角色") +@Data +@NoArgsConstructor +@AllArgsConstructor +public class UserAllocateRoleDTO { + + @ApiModelProperty("操作角色id列表") + @NotNull(message = SecurityValidateConstants.ROLE_ID_NULL) + private List roleIds; + + @ApiModelProperty("操作类型:是否分配") + @NotNull(message = SecurityValidateConstants.ROLE_ALLOCATE_OPERATE_TYPE) + private Boolean allocated; + +} diff --git a/src/main/java/com/newyetai/usercenter/dto/UserContractStatusDTO.java b/src/main/java/com/newyetai/usercenter/dto/UserContractStatusDTO.java new file mode 100644 index 0000000..4282432 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/dto/UserContractStatusDTO.java @@ -0,0 +1,23 @@ +package com.newyetai.usercenter.dto; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class UserContractStatusDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1126318170374281724L; + + private Long orgId; + private Long userId; + private Integer contractStatus; + +} diff --git a/src/main/java/com/newyetai/usercenter/entity/CompanyBankAccount.java b/src/main/java/com/newyetai/usercenter/entity/CompanyBankAccount.java new file mode 100644 index 0000000..4887dcc --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/entity/CompanyBankAccount.java @@ -0,0 +1,38 @@ +package com.newyetai.usercenter.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.OrgBaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@TableName("xs_company_bank_account") +@Data +@AllArgsConstructor +@NoArgsConstructor +@SuperBuilder +public class CompanyBankAccount extends OrgBaseEntity { + + /** + * 支付账号 + */ + private String account; + + /** + * 是否默认银行账户 + */ + private Boolean defaulted; + + /** + * 开户名 + */ + private String accountName; + + /** + * 开户行 + */ + private String accountBankName; + +} diff --git a/src/main/java/com/newyetai/usercenter/entity/CompanyContact.java b/src/main/java/com/newyetai/usercenter/entity/CompanyContact.java new file mode 100644 index 0000000..c212223 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/entity/CompanyContact.java @@ -0,0 +1,53 @@ +package com.newyetai.usercenter.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.OrgBaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.SuperBuilder; + +/** + * @author Jerry.li + * @description 企业联系信息 + * @date 2020/3/27 + */ +@TableName("xs_company_contact") +@Data +@ToString +@SuperBuilder +@AllArgsConstructor +@NoArgsConstructor +public class CompanyContact extends OrgBaseEntity { + + private static final long serialVersionUID = -5534436456179658622L; + + /** + * 联系人 + */ + private String name; + /** + * 联系电话 + */ + private String phone; + /** + * 联系邮箱 + */ + private String email; + /** + * 联系地址 + */ + private String address; + + /** 类型:1联系信息2邮寄信息 **/ + private String type; + + /** 是否默认 **/ + private Boolean defaulted; + + /** 备注信息 **/ + private String remark; + +} diff --git a/src/main/java/com/newyetai/usercenter/entity/CompanyExtend.java b/src/main/java/com/newyetai/usercenter/entity/CompanyExtend.java new file mode 100644 index 0000000..3ec6c2e --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/entity/CompanyExtend.java @@ -0,0 +1,34 @@ +package com.newyetai.usercenter.entity; + +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.OrgBaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + + +/** + * @description: 企业扩展信息 + * @author: chenyun.huang + * @create: 2020-04-10 11:08 + **/ +@EqualsAndHashCode(callSuper = true) +@Data +@TableName("xs_company_extend") +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class CompanyExtend extends OrgBaseEntity { + private static final long serialVersionUID = 5630132200895607964L; + + /** + * 销售 + */ + private Long sellerId; + +} diff --git a/src/main/java/com/newyetai/usercenter/entity/CompanyFile.java b/src/main/java/com/newyetai/usercenter/entity/CompanyFile.java new file mode 100644 index 0000000..3bcf0d3 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/entity/CompanyFile.java @@ -0,0 +1,44 @@ +package com.newyetai.usercenter.entity; + +import java.io.Serializable; +import java.util.Date; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.OrgBaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.SuperBuilder; + +/** + * @author Jerry.li + * @description 企业附件 + * @date 2020/3/27 + */ +@TableName("xs_company_file") +@Data +@ToString +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class CompanyFile extends OrgBaseEntity { + + private static final long serialVersionUID = 3031159277420008898L; + + /** + * 附件编码 + */ + private String fileCode; + /** + * 附件名称 + */ + private String fileName; + /** + * 分类(1-其他;) + */ + private String type; + +} diff --git a/src/main/java/com/newyetai/usercenter/entity/CompanyInvoice.java b/src/main/java/com/newyetai/usercenter/entity/CompanyInvoice.java new file mode 100644 index 0000000..63b67fc --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/entity/CompanyInvoice.java @@ -0,0 +1,56 @@ +package com.newyetai.usercenter.entity; + +import java.io.Serializable; +import java.util.Date; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.OrgBaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.SuperBuilder; + +/** + * @author Jerry.li + * @description 企业发票 + * @date 2020/3/28 + */ +@TableName("xs_company_invoice") +@Data +@ToString +@AllArgsConstructor +@NoArgsConstructor +@SuperBuilder +public class CompanyInvoice extends OrgBaseEntity { + + private static final long serialVersionUID = -5026281298873254982L; + + /** + * 发票抬头 + */ + private String title; + /** + * 税号 + */ + private String taxNo; + /** + * 地址 + */ + private String address; + /** + * 电话号码 + */ + private String phone; + /** + * 开户银行 + */ + private String bankName; + /** + * 银行账号 + */ + private String bankAccount; + +} diff --git a/src/main/java/com/newyetai/usercenter/entity/MessageLog.java b/src/main/java/com/newyetai/usercenter/entity/MessageLog.java new file mode 100644 index 0000000..923dfc8 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/entity/MessageLog.java @@ -0,0 +1,87 @@ +package com.newyetai.usercenter.entity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.Date; + +/** + * @author: Jerry.li + * @description: 消息日志实体 + * @create: 2020-05-26 09:46 + **/ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class MessageLog implements Serializable { + + /** + * 编号 + */ + private Long id; + /** + * 发送者 + */ + private String msgSender; + /** + * 接收者 + */ + private String msgReceiver; + /** + * 消息主题 + */ + private String msgSubject; + /** + * 消息内容 + */ + private String msgContent; + /** + * 激活码 or 者验证码 + */ + private String verifyCode; + /** + * 验证状态:0-未验证 1-已验证 + */ + private Integer verifyStatus; + /** + * 发送状态:0-待发送 1-已发送 9-发送失败 2-手动补发成功 + */ + private Integer sendStatus; + /** + * 消息通道:1-短信 2-邮件 + */ + private Integer msgChannel; + /** + * 模板编号 + */ + private String templateCode; + /** + * 回执ID + */ + private String bizId; + /** + * 请求ID + */ + private String requestId; + /** + * 响应码 + */ + private String respCode; + /** + * 响应描述 + */ + private String respDesc; + /** + * 创建时间 + */ + private Date createTime; + /** + * 更新时间 + */ + private Date lastUpdateTime; + +} diff --git a/src/main/java/com/newyetai/usercenter/entity/RoleStandardType.java b/src/main/java/com/newyetai/usercenter/entity/RoleStandardType.java new file mode 100644 index 0000000..3ccabae --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/entity/RoleStandardType.java @@ -0,0 +1,37 @@ +package com.newyetai.usercenter.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @Author dylanyuan + * @Date 2021/2/19 1:46 下午 + * @Version 1.0 + */ +@EqualsAndHashCode(callSuper = true) +@TableName("xs_role_standard_type") +@NoArgsConstructor +@AllArgsConstructor +@Data +public class RoleStandardType extends BaseEntity { + + private static final long serialVersionUID = 928812997780345557L; + /** + * 编码 + **/ + private String roleCode; + /** + * 名称 + **/ + private String name; + /** + * 平台编码 + **/ + private String platformCode; + +} diff --git a/src/main/java/com/newyetai/usercenter/enums/AllocationType.java b/src/main/java/com/newyetai/usercenter/enums/AllocationType.java new file mode 100644 index 0000000..2d1efbb --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/enums/AllocationType.java @@ -0,0 +1,35 @@ +package com.newyetai.usercenter.enums; + +/** + * @author Jerry.li + * @description 角色分配类型 + * @date 2020/3/26 + */ +public enum AllocationType { + ALLOCATION_TYPE_PERSON("1", "个人"), + ALLOCATION_TYPE_DEPARTMENT("2", "部门"), + ALLOCATION_TYPE_GROUP("3", "组"); + + /** + * 分配类型 + */ + private String type; + /** + * 类型描述 + */ + private String desc; + + AllocationType(String type, String desc) { + this.type = type; + this.desc = desc; + } + + + public String getAllocationType() { + return type; + } + + public String getAllocationTypeDesc() { + return desc; + } +} diff --git a/src/main/java/com/newyetai/usercenter/enums/AuthStatu.java b/src/main/java/com/newyetai/usercenter/enums/AuthStatu.java new file mode 100644 index 0000000..be4a3ab --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/enums/AuthStatu.java @@ -0,0 +1,52 @@ +package com.newyetai.usercenter.enums; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.newyetai.mybatis.handle.BaseEnum; + +import java.util.Arrays; + +/** + * 二要素认证状态 1:待认证 2:认证成功 3:认证失败 + */ +public enum AuthStatu implements BaseEnum { + AUTH_READY("1", "待认证"), + AUTH_SUCCESS("2", "认证成功"), + AUTH_FAILED("3", "认证失败"); + + AuthStatu(String statu, String desc) { + this.statu = statu; + this.desc = desc; + } + + /** + * 认证状态 + */ + @EnumValue + private final String statu; + /** + * 类型描述 + */ + private final String desc; + + public String getStatu() { + return statu; + } + + public String getType() { + return statu; + } + + public String getDesc() { + return desc; + } + + @Override + public String getValue() { + return this.statu; + } + + public static AuthStatu findByStatu(String statu) { + return Arrays.stream(AuthStatu.values()).filter(authStatu -> StrUtil.equals(authStatu.getType(), statu)).findFirst().orElse(null); + } +} diff --git a/src/main/java/com/newyetai/usercenter/enums/OrgTypeEnum.java b/src/main/java/com/newyetai/usercenter/enums/OrgTypeEnum.java new file mode 100644 index 0000000..f493706 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/enums/OrgTypeEnum.java @@ -0,0 +1,62 @@ +package com.newyetai.usercenter.enums; + +import java.util.Map; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.google.common.collect.Maps; +import com.newyetai.mybatis.handle.BaseEnum; + +/** + * 机构类型 + * @author sr on 2024-04-18 + */ +public enum OrgTypeEnum implements BaseEnum { + + ORG_TYPE_PLATFORM("1", "平台"), + ORG_TYPE_GOV("2", "政府机构"), + ORG_TYPE_SIMPLE("3", "用工机构"), + ORG_TYPE_HR("4", "服务机构"), + ; + + OrgTypeEnum(String type, String desc) { + this.type = type; + this.desc = desc; + } + + /** + * 机构类型 + */ + @EnumValue + private final String type; + /** + * 机构类型描述 + */ + private final String desc; + + public String getType() { + return type; + } + + + static Map orgTypeMap ; + static { + OrgTypeEnum[] orgTypes = OrgTypeEnum.values(); + orgTypeMap = Maps.newHashMapWithExpectedSize(orgTypes.length); + for (OrgTypeEnum orgType :OrgTypeEnum.values()) { + orgTypeMap.put(orgType.getType(), orgType); + } + } + + public static OrgTypeEnum findByType(String orgType) { + return orgTypeMap.get(orgType); + } + + @Override + public String getValue() { + return this.type; + } + + + + +} diff --git a/src/main/java/com/newyetai/usercenter/enums/ResourceType.java b/src/main/java/com/newyetai/usercenter/enums/ResourceType.java new file mode 100644 index 0000000..f3ddf7b --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/enums/ResourceType.java @@ -0,0 +1,28 @@ +package com.newyetai.usercenter.enums; + +/** + * @author: Jerry.li + * @description: 资源类型 + * @create: 2020-06-17 09:27 + **/ +public enum ResourceType { + RESOURCE_MENU_TYPE("1", "菜单"), + RESOURCE_COMPONENT_TYPE("2", "组件"), + RESOURCE_INTERFACE_TYPE("3", "接口"); + + ResourceType(String type, String desc) { + this.type = type; + this.desc = desc; + } + + private String type; + private String desc; + + public String getType() { + return type; + } + + public String getDesc() { + return desc; + } +} diff --git a/src/main/java/com/newyetai/usercenter/enums/SmsScenesEnum.java b/src/main/java/com/newyetai/usercenter/enums/SmsScenesEnum.java new file mode 100644 index 0000000..986250f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/enums/SmsScenesEnum.java @@ -0,0 +1,57 @@ +package com.newyetai.usercenter.enums; + +import java.util.Arrays; + +/** + * SMS 短信使用场景 + */ +public enum SmsScenesEnum { + + CREATE_USER_INFO("1", "创建用户"), + UPDATE_USER_INFO("2", "更新用户"), + UPDATE_PAY_PASSWORD("3", "更新支付密码"), + CREATE_SAVE_CODE("4", "设置安全码"), + UPDATE_PASSWORD("5", "更新密码"), + SAVE_ALIPAY_USER_INFO("6", "保存支付宝用户信息", "纽业态", SmsTemplateCodeEnum.CYB_COLLECT_INFO_SMS), + WECHAT_USER_INFO("7", "微信端用户信息绑定"); + + private String type; + private String desc; + private String signName; + private SmsTemplateCodeEnum templateCode; + + SmsScenesEnum(String type, String desc) { + this.type = type; + this.desc = desc; + this.signName = null; + this.templateCode = SmsTemplateCodeEnum.PHONE_SMS; + } + + SmsScenesEnum(String type, String desc, String signName, SmsTemplateCodeEnum templateCode) { + this.type = type; + this.desc = desc; + this.signName = signName; + this.templateCode = templateCode; + } + + public String getType() { + return type; + } + + public String getDesc() { + return desc; + } + + public String getSignName() { + return signName; + } + + public SmsTemplateCodeEnum getTemplateCode() { + return templateCode; + } + + public static SmsScenesEnum findByType(String type) { + return Arrays.stream(SmsScenesEnum.values()) + .filter(smsScenesEnum -> smsScenesEnum.getType().equals(type)).findFirst().orElse(null); + } +} diff --git a/src/main/java/com/newyetai/usercenter/enums/SmsTemplateCodeEnum.java b/src/main/java/com/newyetai/usercenter/enums/SmsTemplateCodeEnum.java new file mode 100644 index 0000000..9781e1e --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/enums/SmsTemplateCodeEnum.java @@ -0,0 +1,74 @@ +package com.newyetai.usercenter.enums; + +import com.newyetai.sdk.sms.dto.ITemplateCode; + +/** + * 短信模版 + * + * @author sr on 2020-07-02 + */ +public enum SmsTemplateCodeEnum implements ITemplateCode { + + /** + * 个人签约认证短信模版 + **/ + PERSON_VERIFY("templatePersonVerify"), + /** + * 结算提醒通知模版 + **/ + SETTLEMENT_NOTIFY("templateSettlementNotify"), + /** + * 结算支付验证 + **/ + SETTLE_CAPTCHA("templateSettleCaptcha"), + /** + * 机构开通通知模版 + **/ + ORG_CREATE("templateOrgCreate"), + /** + * 代发开通通知模板 + **/ + AGENT_SEND_SMS("agentSendSms"), + /** + * 三要素认证开通通知模板 + **/ + THREE_ELEMENT_SMS("threeElementSms"), + /** + * 手机短信模拟 + **/ + PHONE_SMS("phoneSms"), + + /** + * 采源宝信息收集Sms + **/ + CYB_COLLECT_INFO_SMS("cybCollectInfoSms"), + + /** + * 无卡发薪支付成功通知 + */ + UPAY_PAY_SUCCESS("upayPaySuccess"), + + /** 合同续期(人事) **/ + CONTRACT_CONTINUED("contractContinued"), + + /** 机构审批通过 **/ + ORG_APPLY_SUCCESS("orgApplySuccess"), + /** 机构审批不通过 **/ + ORG_APPLY_REJECT("orgApplyReject"), + ; + + /** + * 模版配置键 + **/ + private String templateCodeKey; + + SmsTemplateCodeEnum(String templateCodeKey) { + this.templateCodeKey = templateCodeKey; + } + + @Override + public String getTemplateCodeKey() { + return this.templateCodeKey; + } + +} diff --git a/src/main/java/com/newyetai/usercenter/enums/UserType.java b/src/main/java/com/newyetai/usercenter/enums/UserType.java new file mode 100644 index 0000000..ca00cac --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/enums/UserType.java @@ -0,0 +1,44 @@ +package com.newyetai.usercenter.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.newyetai.mybatis.handle.BaseEnum; + +/** + * @author Jerry.li + * @description 用户类型 + * @date 2020/3/24 + */ +public enum UserType implements BaseEnum { + USER_TYPE_PLATFORM("1", "平台管理员"), + USER_TYPE_ORG("2", "机构管理员"), + USER_TYPE_COMPANY("3", "企业用户"), + USER_TYPE_PERSON("4", "个人用户"); + + UserType(String type, String desc) { + this.type = type; + this.desc = desc; + } + + /** + * 用户类型 + */ + @EnumValue + private final String type; + /** + * 类型描述 + */ + private final String desc; + + public String getType() { + return type; + } + + public String getDesc() { + return desc; + } + + @Override + public String getValue() { + return this.type; + } +} diff --git a/src/main/java/com/newyetai/usercenter/face/controller/FaceController.java b/src/main/java/com/newyetai/usercenter/face/controller/FaceController.java new file mode 100644 index 0000000..e8077eb --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/face/controller/FaceController.java @@ -0,0 +1,48 @@ +package com.newyetai.usercenter.face.controller; + +import com.newyetai.common.AlitaResult; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.face.dto.FaceCreateDTO; +import com.newyetai.usercenter.face.dto.FaceInfoDTO; +import com.newyetai.usercenter.face.dto.FacePageQueryDTO; +import com.newyetai.usercenter.face.service.FaceService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + + +/** + * org控制器 + * + * @author Carlye + * @date 2021/06/16 + */ +@RestController +@RequestMapping("/uc/face") +@Api(tags = "用户活体信息") +public class FaceController { + + @Autowired + private FaceService faceService; + + @ApiOperation("创建") + @PostMapping("/create") + public AlitaResult create(@RequestBody FaceCreateDTO createDTO) { + return AlitaResult.success(faceService.create(createDTO)); + } + + @ApiOperation("删除") + @PostMapping("/delete") + public AlitaResult delete(@RequestBody FaceInfoDTO infoDTO) { + faceService.delete(infoDTO); + return AlitaResult.success(); + } + + @ApiOperation("分页查询") + @GetMapping("/page") + public AlitaResult> page(FacePageQueryDTO queryDTO) { + faceService.page(queryDTO); + return AlitaResult.success(queryDTO.getPageResult()); + } +} diff --git a/src/main/java/com/newyetai/usercenter/face/dao/FaceMapper.java b/src/main/java/com/newyetai/usercenter/face/dao/FaceMapper.java new file mode 100644 index 0000000..a99fb1d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/face/dao/FaceMapper.java @@ -0,0 +1,21 @@ +package com.newyetai.usercenter.face.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.newyetai.usercenter.face.dto.FaceInfoDTO; +import com.newyetai.usercenter.face.dto.FacePageQueryDTO; +import com.newyetai.usercenter.face.entity.Face; + +import java.util.List; + +/** + *

+ * 活体 Mapper 接口 + *

+ * + * @author Carlye + * @since 2021-06-16 + */ +public interface FaceMapper extends BaseMapper { + + List page(FacePageQueryDTO queryDTO); +} diff --git a/src/main/java/com/newyetai/usercenter/face/dto/FaceCreateDTO.java b/src/main/java/com/newyetai/usercenter/face/dto/FaceCreateDTO.java new file mode 100644 index 0000000..12c3ade --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/face/dto/FaceCreateDTO.java @@ -0,0 +1,35 @@ +package com.newyetai.usercenter.face.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class FaceCreateDTO implements Serializable { + private static final long serialVersionUID = -871298279722550146L; + + /** + * 用户ID + */ + private Long userId; + + /** + * 类型 1:照片 2:视频 + */ + @NotNull(message = "活体类型不能为空") + private Integer type; + + /** + * 文件编码 + */ + @NotEmpty(message = "文件编码不能为空") + private String fileCode; +} diff --git a/src/main/java/com/newyetai/usercenter/face/dto/FaceInfoDTO.java b/src/main/java/com/newyetai/usercenter/face/dto/FaceInfoDTO.java new file mode 100644 index 0000000..eb38ca9 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/face/dto/FaceInfoDTO.java @@ -0,0 +1,28 @@ +package com.newyetai.usercenter.face.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class FaceInfoDTO implements Serializable { + private static final long serialVersionUID = 4838665122721131760L; + + private Long id; + + /** + * 类型 1:照片 2:视频 + */ + private Integer type; + + /** + * 文件编码 + */ + private String fileCode; +} diff --git a/src/main/java/com/newyetai/usercenter/face/dto/FacePageQueryDTO.java b/src/main/java/com/newyetai/usercenter/face/dto/FacePageQueryDTO.java new file mode 100644 index 0000000..c63474a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/face/dto/FacePageQueryDTO.java @@ -0,0 +1,32 @@ +package com.newyetai.usercenter.face.dto; + +import com.newyetai.common.dto.PageQueryDTO; +import com.newyetai.common.util.UserContextHolder; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Objects; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class FacePageQueryDTO extends PageQueryDTO { + + private static final long serialVersionUID = -5013896780324404266L; + /** + * 类型 1:照片 2:视频 + */ + private Integer type; + + private Long userId; + + public Long getUserId() { + if (Objects.isNull(userId)) { + userId = UserContextHolder.getExistLoginUserId(); + } + return userId; + } +} diff --git a/src/main/java/com/newyetai/usercenter/face/entity/Face.java b/src/main/java/com/newyetai/usercenter/face/entity/Face.java new file mode 100644 index 0000000..cb803f8 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/face/entity/Face.java @@ -0,0 +1,41 @@ +package com.newyetai.usercenter.face.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; +import com.newyetai.usercenter.face.enums.FaceTypeEnum; +import lombok.*; +import lombok.experimental.Accessors; + +/** + *

+ * 机构 + *

+ * + * @author Carlye + * @since 2021-06-16 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@TableName("uc_user_face") +public class Face extends BaseEntity { + + private static final long serialVersionUID = -2769462084799607560L; + /** + * 用户ID + */ + private Long userId; + + /** + * 类型 1:照片 2:视频 + */ + private FaceTypeEnum type; + + /** + * 文件编码 + */ + private String fileCode; +} diff --git a/src/main/java/com/newyetai/usercenter/face/enums/FaceTypeEnum.java b/src/main/java/com/newyetai/usercenter/face/enums/FaceTypeEnum.java new file mode 100644 index 0000000..ebc0549 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/face/enums/FaceTypeEnum.java @@ -0,0 +1,38 @@ +package com.newyetai.usercenter.face.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; + +/** + * 活体表类型 枚举类型 + * + * @author Carlye + * @date 2021/10/28 + */ +public enum FaceTypeEnum { + + IMG(1, "照片"), + VIDEO(2, "视频"); + + /** + * 关联类型 + */ + @EnumValue + private final Integer type; + /** + * 类型描述 + */ + private final String desc; + + FaceTypeEnum(Integer type, String desc) { + this.type = type; + this.desc = desc; + } + + public Integer getType() { + return type; + } + + public String getDesc() { + return desc; + } +} diff --git a/src/main/java/com/newyetai/usercenter/face/mapper/FaceMapper.xml b/src/main/java/com/newyetai/usercenter/face/mapper/FaceMapper.xml new file mode 100644 index 0000000..c3b0d32 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/face/mapper/FaceMapper.xml @@ -0,0 +1,12 @@ + + + + + + diff --git a/src/main/java/com/newyetai/usercenter/face/service/FaceService.java b/src/main/java/com/newyetai/usercenter/face/service/FaceService.java new file mode 100644 index 0000000..a9aaead --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/face/service/FaceService.java @@ -0,0 +1,38 @@ +package com.newyetai.usercenter.face.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.newyetai.usercenter.face.dto.FaceCreateDTO; +import com.newyetai.usercenter.face.dto.FaceInfoDTO; +import com.newyetai.usercenter.face.dto.FacePageQueryDTO; +import com.newyetai.usercenter.face.entity.Face; +import org.springframework.validation.annotation.Validated; + +import javax.validation.Valid; +import javax.validation.groups.Default; +import java.util.List; + +@Validated(Default.class) +public interface FaceService extends IService { + + /** + * 创建 + * + * @param createDTO 创建dto + */ + FaceInfoDTO create(@Valid FaceCreateDTO createDTO); + + /** + * 删除 + * @param faceInfoDTO + */ + void delete(FaceInfoDTO faceInfoDTO); + + /** + * 页面 + * + * @param queryDTO 查询dto + * @return {@link List}<{@link FaceInfoDTO}> + */ + List page(FacePageQueryDTO queryDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/face/service/impl/FaceServiceImpl.java b/src/main/java/com/newyetai/usercenter/face/service/impl/FaceServiceImpl.java new file mode 100644 index 0000000..8c4fba9 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/face/service/impl/FaceServiceImpl.java @@ -0,0 +1,63 @@ +package com.newyetai.usercenter.face.service.impl; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.EnumUtil; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.usercenter.face.dao.FaceMapper; +import com.newyetai.usercenter.face.dto.FaceCreateDTO; +import com.newyetai.usercenter.face.dto.FaceInfoDTO; +import com.newyetai.usercenter.face.dto.FacePageQueryDTO; +import com.newyetai.usercenter.face.entity.Face; +import com.newyetai.usercenter.face.enums.FaceTypeEnum; +import com.newyetai.usercenter.face.service.FaceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Objects; + +/** + * 用户活体 服务impl + * + * @author Carlye + * @date 2021/06/16 + */ +@Slf4j +@Service +public class FaceServiceImpl extends ServiceImpl implements FaceService { + + @Override + public FaceInfoDTO create(FaceCreateDTO createDTO) { + Long userId = Objects.isNull(createDTO.getUserId()) ? UserContextHolder.getExistLoginUserId() : createDTO.getUserId(); + FaceTypeEnum resolve = EnumUtil.resolve(FaceTypeEnum::getType, createDTO.getType()); + Assert.notNull(resolve, "活体类型错误"); + List list = list(Wrappers.lambdaQuery().eq(Face::getUserId, userId).eq(Face::getType, resolve).eq(Face::getDeleted, false)); + if (list.size() > 0) { + Face face = list.get(0); + return FaceInfoDTO.builder().id(face.getId()).type(face.getType().getType()).fileCode(face.getFileCode()).build(); + } else { + Face face = Face.builder().userId(userId).type(resolve).fileCode(createDTO.getFileCode()).build(); + save(face); + return FaceInfoDTO.builder().id(face.getId()).type(face.getType().getType()).fileCode(face.getFileCode()).build(); + } + } + + @Override + public void delete(FaceInfoDTO faceInfoDTO) { + update(Wrappers.lambdaUpdate() + .set(Face::getDeleted, true) + .set(Face::getUpdateBy, UserContextHolder.getExistLoginUserId()) + .set(Face::getUpdateTime, DateUtil.date()) + .eq(Face::getId, faceInfoDTO.getId()) + .eq(Face::getUserId, UserContextHolder.getExistLoginUserId()) + ); + } + + @Override + public List page(FacePageQueryDTO queryDTO) { + return getBaseMapper().page(queryDTO); + } +} diff --git a/src/main/java/com/newyetai/usercenter/mapper/UcMessageMapper.xml b/src/main/java/com/newyetai/usercenter/mapper/UcMessageMapper.xml new file mode 100644 index 0000000..23632c5 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/mapper/UcMessageMapper.xml @@ -0,0 +1,97 @@ + + + + + + insert into xs_message_log + ( + msg_sender, + msg_receiver, + msg_subject, + msg_content, + msg_channel, + template_code, + verify_code, + verify_status + ) + values( + #{msgSender}, + #{msgReceiver}, + #{msgSubject}, + #{msgContent}, + #{msgChannel}, + #{templateCode}, + #{verifyCode}, + #{verifyStatus} + ) + + + + + + + + update xs_message_log + set + + verify_status = #{verifyStatus}, + + + send_status = #{sendStatus}, + + + biz_id = #{bizId}, + + + request_id = #{requestId}, + + + resp_code = #{respCode}, + + + resp_desc = #{respDesc}, + + last_update_time = now() + where id = #{id} + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/mapper/XsRoleStandardTypeMapper.xml b/src/main/java/com/newyetai/usercenter/mapper/XsRoleStandardTypeMapper.xml new file mode 100644 index 0000000..af9b7ea --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/mapper/XsRoleStandardTypeMapper.xml @@ -0,0 +1,20 @@ + + + + + + diff --git a/src/main/java/com/newyetai/usercenter/notice/config/NoticeProperties.java b/src/main/java/com/newyetai/usercenter/notice/config/NoticeProperties.java new file mode 100644 index 0000000..543280a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/config/NoticeProperties.java @@ -0,0 +1,40 @@ +package com.newyetai.usercenter.notice.config; + +import java.util.HashMap; +import java.util.Map; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import lombok.Data; +import lombok.NoArgsConstructor; + +@ConfigurationProperties(prefix = "notice") +@Data +@Component +public class NoticeProperties { + + private Map wechatOffiaccountMsgs = new HashMap<>(); + + @Data + @NoArgsConstructor + public static class WechatOffiaccountMsgProvider { + + /** 通知模版标识 **/ + private String noticeTemplateCode; + + /** 微信公众号消息模版id **/ + private String templateId; + + /** 微信公众号消息链接 **/ + private String link; + + } + + + public WechatOffiaccountMsgProvider getWechatOffiaccountProvider(String providerCode) { + return this.wechatOffiaccountMsgs.get(providerCode); + } + + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/constant/NoticeChannelTypeEnum.java b/src/main/java/com/newyetai/usercenter/notice/constant/NoticeChannelTypeEnum.java new file mode 100644 index 0000000..626f616 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/constant/NoticeChannelTypeEnum.java @@ -0,0 +1,32 @@ +package com.newyetai.usercenter.notice.constant; + +/** + * 消息通道类型: + * @author sr on 2020-12-21 + */ +public enum NoticeChannelTypeEnum { + + /** 1站内信 **/ + SITE(1), + /** 2短信 **/ + SMS(2), + /** 3钉钉 **/ + DING_TALK(3), + /** 4企业微信 **/ + WORK_WECHAT(4), + /** 5邮件 **/ + MAIL(5), + /** 6微信公众号 **/ + WECHAT_OFFIACCOUNT(6); + + NoticeChannelTypeEnum(Integer type) { + this.type = type; + } + + private Integer type; + + public Integer getType() { + return type; + } + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/constant/NoticeContentTemplateConstants.java b/src/main/java/com/newyetai/usercenter/notice/constant/NoticeContentTemplateConstants.java new file mode 100644 index 0000000..cd5a215 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/constant/NoticeContentTemplateConstants.java @@ -0,0 +1,8 @@ +package com.newyetai.usercenter.notice.constant; + +/** + * @author sr on 2020-12-20 + */ +public interface NoticeContentTemplateConstants { + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/constant/NoticeLevelEnum.java b/src/main/java/com/newyetai/usercenter/notice/constant/NoticeLevelEnum.java new file mode 100644 index 0000000..226917f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/constant/NoticeLevelEnum.java @@ -0,0 +1,24 @@ +package com.newyetai.usercenter.notice.constant; + +/** + * 级别: + * @author sr on 2020-12-21 + */ +public enum NoticeLevelEnum { + + /** 1平台 **/ + PLATFORM(1), + /** 2机构 **/ + ORG(2); + + NoticeLevelEnum(Integer type) { + this.type = type; + } + + private Integer type; + + public Integer getType() { + return type; + } + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/constant/NoticeModuleTypeEnum.java b/src/main/java/com/newyetai/usercenter/notice/constant/NoticeModuleTypeEnum.java new file mode 100644 index 0000000..516feb3 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/constant/NoticeModuleTypeEnum.java @@ -0,0 +1,24 @@ +package com.newyetai.usercenter.notice.constant; + +/** + * 模块分类 + * @author sr on 2020-12-21 + */ +public enum NoticeModuleTypeEnum { + + /** 1业务 **/ + BIZ(1), + /** 2监控/预警 **/ + ACTUATOR(2); + + NoticeModuleTypeEnum(Integer type) { + this.type = type; + } + + private Integer type; + + public Integer getType() { + return type; + } + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/constant/NoticeReceiverSettingConstants.java b/src/main/java/com/newyetai/usercenter/notice/constant/NoticeReceiverSettingConstants.java new file mode 100644 index 0000000..d8daa34 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/constant/NoticeReceiverSettingConstants.java @@ -0,0 +1,8 @@ +package com.newyetai.usercenter.notice.constant; + +/** + * @author sr on 2020-12-20 + */ +public interface NoticeReceiverSettingConstants { + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/constant/NoticeReceiverStatusEnum.java b/src/main/java/com/newyetai/usercenter/notice/constant/NoticeReceiverStatusEnum.java new file mode 100644 index 0000000..50cdf48 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/constant/NoticeReceiverStatusEnum.java @@ -0,0 +1,28 @@ +package com.newyetai.usercenter.notice.constant; + +/** + * 接收状态: + * @author sr on 2020-12-21 + */ +public enum NoticeReceiverStatusEnum { + + /** 1待发送 **/ + INIT(1), + /** 2已发送 **/ + SENT(2), + /** 3发送失败 **/ + SEND_FAIL(3), + /** 4接收已读 **/ + READ(4); + + NoticeReceiverStatusEnum(Integer type) { + this.type = type; + } + + private Integer type; + + public Integer getType() { + return type; + } + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/constant/NoticeReceiverTypeEnum.java b/src/main/java/com/newyetai/usercenter/notice/constant/NoticeReceiverTypeEnum.java new file mode 100644 index 0000000..ed85d7a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/constant/NoticeReceiverTypeEnum.java @@ -0,0 +1,26 @@ +package com.newyetai.usercenter.notice.constant; + +/** + * 接收人关联类型: + * @author sr on 2020-12-21 + */ +public enum NoticeReceiverTypeEnum { + + /** 1用户id **/ + USER(1), + /** 2角色 **/ + ROLE(2), + /** 3标准角色 **/ + STANDARD_ROLE(3); + + NoticeReceiverTypeEnum(Integer type) { + this.type = type; + } + + private Integer type; + + public Integer getType() { + return type; + } + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/constant/NoticeSendStatusEnum.java b/src/main/java/com/newyetai/usercenter/notice/constant/NoticeSendStatusEnum.java new file mode 100644 index 0000000..7df5ce6 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/constant/NoticeSendStatusEnum.java @@ -0,0 +1,25 @@ +package com.newyetai.usercenter.notice.constant; + +/** + * 接收状态: + * @author sr on 2020-12-21 + */ +public enum NoticeSendStatusEnum { + + /** 1待处理 **/ + INIT(1), + /** 2已处理 **/ + SENT(2); + + + NoticeSendStatusEnum(Integer type) { + this.type = type; + } + + private Integer type; + + public Integer getType() { + return type; + } + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/controller/NoticeContentTemplateController.java b/src/main/java/com/newyetai/usercenter/notice/controller/NoticeContentTemplateController.java new file mode 100644 index 0000000..980ca61 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/controller/NoticeContentTemplateController.java @@ -0,0 +1,69 @@ +package com.newyetai.usercenter.notice.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.common.validation.Update; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.notice.dto.NoticeContentTemplateDTO; +import com.newyetai.usercenter.notice.dto.NoticeContentTemplateOperateDTO; +import com.newyetai.usercenter.notice.dto.NoticeContentTemplateQueryDTO; +import com.newyetai.usercenter.notice.service.NoticeContentTemplateService; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +/** + * @author sr on 2020-12-20 + */ +@RestController +@RequestMapping("notice_content_template") +@Api(tags = "通知消息体模版") +public class NoticeContentTemplateController{ + + @Autowired + private NoticeContentTemplateService noticeContentTemplateService; + + @PostMapping("/create") + @ApiOperation("创建") + public AlitaResult create( + @Validated @RequestBody NoticeContentTemplateOperateDTO noticeContentTemplateOperateDTO){ + UserContextHolder.checkPlatformOrg(); + return AlitaResult.success(noticeContentTemplateService.create(noticeContentTemplateOperateDTO)); + } + + @PutMapping("/modify") + @ApiOperation("修改") + public AlitaResult modify( + @Validated(Update.class) @RequestBody NoticeContentTemplateOperateDTO noticeContentTemplateOperateDTO){ + UserContextHolder.checkPlatformOrg(); + noticeContentTemplateService.modify(noticeContentTemplateOperateDTO); + return AlitaResult.success(true); + } + + @DeleteMapping("/remove/{id}") + @ApiOperation("删除") + public AlitaResult remove(@PathVariable Long id){ + UserContextHolder.checkPlatformOrg(); + noticeContentTemplateService.remove(id); + return AlitaResult.success(true); + } + + @GetMapping("/page") + @ApiOperation("分页查询") + public AlitaResult> page(NoticeContentTemplateQueryDTO noticeContentTemplateQueryDTO){ + noticeContentTemplateService.page(noticeContentTemplateQueryDTO); + return AlitaResult.success(noticeContentTemplateQueryDTO.getPageResult()); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/controller/NoticeReceiverSettingController.java b/src/main/java/com/newyetai/usercenter/notice/controller/NoticeReceiverSettingController.java new file mode 100644 index 0000000..8634ccf --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/controller/NoticeReceiverSettingController.java @@ -0,0 +1,84 @@ +package com.newyetai.usercenter.notice.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.newyetai.common.AlitaResult; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.notice.dto.NoticeReceiverSettingDTO; +import com.newyetai.usercenter.notice.dto.NoticeReceiverSettingOperateDTO; +import com.newyetai.usercenter.notice.dto.NoticeReceiverSettingQueryDTO; +import com.newyetai.usercenter.notice.dto.NoticeReceiverSettingRemoveDTO; +import com.newyetai.usercenter.notice.dto.NoticeReceiverSettingRoleDTO; +import com.newyetai.usercenter.notice.dto.NoticeReceiverSettingUserDTO; +import com.newyetai.usercenter.notice.service.NoticeReceiverSettingService; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +/** + * @author sr on 2020-12-20 + */ +@RestController +@RequestMapping("notice_receiver_setting") +@Api(tags = "通知接收人设置") +public class NoticeReceiverSettingController{ + + @Autowired + private NoticeReceiverSettingService noticeReceiverSettingService; + + @PostMapping("/create") + @ApiOperation("创建(新增)") + public AlitaResult create( + @Validated @RequestBody NoticeReceiverSettingOperateDTO noticeReceiverSettingOperateDTO) { + noticeReceiverSettingService.create(noticeReceiverSettingOperateDTO); + return AlitaResult.success(true); + } + + @PostMapping("/save") + @ApiOperation("保存设置(内部判断新增/删除)") + public AlitaResult save( + @Validated @RequestBody NoticeReceiverSettingOperateDTO noticeReceiverSettingOperateDTO) { + noticeReceiverSettingService.save(noticeReceiverSettingOperateDTO); + return AlitaResult.success(true); + } + + @DeleteMapping("/remove") + @ApiOperation("删除") + public AlitaResult remove( + @Validated @RequestBody NoticeReceiverSettingRemoveDTO noticeReceiverSettingRemoveDTO) { + noticeReceiverSettingService.remove(noticeReceiverSettingRemoveDTO); + return AlitaResult.success(true); + } + + @GetMapping("/page") + @ApiOperation("分页查询") + public AlitaResult> page( + NoticeReceiverSettingQueryDTO noticeReceiverSettingQueryDTO) { + noticeReceiverSettingService.list(noticeReceiverSettingQueryDTO); + return AlitaResult.success(noticeReceiverSettingQueryDTO.getPageResult()); + } + + @GetMapping("/page_user") + @ApiOperation("分页查询") + public AlitaResult> pageUser( + @Validated NoticeReceiverSettingQueryDTO noticeReceiverSettingQueryDTO){ + noticeReceiverSettingService.listUser(noticeReceiverSettingQueryDTO); + return AlitaResult.success(noticeReceiverSettingQueryDTO.getPageResult()); + } + + @GetMapping("/page_role") + @ApiOperation("分页查询") + public AlitaResult> pageRole( + @Validated NoticeReceiverSettingQueryDTO noticeReceiverSettingQueryDTO){ + noticeReceiverSettingService.listRole(noticeReceiverSettingQueryDTO); + return AlitaResult.success(noticeReceiverSettingQueryDTO.getPageResult()); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/controller/NoticeSendRecordController.java b/src/main/java/com/newyetai/usercenter/notice/controller/NoticeSendRecordController.java new file mode 100644 index 0000000..c889a56 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/controller/NoticeSendRecordController.java @@ -0,0 +1,47 @@ +package com.newyetai.usercenter.notice.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.newyetai.common.AlitaResult; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.notice.dto.NoticeSendRecordDTO; +import com.newyetai.usercenter.notice.dto.NoticeSendRecordOperateDTO; +import com.newyetai.usercenter.notice.dto.NoticeSendRecordQueryDTO; +import com.newyetai.usercenter.notice.service.NoticeSendRecordService; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +/** + * @author sr on 2020-12-20 + */ +@RestController +@RequestMapping("notice_send_record") +@Api(tags = "通知发送记录(内容模版级)") +public class NoticeSendRecordController { + + @Autowired + private NoticeSendRecordService noticeSendRecordService; + + @PostMapping("/create") + @ApiOperation("创建(发送通知)") + public AlitaResult create( + @Validated @RequestBody NoticeSendRecordOperateDTO noticeSendRecordOperateDTO){ + noticeSendRecordService.create(noticeSendRecordOperateDTO); + return AlitaResult.success(true); + } + + @GetMapping("/page") + @ApiOperation("分页查询") + public AlitaResult> page(NoticeSendRecordQueryDTO noticeSendRecordQueryDTO){ + noticeSendRecordService.page(noticeSendRecordQueryDTO); + return AlitaResult.success(noticeSendRecordQueryDTO.getPageResult()); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/controller/NoticeSendRecordDetailController.java b/src/main/java/com/newyetai/usercenter/notice/controller/NoticeSendRecordDetailController.java new file mode 100644 index 0000000..aff75be --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/controller/NoticeSendRecordDetailController.java @@ -0,0 +1,64 @@ +package com.newyetai.usercenter.notice.controller; + +import com.newyetai.common.AlitaResult; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.notice.dto.NoticeSendRecordDetailDTO; +import com.newyetai.usercenter.notice.dto.NoticeSendRecordDetailQueryDTO; +import com.newyetai.usercenter.notice.dto.NoticeSendRecordDetailReqDTO; +import com.newyetai.usercenter.notice.service.NoticeSendRecordDetailService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * @author sr on 2020-12-20 + */ +@RestController +@RequestMapping("notice_send_record_detail") +@Api(tags = "通知发送记录明细") +public class NoticeSendRecordDetailController { + + @Autowired + private NoticeSendRecordDetailService noticeSendRecordDetailService; + + @PostMapping("/page") + @ApiOperation("分页查询(当前登录人通知)") + public AlitaResult> page(@RequestBody + NoticeSendRecordDetailQueryDTO noticeSendRecordDetailQueryDTO) { + noticeSendRecordDetailQueryDTO.setUserId(noticeSendRecordDetailQueryDTO.getOperateUserId()); + noticeSendRecordDetailService.list(noticeSendRecordDetailQueryDTO); + return AlitaResult.success(noticeSendRecordDetailQueryDTO.getPageResult()); + } + + @GetMapping("/detail") + @ApiOperation("单个明细查询") + public AlitaResult detail(@Validated NoticeSendRecordDetailReqDTO reqDTO) { + return AlitaResult.success(noticeSendRecordDetailService.detail(reqDTO)); + } + + + @PostMapping("/count") + @ApiOperation("消息数量查询(当前登录人通知)") + public AlitaResult count(@RequestBody NoticeSendRecordDetailQueryDTO noticeSendRecordDetailQueryDTO) { + noticeSendRecordDetailQueryDTO.setUserId(noticeSendRecordDetailQueryDTO.getOperateUserId()); + return AlitaResult.success(noticeSendRecordDetailService.count(noticeSendRecordDetailQueryDTO)); + } + + // 已读 + @PostMapping("/read/{recordDetailId}") + @ApiOperation("已读通知") + public AlitaResult read(@PathVariable Long recordDetailId){ + noticeSendRecordDetailService.read(recordDetailId); + return AlitaResult.success(true); + } + + @PostMapping("/read_all") + @ApiOperation("已读通知") + public AlitaResult readAll(){ + noticeSendRecordDetailService.readAll(); + return AlitaResult.success(true); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/controller/NoticeTemplateController.java b/src/main/java/com/newyetai/usercenter/notice/controller/NoticeTemplateController.java new file mode 100644 index 0000000..59c9ab3 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/controller/NoticeTemplateController.java @@ -0,0 +1,75 @@ +package com.newyetai.usercenter.notice.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.common.validation.Update; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.notice.dto.NoticeTemplateDTO; +import com.newyetai.usercenter.notice.dto.NoticeTemplateOperateDTO; +import com.newyetai.usercenter.notice.dto.NoticeTemplateQueryDTO; +import com.newyetai.usercenter.notice.service.NoticeTemplateService; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +/** + * @author sr on 2020-12-17 + */ +@RestController +@RequestMapping("notice_template") +@Api(tags = "通知模版") +public class NoticeTemplateController{ + + @Autowired + private NoticeTemplateService noticeTemplateService; + + @PostMapping("/create") + @ApiOperation("创建") + public AlitaResult create( + @Validated @RequestBody NoticeTemplateOperateDTO noticeTemplateOperateDTO) { + UserContextHolder.checkPlatformOrg(); + return AlitaResult.success(noticeTemplateService.create(noticeTemplateOperateDTO)); + } + + @PutMapping("/modify") + @ApiOperation("修改") + public AlitaResult modify( + @Validated(Update.class) @RequestBody NoticeTemplateOperateDTO noticeTemplateOperateDTO) { + UserContextHolder.checkPlatformOrg(); + noticeTemplateService.modify(noticeTemplateOperateDTO); + return AlitaResult.success(true); + } + + @DeleteMapping("/remove/{id}") + @ApiOperation("删除") + public AlitaResult remove(@PathVariable Long id) { + UserContextHolder.checkPlatformOrg(); + noticeTemplateService.remove(id); + return AlitaResult.success(true); + } + + @GetMapping("/page") + @ApiOperation("分页查询") + public AlitaResult> page(NoticeTemplateQueryDTO noticeTemplateQueryDTO) { + noticeTemplateService.page(noticeTemplateQueryDTO); + return AlitaResult.success(noticeTemplateQueryDTO.getPageResult()); + } + + @GetMapping("/find/{id}") + @ApiOperation("单个查询") + public AlitaResult find(@PathVariable Long id) { + return AlitaResult.success(noticeTemplateService.find(id)); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/dao/NoticeContentTemplateMapper.java b/src/main/java/com/newyetai/usercenter/notice/dao/NoticeContentTemplateMapper.java new file mode 100644 index 0000000..d1e4da2 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/dao/NoticeContentTemplateMapper.java @@ -0,0 +1,29 @@ +package com.newyetai.usercenter.notice.dao; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.usercenter.notice.dto.NoticeContentTemplateDTO; +import com.newyetai.usercenter.notice.dto.NoticeContentTemplateQueryDTO; +import com.newyetai.usercenter.notice.entity.NoticeContentTemplate; + +/** + * 通知消息体模版 + * + * @author sr on 2020-12-20 + */ +public interface NoticeContentTemplateMapper extends MyMapper { + + /** + * 查询 + * + * @param noticeContentTemplateQueryDTO + * @return + * @author sr on 2020-12-20 + */ + List listNoticeContentTemplateDTO( + @Param("param") NoticeContentTemplateQueryDTO noticeContentTemplateQueryDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/dao/NoticeReceiverSettingMapper.java b/src/main/java/com/newyetai/usercenter/notice/dao/NoticeReceiverSettingMapper.java new file mode 100644 index 0000000..2380d6a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/dao/NoticeReceiverSettingMapper.java @@ -0,0 +1,110 @@ +package com.newyetai.usercenter.notice.dao; + +import java.util.List; +import java.util.Set; + +import org.apache.ibatis.annotations.Param; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.usercenter.notice.dto.NoticeReceiverSettingDTO; +import com.newyetai.usercenter.notice.dto.NoticeReceiverSettingOperateDTO; +import com.newyetai.usercenter.notice.dto.NoticeReceiverSettingQueryDTO; +import com.newyetai.usercenter.notice.dto.NoticeReceiverSettingRemoveDTO; +import com.newyetai.usercenter.notice.dto.NoticeReceiverSettingRoleDTO; +import com.newyetai.usercenter.notice.dto.NoticeReceiverSettingUserDTO; +import com.newyetai.usercenter.notice.entity.NoticeReceiverSetting; + +/** + * 通知接收人设置 + * + * @author sr on 2020-12-20 + */ +public interface NoticeReceiverSettingMapper extends MyMapper { + + /** + * 查询 + * + * @param noticeReceiverSettingQueryDTO + * @return + * @author sr on 2020-12-20 + */ + List listNoticeReceiverSettingDTO( + @Param("param") NoticeReceiverSettingQueryDTO noticeReceiverSettingQueryDTO); + + /** + * 根据模版id删除接收人配置 + * + * @param noticeReceiverSettingRemoveDTO + * @return + * @author sr on 2020-12-20 + */ + int remove(@Param("param") NoticeReceiverSettingRemoveDTO noticeReceiverSettingRemoveDTO); + + /** + * 查询操作机构接收人现有配置 + * + * @param noticeReceiverSettingOperateDTO + * @return + * @author sr on 2020-12-20 + */ + Set findReceiverUnionIds( + @Param("param") NoticeReceiverSettingOperateDTO noticeReceiverSettingOperateDTO); + + /** + * 新增接收人配置 + * @param noticeReceiverSettingOperateDTO + * @param receiverUnionIds + * @return + * @author sr on 2020-12-21 + */ + int create(@Param("param") NoticeReceiverSettingOperateDTO noticeReceiverSettingOperateDTO, + @Param("receiverUnionIds") Set receiverUnionIds); + + /** + * 根据关联id获取用户id + * + * @param orgId + * @param unionType + * @param unionIds + * @return + * @author sr on 2020-12-21 + */ + Set findUserIdByUnionType(Long orgId, Integer unionType, Set unionIds); + + /** + * 获取有效用户 + * + * @return + * @author sr on 2020-12-21 + */ + Set validUser(Long orgId, Set userIds); + + /** + * 获取有效角色 + * @param orgId + * @param roleIds + * @return + * @author sr on 2020-12-21 + */ + Set validRole(Long orgId, Set roleIds); + + /** + * 查询接收人-用户 + * + * @param noticeReceiverSettingQueryDTO + * @return + * @author sr on 2021-01-07 + */ + List listNoticeReceiverSettingUserDTO( + @Param("param") NoticeReceiverSettingQueryDTO noticeReceiverSettingQueryDTO); + + /** + * 查询接收人-角色 + * + * @param noticeReceiverSettingQueryDTO + * @return + * @author sr on 2021-01-07 + */ + List listNoticeReceiverSettingRoleDTO( + @Param("param") NoticeReceiverSettingQueryDTO noticeReceiverSettingQueryDTO); +} diff --git a/src/main/java/com/newyetai/usercenter/notice/dao/NoticeSendRecordDetailMapper.java b/src/main/java/com/newyetai/usercenter/notice/dao/NoticeSendRecordDetailMapper.java new file mode 100644 index 0000000..7f3742f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/dao/NoticeSendRecordDetailMapper.java @@ -0,0 +1,55 @@ +package com.newyetai.usercenter.notice.dao; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.usercenter.notice.dto.NoticeSendRecordDetailDTO; +import com.newyetai.usercenter.notice.dto.NoticeSendRecordDetailQueryDTO; +import com.newyetai.usercenter.notice.dto.NoticeSendRecordDetailReqDTO; +import com.newyetai.usercenter.notice.dto.RecordDetailUpdateStatusDTO; +import com.newyetai.usercenter.notice.entity.NoticeSendRecordDetail; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 通知发送记录明细(接收人) + * + * @author sr on 2020-12-20 + */ +public interface NoticeSendRecordDetailMapper extends MyMapper { + + /** + * 查询 + * + * @param noticeSendRecordDetailQueryDTO + * @return + * @author sr on 2020-12-20 + */ + List listNoticeSendRecordDetailDTO( + @Param("param") NoticeSendRecordDetailQueryDTO noticeSendRecordDetailQueryDTO); + + /** + * @param noticeSendRecordDetails + * @param operateUserId + * @author sr on 2020-12-21 + */ + void createDetails(@Param("entities") List noticeSendRecordDetails, + @Param("operateUserId") Long operateUserId); + + int modifyStatus(@Param("param") RecordDetailUpdateStatusDTO recordDetailUpdateStatusDTO); + + /** + * 详细通知发送记录数 + * + * @param noticeSendRecordDetailQueryDTO 通知发送记录详细查询dto + * @return {@link Integer} + */ + Integer countNoticeSendRecordDetail(@Param("param") NoticeSendRecordDetailQueryDTO noticeSendRecordDetailQueryDTO); + + /** + * 查询消息详情 + * + * @param reqDTO 通知发送记录详细查询dto + * @return {@link NoticeSendRecordDetailDTO} + */ + NoticeSendRecordDetailDTO findNoticeSendRecordDetailDTO(@Param("param") NoticeSendRecordDetailReqDTO reqDTO); +} diff --git a/src/main/java/com/newyetai/usercenter/notice/dao/NoticeSendRecordMapper.java b/src/main/java/com/newyetai/usercenter/notice/dao/NoticeSendRecordMapper.java new file mode 100644 index 0000000..0ef7580 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/dao/NoticeSendRecordMapper.java @@ -0,0 +1,38 @@ +package com.newyetai.usercenter.notice.dao; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.usercenter.notice.dto.NoticeSendRecordDTO; +import com.newyetai.usercenter.notice.dto.NoticeSendRecordModifyDTO; +import com.newyetai.usercenter.notice.dto.NoticeSendRecordQueryDTO; +import com.newyetai.usercenter.notice.entity.NoticeSendRecord; + +/** + * 通知发送记录(内容模版级) + * + * @author sr on 2020-12-20 + */ +public interface NoticeSendRecordMapper extends MyMapper { + + /** + * 查询 + * + * @param noticeSendRecordQueryDTO + * @return + * @author sr on 2020-12-20 + */ + List listNoticeSendRecordDTO(@Param("param") NoticeSendRecordQueryDTO noticeSendRecordQueryDTO); + + /** + * 修改 + * + * @param noticeSendRecordModifyDTO + * @return + * @author sr on 2021-02-08 + */ + int modify(@Param("param")NoticeSendRecordModifyDTO noticeSendRecordModifyDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/dao/NoticeTemplateMapper.java b/src/main/java/com/newyetai/usercenter/notice/dao/NoticeTemplateMapper.java new file mode 100644 index 0000000..cd4d746 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/dao/NoticeTemplateMapper.java @@ -0,0 +1,29 @@ +package com.newyetai.usercenter.notice.dao; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.usercenter.notice.dto.NoticeTemplateDTO; +import com.newyetai.usercenter.notice.dto.NoticeTemplateQueryDTO; +import com.newyetai.usercenter.notice.entity.NoticeTemplate; + +/** + * 通知模版 + * + * @author sr on 2020-12-17 + */ +public interface NoticeTemplateMapper extends MyMapper { + + /** + * 查询 + * + * @param noticeTemplateQueryDto + * @return + * @author sr on 2020-12-17 + */ + List listNoticeTemplateDTO( + @Param("param") NoticeTemplateQueryDTO noticeTemplateQueryDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/dto/NoticeContentTemplateDTO.java b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeContentTemplateDTO.java new file mode 100644 index 0000000..c90f080 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeContentTemplateDTO.java @@ -0,0 +1,43 @@ +package com.newyetai.usercenter.notice.dto; + +import java.io.Serializable; + +import com.newyetai.common.dto.BaseDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2020-12-17 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@ApiModel(description = "通知消息体模版") +public class NoticeContentTemplateDTO extends BaseDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("通知模版id") + private Long templateId ; + @ApiModelProperty("消息通道类型:1站内信,2短信,3钉钉,4企业微信,5邮件(见notice_channel_type)") + private Integer channelType ; + @ApiModelProperty("标题") + private String title; + @ApiModelProperty("内容模版") + private String contentTemplate ; + @ApiModelProperty("是否启用") + private Boolean enabled; + @ApiModelProperty("链接") + private String link; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/notice/dto/NoticeContentTemplateOperateDTO.java b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeContentTemplateOperateDTO.java new file mode 100644 index 0000000..744febd --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeContentTemplateOperateDTO.java @@ -0,0 +1,53 @@ +package com.newyetai.usercenter.notice.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import com.newyetai.common.dto.BaseOperateDTO; +import com.newyetai.common.validation.Update; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2020-12-20 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "通知消息体模版") +public class NoticeContentTemplateOperateDTO extends BaseOperateDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @NotNull(message = "id不能为空", groups = {Update.class}) + private Long id; + @ApiModelProperty("通知模版id") + @NotNull(message = "通知模版id不能为空") + private Long templateId ; + @ApiModelProperty("消息通道类型:1站内信,2短信,3钉钉,4企业微信,5邮件(见notice_channel_type)") + @NotNull(message = "消息通道类型不能为空") + private Integer channelType ; + @ApiModelProperty("标题") + @NotBlank(message = "标题不能为空") + private String title; + @ApiModelProperty("内容模版") + @NotBlank(message = "内容模版不能为空") + private String contentTemplate ; + @ApiModelProperty("是否启用") + private Boolean enabled; + @ApiModelProperty("链接") + private String link; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/notice/dto/NoticeContentTemplateQueryDTO.java b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeContentTemplateQueryDTO.java new file mode 100644 index 0000000..880301a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeContentTemplateQueryDTO.java @@ -0,0 +1,40 @@ +package com.newyetai.usercenter.notice.dto; + +import java.io.Serializable; + +import com.newyetai.common.dto.PageQueryDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2020-12-17 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "通知消息体模版查询条件") +public class NoticeContentTemplateQueryDTO extends PageQueryDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + @ApiModelProperty("通知模版id") + private Long templateId ; + @ApiModelProperty("消息通道类型:1站内信,2短信,3钉钉,4企业微信,5邮件 等(见notice_channel_type)") + private Integer channelType ; + @ApiModelProperty("标题(模糊匹配)") + private String titleLike; + @ApiModelProperty("是否启用") + private Boolean enabled; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/notice/dto/NoticeReceiverSettingDTO.java b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeReceiverSettingDTO.java new file mode 100644 index 0000000..3e0149c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeReceiverSettingDTO.java @@ -0,0 +1,43 @@ +package com.newyetai.usercenter.notice.dto; + +import java.io.Serializable; + +import com.newyetai.common.dto.BaseDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2020-12-17 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@ApiModel(description = "通知接收人设置") +public class NoticeReceiverSettingDTO extends BaseDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("通知模版id") + private Long templateId ; + @ApiModelProperty("机构id") + private Long orgId ; + @ApiModelProperty("接收人关联类型:1用户id,2角色,3标准角色(见notice_receiver_type)") + private Integer receiverUnionType ; + @ApiModelProperty("接收人关联id:用户id,角色id,标准角色id") + private Long receiverUnionId ; + @ApiModelProperty("接受人名称") + private String receiverName; + @ApiModelProperty("是否启用") + private Boolean enabled; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/notice/dto/NoticeReceiverSettingOperateDTO.java b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeReceiverSettingOperateDTO.java new file mode 100644 index 0000000..bc111be --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeReceiverSettingOperateDTO.java @@ -0,0 +1,42 @@ +package com.newyetai.usercenter.notice.dto; + +import java.io.Serializable; +import java.util.Set; + +import javax.validation.constraints.NotNull; + +import com.newyetai.common.dto.BaseOperateDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2020-12-20 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "通知接收人设置") +public class NoticeReceiverSettingOperateDTO extends BaseOperateDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("通知模版id") + @NotNull(message = "通知模版id不能为空") + private Long templateId ; + @ApiModelProperty("接收人关联类型:1用户id,2角色,3标准角色(见notice_receiver_type)") + @NotNull(message = "接收人关联类型不能为空") + private Integer receiverUnionType ; + @ApiModelProperty("接收人关联id:用户id,角色id,标准角色id") + @NotNull(message = "接收人关联id不能为空") + private Set receiverUnionIds ; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/notice/dto/NoticeReceiverSettingQueryDTO.java b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeReceiverSettingQueryDTO.java new file mode 100644 index 0000000..2491b59 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeReceiverSettingQueryDTO.java @@ -0,0 +1,47 @@ +package com.newyetai.usercenter.notice.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotNull; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import io.swagger.annotations.ApiModel; + +import com.newyetai.common.dto.PageQueryDTO; + +/** + * PageQueryDTO 范型 NoticeReceiverSettingDTO或其子类 + * + * @author sr on 2020-12-17 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "通知接收人设置查询条件") +public class NoticeReceiverSettingQueryDTO extends PageQueryDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + @ApiModelProperty("通知模版id") + @NotNull(message = "通知模版id不能为空") + private Long templateId ; + @ApiModelProperty("机构id") + private Long orgId ; + @ApiModelProperty("接收人关联类型:1用户id,2角色,3标准角色(见notice_receiver_type)") + private Integer receiverUnionType ; + + public Long getOrgId() { + return orgId == null ? getOperateOrgId() : orgId; + } + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/notice/dto/NoticeReceiverSettingRemoveDTO.java b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeReceiverSettingRemoveDTO.java new file mode 100644 index 0000000..741a417 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeReceiverSettingRemoveDTO.java @@ -0,0 +1,50 @@ +package com.newyetai.usercenter.notice.dto; + +import java.io.Serializable; +import java.util.Set; + +import javax.validation.constraints.NotNull; + +import com.newyetai.common.dto.BaseOperateDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2020-12-20 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "删除通知接收人") +public class NoticeReceiverSettingRemoveDTO extends BaseOperateDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = -9143022441853162885L; + + @ApiModelProperty("通知模版id") + @NotNull(message = "通知模版id不能为空") + private Long templateId ; + @ApiModelProperty("接收人关联类型:1用户id,2角色,3标准角色(见notice_receiver_type)") + @NotNull(message = "接收人关联类型不能为空") + private Integer receiverUnionType ; + @ApiModelProperty("接收人关联id:用户id,角色id,标准角色id") + private Set receiverUnionIds ; + + @Builder + public NoticeReceiverSettingRemoveDTO(Long operateOrgId, Long operateUserId, + @NotNull(message = "通知模版id不能为空") Long templateId, + @NotNull(message = "接收人关联类型不能为空") Integer receiverUnionType, Set receiverUnionIds) { + super(operateOrgId, operateUserId); + this.templateId = templateId; + this.receiverUnionType = receiverUnionType; + this.receiverUnionIds = receiverUnionIds; + } + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/dto/NoticeReceiverSettingRoleDTO.java b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeReceiverSettingRoleDTO.java new file mode 100644 index 0000000..5a03daa --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeReceiverSettingRoleDTO.java @@ -0,0 +1,30 @@ +package com.newyetai.usercenter.notice.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2021-01-07 + */ +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel(description = "通知接收人设置--用户") +public class NoticeReceiverSettingRoleDTO extends NoticeReceiverSettingDTO{ + + /** **/ + private static final long serialVersionUID = 8752617190208418705L; + + @ApiModelProperty("角色名称") + private String roleName; + @ApiModelProperty("是否启用") + private Boolean enabled; + @ApiModelProperty("标准角色") + private Integer standardType; + @ApiModelProperty("所属平台") + private Integer platformCode; + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/dto/NoticeReceiverSettingUserDTO.java b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeReceiverSettingUserDTO.java new file mode 100644 index 0000000..d86886d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeReceiverSettingUserDTO.java @@ -0,0 +1,28 @@ +package com.newyetai.usercenter.notice.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2021-01-07 + */ +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel(description = "通知接收人设置--用户") +public class NoticeReceiverSettingUserDTO extends NoticeReceiverSettingDTO{ + + /** **/ + private static final long serialVersionUID = 8752617190208418705L; + + @ApiModelProperty("账户名") + private String username; + @ApiModelProperty("中文名") + private String chineseName; + @ApiModelProperty("是否启用") + private Boolean enabled; + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/dto/NoticeSendRecordDTO.java b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeSendRecordDTO.java new file mode 100644 index 0000000..8b02b43 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeSendRecordDTO.java @@ -0,0 +1,76 @@ +package com.newyetai.usercenter.notice.dto; + +import java.io.Serializable; +import java.util.Collections; +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.common.util.JsonUtils; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2020-12-17 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@ApiModel(description = "通知发送记录(内容模版级)") +public class NoticeSendRecordDTO extends BaseDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("通知模版id") + private Long templateId ; + @ApiModelProperty("发送方机构id") + private Long senderOrgId ; + @ApiModelProperty("接收方机构id") + private Long receiverOrgId ; + @ApiModelProperty("消息体模版id") + private Long contentTemplateId ; + @ApiModelProperty("消息体参数") + private String contentParamData ; + @ApiModelProperty("消息体") + private String content ; + @ApiModelProperty("是否指定接收方(非预先设定)") + private Boolean appointed ; + + @ApiModelProperty("状态:1待处理,2已处理(见notice_send_status)") + private Integer status ; + @ApiModelProperty("消息通道类型:1站内信,2短信,3钉钉,4企业微信,5邮件 等(见notice_channel_type)") + private Integer channelType ; + @ApiModelProperty("标题") + private String title; + @ApiModelProperty("内容模版") + private String contentTemplate ; + @ApiModelProperty("链接") + private String link; + + @JsonIgnore + private Map contentParamDataMap; + + public Map getContentParamDataMap(){ + if (contentParamDataMap == null) { + if (StringUtils.isNotBlank(contentParamData)) { + contentParamDataMap = JsonUtils.toObject(this.getContentParamData(), Map.class); + } else { + contentParamDataMap = Collections.emptyMap(); + } + } + return contentParamDataMap; + } + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/notice/dto/NoticeSendRecordDetailDTO.java b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeSendRecordDetailDTO.java new file mode 100644 index 0000000..cb1ae16 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeSendRecordDetailDTO.java @@ -0,0 +1,48 @@ +package com.newyetai.usercenter.notice.dto; + +import java.io.Serializable; + +import com.newyetai.common.dto.BaseDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2020-12-17 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@ApiModel(description = "通知发送记录明细(接收人)") +public class NoticeSendRecordDetailDTO extends BaseDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("发送记录id") + private Long recordId ; + @ApiModelProperty("接收人id") + private Long userId ; + @ApiModelProperty("接收方帐号") + private String receiverAccountNo ; + @ApiModelProperty("接收状态:1待发送,2已发送,3发送失败,4接收已读(见notice_receiver_status)") + private Integer receiverStatus ; + + @ApiModelProperty("通知模版code") + private String templateCode; + @ApiModelProperty("标题") + private String title; + @ApiModelProperty("链接") + private String link; + @ApiModelProperty("消息体") + private String content ; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/notice/dto/NoticeSendRecordDetailOperateDTO.java b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeSendRecordDetailOperateDTO.java new file mode 100644 index 0000000..80a58cb --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeSendRecordDetailOperateDTO.java @@ -0,0 +1,35 @@ +package com.newyetai.usercenter.notice.dto; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2020-12-20 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "通知发送记录明细(接收人)") +public class NoticeSendRecordDetailOperateDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("发送记录id") + private Long recordId ; + @ApiModelProperty("接收人id") + private Long userId ; + @ApiModelProperty("接收方帐号") + private String receiverAccountNo ; + @ApiModelProperty("接收状态:1待发送,2已发送,3发送失败,4接收已读(见notice_receiver_status)") + private Integer receiverStatus ; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/notice/dto/NoticeSendRecordDetailQueryDTO.java b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeSendRecordDetailQueryDTO.java new file mode 100644 index 0000000..63306cf --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeSendRecordDetailQueryDTO.java @@ -0,0 +1,63 @@ +package com.newyetai.usercenter.notice.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.newyetai.common.dto.PageQueryDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.Date; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * @author sr on 2020-12-17 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "通知发送记录明细(接收人)查询条件") +public class NoticeSendRecordDetailQueryDTO extends PageQueryDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + @ApiModelProperty("发送记录id") + private Long recordId ; + @ApiModelProperty("通知模版id") + private Long templateId ; + // 或模版code + @ApiModelProperty("通知模版code") + private String templateCode; + @ApiModelProperty("消息通道类型:1站内信,2短信,3钉钉,4企业微信,5邮件(见notice_channel_type)") + private Integer channelType ; + @JsonIgnore + @ApiModelProperty("接收人id") + private Long userId ; + @ApiModelProperty("接收状态:1待发送,2已发送,3发送失败,4接收已读(见notice_receiver_status)") + private Integer receiverStatus ; + @ApiModelProperty("消息通知时间起") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat( + shape = JsonFormat.Shape.STRING, + pattern = "yyyy-MM-dd HH:mm:ss", + timezone = "GMT+8" + ) + private Date createTimeStart ; + @ApiModelProperty("消息通知时间止") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat( + shape = JsonFormat.Shape.STRING, + pattern = "yyyy-MM-dd HH:mm:ss", + timezone = "GMT+8" + ) + private Date createTimeEnd ; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/notice/dto/NoticeSendRecordDetailReqDTO.java b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeSendRecordDetailReqDTO.java new file mode 100644 index 0000000..d03aba0 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeSendRecordDetailReqDTO.java @@ -0,0 +1,43 @@ +package com.newyetai.usercenter.notice.dto; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.newyetai.common.util.UserContextHolder; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.Objects; + +/** + * @author sr on 2020-12-17 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "通知发送记录明细(接收人)查询条件") +public class NoticeSendRecordDetailReqDTO implements Serializable{ + + private static final long serialVersionUID = -3715540940245404664L; + /** **/ + + @ApiModelProperty("id") + @NotNull(message = "消息ID不能为空") + private Long id; + + @JsonIgnore + @ApiModelProperty("接收人id") + private Long userId ; + + public Long getUserId() { + if (Objects.isNull(userId)){ + userId = UserContextHolder.getExistLoginUserId(); + } + return userId; + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/notice/dto/NoticeSendRecordModifyDTO.java b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeSendRecordModifyDTO.java new file mode 100644 index 0000000..3093944 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeSendRecordModifyDTO.java @@ -0,0 +1,34 @@ +package com.newyetai.usercenter.notice.dto; + +import com.newyetai.common.dto.BaseOperateDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2021-02-08 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "通知发送记录-修改") +public class NoticeSendRecordModifyDTO extends BaseOperateDTO{ + + /** **/ + private static final long serialVersionUID = 1035598395983126645L; + + @ApiModelProperty("id") + private Long id; + @ApiModelProperty("旧状态") + public Integer oldStatus; + @ApiModelProperty("新状态") + public Integer newStatus; + @ApiModelProperty("消息体") + private String content ; + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/dto/NoticeSendRecordOperateDTO.java b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeSendRecordOperateDTO.java new file mode 100644 index 0000000..b8ccf03 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeSendRecordOperateDTO.java @@ -0,0 +1,62 @@ +package com.newyetai.usercenter.notice.dto; + +import java.io.Serializable; +import java.util.Map; +import java.util.Set; + +import com.google.common.collect.Maps; +import com.newyetai.common.dto.BaseOperateDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Builder.Default; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2020-12-20 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "通知发送记录(内容模版级)") +public class NoticeSendRecordOperateDTO extends BaseOperateDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("通知模版id") + private Long templateId ; + // 或模版code + @ApiModelProperty("通知模版code") + private String templateCode; + @ApiModelProperty("消息体模版id") + private Long contentTemplateId ; + // 或消息体通道类型 + @ApiModelProperty("消息通道类型:1站内信,2短信,3钉钉,4企业微信,5邮件(见notice_channel_type)") + private Integer channelType ; + @ApiModelProperty("接收方机构id,不传平台模版取1,非平台模版取当前上下文机构id") + private Long receiverOrgId ; + @ApiModelProperty("消息体参数") + @Default + private Map contentParamDataMap = Maps.newHashMap(); + @ApiModelProperty("指定接收人") + private Set receiverUserIds; + + /** 定制,通道类型不能为空 **/ + @ApiModelProperty("定制模版内容") + private Boolean customContent; + @ApiModelProperty("标题") + private String title; + @ApiModelProperty("内容模版") + private String contentTemplate ; + @ApiModelProperty("链接") + private String link; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/notice/dto/NoticeSendRecordQueryDTO.java b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeSendRecordQueryDTO.java new file mode 100644 index 0000000..d3eee68 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeSendRecordQueryDTO.java @@ -0,0 +1,44 @@ +package com.newyetai.usercenter.notice.dto; + +import java.io.Serializable; + +import com.newyetai.common.dto.PageQueryDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2020-12-17 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "通知发送记录(内容模版级)查询条件") +public class NoticeSendRecordQueryDTO extends PageQueryDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + @ApiModelProperty("通知模版id") + private Long templateId ; + @ApiModelProperty("通知模版code") + private String templateCode; + @ApiModelProperty("发送方机构id") + private Long senderOrgId ; + @ApiModelProperty("消息通道类型:1站内信,2短信,3钉钉,4企业微信,5邮件(见notice_channel_type)") + private Integer channelType ; + @ApiModelProperty("接收人id") + private Long userId ; + @ApiModelProperty("状态:1待处理,2已处理(见notice_send_status)") + private Integer status ; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/notice/dto/NoticeTemplateDTO.java b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeTemplateDTO.java new file mode 100644 index 0000000..25181d6 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeTemplateDTO.java @@ -0,0 +1,42 @@ +package com.newyetai.usercenter.notice.dto; + +import java.io.Serializable; + +import com.newyetai.common.dto.BaseDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2020-12-17 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@ApiModel(description = "通知") +public class NoticeTemplateDTO extends BaseDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("通知模版code") + private String templateCode; + @ApiModelProperty("通知名称") + private String templateName ; + @ApiModelProperty("模块分类:1业务,2监控/预警(见notice_module_type)") + private Integer moduleType; + @ApiModelProperty("业务分类:") + private Integer bizType; + @ApiModelProperty("级别:1平台,2机构(见notice_level)") + private Integer level; + @ApiModelProperty("是否启用") + private Boolean enabled; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/notice/dto/NoticeTemplateOperateDTO.java b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeTemplateOperateDTO.java new file mode 100644 index 0000000..80b78b6 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeTemplateOperateDTO.java @@ -0,0 +1,53 @@ +package com.newyetai.usercenter.notice.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import com.newyetai.common.dto.BaseOperateDTO; +import com.newyetai.common.validation.Update; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2020-12-17 + */ +@NoArgsConstructor +@AllArgsConstructor +@Builder +@Data +@EqualsAndHashCode(callSuper = true) +@ApiModel(description = "通知") +public class NoticeTemplateOperateDTO extends BaseOperateDTO implements Serializable { + + /** **/ + private static final long serialVersionUID = 6246259217863925980L; + + @ApiModelProperty("id") + @NotNull(message = "id不能为空", groups = {Update.class}) + private Long id; + @ApiModelProperty("通知模版code") + @NotBlank(message = "模版标识不能为空") + private String templateCode; + @ApiModelProperty("通知名称") + @NotBlank(message = "模版名称不能为空") + private String templateName ; + @ApiModelProperty("模块分类:1业务,2监控/预警(见notice_module_type)") + @NotNull(message = "模块分类不能为空") + private Integer moduleType; + @ApiModelProperty("业务分类:") + private Integer bizType; + @ApiModelProperty("级别:1平台,2机构(见notice_level)") + @NotNull(message = "级别不能为空") + private Integer level; + @ApiModelProperty("是否启用") + private Boolean enabled; + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/dto/NoticeTemplateQueryDTO.java b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeTemplateQueryDTO.java new file mode 100644 index 0000000..d3758f4 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/dto/NoticeTemplateQueryDTO.java @@ -0,0 +1,41 @@ +package com.newyetai.usercenter.notice.dto; + +import com.newyetai.common.annotation.trimAndUpper.TrimAndUpper; +import com.newyetai.common.dto.PageQueryDTO; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import java.io.Serializable; + +/** + * @author sr on 2020-12-17 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class NoticeTemplateQueryDTO extends PageQueryDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + @ApiModelProperty("通知模版code") + private String templateCode; + @ApiModelProperty("通知模版code(模糊匹配)") + @TrimAndUpper(TrimAndUpper.ExecuteType.TRIM) + private String templateCodeLike; + @ApiModelProperty("通知名称(模糊匹配)") + @TrimAndUpper(TrimAndUpper.ExecuteType.TRIM) + private String templateNameLike ; + @ApiModelProperty("模块分类:1业务,2监控/预警(见notice_module_type)") + private Integer moduleType; + @ApiModelProperty("级别:1平台,2机构(见notice_level)") + private Integer level; + @ApiModelProperty("是否启用") + private Boolean enabled; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/notice/dto/RecordDetailUpdateStatusDTO.java b/src/main/java/com/newyetai/usercenter/notice/dto/RecordDetailUpdateStatusDTO.java new file mode 100644 index 0000000..598ae1a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/dto/RecordDetailUpdateStatusDTO.java @@ -0,0 +1,48 @@ +package com.newyetai.usercenter.notice.dto; + +import java.io.Serializable; +import java.util.Set; + +import javax.validation.constraints.NotEmpty; + +import com.newyetai.common.dto.BaseOperateDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2020-12-28 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel("通知发送记录更新状态") +public class RecordDetailUpdateStatusDTO extends BaseOperateDTO implements Serializable { + + /** **/ + private static final long serialVersionUID = 2700111335512586751L; + + @ApiModelProperty("旧状态") + @NotEmpty(message = "旧状态不能为空") + private Integer oldStatus; + @ApiModelProperty("新状态") + @NotEmpty(message = "新状态不能为空") + private Integer newStatus; + @ApiModelProperty("通知发送记录明细id") + private Long recordDetailId; + @ApiModelProperty("通知发送记录明细id集合") + private Set recordDetailIds; + @ApiModelProperty("通知发送记录id") + private Long recordId; + @ApiModelProperty("消息通道类型") + @NotEmpty(message = "消息通道类型不能为空") + private Integer channelType; + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/entity/NoticeContentTemplate.java b/src/main/java/com/newyetai/usercenter/notice/entity/NoticeContentTemplate.java new file mode 100644 index 0000000..035715f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/entity/NoticeContentTemplate.java @@ -0,0 +1,56 @@ +package com.newyetai.usercenter.notice.entity; + +import java.io.Serializable; +import java.util.Date; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; +import com.newyetai.usercenter.notice.constant.NoticeChannelTypeEnum; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * 通知消息体模版 + * + * @author sr on 2020-12-17 + */ +@TableName("notice_content_template") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Data +public class NoticeContentTemplate extends BaseEntity implements Serializable { + + /** **/ + private static final long serialVersionUID = 1L; + /** 通知模版id */ + private Long templateId ; + /** {@link NoticeChannelTypeEnum} 消息通道类型:1站内信,2短信,3钉钉,4企业微信,5邮件 等(见notice_channel_type) */ + private Integer channelType ; + /** 标题 **/ + private String title; + /** 内容模版 */ + private String contentTemplate ; + /** 是否启用 **/ + private Boolean enabled; + /** 链接 **/ + private String link; + + @Builder + public NoticeContentTemplate(Long id, Boolean deleted, Long createBy, Date createTime, + Long updateBy, Date updateTime, Long proxyBy, Long templateId, Integer channelType, + String title, String contentTemplate, Boolean enabled, String link) { + super(id, deleted, createBy, createTime, updateBy, updateTime, proxyBy); + this.templateId = templateId; + this.channelType = channelType; + this.title = title; + this.contentTemplate = contentTemplate; + this.enabled = enabled; + this.link = link; + } + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/entity/NoticeReceiverSetting.java b/src/main/java/com/newyetai/usercenter/notice/entity/NoticeReceiverSetting.java new file mode 100644 index 0000000..d9bf7f2 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/entity/NoticeReceiverSetting.java @@ -0,0 +1,50 @@ +package com.newyetai.usercenter.notice.entity; + +import java.io.Serializable; +import java.util.Date; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * 通知接收人设置 + * + * @author sr on 2020-12-17 + */ +@TableName("notice_receiver_setting") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Data +public class NoticeReceiverSetting extends BaseEntity implements Serializable { + + /** **/ + private static final long serialVersionUID = 1L; + + /** 通知模版id */ + private Long templateId ; + /** 机构id */ + private Long orgId ; + /** 接收人关联类型:1用户id,2角色,3标准角色(见notice_receiver_type) */ + private Integer receiverUnionType ; + /** 接收人关联id:用户id,角色id,标准角色id */ + private Long receiverUnionId ; + + @Builder + public NoticeReceiverSetting(Long id, Boolean deleted, Long createBy, Date createTime, + Long updateBy, Date updateTime, Long proxyBy, Long templateId, Long orgId, + Integer receiverUnionType, Long receiverUnionId) { + super(id, deleted, createBy, createTime, updateBy, updateTime, proxyBy); + this.templateId = templateId; + this.orgId = orgId; + this.receiverUnionType = receiverUnionType; + this.receiverUnionId = receiverUnionId; + } + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/entity/NoticeSendRecord.java b/src/main/java/com/newyetai/usercenter/notice/entity/NoticeSendRecord.java new file mode 100644 index 0000000..194d711 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/entity/NoticeSendRecord.java @@ -0,0 +1,56 @@ +package com.newyetai.usercenter.notice.entity; + +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; +import com.newyetai.usercenter.notice.constant.NoticeChannelTypeEnum; +import com.newyetai.usercenter.notice.constant.NoticeSendStatusEnum; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * 通知发送记录(内容模版级) + * + * @author sr on 2020-12-17 + */ +@TableName("notice_send_record") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Data +public class NoticeSendRecord extends BaseEntity implements Serializable { + + /** **/ + private static final long serialVersionUID = 1L; + + /** 通知模版id */ + private Long templateId ; + /** 发送方机构id */ + private Long senderOrgId ; + /** 接收方机构id */ + private Long receiverOrgId ; + /** 消息体模版id */ + private Long contentTemplateId ; + /** 消息体参数 */ + private String contentParamData ; + /** 消息体 */ + private String content ; + /** 是否指定接收方(非预先设定) **/ + private Boolean appointed ; + + /** {@link NoticeSendStatusEnum}状态:1待处理,2已处理(见notice_send_status) */ + private Integer status ; + /** {@link NoticeChannelTypeEnum} 消息通道类型:1站内信,2短信,3钉钉,4企业微信,5邮件 等(见notice_channel_type) */ + private Integer channelType ; + /** 标题 **/ + private String title; + /** 内容模版 */ + private String contentTemplate ; + /** 链接 **/ + private String link; + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/entity/NoticeSendRecordDetail.java b/src/main/java/com/newyetai/usercenter/notice/entity/NoticeSendRecordDetail.java new file mode 100644 index 0000000..780193a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/entity/NoticeSendRecordDetail.java @@ -0,0 +1,51 @@ +package com.newyetai.usercenter.notice.entity; + +import java.io.Serializable; +import java.util.Date; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * 通知发送记录明细(接收人) + * + * @author sr on 2020-12-17 + */ +@TableName("notice_send_record_detail") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Builder +@Data +public class NoticeSendRecordDetail extends BaseEntity implements Serializable { + + /** **/ + private static final long serialVersionUID = 1L; + + /** 发送记录id */ + private Long recordId ; + /** 接收人id */ + private Long userId ; + /** 接收方帐号 */ + private String receiverAccountNo ; + /** 接收状态:1待发送,2已发送,3发送失败,4接收已读(见notice_receiver_status) */ + private Integer receiverStatus ; + + @Builder + public NoticeSendRecordDetail(Long id, Boolean deleted, Long createBy, Date createTime, + Long updateBy, Date updateTime, Long proxyBy, Long recordId, Long userId, + String receiverAccountNo, Integer receiverStatus) { + super(id, deleted, createBy, createTime, updateBy, updateTime, proxyBy); + this.recordId = recordId; + this.userId = userId; + this.receiverAccountNo = receiverAccountNo; + this.receiverStatus = receiverStatus; + } + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/entity/NoticeTemplate.java b/src/main/java/com/newyetai/usercenter/notice/entity/NoticeTemplate.java new file mode 100644 index 0000000..fce62d4 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/entity/NoticeTemplate.java @@ -0,0 +1,57 @@ +package com.newyetai.usercenter.notice.entity; + +import java.io.Serializable; +import java.util.Date; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * 通知模版 + * + * @author sr on 2020-12-17 + */ +@TableName("notice_template") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Data +public class NoticeTemplate extends BaseEntity implements Serializable { + + /** **/ + private static final long serialVersionUID = 1L; + + /** 通知模版code */ + private String templateCode ; + /** 通知名称 **/ + private String templateName ; + /** 模块分类:1业务,2监控/预警(见notice_module_type) */ + private Integer moduleType ; + /** 业务分类: */ + private Integer bizType ; + /** 级别:1平台,2机构(见notice_level) */ + private Integer level ; + /** 是否启用 **/ + private Boolean enabled; + + @Builder + public NoticeTemplate(Long id, Boolean deleted, Long createBy, Date createTime, Long updateBy, + Date updateTime, Long proxyBy, String templateCode, String templateName, Integer moduleType, Integer bizType, + Integer level, Boolean enabled) { + super(id, deleted, createBy, createTime, updateBy, updateTime, proxyBy); + this.templateCode = templateCode; + this.templateName = templateName; + this.moduleType = moduleType; + this.bizType = bizType; + this.level = level; + this.enabled = enabled; + } + + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/mapper/NoticeContentTemplateMapper.xml b/src/main/java/com/newyetai/usercenter/notice/mapper/NoticeContentTemplateMapper.xml new file mode 100644 index 0000000..fb5dbdc --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/mapper/NoticeContentTemplateMapper.xml @@ -0,0 +1,29 @@ + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/notice/mapper/NoticeReceiverSettingMapper.xml b/src/main/java/com/newyetai/usercenter/notice/mapper/NoticeReceiverSettingMapper.xml new file mode 100644 index 0000000..9ad9397 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/mapper/NoticeReceiverSettingMapper.xml @@ -0,0 +1,207 @@ + + + + + + + update + notice_receiver_setting + set + deleted = 1, + update_time = now(), + update_by = #{param.operateUserId} + where + template_id = #{param.templateId} + and receiver_union_type = #{param.receiverUnionType} + and org_id = #{param.operateOrgId} + and deleted = 0 + + and receiver_union_id in + + #{receiverUnionId} + + + + + + + + insert into notice_receiver_setting + ( + template_id, + org_id, + receiver_union_type, + receiver_union_id, + deleted, + create_by, + create_time + ) values + + (#{param.templateId}, + #{param.operateOrgId}, + #{param.receiverUnionType}, + #{receiverUnionId}, + 0, + #{param.operateUserId}, + now()) + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/notice/mapper/NoticeSendRecordDetailMapper.xml b/src/main/java/com/newyetai/usercenter/notice/mapper/NoticeSendRecordDetailMapper.xml new file mode 100644 index 0000000..339a3ee --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/mapper/NoticeSendRecordDetailMapper.xml @@ -0,0 +1,171 @@ + + + + + + + + + insert into notice_send_record_detail + ( + record_id, + user_id, + receiver_account_no, + receiver_status, + deleted, + create_by, + create_time + ) + values + + (#{item.recordId}, + #{item.userId}, + #{item.receiverAccountNo}, + #{item.receiverStatus}, + 0, + #{operateUserId}, + now()) + + + + + update notice_send_record_detail rd + set + rd.receiver_status = #{param.newStatus}, + rd.update_by = #{param.operateUserId}, + rd.update_time = now() + where + rd.receiver_status = #{param.oldStatus} + and rd.deleted = 0 + + and exists ( + select * + from notice_send_record r + where r.id = rd.record_id + and r.deleted = 0 + and r.channel_type = #{param.channelType} + ) + + + and rd.user_id = #{param.operateUserId} + + + and rd.id = #{param.recordDetailId} + + + and rd.record_id = #{param.param.recordId} + + + and rd.id in + + #{detailId} + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/notice/mapper/NoticeSendRecordMapper.xml b/src/main/java/com/newyetai/usercenter/notice/mapper/NoticeSendRecordMapper.xml new file mode 100644 index 0000000..b5fabb8 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/mapper/NoticeSendRecordMapper.xml @@ -0,0 +1,58 @@ + + + + + + + update + notice_send_record + + status = #{param.newStatus}, + update_by = #{param.operateUserId}, + update_time = now(), + + content = #{param.content}, + + + where + id = #{param.id} + and status = #{param.oldStatus} + and deleted = 0 + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/notice/mapper/NoticeTemplateMapper.xml b/src/main/java/com/newyetai/usercenter/notice/mapper/NoticeTemplateMapper.xml new file mode 100644 index 0000000..3877a5c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/mapper/NoticeTemplateMapper.xml @@ -0,0 +1,37 @@ + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/notice/mapstruct/NoticeContentTemplateMapMapper.java b/src/main/java/com/newyetai/usercenter/notice/mapstruct/NoticeContentTemplateMapMapper.java new file mode 100644 index 0000000..190342b --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/mapstruct/NoticeContentTemplateMapMapper.java @@ -0,0 +1,37 @@ +package com.newyetai.usercenter.notice.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.newyetai.usercenter.notice.dto.NoticeContentTemplateDTO; +import com.newyetai.usercenter.notice.entity.NoticeContentTemplate; +import com.newyetai.usercenter.notice.dto.NoticeContentTemplateOperateDTO; + +/** + * @author sr on 2020-12-20 + */ +@Mapper +public interface NoticeContentTemplateMapMapper { + + NoticeContentTemplateMapMapper INSTANCE = + Mappers.getMapper(NoticeContentTemplateMapMapper.class); + + /** + * dto to entity + * + * @param noticeContentTemplateDto + * @return + * @author sr on 2020-12-20 + */ + NoticeContentTemplate toEntity( + NoticeContentTemplateDTO noticeContentTemplateDto); + + + /** + * @param noticeContentTemplateOperateDTO + * @return + * @author sr on 2020-12-20 + */ + NoticeContentTemplate toEntity(NoticeContentTemplateOperateDTO noticeContentTemplateOperateDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/mapstruct/NoticeReceiverSettingMapMapper.java b/src/main/java/com/newyetai/usercenter/notice/mapstruct/NoticeReceiverSettingMapMapper.java new file mode 100644 index 0000000..68a217c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/mapstruct/NoticeReceiverSettingMapMapper.java @@ -0,0 +1,45 @@ +package com.newyetai.usercenter.notice.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.newyetai.usercenter.notice.dto.NoticeReceiverSettingDTO; +import com.newyetai.usercenter.notice.entity.NoticeReceiverSetting; +import com.newyetai.usercenter.notice.dto.NoticeReceiverSettingOperateDTO; +import com.newyetai.usercenter.notice.dto.NoticeReceiverSettingRemoveDTO; + +/** + * @author sr on 2020-12-20 + */ +@Mapper +public interface NoticeReceiverSettingMapMapper { + + NoticeReceiverSettingMapMapper INSTANCE = + Mappers.getMapper(NoticeReceiverSettingMapMapper.class); + + /** + * dto to entity + * + * @param noticeReceiverSettingDto + * @return + * @author sr on 2020-12-20 + */ + NoticeReceiverSetting toEntity( + NoticeReceiverSettingDTO noticeReceiverSettingDto); + + + /** + * @param noticeReceiverSettingOperateDTO + * @return + * @author sr on 2020-12-20 + */ + NoticeReceiverSetting toEntity(NoticeReceiverSettingOperateDTO noticeReceiverSettingOperateDTO); + + /** + * @param noticeReceiverSettingOperateDTO + * @return + * @author sr on 2020-12-21 + */ + NoticeReceiverSettingRemoveDTO toRemoveDTO(NoticeReceiverSettingOperateDTO noticeReceiverSettingOperateDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/mapstruct/NoticeSendRecordDetailMapMapper.java b/src/main/java/com/newyetai/usercenter/notice/mapstruct/NoticeSendRecordDetailMapMapper.java new file mode 100644 index 0000000..e9cf0f4 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/mapstruct/NoticeSendRecordDetailMapMapper.java @@ -0,0 +1,29 @@ +package com.newyetai.usercenter.notice.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.newyetai.usercenter.notice.dto.NoticeSendRecordDetailDTO; +import com.newyetai.usercenter.notice.entity.NoticeSendRecordDetail; + +/** + * @author sr on 2020-12-20 + */ +@Mapper +public interface NoticeSendRecordDetailMapMapper { + + NoticeSendRecordDetailMapMapper INSTANCE = + Mappers.getMapper(NoticeSendRecordDetailMapMapper.class); + + /** + * dto to entity + * + * @param noticeSendRecordDetailDto + * @return + * @author sr on 2020-12-20 + */ + NoticeSendRecordDetail toEntity( + NoticeSendRecordDetailDTO noticeSendRecordDetailDto); + + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/mapstruct/NoticeSendRecordMapMapper.java b/src/main/java/com/newyetai/usercenter/notice/mapstruct/NoticeSendRecordMapMapper.java new file mode 100644 index 0000000..34f209a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/mapstruct/NoticeSendRecordMapMapper.java @@ -0,0 +1,36 @@ +package com.newyetai.usercenter.notice.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.newyetai.usercenter.notice.dto.NoticeContentTemplateDTO; +import com.newyetai.usercenter.notice.dto.NoticeSendRecordDTO; +import com.newyetai.usercenter.notice.dto.NoticeSendRecordOperateDTO; +import com.newyetai.usercenter.notice.entity.NoticeSendRecord; + +/** + * @author sr on 2020-12-20 + */ +@Mapper +public interface NoticeSendRecordMapMapper { + + NoticeSendRecordMapMapper INSTANCE = + Mappers.getMapper(NoticeSendRecordMapMapper.class); + + /** + * dto to entity + * + * @param noticeSendRecordDto + * @return + * @author sr on 2020-12-20 + */ + NoticeSendRecord toEntity( + NoticeSendRecordDTO noticeSendRecordDto); + + + NoticeSendRecordOperateDTO clone(NoticeSendRecordOperateDTO dto); + + NoticeContentTemplateDTO toContentTemplate(NoticeSendRecordOperateDTO dto); + + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/mapstruct/NoticeTemplateMapMapper.java b/src/main/java/com/newyetai/usercenter/notice/mapstruct/NoticeTemplateMapMapper.java new file mode 100644 index 0000000..2c969c5 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/mapstruct/NoticeTemplateMapMapper.java @@ -0,0 +1,35 @@ +package com.newyetai.usercenter.notice.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.newyetai.usercenter.notice.dto.NoticeTemplateDTO; +import com.newyetai.usercenter.notice.dto.NoticeTemplateOperateDTO; +import com.newyetai.usercenter.notice.entity.NoticeTemplate; + +/** + * @author sr on 2020-12-17 + */ +@Mapper +public interface NoticeTemplateMapMapper { + + NoticeTemplateMapMapper INSTANCE = + Mappers.getMapper(NoticeTemplateMapMapper.class); + + /** + * dto to entity + * + * @param noticeTemplateDto + * @return + * @author sr on 2020-12-17 + */ + NoticeTemplate toEntity(NoticeTemplateDTO noticeTemplateDto); + + /** + * @param noticeTemplateOperateDTO + * @return + * @author sr on 2020-12-17 + */ + NoticeTemplate toEntity(NoticeTemplateOperateDTO noticeTemplateOperateDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/service/INoticeChannelProvider.java b/src/main/java/com/newyetai/usercenter/notice/service/INoticeChannelProvider.java new file mode 100644 index 0000000..d99717a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/service/INoticeChannelProvider.java @@ -0,0 +1,75 @@ +package com.newyetai.usercenter.notice.service; + +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.freemarker.util.FreeMarkerTemplateUtils; +import com.newyetai.mq.consumer.handler.ITopicMqHandler; +import com.newyetai.mq.dto.TopicMqMessage; +import com.newyetai.mq.util.MqSendUtils; +import com.newyetai.security.util.MockUtils; +import com.newyetai.usercenter.notice.constant.NoticeChannelTypeEnum; +import com.newyetai.usercenter.notice.dto.NoticeSendRecordDTO; +import com.newyetai.usercenter.notice.util.NoticeSendRecordUtils; +import com.newyetai.usercenter.userprod.constant.UcMqSelfConstants; + +public interface INoticeChannelProvider extends ITopicMqHandler{ + + Logger LOGGER = LoggerFactory.getLogger(INoticeChannelProvider.class); + + /** + * + * @return {@link NoticeChannelTypeEnum} + * @author sr on 2021-01-04 + */ + Integer getChannelType(); + + default String format(String contentTemplate, Map contentParamDataMap) { + return FreeMarkerTemplateUtils.formatString(contentTemplate, contentParamDataMap); + } + + /** + * 发送(保存发送记录+明细+处理真实通道消息发送) + * + * @param noticeSendRecordDTO + * @author sr on 2021-02-19 + */ + void send(NoticeSendRecordDTO noticeSendRecordDTO); + + /** + * 异步,发送mq + * + * @param noticeSendRecordDTO + * @return + * @author sr on 2021-02-19 + */ + default AlitaResult asyncDeal(NoticeSendRecordDTO noticeSendRecordDTO) { + return MqSendUtils.send( + getRoutingKey(), + noticeSendRecordDTO); + } + + /** + * mq routingKey: {@link UcMqSelfConstants}.ROUTING_KEY_NOTICE_CHANNEL_DEAL_PREFIX_channelType + */ + default String getRoutingKey() { + return NoticeSendRecordUtils.getNoticeChannelDealKey(getChannelType()); + } + + /** + * 接收异步mq消息,处理send + */ + default void onMessage(TopicMqMessage message) { + try { + // mock用户 + MockUtils.mockPlatUser(); + send(message.getData()); + } catch (Exception e) { + LOGGER.info("notice channel deal error:{}", e); + } + } + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/service/NoticeContentTemplateService.java b/src/main/java/com/newyetai/usercenter/notice/service/NoticeContentTemplateService.java new file mode 100644 index 0000000..62f8e24 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/service/NoticeContentTemplateService.java @@ -0,0 +1,50 @@ +package com.newyetai.usercenter.notice.service; + +import java.util.List; + +import com.newyetai.usercenter.notice.dto.NoticeContentTemplateQueryDTO; +import com.newyetai.usercenter.notice.dto.NoticeContentTemplateOperateDTO; +import com.newyetai.usercenter.notice.dto.NoticeContentTemplateDTO; + +/** + * 通知消息体模版 + * + * @author sr on 2020-12-20 + */ +public interface NoticeContentTemplateService { + + /** + * 新增 + * + * @param noticeContentTemplateOperateDTO + * @return + * @author sr on 2020-12-20 + */ + Long create(NoticeContentTemplateOperateDTO noticeContentTemplateOperateDTO); + + /** + * 修改 + * + * @param noticeContentTemplateOperateDTO + * @author sr on 2020-12-20 + */ + void modify(NoticeContentTemplateOperateDTO noticeContentTemplateOperateDTO); + + /** + * 删除 + * + * @param id + * @author sr on 2020-12-20 + */ + void remove(Long id); + + /** + * 查询 + * + * @param noticeContentTemplateQueryDTO + * @return + * @author sr on 2020-12-20 + */ + List page(NoticeContentTemplateQueryDTO noticeContentTemplateQueryDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/service/NoticeReceiverSettingService.java b/src/main/java/com/newyetai/usercenter/notice/service/NoticeReceiverSettingService.java new file mode 100644 index 0000000..1d128ac --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/service/NoticeReceiverSettingService.java @@ -0,0 +1,93 @@ +package com.newyetai.usercenter.notice.service; + +import java.util.List; +import java.util.Set; + +import com.newyetai.usercenter.notice.dto.NoticeReceiverSettingDTO; +import com.newyetai.usercenter.notice.dto.NoticeReceiverSettingOperateDTO; +import com.newyetai.usercenter.notice.dto.NoticeReceiverSettingQueryDTO; +import com.newyetai.usercenter.notice.dto.NoticeReceiverSettingRemoveDTO; +import com.newyetai.usercenter.notice.dto.NoticeReceiverSettingRoleDTO; +import com.newyetai.usercenter.notice.dto.NoticeReceiverSettingUserDTO; + +/** + * 通知接收人设置 + * + * @author sr on 2020-12-20 + */ +public interface NoticeReceiverSettingService { + + /** + * 创建(新增) + * + * @param noticeReceiverSettingOperateDTO + * @author sr on 2021-01-07 + */ + void create(NoticeReceiverSettingOperateDTO noticeReceiverSettingOperateDTO); + + /** + * 保存设置(内部判断新增/删除) + * + * @param noticeReceiverSettingOperateDTO + * @return + * @author sr on 2020-12-20 + */ + void save(NoticeReceiverSettingOperateDTO noticeReceiverSettingOperateDTO); + + + /** + * 删除 + * + * @param id + * @author sr on 2020-12-20 + */ + void remove(Long id); + + /** + * 删除 + * + * @param noticeReceiverSettingRemoveDTO + * @author sr on 2020-12-20 + */ + void remove(NoticeReceiverSettingRemoveDTO noticeReceiverSettingRemoveDTO); + + /** + * 查询 + * + * @param noticeReceiverSettingQueryDTO + * @return + * @author sr on 2020-12-20 + */ + List list(NoticeReceiverSettingQueryDTO noticeReceiverSettingQueryDTO); + + /** + * 获取指定模版的所有接收人id + * + * @param templateId + * @param receiverOrgId + * @return + * @author sr on 2021-01-07 + */ + Set getReceiverIds(Long templateId, Long receiverOrgId); + + /** + * 查询接收人配置-人列表 + * + * @param noticeReceiverSettingQueryDTO + * @return + * @author sr on 2021-01-07 + */ + List listUser( + NoticeReceiverSettingQueryDTO noticeReceiverSettingQueryDTO); + + /** + * 查询接收人配置-角色列表 + * + * @param noticeReceiverSettingQueryDTO + * @return + * @author sr on 2021-01-07 + */ + List listRole( + NoticeReceiverSettingQueryDTO noticeReceiverSettingQueryDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/service/NoticeSendRecordDetailService.java b/src/main/java/com/newyetai/usercenter/notice/service/NoticeSendRecordDetailService.java new file mode 100644 index 0000000..6eb2561 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/service/NoticeSendRecordDetailService.java @@ -0,0 +1,45 @@ +package com.newyetai.usercenter.notice.service; + +import com.newyetai.usercenter.notice.dto.NoticeSendRecordDetailDTO; +import com.newyetai.usercenter.notice.dto.NoticeSendRecordDetailQueryDTO; +import com.newyetai.usercenter.notice.dto.NoticeSendRecordDetailReqDTO; + +import java.util.List; + +/** + * 通知发送记录明细(接收人) + * + * @author sr on 2020-12-20 + */ +public interface NoticeSendRecordDetailService { + + /** + * 查询 + * + * @param noticeSendRecordDetailQueryDTO + * @return + * @author sr on 2020-12-20 + */ + List list(NoticeSendRecordDetailQueryDTO noticeSendRecordDetailQueryDTO); + + /** + * 消息明细 + * + * @param reqDTO 通知发送记录详细查询dto + * @return {@link NoticeSendRecordDetailDTO} + */ + NoticeSendRecordDetailDTO detail(NoticeSendRecordDetailReqDTO reqDTO); + + /** + * 消息数量 + * + * @param noticeSendRecordDetailQueryDTO 通知发送记录详细查询dto + * @return {@link Integer} + */ + Integer count(NoticeSendRecordDetailQueryDTO noticeSendRecordDetailQueryDTO); + + void read(Long recordDetailId); + + void readAll(); + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/service/NoticeSendRecordService.java b/src/main/java/com/newyetai/usercenter/notice/service/NoticeSendRecordService.java new file mode 100644 index 0000000..3e99d77 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/service/NoticeSendRecordService.java @@ -0,0 +1,35 @@ +package com.newyetai.usercenter.notice.service; + +import java.util.List; + +import com.newyetai.usercenter.notice.dto.NoticeSendRecordQueryDTO; +import com.newyetai.usercenter.notice.dto.NoticeSendRecordOperateDTO; +import com.newyetai.usercenter.notice.dto.NoticeSendRecordDTO; + +/** + * 通知发送记录(内容模版级) + * + * @author sr on 2020-12-20 + */ +public interface NoticeSendRecordService { + + /** + * 新增 + * + * @param noticeSendRecordOperateDTO + * @return + * @author sr on 2020-12-20 + */ + void create(NoticeSendRecordOperateDTO noticeSendRecordOperateDTO); + + + /** + * 查询 + * + * @param noticeSendRecordQueryDTO + * @return + * @author sr on 2020-12-20 + */ + List page(NoticeSendRecordQueryDTO noticeSendRecordQueryDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/service/NoticeTemplateService.java b/src/main/java/com/newyetai/usercenter/notice/service/NoticeTemplateService.java new file mode 100644 index 0000000..e98e57d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/service/NoticeTemplateService.java @@ -0,0 +1,65 @@ +package com.newyetai.usercenter.notice.service; + +import java.util.List; + +import com.newyetai.usercenter.notice.dto.NoticeTemplateDTO; +import com.newyetai.usercenter.notice.dto.NoticeTemplateOperateDTO; +import com.newyetai.usercenter.notice.dto.NoticeTemplateQueryDTO; + +/** + * 通知模版 + * + * @author sr on 2020-12-17 + */ +public interface NoticeTemplateService { + + /** + * 新增 + * + * @param noticeTemplateOperateDTO + * @return + * @author sr on 2020-12-17 + */ + Long create(NoticeTemplateOperateDTO noticeTemplateOperateDTO); + + /** + * 修改 + * + * @param noticeTemplateOperateDTO + * @author sr on 2020-12-17 + */ + void modify(NoticeTemplateOperateDTO noticeTemplateOperateDTO); + + /** + * 删除 + * + * @param id + * @author sr on 2020-12-17 + */ + void remove(Long id); + + /** + * 查询 + * + * @param noticeTemplateQueryDTO + * @return + * @author sr on 2020-12-17 + */ + List page(NoticeTemplateQueryDTO noticeTemplateQueryDTO); + + /** + * 校验模版 + * + * @param templateId + * @author sr on 2020-12-28 + */ + void checkTemplate(Long templateId); + + /** + * @param id + * @return + * @author sr on 2021-02-01 + */ + NoticeTemplateDTO find(Long id); + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/service/impl/NoticeContentTemplateServiceImpl.java b/src/main/java/com/newyetai/usercenter/notice/service/impl/NoticeContentTemplateServiceImpl.java new file mode 100644 index 0000000..26adfd7 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/service/impl/NoticeContentTemplateServiceImpl.java @@ -0,0 +1,89 @@ +package com.newyetai.usercenter.notice.service.impl; + +import java.util.List; + +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.usercenter.notice.constant.NoticeChannelTypeEnum; +import com.newyetai.usercenter.notice.dao.NoticeContentTemplateMapper; +import com.newyetai.usercenter.notice.dto.NoticeContentTemplateDTO; +import com.newyetai.usercenter.notice.dto.NoticeContentTemplateOperateDTO; +import com.newyetai.usercenter.notice.dto.NoticeContentTemplateQueryDTO; +import com.newyetai.usercenter.notice.entity.NoticeContentTemplate; +import com.newyetai.usercenter.notice.mapstruct.NoticeContentTemplateMapMapper; +import com.newyetai.usercenter.notice.service.NoticeContentTemplateService; +import com.newyetai.usercenter.notice.service.NoticeTemplateService; + +/** + * @author sr on 2020-12-20 + */ +@Service +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class NoticeContentTemplateServiceImpl implements NoticeContentTemplateService { + + private final NoticeContentTemplateMapper noticeContentTemplateMapper; + + private final NoticeTemplateService noticeTemplateService; + + private void checkExist(Long templateId, Integer channelType) { + boolean exists = noticeContentTemplateMapper.existsEntity( + NoticeContentTemplate.builder().templateId(templateId).channelType(channelType).deleted(false).build()); + Assert.isTrue(!exists, "该模版消息通道类型已存在"); + } + + @Override + @Transactional + public Long create(NoticeContentTemplateOperateDTO noticeContentTemplateOperateDTO) { + Assert.isTrue( + NoticeChannelTypeEnum.SITE.getType() + .equals(noticeContentTemplateOperateDTO.getChannelType()), + "暂只支持站内信配置"); + Long templateId = noticeContentTemplateOperateDTO.getTemplateId(); + // 校验模版是否有效 + noticeTemplateService.checkTemplate(templateId); + this.checkExist(templateId, + noticeContentTemplateOperateDTO.getChannelType()); + // 设置初始值 + if (noticeContentTemplateOperateDTO.getEnabled() == null) { + noticeContentTemplateOperateDTO.setEnabled(true); + } + NoticeContentTemplate noticeContentTemplate = + NoticeContentTemplateMapMapper.INSTANCE.toEntity(noticeContentTemplateOperateDTO); + noticeContentTemplateMapper.saveEntity(noticeContentTemplate, + UserContextHolder.getLoginUserId()); + return noticeContentTemplate.getId(); + } + + @Override + @Transactional + public void modify(NoticeContentTemplateOperateDTO noticeContentTemplateOperateDTO) { + noticeContentTemplateMapper.updateEntitySelective( + NoticeContentTemplate.builder().id(noticeContentTemplateOperateDTO.getId()) + .channelType(noticeContentTemplateOperateDTO.getChannelType()) + .title(noticeContentTemplateOperateDTO.getTitle()) + .contentTemplate(noticeContentTemplateOperateDTO.getContentTemplate()) + .enabled(noticeContentTemplateOperateDTO.getEnabled()) + .link(noticeContentTemplateOperateDTO.getLink()) + .build(), + UserContextHolder.getLoginUserId()); + } + + @Override + @Transactional + public void remove(Long id) { + noticeContentTemplateMapper.deleteEntity(NoticeContentTemplate.builder().id(id).build(), + UserContextHolder.getLoginUserId()); + } + + @Override + public List page( + NoticeContentTemplateQueryDTO noticeContentTemplateQueryDTO) { + return noticeContentTemplateMapper.listNoticeContentTemplateDTO(noticeContentTemplateQueryDTO); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/service/impl/NoticeReceiverSettingServiceImpl.java b/src/main/java/com/newyetai/usercenter/notice/service/impl/NoticeReceiverSettingServiceImpl.java new file mode 100644 index 0000000..50cc348 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/service/impl/NoticeReceiverSettingServiceImpl.java @@ -0,0 +1,162 @@ +package com.newyetai.usercenter.notice.service.impl; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.google.common.collect.Sets; +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.usercenter.notice.constant.NoticeLevelEnum; +import com.newyetai.usercenter.notice.constant.NoticeReceiverTypeEnum; +import com.newyetai.usercenter.notice.dao.NoticeReceiverSettingMapper; +import com.newyetai.usercenter.notice.dao.NoticeTemplateMapper; +import com.newyetai.usercenter.notice.dto.NoticeReceiverSettingDTO; +import com.newyetai.usercenter.notice.dto.NoticeReceiverSettingOperateDTO; +import com.newyetai.usercenter.notice.dto.NoticeReceiverSettingQueryDTO; +import com.newyetai.usercenter.notice.dto.NoticeReceiverSettingRemoveDTO; +import com.newyetai.usercenter.notice.dto.NoticeReceiverSettingRoleDTO; +import com.newyetai.usercenter.notice.dto.NoticeReceiverSettingUserDTO; +import com.newyetai.usercenter.notice.entity.NoticeReceiverSetting; +import com.newyetai.usercenter.notice.entity.NoticeTemplate; +import com.newyetai.usercenter.notice.mapstruct.NoticeReceiverSettingMapMapper; +import com.newyetai.usercenter.notice.service.NoticeReceiverSettingService; + +/** + * @author sr on 2020-12-20 + */ +@Service +public class NoticeReceiverSettingServiceImpl implements NoticeReceiverSettingService { + + @Autowired + private NoticeReceiverSettingMapper noticeReceiverSettingMapper; + + @Autowired + private NoticeTemplateMapper noticeTemplateMapper; + + @Override + @Transactional + public void create(NoticeReceiverSettingOperateDTO noticeReceiverSettingOperateDTO) { + this.save(noticeReceiverSettingOperateDTO, true); + } + + @Override + @Transactional + public void save(NoticeReceiverSettingOperateDTO noticeReceiverSettingOperateDTO) { + this.save(noticeReceiverSettingOperateDTO, false); + } + + private void save(NoticeReceiverSettingOperateDTO noticeReceiverSettingOperateDTO, boolean created) { + NoticeTemplate noticeTemplate = + noticeTemplateMapper.getById(noticeReceiverSettingOperateDTO.getTemplateId()); + if (NoticeLevelEnum.PLATFORM.getType().equals(noticeTemplate.getLevel()) + && !CommonConstants.PLATFORM_ORG_ID + .equals(noticeReceiverSettingOperateDTO.getOperateOrgId())) { + throw new BusinessException("该模版不支持机构设置"); + } + // 校验传入接收人信息是否有效 + Long orgId = noticeReceiverSettingOperateDTO.getOperateOrgId(); + Integer receiverUnionType = noticeReceiverSettingOperateDTO.getReceiverUnionType(); + Set newReceiverUnionIds = noticeReceiverSettingOperateDTO.getReceiverUnionIds(); + if (NoticeReceiverTypeEnum.USER.getType().equals(receiverUnionType)) { + Assert.isTrue(noticeReceiverSettingMapper.validUser(orgId, newReceiverUnionIds) + .size() == newReceiverUnionIds.size(), "接收人关联无效"); + } else if (NoticeReceiverTypeEnum.ROLE.getType().equals(receiverUnionType)) { + Assert.isTrue(noticeReceiverSettingMapper.validRole(orgId, newReceiverUnionIds) + .size() == newReceiverUnionIds.size(), "接收人关联无效"); + } + + // 查询当前机构现有templateId/receiverUnionType 配置 + Set currentReceiverUnionIds = + noticeReceiverSettingMapper.findReceiverUnionIds(noticeReceiverSettingOperateDTO); + + // 新增 + Set createReceiverUnionIds = Sets.newHashSet(newReceiverUnionIds); + createReceiverUnionIds.removeAll(currentReceiverUnionIds); + if (!createReceiverUnionIds.isEmpty()) { + noticeReceiverSettingMapper.create(noticeReceiverSettingOperateDTO, createReceiverUnionIds); + } + // 新增不处理删除 + if (!created) { + // 删除 + Set removeReceiverUnionIds = Sets.newHashSet(currentReceiverUnionIds); + removeReceiverUnionIds.removeAll(newReceiverUnionIds); + if (!removeReceiverUnionIds.isEmpty()) { + NoticeReceiverSettingRemoveDTO removeDto = + NoticeReceiverSettingMapMapper.INSTANCE.toRemoveDTO(noticeReceiverSettingOperateDTO); + removeDto.setReceiverUnionIds(removeReceiverUnionIds); + this.remove(removeDto); + } + } + + } + + @Override + @Transactional + public void remove(Long id) { + noticeReceiverSettingMapper.deleteEntity(NoticeReceiverSetting.builder().id(id).build(), + UserContextHolder.getLoginUserId()); + } + + @Override + @Transactional + public void remove(NoticeReceiverSettingRemoveDTO noticeReceiverSettingRemoveDTO) { + // 只能删除当前登录人机构的配置;如需代机构删除配置请另外实现 + noticeReceiverSettingMapper.remove(noticeReceiverSettingRemoveDTO); + } + + @Override + public List list( + NoticeReceiverSettingQueryDTO noticeReceiverSettingQueryDTO) { + // 暂只支持查询当前机构 + noticeReceiverSettingQueryDTO.setOrgId(noticeReceiverSettingQueryDTO.getOperateOrgId()); + return noticeReceiverSettingMapper.listNoticeReceiverSettingDTO(noticeReceiverSettingQueryDTO); + } + + @Override + public Set getReceiverIds(Long templateId, Long receiverOrgId) { + // 获取接收人配置 + List noticeReceiverSettingDTOs = + noticeReceiverSettingMapper.listNoticeReceiverSettingDTO(NoticeReceiverSettingQueryDTO + .builder().templateId(templateId).orgId(receiverOrgId).build()); + Map> noticeReceiverSettingMap = + noticeReceiverSettingDTOs.stream() + .collect(Collectors.toMap(NoticeReceiverSettingDTO::getReceiverUnionType, + dto -> Sets.newHashSet(dto.getReceiverUnionId()), (o, n) -> { + o.addAll(n); + return o; + }, HashMap::new)); + // 根据接收人配置获取人id; orgId+unionType+unionIds + Set userIds = Sets.newHashSet(); + noticeReceiverSettingMap.forEach((k, v) -> { + if (NoticeReceiverTypeEnum.USER.getType().equals(k)) { + userIds.addAll(v); + } else { + userIds + .addAll(noticeReceiverSettingMapper.findUserIdByUnionType(receiverOrgId, k, v)); + } + }); + return userIds; + } + + @Override + public List listUser( + NoticeReceiverSettingQueryDTO noticeReceiverSettingQueryDTO) { + return noticeReceiverSettingMapper.listNoticeReceiverSettingUserDTO(noticeReceiverSettingQueryDTO); + } + + @Override + public List listRole( + NoticeReceiverSettingQueryDTO noticeReceiverSettingQueryDTO) { + return noticeReceiverSettingMapper.listNoticeReceiverSettingRoleDTO(noticeReceiverSettingQueryDTO); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/service/impl/NoticeSendRecordDetailServiceImpl.java b/src/main/java/com/newyetai/usercenter/notice/service/impl/NoticeSendRecordDetailServiceImpl.java new file mode 100644 index 0000000..2e4ccd3 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/service/impl/NoticeSendRecordDetailServiceImpl.java @@ -0,0 +1,62 @@ +package com.newyetai.usercenter.notice.service.impl; + +import com.newyetai.common.exception.util.Assert; +import com.newyetai.usercenter.notice.constant.NoticeChannelTypeEnum; +import com.newyetai.usercenter.notice.dao.NoticeSendRecordDetailMapper; +import com.newyetai.usercenter.notice.dto.NoticeSendRecordDetailDTO; +import com.newyetai.usercenter.notice.dto.NoticeSendRecordDetailQueryDTO; +import com.newyetai.usercenter.notice.dto.NoticeSendRecordDetailReqDTO; +import com.newyetai.usercenter.notice.service.NoticeSendRecordDetailService; +import com.newyetai.usercenter.notice.util.NoticeSendRecordDetailUtils; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + * @author sr on 2020-12-20 + */ +@Service +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class NoticeSendRecordDetailServiceImpl implements NoticeSendRecordDetailService { + + private final NoticeSendRecordDetailMapper noticeSendRecordDetailMapper; + + @Override + public NoticeSendRecordDetailDTO detail(NoticeSendRecordDetailReqDTO reqDTO) { + return noticeSendRecordDetailMapper.findNoticeSendRecordDetailDTO(reqDTO); + } + + @Override + public List list( + NoticeSendRecordDetailQueryDTO noticeSendRecordDetailQueryDTO) { + return noticeSendRecordDetailMapper + .listNoticeSendRecordDetailDTO(noticeSendRecordDetailQueryDTO); + } + + @Override + public Integer count(NoticeSendRecordDetailQueryDTO noticeSendRecordDetailQueryDTO) { + noticeSendRecordDetailQueryDTO.setNeedPage(Boolean.FALSE); + noticeSendRecordDetailQueryDTO.setPageSize(0); + return noticeSendRecordDetailMapper + .countNoticeSendRecordDetail(noticeSendRecordDetailQueryDTO); + } + + @Override + @Transactional + public void read(Long recordDetailId) { + Assert.notNull(recordDetailId, "通知明细id不能为空"); + int modifyNum = noticeSendRecordDetailMapper + .modifyStatus(NoticeSendRecordDetailUtils.buildRead(recordDetailId, NoticeChannelTypeEnum.SITE.getType())); + Assert.isTrue(modifyNum > 0, "请勿重复读取,请检查数据或刷新数据"); + } + + @Override + @Transactional + public void readAll() { + noticeSendRecordDetailMapper.modifyStatus(NoticeSendRecordDetailUtils.buildReadAll(NoticeChannelTypeEnum.SITE.getType())); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/service/impl/NoticeSendRecordServiceImpl.java b/src/main/java/com/newyetai/usercenter/notice/service/impl/NoticeSendRecordServiceImpl.java new file mode 100644 index 0000000..42e3ca4 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/service/impl/NoticeSendRecordServiceImpl.java @@ -0,0 +1,181 @@ +package com.newyetai.usercenter.notice.service.impl; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.BaseDtoUtils; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.usercenter.notice.constant.NoticeLevelEnum; +import com.newyetai.usercenter.notice.constant.NoticeReceiverStatusEnum; +import com.newyetai.usercenter.notice.constant.NoticeSendStatusEnum; +import com.newyetai.usercenter.notice.dao.NoticeContentTemplateMapper; +import com.newyetai.usercenter.notice.dao.NoticeSendRecordDetailMapper; +import com.newyetai.usercenter.notice.dao.NoticeSendRecordMapper; +import com.newyetai.usercenter.notice.dao.NoticeTemplateMapper; +import com.newyetai.usercenter.notice.dto.NoticeContentTemplateDTO; +import com.newyetai.usercenter.notice.dto.NoticeContentTemplateQueryDTO; +import com.newyetai.usercenter.notice.dto.NoticeSendRecordDTO; +import com.newyetai.usercenter.notice.dto.NoticeSendRecordOperateDTO; +import com.newyetai.usercenter.notice.dto.NoticeSendRecordQueryDTO; +import com.newyetai.usercenter.notice.dto.NoticeTemplateDTO; +import com.newyetai.usercenter.notice.dto.NoticeTemplateQueryDTO; +import com.newyetai.usercenter.notice.entity.NoticeSendRecord; +import com.newyetai.usercenter.notice.entity.NoticeSendRecordDetail; +import com.newyetai.usercenter.notice.mapstruct.NoticeSendRecordMapMapper; +import com.newyetai.usercenter.notice.service.INoticeChannelProvider; +import com.newyetai.usercenter.notice.service.NoticeReceiverSettingService; +import com.newyetai.usercenter.notice.service.NoticeSendRecordService; + +import lombok.extern.slf4j.Slf4j; + +/** + * @author sr on 2020-12-20 + */ +@Service +@Slf4j +public class NoticeSendRecordServiceImpl implements NoticeSendRecordService { + + @Autowired + private NoticeSendRecordMapper noticeSendRecordMapper; + + @Autowired + private NoticeTemplateMapper noticeTemplateMapper; + + @Autowired + private NoticeContentTemplateMapper noticeContentTemplateMapper; + + @Autowired + private NoticeReceiverSettingService noticeReceiverSettingService; + + @Autowired + private NoticeSendRecordDetailMapper noticeSendRecordDetailMapper; + + private Map channelProviderMap; + + @Autowired + public void setChannelProviderMap(List channelProviders) { + channelProviderMap = + channelProviders.stream() + .collect(Collectors.toMap(k -> k.getChannelType(), v -> v)); + } + + @Override + @Transactional + public void create(NoticeSendRecordOperateDTO noticeSendRecordOperateDTO) { + // 克隆操作对象,清洗参数,替换流程中需要的正确的id等属性 + NoticeSendRecordOperateDTO tempOperateDto = + NoticeSendRecordMapMapper.INSTANCE.clone(noticeSendRecordOperateDTO); + Long templateId = noticeSendRecordOperateDTO.getTemplateId(); + String templateCode = noticeSendRecordOperateDTO.getTemplateCode(); + // 判断参数必填 + Assert.isTrue(templateId != null || StringUtils.isNotBlank(templateCode), "通知模版参数缺失"); + // 获取模版,级别-》机构id + NoticeTemplateQueryDTO noticeTemplateQueryDTO = + NoticeTemplateQueryDTO.builder().id(templateId).templateCode(templateCode).enabled(true) + .build(); + noticeTemplateQueryDTO.setNeedPage(false); + List noticeTemplateDTOs = + noticeTemplateMapper.listNoticeTemplateDTO(noticeTemplateQueryDTO); + Assert.isTrue(!noticeTemplateDTOs.isEmpty(), "未找到对应通知模版"); + NoticeTemplateDTO noticeTemplateDTO = noticeTemplateDTOs.get(0); + tempOperateDto.setTemplateId(noticeTemplateDTO.getId()); + // 平台模版指定接收人机构为平台 + Long receiverOrgId = + NoticeLevelEnum.PLATFORM.getType().equals(noticeTemplateDTOs.get(0).getLevel()) + ? CommonConstants.PLATFORM_ORG_ID + : noticeSendRecordOperateDTO.getReceiverOrgId(); + if (receiverOrgId == null) { + receiverOrgId = noticeSendRecordOperateDTO.getOperateOrgId(); + } + tempOperateDto.setReceiverOrgId(receiverOrgId); + + // 是否定制内容模版 + if (BooleanUtils.isTrue(noticeSendRecordOperateDTO.getCustomContent())) { + Assert.isTrue(noticeSendRecordOperateDTO.getChannelType() != null, "定制内容模版,消息通道类型不能为空"); + dealByChannel(tempOperateDto, + NoticeSendRecordMapMapper.INSTANCE.toContentTemplate(tempOperateDto)); + } else { + // 获取内容模版, 未指定模版->获取所有内容模版 + List noticeContentTemplateDTOs = noticeContentTemplateMapper + .listNoticeContentTemplateDTO(NoticeContentTemplateQueryDTO.builder() + .id(noticeSendRecordOperateDTO.getContentTemplateId()) + .templateId(tempOperateDto.getTemplateId()) + .channelType(noticeSendRecordOperateDTO.getChannelType()).enabled(true).build()); + Assert.isTrue(!noticeContentTemplateDTOs.isEmpty(), "未找到对应通知内容模版"); + noticeContentTemplateDTOs.forEach( + noticeContentTemplateDTO -> dealByChannel(tempOperateDto, + noticeContentTemplateDTO)); + } + } + + private void dealByChannel(NoticeSendRecordOperateDTO noticeSendRecordOperateDTO, + NoticeContentTemplateDTO noticeContentTemplateDTO) { + INoticeChannelProvider channelProvicer = + channelProviderMap.get(noticeContentTemplateDTO.getChannelType()); + if (channelProvicer == null) { + log.error("无对应消息通道处理..."); + } + Set receiverUserIds = noticeSendRecordOperateDTO.getReceiverUserIds(); + NoticeSendRecordDTO noticeSendRecordDTO = + NoticeSendRecordDTO.builder().templateId(noticeSendRecordOperateDTO.getTemplateId()) + .senderOrgId(noticeSendRecordOperateDTO.getOperateOrgId()) + .receiverOrgId(noticeSendRecordOperateDTO.getReceiverOrgId()) + .contentTemplateId(noticeContentTemplateDTO.getId()) + .contentParamData( + JsonUtils.toJsonString(noticeSendRecordOperateDTO.getContentParamDataMap())) + .appointed(CollectionUtils.isNotEmpty(receiverUserIds)) + .status(NoticeSendStatusEnum.INIT.getType()) + .channelType(noticeContentTemplateDTO.getChannelType()) + .title(noticeContentTemplateDTO.getTitle()) + .contentTemplate(noticeContentTemplateDTO.getContentTemplate()) + .link(noticeContentTemplateDTO.getLink()).build(); + + this.createDetail(noticeSendRecordDTO, receiverUserIds, NoticeReceiverStatusEnum.INIT.getType()); + // mq 触发消息通道真实处理流程 + channelProvicer.asyncDeal(noticeSendRecordDTO); + + } + + private void createDetail(NoticeSendRecordDTO noticeSendRecordDTO, Set receiverUserIds, + Integer receiverStatus) { + NoticeSendRecord noticeSendRecord = + NoticeSendRecordMapMapper.INSTANCE.toEntity(noticeSendRecordDTO); + noticeSendRecordMapper.saveEntity(noticeSendRecord, + UserContextHolder.getLoginUserId()); + BaseDtoUtils.createCopy(noticeSendRecord, noticeSendRecordDTO); + // TODO 根据channel获取接收人相关帐号List noticeSendRecordDetailOperateDTOs + if (CollectionUtils.isEmpty(receiverUserIds)) { + receiverUserIds = + noticeReceiverSettingService.getReceiverIds(noticeSendRecordDTO.getTemplateId(), + noticeSendRecordDTO.getReceiverOrgId()); + } + // 插入发送记录明细;占位符替换内容模版内容 + Long recordId = noticeSendRecord.getId(); + List noticeSendRecordDetails = receiverUserIds.stream() + .map(userId -> NoticeSendRecordDetail.builder().recordId(recordId).userId(userId) + .receiverStatus(receiverStatus).build()) + .collect(Collectors.toList()); + noticeSendRecordDetailMapper.saveEntites(noticeSendRecordDetails, + UserContextHolder.getLoginUserId()); + } + + @Override + public List page(NoticeSendRecordQueryDTO noticeSendRecordQueryDTO) { + // 暂只支持查询当前机构 + noticeSendRecordQueryDTO.setSenderOrgId(noticeSendRecordQueryDTO.getOperateOrgId()); + return noticeSendRecordMapper.listNoticeSendRecordDTO(noticeSendRecordQueryDTO); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/service/impl/NoticeTemplateServiceImpl.java b/src/main/java/com/newyetai/usercenter/notice/service/impl/NoticeTemplateServiceImpl.java new file mode 100644 index 0000000..5cd97ab --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/service/impl/NoticeTemplateServiceImpl.java @@ -0,0 +1,94 @@ +package com.newyetai.usercenter.notice.service.impl; + + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.usercenter.notice.constant.NoticeLevelEnum; +import com.newyetai.usercenter.notice.dao.NoticeTemplateMapper; +import com.newyetai.usercenter.notice.dto.NoticeTemplateDTO; +import com.newyetai.usercenter.notice.dto.NoticeTemplateOperateDTO; +import com.newyetai.usercenter.notice.dto.NoticeTemplateQueryDTO; +import com.newyetai.usercenter.notice.entity.NoticeTemplate; +import com.newyetai.usercenter.notice.mapstruct.NoticeTemplateMapMapper; +import com.newyetai.usercenter.notice.service.NoticeTemplateService; + +/** + * @author sr on 2020-12-17 + */ +@Service +public class NoticeTemplateServiceImpl implements NoticeTemplateService { + + @Autowired + private NoticeTemplateMapper noticeTemplateMapper; + + private void exist(NoticeTemplateOperateDTO noticeTemplateOperateDTO) { + // templateCode 验重 + boolean exists = noticeTemplateMapper.existsEntity( + NoticeTemplate.builder().id(noticeTemplateOperateDTO.getId()) + .templateCode(noticeTemplateOperateDTO.getTemplateCode()).build()); + Assert.isTrue(!exists, "模版标识已存在"); + Assert.isTrue( + NoticeLevelEnum.ORG.getType().equals(noticeTemplateOperateDTO.getLevel()) + || CommonConstants.PLATFORM_ORG_ID.equals(noticeTemplateOperateDTO.getOperateOrgId()), + "不支持机构设置该级别模版"); + } + + @Override + @Transactional + public Long create(NoticeTemplateOperateDTO noticeTemplateOperateDTO) { + this.exist(noticeTemplateOperateDTO); + // 设置初始值 + if (noticeTemplateOperateDTO.getEnabled() == null) { + noticeTemplateOperateDTO.setEnabled(true); + } + NoticeTemplate noticeTemplate = + NoticeTemplateMapMapper.INSTANCE.toEntity(noticeTemplateOperateDTO); + noticeTemplateMapper.saveEntity(noticeTemplate, UserContextHolder.getLoginUserId()); + return noticeTemplate.getId(); + } + + @Override + @Transactional + public void modify(NoticeTemplateOperateDTO noticeTemplateOperateDTO) { + this.exist(noticeTemplateOperateDTO); + NoticeTemplate noticeTemplate = + NoticeTemplateMapMapper.INSTANCE.toEntity(noticeTemplateOperateDTO); + noticeTemplateMapper.updateEntitySelective(noticeTemplate, UserContextHolder.getLoginUserId()); + } + + @Override + @Transactional + public void remove(Long id) { + noticeTemplateMapper.deleteEntity(NoticeTemplate.builder().id(id).build(), + UserContextHolder.getLoginUserId()); + } + + @Override + public List page(NoticeTemplateQueryDTO noticeTemplateQueryDTO) { + return noticeTemplateMapper.listNoticeTemplateDTO(noticeTemplateQueryDTO); + } + + @Override + public void checkTemplate(Long templateId) { + NoticeTemplate noticeTemplate = noticeTemplateMapper.getById(templateId); + Assert.isTrue(noticeTemplate != null, "未找到对应通知模版"); + Assert.isTrue(noticeTemplate.getEnabled(), "该通知模版无法操作"); + } + + @Override + public NoticeTemplateDTO find(Long id) { + Assert.notNull(id, "id为空"); + List templateDtos = + noticeTemplateMapper.listNoticeTemplateDTO(NoticeTemplateQueryDTO.builder().id(id).build()); + Assert.isTrue(!templateDtos.isEmpty(), "未找到对应模版"); + return templateDtos.get(0); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/service/provider/AbstractNoticeChannelProvider.java b/src/main/java/com/newyetai/usercenter/notice/service/provider/AbstractNoticeChannelProvider.java new file mode 100644 index 0000000..4bf51e8 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/service/provider/AbstractNoticeChannelProvider.java @@ -0,0 +1,124 @@ +package com.newyetai.usercenter.notice.service.provider; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.springframework.transaction.annotation.Transactional; + +import com.google.common.collect.Sets; +import com.newyetai.common.AlitaResult; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.usercenter.notice.constant.NoticeReceiverStatusEnum; +import com.newyetai.usercenter.notice.constant.NoticeSendStatusEnum; +import com.newyetai.usercenter.notice.dao.NoticeSendRecordDetailMapper; +import com.newyetai.usercenter.notice.dao.NoticeSendRecordMapper; +import com.newyetai.usercenter.notice.dto.NoticeSendRecordDTO; +import com.newyetai.usercenter.notice.dto.NoticeSendRecordDetailDTO; +import com.newyetai.usercenter.notice.dto.NoticeSendRecordDetailQueryDTO; +import com.newyetai.usercenter.notice.dto.NoticeSendRecordModifyDTO; +import com.newyetai.usercenter.notice.service.INoticeChannelProvider; +import com.newyetai.usercenter.notice.util.NoticeSendRecordDetailUtils; + +import lombok.extern.slf4j.Slf4j; + +/** + * 通知处理抽象类 + * + * @author sr on 2021-02-19 + */ +@Slf4j +public abstract class AbstractNoticeChannelProvider implements INoticeChannelProvider { + + private NoticeSendRecordMapper noticeSendRecordMapper; + + private NoticeSendRecordDetailMapper noticeSendRecordDetailMapper; + + public AbstractNoticeChannelProvider(NoticeSendRecordMapper noticeSendRecordMapper, + NoticeSendRecordDetailMapper noticeSendRecordDetailMapper) { + this.noticeSendRecordMapper = noticeSendRecordMapper; + this.noticeSendRecordDetailMapper = noticeSendRecordDetailMapper; + } + + public void beforeSendDetails(NoticeSendRecordDTO noticeSendRecordDTO) {} + + /** + * 处理发送记录下所有明细 + * @param noticeSendRecordDTO + * @author sr on 2021-02-19 + */ + public void sendDetails(NoticeSendRecordDTO noticeSendRecordDTO) { + NoticeSendRecordDetailQueryDTO noticeSendRecordDetailQueryDTO = + NoticeSendRecordDetailQueryDTO.builder().recordId(noticeSendRecordDTO.getId()) + .receiverStatus(NoticeReceiverStatusEnum.INIT.getType()).build(); + List recordDetails = + noticeSendRecordDetailMapper + .listNoticeSendRecordDetailDTO(noticeSendRecordDetailQueryDTO); + if (recordDetails.isEmpty()) { + return; + } + Set sucRecordDetailIds = Sets.newHashSetWithExpectedSize(recordDetails.size()); + Set errRecordDetailIds = Sets.newHashSetWithExpectedSize(recordDetails.size()); + recordDetails.forEach(detail -> { + AlitaResult invokeResult = null; + try { + invokeResult = this.invoke(noticeSendRecordDTO, detail); + } catch (Exception e) { + invokeResult = AlitaResult.bizError(ExceptionUtils.getStackTrace(e)); + } + if (invokeResult.getSuccess()) { + sucRecordDetailIds.add(detail.getId()); + } else { + errRecordDetailIds.add(detail.getId()); + log.error("notice sendDetail, id-{} error:{}", detail.getId(), invokeResult.getMsg()); + } + }); + // 更新状态 + if (!sucRecordDetailIds.isEmpty()) { + noticeSendRecordDetailMapper.modifyStatus(NoticeSendRecordDetailUtils.buildSend( + sucRecordDetailIds, getChannelType(), NoticeReceiverStatusEnum.SENT.getType())); + } + if (!errRecordDetailIds.isEmpty()) { + noticeSendRecordDetailMapper.modifyStatus(NoticeSendRecordDetailUtils.buildSend( + errRecordDetailIds, getChannelType(), NoticeReceiverStatusEnum.SEND_FAIL.getType())); + } + } + + public void afterSendDetails(NoticeSendRecordDTO noticeSendRecordDTO) {} + + + /** + * 单个明细真实发送处理 + * @param noticeSendRecordDTO + * @param noticeSendRecordDetailDTO + * @return + * @author sr on 2021-02-19 + */ + public AlitaResult invoke(NoticeSendRecordDTO noticeSendRecordDTO, + NoticeSendRecordDetailDTO noticeSendRecordDetailDTO) { + return AlitaResult.bizError("未实现单个明细实际调用"); + } + + + @SuppressWarnings("unchecked") + @Transactional + public void send(NoticeSendRecordDTO noticeSendRecordDTO) { + // 组装消息体 + String contentTemplate = noticeSendRecordDTO.getContentTemplate(); + String content = this.format(contentTemplate, + JsonUtils.toObject(noticeSendRecordDTO.getContentParamData(), Map.class)); + noticeSendRecordDTO.setContent(content); + int updateNum = noticeSendRecordMapper + .modify(NoticeSendRecordModifyDTO.builder().id(noticeSendRecordDTO.getId()) + .oldStatus(NoticeSendStatusEnum.INIT.getType()) + .newStatus(NoticeSendStatusEnum.SENT.getType()) + .content(content).build()); + Assert.isTrue(updateNum > 0, "当前通知发送记录无法操作"); + beforeSendDetails(noticeSendRecordDTO); + this.sendDetails(noticeSendRecordDTO); + afterSendDetails(noticeSendRecordDTO); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/service/provider/SiteNoticeChannelProvider.java b/src/main/java/com/newyetai/usercenter/notice/service/provider/SiteNoticeChannelProvider.java new file mode 100644 index 0000000..dec1b25 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/service/provider/SiteNoticeChannelProvider.java @@ -0,0 +1,47 @@ +package com.newyetai.usercenter.notice.service.provider; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.newyetai.common.AlitaResult; +import com.newyetai.mq.producer.sender.IMqSender; +import com.newyetai.mq.util.MqSendUtils; +import com.newyetai.usercenter.notice.constant.NoticeChannelTypeEnum; +import com.newyetai.usercenter.notice.dao.NoticeSendRecordDetailMapper; +import com.newyetai.usercenter.notice.dao.NoticeSendRecordMapper; +import com.newyetai.usercenter.notice.dto.NoticeSendRecordDTO; +import com.newyetai.usercenter.notice.dto.NoticeSendRecordDetailDTO; + +/** + * 站内信 + * + * @author sr on 2021-01-04 + */ +@Service +public class SiteNoticeChannelProvider extends AbstractNoticeChannelProvider { + + public SiteNoticeChannelProvider(NoticeSendRecordMapper noticeSendRecordMapper, + NoticeSendRecordDetailMapper noticeSendRecordDetailMapper) { + super(noticeSendRecordMapper, noticeSendRecordDetailMapper); + } + + @Override + public Integer getChannelType() { + return NoticeChannelTypeEnum.SITE.getType(); + } + + public AlitaResult invoke(NoticeSendRecordDTO noticeSendRecordDTO, + NoticeSendRecordDetailDTO noticeSendRecordDetailDTO) { + /* TODO mq实现通知各系统(websocket) + AlitaResult mqResult = MqSendUtils.send(UcMqConstants.ROUTING_KEY_SITE_NOTICE, detail); + Long detailId = detail.getId(); + if (mqResult.getSuccess()) { + return true; + } else { + return false; + }*/ + return noticeSendRecordDTO.getContent() != null ? AlitaResult.success() + : AlitaResult.bizError("消息内容为空,模版替换失败"); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/service/provider/WechatOffiaccountNoticeChannelProvider.java b/src/main/java/com/newyetai/usercenter/notice/service/provider/WechatOffiaccountNoticeChannelProvider.java new file mode 100644 index 0000000..03adeb9 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/service/provider/WechatOffiaccountNoticeChannelProvider.java @@ -0,0 +1,98 @@ +package com.newyetai.usercenter.notice.service.provider; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.sdk.wechat.WechatClient; +import com.newyetai.sdk.wechat.model.KeyData; +import com.newyetai.sdk.wechat.model.TemplateMessageReq; +import com.newyetai.sdk.wechat.util.MessageParamUtils; +import com.newyetai.usercenter.auth.constant.AuthTypeEnum; +import com.newyetai.usercenter.auth.dto.AuthClientQueryDTO; +import com.newyetai.usercenter.auth.dto.AuthDetailDTO; +import com.newyetai.usercenter.auth.dto.AuthDetailQueryDTO; +import com.newyetai.usercenter.auth.service.AuthDetailService; +import com.newyetai.usercenter.auth.util.AuthClientUtils; +import com.newyetai.usercenter.notice.constant.NoticeChannelTypeEnum; +import com.newyetai.usercenter.notice.dao.NoticeSendRecordDetailMapper; +import com.newyetai.usercenter.notice.dao.NoticeSendRecordMapper; +import com.newyetai.usercenter.notice.dto.NoticeSendRecordDTO; +import com.newyetai.usercenter.notice.dto.NoticeSendRecordDetailDTO; + +/** + * 微信公众号模版消息发送 + * @author sr on 2021-02-19 + */ +@Service +public class WechatOffiaccountNoticeChannelProvider extends AbstractNoticeChannelProvider { + + @Autowired + private AuthDetailService authDetailService; + + /** 缓存微信公众号模版参数 recordId:templateData **/ + private Map> recordTemplateData = + new ConcurrentHashMap>(200); + + public WechatOffiaccountNoticeChannelProvider(NoticeSendRecordMapper noticeSendRecordMapper, + NoticeSendRecordDetailMapper noticeSendRecordDetailMapper) { + super(noticeSendRecordMapper, noticeSendRecordDetailMapper); + } + + @Override + public Integer getChannelType() { + return NoticeChannelTypeEnum.WECHAT_OFFIACCOUNT.getType(); + } + + @Override + public String format(String contentTemplate, Map contentParamDataMap) { + return null; + } + + @Override + public void beforeSendDetails(NoticeSendRecordDTO noticeSendRecordDTO) { + Long recordId = noticeSendRecordDTO.getId(); + Map templateData = recordTemplateData.get(recordId); + if (templateData == null) { + templateData = + MessageParamUtils.dealData(noticeSendRecordDTO.getContentParamDataMap()); + recordTemplateData.put(recordId, templateData); + } + } + + @Override + public AlitaResult invoke(NoticeSendRecordDTO noticeSendRecordDTO, + NoticeSendRecordDetailDTO noticeSendRecordDetailDTO) { + + Long userId = noticeSendRecordDetailDTO.getUserId(); + Assert.isTrue(userId != null, "用户id为空"); + // 查询微信授权信息 + List authDetailDTOs = authDetailService.list(AuthDetailQueryDTO.builder() + .authTypeCode(AuthTypeEnum.WECHAT.getCode()).userId(userId).build()); + Assert.isTrue(!authDetailDTOs.isEmpty(), "未找到用户微信授权信息"); + AuthDetailDTO authDetailDTO = authDetailDTOs.get(0); + String openId = authDetailDTO.getOpenId(); + // 发送公众号 + String token = AuthClientUtils + .getService().getAccessToken(AuthClientQueryDTO.builder().id(authDetailDTO.getAuthClientId()).build()); + TemplateMessageReq templateMessageRequestParam = + TemplateMessageReq.builder().accessToken( + token) + .toUser(openId) + .templateId(noticeSendRecordDTO.getContentTemplate()) + .data(recordTemplateData.get(noticeSendRecordDTO.getId())) + .url(noticeSendRecordDTO.getLink()).build(); + return WechatClient.sendTemplateMessage(templateMessageRequestParam); + } + + @Override + public void afterSendDetails(NoticeSendRecordDTO noticeSendRecordDTO) { + recordTemplateData.remove(noticeSendRecordDTO.getId()); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/util/NoticeSendRecordDetailUtils.java b/src/main/java/com/newyetai/usercenter/notice/util/NoticeSendRecordDetailUtils.java new file mode 100644 index 0000000..a1910d8 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/util/NoticeSendRecordDetailUtils.java @@ -0,0 +1,34 @@ +package com.newyetai.usercenter.notice.util; + +import java.util.Set; + +import com.newyetai.usercenter.notice.constant.NoticeReceiverStatusEnum; +import com.newyetai.usercenter.notice.dto.RecordDetailUpdateStatusDTO; + +/** + * @author sr on 2020-12-20 + */ +public class NoticeSendRecordDetailUtils { + + public static RecordDetailUpdateStatusDTO buildRead(Long recordDetailId, Integer channelType) { + RecordDetailUpdateStatusDTO recordDetailUpdateStatusDTO = buildReadAll(channelType); + recordDetailUpdateStatusDTO.setRecordDetailId(recordDetailId); + return recordDetailUpdateStatusDTO; + } + + public static RecordDetailUpdateStatusDTO buildReadAll(Integer channelType) { + return RecordDetailUpdateStatusDTO.builder().channelType(channelType) + .oldStatus(NoticeReceiverStatusEnum.SENT.getType()) + .newStatus(NoticeReceiverStatusEnum.READ.getType()).build(); + } + + public static RecordDetailUpdateStatusDTO buildSend(Set recordDetailIds, Integer channelType, + Integer sendStatus) { + return RecordDetailUpdateStatusDTO.builder() + .channelType(channelType) + .oldStatus(NoticeReceiverStatusEnum.INIT.getType()) + .newStatus(sendStatus) + .recordDetailIds(recordDetailIds).build(); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/notice/util/NoticeSendRecordUtils.java b/src/main/java/com/newyetai/usercenter/notice/util/NoticeSendRecordUtils.java new file mode 100644 index 0000000..bbee4a2 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/notice/util/NoticeSendRecordUtils.java @@ -0,0 +1,23 @@ +package com.newyetai.usercenter.notice.util; + +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.usercenter.userprod.constant.UcMqSelfConstants; + +/** + * @author sr on 2020-12-20 + */ +public class NoticeSendRecordUtils { + + /** + * 根据消息通道获取通道处理mq的routingKey + * + * @param channelType + * @return + * @author sr on 2021-02-04 + */ + public static String getNoticeChannelDealKey(Integer channelType) { + return String.join(CommonConstants.UNDERLINE, + UcMqSelfConstants.ROUTING_KEY_NOTICE_CHANNEL_DEAL_PREFIX, channelType.toString()); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/org/constant/OrgTypeConstants.java b/src/main/java/com/newyetai/usercenter/org/constant/OrgTypeConstants.java new file mode 100644 index 0000000..9b6a5c9 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/constant/OrgTypeConstants.java @@ -0,0 +1,30 @@ +package com.newyetai.usercenter.org.constant; + +import com.newyetai.common.constant.SystemCodeEnum; + +/** + * 机构类型 + * @author sr on 2022-11-28 + */ +public class OrgTypeConstants { + + /** 招聘系统 **/ + public static RecruitOrgType recruit ; + + public interface RecruitOrgType{ + /** 平台 **/ + Integer PLAFORM = 1; + /** 运营 **/ + Integer OPERATION = 2; + /** 普通 **/ + Integer SIMPLE = 3; + + default Integer getPlateformCode() { + return SystemCodeEnum.ALITA_RECRUIT.getCode(); + } + } + + + + +} diff --git a/src/main/java/com/newyetai/usercenter/org/controller/OrgController.java b/src/main/java/com/newyetai/usercenter/org/controller/OrgController.java new file mode 100644 index 0000000..00d35b7 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/controller/OrgController.java @@ -0,0 +1,113 @@ +package com.newyetai.usercenter.org.controller; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.enums.OrgTypeEnum; +import com.newyetai.usercenter.org.dto.OrgCreateDTO; +import com.newyetai.usercenter.org.dto.OrgDTO; +import com.newyetai.usercenter.org.dto.OrgModifyDTO; +import com.newyetai.usercenter.org.dto.OrgQueryDTO; +import com.newyetai.usercenter.org.dto.UcOpenOrgPartQueryDTO; +import com.newyetai.usercenter.org.dto.UcOrgInfoReqDTO; +import com.newyetai.usercenter.org.dto.UcOrgInfoResDTO; +import com.newyetai.usercenter.org.dto.UcOrgPartInfoDTO; +import com.newyetai.usercenter.org.dto.UcOrgPartQueryDTO; +import com.newyetai.usercenter.org.service.OrgService; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + + +/** + * org控制器 + * + * @author Carlye + * @date 2021/06/16 + */ +@RestController +@Api(tags = "机构信息") +public class OrgController { + + @Autowired + private OrgService orgService; + + @GetMapping("/uc/org/page") + @ApiOperation("分页查询机构") + public AlitaResult> page(OrgQueryDTO orgQueryDTO) { + orgService.page(orgQueryDTO); + return AlitaResult.success(orgQueryDTO.getPageResult()); + } + + + @PostMapping("/uc/org/create") + @ApiOperation("分页查询机构") + public AlitaResult create(@Validated @RequestBody OrgCreateDTO orgCreateDTO) { + orgService.create(orgCreateDTO); + return AlitaResult.success(); + } + + @PutMapping("/uc/org/modify") + @ApiOperation("修改机构") + public AlitaResult modify(@RequestBody @Validated OrgModifyDTO orgModifyDTO) { + orgService.modify(orgModifyDTO); + return AlitaResult.success(); + } + + @GetMapping("/uc/org/find") + @ApiOperation("查看机构信息") + public AlitaResult find() { + return AlitaResult.success(orgService.find(OrgQueryDTO.builder().id(UserContextHolder.getExistLoginOrgId()).build())); + } + + @GetMapping("/anon/uc/org/user/page") + @ApiOperation("分页查询机构-小程序用查询指定类型机构") + public AlitaResult> userPage(@RequestParam(value = "orgNameLike",required = false) String orgNameLike, @RequestParam(value = "pageNo",defaultValue = "1",required = false) Integer pageNo, @RequestParam(value = "pageSize",defaultValue = "20",required = false) Integer pageSize) { + OrgQueryDTO orgQueryDTO = new OrgQueryDTO(); + orgQueryDTO.setType(OrgTypeEnum.ORG_TYPE_GOV.getType()); + orgQueryDTO.setPageNo(pageNo); + orgQueryDTO.setPageSize(pageSize); + orgQueryDTO.setOrgNameLike(orgNameLike); + orgService.page(orgQueryDTO); + return AlitaResult.success(orgQueryDTO.getPageResult()); + } +//***********************************分隔符*********************************************** + + + @GetMapping("/info") + @ApiOperation("查询机构信息") + public AlitaResult info(UcOrgInfoReqDTO reqDTO) { + return AlitaResult.success(orgService.info(reqDTO)); + } + + @GetMapping("/part_info_list") + @ApiOperation("查询机构部分的信息") + public AlitaResult> orgPartInfoList(UcOrgPartQueryDTO queryDTO) { + orgService.orgPartInfoList(queryDTO); + return AlitaResult.success(queryDTO.getPageResult()); + } + + @GetMapping("/find_all_org") + @ApiOperation("查询所有机构信息") + public AlitaResult> findAllOrg() { + return AlitaResult.success(orgService.findAllOrg()); + } + + @GetMapping("/open_part_info_list") + @ApiOperation("开放接口--查询机构部分的信息") + public AlitaResult> openOrgPartInfoList(@Validated UcOpenOrgPartQueryDTO queryDTO) { + return AlitaResult.success(orgService.openOrgPartInfoList(queryDTO)); + } +} diff --git a/src/main/java/com/newyetai/usercenter/org/controller/OrgRelationController.java b/src/main/java/com/newyetai/usercenter/org/controller/OrgRelationController.java new file mode 100644 index 0000000..8d68ee1 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/controller/OrgRelationController.java @@ -0,0 +1,62 @@ +package com.newyetai.usercenter.org.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.newyetai.common.AlitaResult; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.org.dto.OrgRelationCreateDTO; +import com.newyetai.usercenter.org.dto.OrgRelationDTO; +import com.newyetai.usercenter.org.dto.OrgRelationModifyDTO; +import com.newyetai.usercenter.org.dto.OrgRelationQueryDTO; +import com.newyetai.usercenter.org.dto.OrgRelationQueryOrgDTO; +import com.newyetai.usercenter.org.dto.SelectOrgDTO; +import com.newyetai.usercenter.org.service.OrgRelationService; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +/** + * @author sr on 2022-05-25 + */ +@RestController +@RequestMapping("org_relation") +@Api(tags = "机构关系表") +public class OrgRelationController { + + @Autowired + private OrgRelationService orgRelationService; + + @PostMapping + @ApiOperation("新增机构关系") + public AlitaResult create(@Validated @RequestBody OrgRelationCreateDTO orgRelationCreateDTO) { + return AlitaResult.success(orgRelationService.create(orgRelationCreateDTO)); + } + + @PutMapping + @ApiOperation("修改机构关系") + public AlitaResult modify(@Validated @RequestBody OrgRelationModifyDTO orgRelationModifyDTO) { + orgRelationService.modify(orgRelationModifyDTO); + return AlitaResult.success(); + } + + @GetMapping("/find") + @ApiOperation("查询单个机构关系") + public AlitaResult find(OrgRelationQueryDTO orgRelationQueryDTO) { + return AlitaResult.success(orgRelationService.find(orgRelationQueryDTO)); + } + + @GetMapping("/page_org") + @ApiOperation("分页查询机构") + public AlitaResult> pageOrg(@Validated OrgRelationQueryOrgDTO orgRelationQueryOrgDTO){ + orgRelationService.pageOrg(orgRelationQueryOrgDTO); + return AlitaResult.success(orgRelationQueryOrgDTO.getPageResult()); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/org/dao/ImportDetailOrgMapper.java b/src/main/java/com/newyetai/usercenter/org/dao/ImportDetailOrgMapper.java new file mode 100644 index 0000000..25f77bb --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/dao/ImportDetailOrgMapper.java @@ -0,0 +1,26 @@ +package com.newyetai.usercenter.org.dao; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.usercenter.org.entity.ImportDetailOrg; +import com.newyetai.usercenter.org.dto.ImportDetailOrgDTO; +import com.newyetai.usercenter.org.dto.ImportDetailOrgQueryDTO; +import com.newyetai.usercenter.org.dto.ImportDetailOrgPageQueryDTO; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 机构导入表 + * + * @author guixinman + * @since 1.0.0 2024-06-12 + */ +@Mapper +public interface ImportDetailOrgMapper extends MyMapper { + + List page(@Param("param") ImportDetailOrgPageQueryDTO queryDTO); + + List list(@Param("param") ImportDetailOrgQueryDTO queryDTO); +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/org/dao/OrgMapper.java b/src/main/java/com/newyetai/usercenter/org/dao/OrgMapper.java new file mode 100644 index 0000000..d65143d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/dao/OrgMapper.java @@ -0,0 +1,51 @@ +package com.newyetai.usercenter.org.dao; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.usercenter.org.dto.OrgDTO; +import com.newyetai.usercenter.org.dto.OrgModifyDTO; +import com.newyetai.usercenter.org.dto.OrgQueryDTO; +import com.newyetai.usercenter.org.dto.UcOpenOrgPartQueryDTO; +import com.newyetai.usercenter.org.dto.UcOrgInfoReqDTO; +import com.newyetai.usercenter.org.dto.UcOrgInfoResDTO; +import com.newyetai.usercenter.org.dto.UcOrgPartInfoDTO; +import com.newyetai.usercenter.org.dto.UcOrgPartQueryDTO; +import com.newyetai.usercenter.org.entity.Org; + +/** + * 机构 + * @author sr on 2024-04-18 + */ +public interface OrgMapper extends MyMapper { + + List listOrgDTO(@Param("param") OrgQueryDTO orgQueryDTO); + + void modifyByOrgId(@Param("param") OrgModifyDTO orgModifyDTO); + + +//***********************************分隔符*********************************************** + + UcOrgInfoResDTO info(@Param("param") UcOrgInfoReqDTO reqDTO); + + /** + * 组织部分信息列表 + * + * @param queryDTO 查询dto + * @return {@link UcOrgPartInfoDTO} + */ + List orgPartInfoList(@Param("param") UcOrgPartQueryDTO queryDTO); + + + List findAllOrg(); + + /** + * @description: 开放接口--查询机构部分的信息 + * @return: 根据产品编号 查询 所有机构名称+orgId + * @author: guixinman + * @param: 产品编号 + */ + List openOrgPartInfoList(@Param("param") UcOpenOrgPartQueryDTO queryDTO); +} diff --git a/src/main/java/com/newyetai/usercenter/org/dao/OrgRelationMapper.java b/src/main/java/com/newyetai/usercenter/org/dao/OrgRelationMapper.java new file mode 100644 index 0000000..6bda02e --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/dao/OrgRelationMapper.java @@ -0,0 +1,32 @@ +package com.newyetai.usercenter.org.dao; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.newyetai.usercenter.org.dto.OrgRelationDTO; +import com.newyetai.usercenter.org.dto.OrgRelationQueryDTO; +import com.newyetai.usercenter.org.dto.OrgRelationQueryOrgDTO; +import com.newyetai.usercenter.org.dto.SelectOrgDTO; +import com.newyetai.usercenter.org.entity.OrgRelation; +import com.newyetai.tkmybatis.mybatis.MyMapper; + +/** + * 机构关系表 + * + * @author sr on 2022-05-25 + */ +public interface OrgRelationMapper extends MyMapper { + + /** + * 查询 + * + * @param orgRelationQueryDTO + * @return + * @author sr on 2022-05-25 + */ + List listOrgRelationDTO(@Param("param") OrgRelationQueryDTO orgRelationQueryDTO); + + List listOrg(@Param("param") OrgRelationQueryOrgDTO orgRelationQueryOrgDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/org/dto/ImportDetailOrgDTO.java b/src/main/java/com/newyetai/usercenter/org/dto/ImportDetailOrgDTO.java new file mode 100644 index 0000000..20ee006 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/dto/ImportDetailOrgDTO.java @@ -0,0 +1,101 @@ +package com.newyetai.usercenter.org.dto; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.component.commonimport.dto.ImportDetailSuperDTO; + +import cn.hutool.core.util.StrUtil; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.SuperBuilder; + +import java.util.Date; + +/** + * 机构导入表 + * + * @author guixinman + * @since 1.0.0 2024-06-12 + */ +@ApiModel("机构导入表") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class ImportDetailOrgDTO extends ImportDetailSuperDTO { + private static final long serialVersionUID = 1L; + + @ApiModelProperty("导入任务ID") + private Long mainId; + + @ApiModelProperty("机构ID") + private Long orgId; + + @ApiModelProperty("模板全量数据") + private String dataJson; + + @ApiModelProperty("机构名称") + private String orgName; + + @ApiModelProperty("机构类型(1.平台 2.渠道代理商 3.普通机构 4.定制机构 5.散户机构 6.产品机构)") + private String type; + + @ApiModelProperty("招聘岗位类型") + private String recruitPositionType; + + @ApiModelProperty("管理员姓名") + private String realName; + + @ApiModelProperty("手机号") + private String phone; + + @ApiModelProperty("统一社会信用代码") + private String creditCode; + + @ApiModelProperty("注册地址") + private String registeredAddress; + + @ApiModelProperty("规模 数据字典") + private String companySize; + + @ApiModelProperty("所属行业") + private String trade; + + @ApiModelProperty("机构描述") + private String description; + + @ApiModelProperty("任务地点全称") + private String addressName; + + @ApiModelProperty("任务地点编码") + private String addressCode; + + /** + * 上级机构名称 + */ + private String parentOrgName; + + @ApiModelProperty("明细状态") + private Integer detailStatus; + + @ApiModelProperty("失败原因") + private String failReason; + + @ApiModelProperty("外部生成明细id") + private Long extraDetailId; + + @ApiModelProperty("备注") + private String remark; + + public void appendFailMsg(String msg) { + if (StrUtil.isEmpty(msg)) { + return; + } + if (StrUtil.isEmpty(getFailReason())) { + setFailReason(msg); + } else { + setFailReason(String.join(",", getFailReason(), msg)); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/org/dto/ImportDetailOrgExecuteDTO.java b/src/main/java/com/newyetai/usercenter/org/dto/ImportDetailOrgExecuteDTO.java new file mode 100644 index 0000000..f6a3aca --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/dto/ImportDetailOrgExecuteDTO.java @@ -0,0 +1,14 @@ +package com.newyetai.usercenter.org.dto; + +import com.newyetai.component.commonimport.dto.ImportExecuteSuperDTO; + +import lombok.Data; + +/** + * @description: 确定导入DTO + * @author: guixinman + * @create: 2024-06-12 13:41 + **/ +@Data +public class ImportDetailOrgExecuteDTO extends ImportExecuteSuperDTO { +} diff --git a/src/main/java/com/newyetai/usercenter/org/dto/ImportDetailOrgExportDTO.java b/src/main/java/com/newyetai/usercenter/org/dto/ImportDetailOrgExportDTO.java new file mode 100644 index 0000000..1631ea5 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/dto/ImportDetailOrgExportDTO.java @@ -0,0 +1,65 @@ +package com.newyetai.usercenter.org.dto; + +import com.alibaba.excel.annotation.ExcelProperty; + +import java.io.Serializable; + + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @description: + * @author: guixinman + * @create: 2024-06-13 10:41 + **/ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ImportDetailOrgExportDTO implements Serializable { + + @ExcelProperty("机构名称") + private String orgName; + + @ExcelProperty("机构类型") + private String type; + + @ExcelProperty("招聘岗位类型") + private String recruitPositionType; + + @ExcelProperty("管理员姓名") + private String realName; + + @ExcelProperty("手机号") + private String phone; + + @ExcelProperty("统一社会信用代码") + private String creditCode; + + @ExcelProperty("注册地址") + private String registeredAddress; + + @ExcelProperty("规模") + private String companySize; + + @ExcelProperty("所属行业") + private String trade; + + @ExcelProperty("机构描述") + private String description; + + @ExcelProperty("任务地点全称") + private String addressName; + + @ExcelProperty("上级机构名称") + private String parentOrgName; + + @ExcelProperty("失败原因") + private String failReason; + + @ExcelProperty("备注") + private String remark; +} diff --git a/src/main/java/com/newyetai/usercenter/org/dto/ImportDetailOrgListenerDTO.java b/src/main/java/com/newyetai/usercenter/org/dto/ImportDetailOrgListenerDTO.java new file mode 100644 index 0000000..169bb5c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/dto/ImportDetailOrgListenerDTO.java @@ -0,0 +1,53 @@ +package com.newyetai.usercenter.org.dto; + +import com.newyetai.component.commonimport.service.IImportDetailForm; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @description: 机构导入 + * @author: guixinman + * @create: 2024-06-12 13:42 + **/ +@Data +public class ImportDetailOrgListenerDTO implements IImportDetailForm { + + @ApiModelProperty("机构名称") + private String orgName; + + @ApiModelProperty("机构类型(1.平台 2.渠道代理商 3.普通机构 4.定制机构 5.散户机构 6.产品机构)") + private String type; + + @ApiModelProperty("招聘岗位类型") + private String recruitPositionType; + + @ApiModelProperty("管理员姓名") + private String realName; + + @ApiModelProperty("手机号") + private String phone; + + @ApiModelProperty("统一社会信用代码") + private String creditCode; + + @ApiModelProperty("注册地址") + private String registeredAddress; + + @ApiModelProperty("规模 数据字典") + private String companySize; + + @ApiModelProperty("所属行业") + private String trade; + + @ApiModelProperty("任务地点全称") + private String addressName; + + @ApiModelProperty("机构描述") + private String description; + + /** + * 上级机构名称 + */ + private String parentOrgName; +} diff --git a/src/main/java/com/newyetai/usercenter/org/dto/ImportDetailOrgOperatorDTO.java b/src/main/java/com/newyetai/usercenter/org/dto/ImportDetailOrgOperatorDTO.java new file mode 100644 index 0000000..1f7a93a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/dto/ImportDetailOrgOperatorDTO.java @@ -0,0 +1,101 @@ +package com.newyetai.usercenter.org.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.format.annotation.DateTimeFormat; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +import java.util.Date; + +/** + * 机构导入表 + * + * @author guixinman + * @since 1.0.0 2024-06-12 + */ +@ApiModel("机构导入表") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ImportDetailOrgOperatorDTO implements Serializable { + private static final long serialVersionUID = 1L; + + private Long id; + + @ApiModelProperty("导入任务ID") + private Long mainId; + + @ApiModelProperty("机构ID") + private Long orgId; + + @ApiModelProperty("模板全量数据") + private String dataJson; + + @ApiModelProperty("机构名称") + private String orgName; + + @ApiModelProperty("机构类型(1.平台 2.渠道代理商 3.普通机构 4.定制机构 5.散户机构 6.产品机构)") + private String type; + + @ApiModelProperty("招聘岗位类型") + private String recruitPositionType; + + @ApiModelProperty("管理员姓名") + private String realName; + + @ApiModelProperty("手机号") + private String phone; + + @ApiModelProperty("统一社会信用代码") + private String creditCode; + + @ApiModelProperty("注册地址") + private String registeredAddress; + + @ApiModelProperty("规模 数据字典") + private String companySize; + + @ApiModelProperty("所属行业") + private String trade; + + @ApiModelProperty("机构描述") + private String description; + + @ApiModelProperty("任务地点全称") + private String addressName; + + @ApiModelProperty("任务地点编码") + private String addressCode; + + /** + * 上级机构名称 + */ + private String parentOrgName; + + @ApiModelProperty("明细状态") + private Integer detailStatus; + + @ApiModelProperty("失败原因") + private String failReason; + + @ApiModelProperty("外部生成明细id") + private Long extraDetailId; + + @ApiModelProperty("备注") + private String remark; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/org/dto/ImportDetailOrgPageQueryDTO.java b/src/main/java/com/newyetai/usercenter/org/dto/ImportDetailOrgPageQueryDTO.java new file mode 100644 index 0000000..dd886e2 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/dto/ImportDetailOrgPageQueryDTO.java @@ -0,0 +1,114 @@ +package com.newyetai.usercenter.org.dto; + +import com.newyetai.common.dto.PageQueryDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import java.io.Serializable; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.format.annotation.DateTimeFormat; + + +import java.util.Date; + +/** + * 机构导入表 + * + * @author guixinman + * @since 1.0.0 2024-06-12 + */ + +@ApiModel("机构导入表") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class ImportDetailOrgPageQueryDTO extends PageQueryDTO { + private static final long serialVersionUID = 1L; + + private Long id; + + @ApiModelProperty("导入任务ID") + private Long mainId; + + @ApiModelProperty("机构ID") + private Long orgId; + + @ApiModelProperty("模板全量数据") + private String dataJson; + + @ApiModelProperty("机构名称 (模糊匹配)") + private String orgNameLike; + + @ApiModelProperty("机构类型(1.平台 2.渠道代理商 3.普通机构 4.定制机构 5.散户机构 6.产品机构)") + private String type; + + @ApiModelProperty("招聘岗位类型") + private String recruitPositionType; + + @ApiModelProperty("管理员姓名") + private String realName; + + @ApiModelProperty("手机号") + private String phone; + + @ApiModelProperty("统一社会信用代码") + private String creditCode; + + @ApiModelProperty("注册地址") + private String registeredAddress; + + @ApiModelProperty("规模 数据字典") + private String companySize; + + @ApiModelProperty("所属行业") + private String trade; + + @ApiModelProperty("机构描述") + private String description; + + @ApiModelProperty("任务地点全称 (模糊匹配)") + private String addressNameLike; + + @ApiModelProperty("任务地点编码") + private String addressCode; + + @ApiModelProperty("明细状态") + private Integer detailStatus; + + @ApiModelProperty("失败原因") + private String failReason; + + @ApiModelProperty("外部生成明细id") + private Long extraDetailId; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("更新时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeStart; + + @ApiModelProperty("更新时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeEnd; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/org/dto/ImportDetailOrgQueryDTO.java b/src/main/java/com/newyetai/usercenter/org/dto/ImportDetailOrgQueryDTO.java new file mode 100644 index 0000000..1f2b125 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/dto/ImportDetailOrgQueryDTO.java @@ -0,0 +1,114 @@ +package com.newyetai.usercenter.org.dto; + +import com.newyetai.common.dto.BaseDTO; + +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; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +/** + * 机构导入表 + * + * @author guixinman + * @since 1.0.0 2024-06-12 + */ +@ApiModel("机构导入表") +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ImportDetailOrgQueryDTO implements Serializable { + private static final long serialVersionUID = 1L; + + private Long id; + + @ApiModelProperty("导入任务ID") + private Long mainId; + + @ApiModelProperty("机构ID") + private Long orgId; + + @ApiModelProperty("模板全量数据") + private String dataJson; + + @ApiModelProperty("机构名称 (模糊匹配)") + private String orgNameLike; + + @ApiModelProperty("机构类型(1.平台 2.渠道代理商 3.普通机构 4.定制机构 5.散户机构 6.产品机构)") + private String type; + + @ApiModelProperty("招聘岗位类型") + private String recruitPositionType; + + @ApiModelProperty("管理员姓名") + private String realName; + + @ApiModelProperty("手机号") + private String phone; + + @ApiModelProperty("统一社会信用代码") + private String creditCode; + + @ApiModelProperty("注册地址") + private String registeredAddress; + + @ApiModelProperty("规模 数据字典") + private String companySize; + + @ApiModelProperty("所属行业") + private String trade; + + @ApiModelProperty("机构描述") + private String description; + + @ApiModelProperty("任务地点全称 (模糊匹配)") + private String addressNameLike; + + @ApiModelProperty("任务地点编码") + private String addressCode; + + @ApiModelProperty("明细状态") + private Integer detailStatus; + + @ApiModelProperty("失败原因") + private String failReason; + + @ApiModelProperty("外部生成明细id") + private Long extraDetailId; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + @ApiModelProperty("更新时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeStart; + + @ApiModelProperty("更新时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTimeEnd; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/org/dto/OrgCreateDTO.java b/src/main/java/com/newyetai/usercenter/org/dto/OrgCreateDTO.java new file mode 100644 index 0000000..d6f6092 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/dto/OrgCreateDTO.java @@ -0,0 +1,100 @@ +package com.newyetai.usercenter.org.dto; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +import org.junit.jupiter.params.shadow.com.univocity.parsers.annotations.Trim; + +import com.newyetai.common.annotation.trimAndUpper.TrimAndUpper; +import com.newyetai.common.dto.BaseOperateDTO; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.annotation.Expression; +import com.newyetai.common.validation.annotation.Phone; +import com.newyetai.common.validation.constants.ValidProviderEnum; +import com.newyetai.usercenter.enums.OrgTypeEnum; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Builder +@Data +@ApiModel(description = "机构") +public class OrgCreateDTO extends BaseOperateDTO{ + + /** **/ + private static final long serialVersionUID = 7745034806528023290L; + + @ApiModelProperty("机构类型") + @NotEmpty(message = "机构类型不能为空") + private String type; + @ApiModelProperty("机构名称") + @NotBlank(message = "机构名称不能为空") + private String orgName; + @ApiModelProperty("手机号") + @Expression(type = ValidProviderEnum.PHONE, message = "管理员手机号格式不正确") + private String phone; + + @NotBlank(message = "管理员姓名不能为空") + @ApiModelProperty("管理员姓名") + private String realName; + + @ApiModelProperty("唯一社会信用代码") + @NotBlank(message = "唯一社会信用代码不能为空") + private String creditCode; + @ApiModelProperty("企业所在地") +// @NotBlank(message = "企业所在地不能为空") + private String addressCode; + @ApiModelProperty("上级机构") + @NotNull(message = "上级机构不能为空") + private Long parentId; + + /** + * 招聘岗位类型 + */ + private String recruitPositionType; + + /** + * 营业执照 + */ + private String businessLicense; + + /** + * 注册地址 + */ + private String registeredAddress; + + /** + * 规模 + */ + private String companySize; + + /** + * 所属行业 + */ + private String trade; + + /** + * 机构描述 + */ + private String description; + + /** + * 企业所在地 地点全称 + */ + @NotBlank(message = "企业所在地不能为空") + private String addressName; + + /** + * logo + */ + private String orgLogo; +} diff --git a/src/main/java/com/newyetai/usercenter/org/dto/OrgDTO.java b/src/main/java/com/newyetai/usercenter/org/dto/OrgDTO.java new file mode 100644 index 0000000..6ac403d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/dto/OrgDTO.java @@ -0,0 +1,151 @@ +package com.newyetai.usercenter.org.dto; + +import com.google.common.collect.Lists; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.common.util.TreeNode; + +import java.util.List; +import java.util.Optional; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 机构 + * @author sr on 2024-04-18 + */ +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class OrgDTO extends BaseDTO implements TreeNode { + + /** **/ + private static final long serialVersionUID = 5038840445751414497L; + + /** + * 机构名称 + */ + private String orgName; + + /** + * 机构编号 + */ + private String orgCode; + + /** + * 机构类型 + */ + private String type; + + /** + * 企业所在地 地点编码 + */ + private String addressCode; + + /** + * 企业所在地 地点全称 + */ + private String addressName; + + /** + * 机构描述 + */ + private String description; + + /** + * 是否启用 + */ + private Boolean enable; + + /** + * 是否激活 + */ + private Boolean activated; + + /** + * 上级机构ID + */ + private Long parentId; + + /** 上级机构名称 **/ + private String parentName; + + /** + * 机构账号激活码 + */ + private String activationCode; + + /** + * 手机号码 + */ + private String phone; + + /** + * 唯一社会信用代码 + */ + private String creditCode; + + /** + * 所属行业 + */ + private String trade; + + /** + * logo + */ + private String orgLogo; + + /** + * 注册地址 + */ + private String registeredAddress; + + /** + * 规模 + */ + private String companySize; + + /** + * 营业执照 + */ + private String businessLicense; + + private String realName; + + /** + * 招聘岗位类型 + */ + private String recruitPositionType; + + @JsonIgnore + private List children = Lists.newArrayList(); + public List getChildren() { + if (this.children == null) { + this.children = Lists.newArrayList(); + } + return this.children; + } + + public void setChildren(List children) { + this.children = children; + } + + @Override + public void addChildren(OrgDTO node) { + List orgDTOS = Optional.ofNullable(getChildren()) + .orElse(Lists.newArrayList()); + orgDTOS.add(node); + setChildren(orgDTOS); + } + + public Long getParentId() { + return Optional.ofNullable(parentId).orElse(0L); + } +} diff --git a/src/main/java/com/newyetai/usercenter/org/dto/OrgModifyDTO.java b/src/main/java/com/newyetai/usercenter/org/dto/OrgModifyDTO.java new file mode 100644 index 0000000..95b9157 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/dto/OrgModifyDTO.java @@ -0,0 +1,72 @@ +package com.newyetai.usercenter.org.dto; + +import com.newyetai.common.dto.BaseOperateDTO; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import lombok.Data; + +/** + * @description: + * @author: guixinman + * @create: 2024-04-26 10:53 + **/ +@Data +public class OrgModifyDTO extends BaseOperateDTO { + + @NotNull(message = "id不能为空") + private Long id; + + /** + * logo + */ + private String orgLogo; + + /** + * 规模 + */ + private String companySize; + + /** + * 企业所在地 地点编码 + */ + private String addressCode; + + /** + * 营业执照 + */ + private String businessLicense; + + /** + * 唯一社会信用代码 + */ + private String creditCode; + + /** + * 企业所在地 地点全称 + */ + private String addressName; + + /** + * 注册地址 + */ + private String registeredAddress; + + + /** + * 所属行业 + */ + private String trade; + + /** + * 机构描述 + */ + private String description; + + /** + * 是否启用 + */ + private Boolean enable; + +} diff --git a/src/main/java/com/newyetai/usercenter/org/dto/OrgQueryDTO.java b/src/main/java/com/newyetai/usercenter/org/dto/OrgQueryDTO.java new file mode 100644 index 0000000..5a58ee7 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/dto/OrgQueryDTO.java @@ -0,0 +1,62 @@ +package com.newyetai.usercenter.org.dto; + + +import java.util.Date; +import java.util.Set; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +import org.springframework.format.annotation.DateTimeFormat; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.newyetai.common.dto.PageQueryDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2024-04-09 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "动态表格查询条件") +public class OrgQueryDTO extends PageQueryDTO{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + @ApiModelProperty("机构类型") + @NotEmpty(message = "机构类型不能为空") + private String type; + private Set types; + @ApiModelProperty("机构名称") + private String orgName; + @ApiModelProperty("机构名称(模糊匹配)") + private String orgNameLike; + @ApiModelProperty("机构编号") + private String orgCode; + @ApiModelProperty("上级机构") + private Long parentId; + @ApiModelProperty("是否启用") + private Boolean enable; + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + private Set orgIds; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/org/dto/OrgRelationCreateDTO.java b/src/main/java/com/newyetai/usercenter/org/dto/OrgRelationCreateDTO.java new file mode 100644 index 0000000..e043adc --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/dto/OrgRelationCreateDTO.java @@ -0,0 +1,50 @@ +package com.newyetai.usercenter.org.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotNull; + +import com.newyetai.common.dto.BaseOperateDTO; +import com.newyetai.usercenter.org.constant.OrgTypeConstants; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Builder.Default; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2022-05-25 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "机构关系表创建") +public class OrgRelationCreateDTO extends BaseOperateDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + + @ApiModelProperty("机构id") + @NotNull(message = "机构id不能为空") + private Long orgId; + @ApiModelProperty("类型") + @Default + @NotNull(message = "机构类型不能为空") + private Integer orgType = OrgTypeConstants.recruit.SIMPLE; + @ApiModelProperty("上级id") + private Long parentId; + @ApiModelProperty("平台编码") + @NotNull(message = "平台编码不能为空") + private Integer platformCode; + @ApiModelProperty("平台名称") + private String platformName; + + + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/org/dto/OrgRelationDTO.java b/src/main/java/com/newyetai/usercenter/org/dto/OrgRelationDTO.java new file mode 100644 index 0000000..c48454e --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/dto/OrgRelationDTO.java @@ -0,0 +1,42 @@ +package com.newyetai.usercenter.org.dto; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.usercenter.notice.dto.NoticeReceiverSettingDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2022-05-25 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@ApiModel(description = "机构关系表") +public class OrgRelationDTO extends BaseDTO { + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("机构id") + private Long orgId; + @ApiModelProperty("类型") + private Integer orgType; + @ApiModelProperty("上级id") + private Long parentId; + @ApiModelProperty("路径") + private String path; + @ApiModelProperty("平台编码") + private Integer platformCode; + @ApiModelProperty("平台名称") + private String platformName; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/org/dto/OrgRelationModifyDTO.java b/src/main/java/com/newyetai/usercenter/org/dto/OrgRelationModifyDTO.java new file mode 100644 index 0000000..dbd22e8 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/dto/OrgRelationModifyDTO.java @@ -0,0 +1,37 @@ +package com.newyetai.usercenter.org.dto; + +import javax.validation.constraints.NotNull; + +import com.newyetai.common.dto.BaseOperateDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2022-05-25 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "机构关系表操作") +public class OrgRelationModifyDTO extends BaseOperateDTO{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @NotNull(message = "id不能为空") + private Long id; + @ApiModelProperty("类型") + private Integer orgType; + @ApiModelProperty("上级id") + private Long parentId; + @ApiModelProperty("平台名称") + private String platformName; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/org/dto/OrgRelationQueryDTO.java b/src/main/java/com/newyetai/usercenter/org/dto/OrgRelationQueryDTO.java new file mode 100644 index 0000000..5272b6e --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/dto/OrgRelationQueryDTO.java @@ -0,0 +1,36 @@ +package com.newyetai.usercenter.org.dto; + +import java.io.Serializable; + +import com.newyetai.common.dto.PageQueryDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2022-05-25 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "机构关系表查询条件") +public class OrgRelationQueryDTO extends PageQueryDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + @ApiModelProperty("机构id") + private Long orgId; + @ApiModelProperty("平台编码") + private Integer platformCode; + @ApiModelProperty("上级机构id") + private Long upOrgId; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/org/dto/OrgRelationQueryOrgDTO.java b/src/main/java/com/newyetai/usercenter/org/dto/OrgRelationQueryOrgDTO.java new file mode 100644 index 0000000..b0aab15 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/dto/OrgRelationQueryOrgDTO.java @@ -0,0 +1,45 @@ +package com.newyetai.usercenter.org.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotNull; + +import com.newyetai.common.dto.PageQueryDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2022-05-25 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "机构关系表查询条件") +public class OrgRelationQueryOrgDTO extends PageQueryDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("类型") + private Integer orgType; + + @ApiModelProperty("机构名称-模糊") + private Integer orgNameLike; + + @ApiModelProperty("平台编码") + @NotNull(message = "平台编码不能为空") + private Integer platformCode; + + @ApiModelProperty("上层机构id") + private Long upOrgId; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/org/dto/SelectOrgDTO.java b/src/main/java/com/newyetai/usercenter/org/dto/SelectOrgDTO.java new file mode 100644 index 0000000..3c038ae --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/dto/SelectOrgDTO.java @@ -0,0 +1,31 @@ +package com.newyetai.usercenter.org.dto; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "机构信息(供选择)") +@Builder +public class SelectOrgDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 59302802862397459L; + + @ApiModelProperty("机构id") + private Long orgId; + + @ApiModelProperty("机构名称") + private String orgName; + + @ApiModelProperty("上级id") + private Long parentId; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/org/dto/UcOpenOrgPartQueryDTO.java b/src/main/java/com/newyetai/usercenter/org/dto/UcOpenOrgPartQueryDTO.java new file mode 100644 index 0000000..3d7dd18 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/dto/UcOpenOrgPartQueryDTO.java @@ -0,0 +1,24 @@ +package com.newyetai.usercenter.org.dto; + +import com.newyetai.common.dto.BaseOperateDTO; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import java.io.Serializable; + +/** + * @description: 提供给第三方使用(灵宸) + * @author: guixinman + * @create: 2023-04-25 14:39 + **/ +@Data +public class UcOpenOrgPartQueryDTO extends BaseOperateDTO implements Serializable{ + + private static final long serialVersionUID = -2069753408108532710L; + + @NotBlank(message = "产品编号不能为空") + @ApiModelProperty("产品编号") + private String productCode; +} + diff --git a/src/main/java/com/newyetai/usercenter/org/dto/UcOrgInfoReqDTO.java b/src/main/java/com/newyetai/usercenter/org/dto/UcOrgInfoReqDTO.java new file mode 100644 index 0000000..f98d928 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/dto/UcOrgInfoReqDTO.java @@ -0,0 +1,27 @@ +package com.newyetai.usercenter.org.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +@Data +@Builder +@ApiModel("个人端-企业信息-请求DTO") +@NoArgsConstructor +@AllArgsConstructor +public class UcOrgInfoReqDTO implements Serializable { + + private static final long serialVersionUID = 8213441568149895962L; + @ApiModelProperty("机构ID") + @NotNull(message = "机构ID不能为空") + private Long orgId; + + @ApiModelProperty("机构名称") + private String orgName; +} diff --git a/src/main/java/com/newyetai/usercenter/org/dto/UcOrgInfoResDTO.java b/src/main/java/com/newyetai/usercenter/org/dto/UcOrgInfoResDTO.java new file mode 100644 index 0000000..52fee0d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/dto/UcOrgInfoResDTO.java @@ -0,0 +1,40 @@ +package com.newyetai.usercenter.org.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; + +@Data +@Builder +@ApiModel("个人端-企业信息-响应DTO") +@NoArgsConstructor +@AllArgsConstructor +public class UcOrgInfoResDTO implements Serializable { + private static final long serialVersionUID = 8612024599522361343L; + + @ApiModelProperty("机构ID") + private Long orgId; + + @ApiModelProperty("机构Code") + private String orgCode; + + @ApiModelProperty("机构描述") + private String description; + + @ApiModelProperty("机构名称") + private String orgName; + + @ApiModelProperty("机构管理员联系电话") + private String phone; + + @ApiModelProperty("机构管理员名称") + private String realName; + + @ApiModelProperty("优质企业") + private Boolean quality; +} diff --git a/src/main/java/com/newyetai/usercenter/org/dto/UcOrgPartInfoDTO.java b/src/main/java/com/newyetai/usercenter/org/dto/UcOrgPartInfoDTO.java new file mode 100644 index 0000000..c803a0f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/dto/UcOrgPartInfoDTO.java @@ -0,0 +1,47 @@ +package com.newyetai.usercenter.org.dto; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +import org.apache.commons.lang3.StringUtils; + +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; +import java.util.Arrays; +import java.util.List; + +@Data +@Builder +@ApiModel("个人端-企业部分信息-响应DTO") +@NoArgsConstructor +@AllArgsConstructor +public class UcOrgPartInfoDTO implements Serializable { + private static final long serialVersionUID = 8612024599522361343L; + + @ApiModelProperty("机构ID") + private Long orgId; + + @ApiModelProperty("机构名称") + private String orgName; + + @ApiModelProperty("企业电话") + private String phone; + + @ApiModelProperty("开户银行") + private String bankName; + + @ApiModelProperty("银行账号") + private String bankAccount; + + @JsonIgnore + @ApiModelProperty("科目") + private String categoryName; + + private List categoryNames; + +} diff --git a/src/main/java/com/newyetai/usercenter/org/dto/UcOrgPartQueryDTO.java b/src/main/java/com/newyetai/usercenter/org/dto/UcOrgPartQueryDTO.java new file mode 100644 index 0000000..9e9e2e1 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/dto/UcOrgPartQueryDTO.java @@ -0,0 +1,20 @@ +package com.newyetai.usercenter.org.dto; + +import com.newyetai.common.dto.PageQueryDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +@EqualsAndHashCode(callSuper = true) +@Data +@Builder +@ApiModel("个人端-企业部分信息-分页查询DTO") +@NoArgsConstructor +@AllArgsConstructor +public class UcOrgPartQueryDTO extends PageQueryDTO { + + private static final long serialVersionUID = -3571112498546235421L; + + @ApiModelProperty("机构名称") + private String orgName; +} diff --git a/src/main/java/com/newyetai/usercenter/org/entity/ImportDetailOrg.java b/src/main/java/com/newyetai/usercenter/org/entity/ImportDetailOrg.java new file mode 100644 index 0000000..552bcec --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/entity/ImportDetailOrg.java @@ -0,0 +1,107 @@ +package com.newyetai.usercenter.org.entity; + +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import com.baomidou.mybatisplus.annotation.*; +import com.newyetai.common.entity.BaseEntity; + +/** + * 机构导入表 + * + * @author guixinman + * @since 1.0.0 2024-06-12 + */ +@TableName(value = "hr_import_detail_org") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class ImportDetailOrg extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * 导入任务ID + */ + private Long mainId; + /** + * 机构ID + */ + private Long orgId; + /** + * 模板全量数据 + */ + private String dataJson; + /** + * 机构名称 + */ + private String orgName; + /** + * 机构类型(1.平台 2.渠道代理商 3.普通机构 4.定制机构 5.散户机构 6.产品机构) + */ + private String type; + /** + * 招聘岗位类型 + */ + private String recruitPositionType; + + @ApiModelProperty("管理员姓名") + private String realName; + + /** + * 手机号 + */ + private String phone; + /** + * 统一社会信用代码 + */ + private String creditCode; + /** + * 注册地址 + */ + private String registeredAddress; + /** + * 规模 数据字典 + */ + private String companySize; + /** + * 所属行业 + */ + private String trade; + /** + * 机构描述 + */ + private String description; + /** + * 任务地点全称 + */ + private String addressName; + + /** + * 任务地点编码 + */ + private String addressCode; + + /** + * 上级机构名称 + */ + private String parentOrgName; + /** + * 明细状态 + */ + private Integer detailStatus; + /** + * 失败原因 + */ + private String failReason; + /** + * 外部生成明细id + */ + private Long extraDetailId; + /** + * 备注 + */ + private String remark; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/org/entity/Org.java b/src/main/java/com/newyetai/usercenter/org/entity/Org.java new file mode 100644 index 0000000..7ea8b4e --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/entity/Org.java @@ -0,0 +1,110 @@ +package com.newyetai.usercenter.org.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; +import lombok.*; +import lombok.experimental.Accessors; + +/** + * @author sr on 2024-04-18 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@TableName("xs_org") +public class Org extends BaseEntity { + + + /** + * 机构名称 + */ + private String orgName; + + /** + * 机构编号 + */ + private String orgCode; + + /** + * 机构类型 + */ + private String type; + + /** + * 企业所在地 地点编码 + */ + private String addressCode; + + /** + * 企业所在地 地点全称 + */ + private String addressName; + + /** + * 机构描述 + */ + private String description; + + /** + * 是否启用 + */ + private Boolean enable; + + /** + * 是否激活 + */ + private Boolean activated; + + /** + * 父机构ID + */ + private Long parentId; + + /** + * 机构账号激活码 + */ + private String activationCode; + + /** + * 手机号码 + */ + private String phone; + + /** + * 唯一社会信用代码 + */ + private String creditCode; + + /** + * 所属行业 + */ + private String trade; + + /** + * logo + */ + private String orgLogo; + + /** + * 注册地址 + */ + private String registeredAddress; + + /** + * 规模 + */ + private String companySize; + + /** + * 营业执照 + */ + private String businessLicense; + + /** + * 招聘岗位类型 + */ + private String recruitPositionType; +} diff --git a/src/main/java/com/newyetai/usercenter/org/entity/OrgRelation.java b/src/main/java/com/newyetai/usercenter/org/entity/OrgRelation.java new file mode 100644 index 0000000..1313047 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/entity/OrgRelation.java @@ -0,0 +1,41 @@ +package com.newyetai.usercenter.org.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 机构关系表 + * + * @author sr on 2022-05-25 + */ +@TableName("uc_org_relation") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +public class OrgRelation extends BaseEntity { + + /** **/ + private static final long serialVersionUID = 1L; + + /** 机构id **/ + private Long orgId; + /** 类型 **/ + private Integer orgType; + /** 上级id **/ + private Long parentId; + /** 路径 **/ + private String path; + /** 平台编码 **/ + private Integer platformCode; + /** 平台名称 **/ + private String platformName; + +} diff --git a/src/main/java/com/newyetai/usercenter/org/enums/RecruitPositionTypeEnum.java b/src/main/java/com/newyetai/usercenter/org/enums/RecruitPositionTypeEnum.java new file mode 100644 index 0000000..9cafee3 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/enums/RecruitPositionTypeEnum.java @@ -0,0 +1,27 @@ +package com.newyetai.usercenter.org.enums; + +public enum RecruitPositionTypeEnum { + ODD_JOB("1", "零工"), + GENERAL_WORKER("2", "普工"), + ODD_JOB_OR_GENERAL_WORKER("3", "零工+普工"); + + private String type; + /** + * 类型描述 + */ + private String desc; + + + RecruitPositionTypeEnum(String type, String desc) { + this.type = type; + this.desc = desc; + } + + public String getType() { + return type; + } + + public String getDesc() { + return desc; + } +} diff --git a/src/main/java/com/newyetai/usercenter/org/mapper/ImportDetailOrgMapper.xml b/src/main/java/com/newyetai/usercenter/org/mapper/ImportDetailOrgMapper.xml new file mode 100644 index 0000000..fe5f605 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/mapper/ImportDetailOrgMapper.xml @@ -0,0 +1,94 @@ + + + + + + + + + + + FROM + hr_import_detail_org t + WHERE t.deleted = 0 + + AND t.id = #{param.id} + + + AND t.main_id = #{param.mainId} + + + AND t.org_id = #{param.orgId} + + + AND t.data_json = #{param.dataJson} + + + + AND t.org_name like #{orgNameLike} + + + AND t.type = #{param.type} + + + AND t.recruit_position_type = #{param.recruitPositionType} + + + AND t.phone = #{param.phone} + + + AND t.credit_code = #{param.creditCode} + + + AND t.registered_address = #{param.registeredAddress} + + + AND t.company_size = #{param.companySize} + + + AND t.trade = #{param.trade} + + + AND t.description = #{param.description} + + + + AND t.address_name like #{addressNameLike} + + + AND t.address_code = #{param.addressCode} + + + AND t.detail_status = #{param.detailStatus} + + + AND t.fail_reason = #{param.failReason} + + + AND t.extra_detail_id = #{param.extraDetailId} + + + AND t.remark = #{param.remark} + + + AND t.create_time >= #{param.createTimeStart} + + + AND t.create_time <= #{param.createTimeEnd} + + + AND t.update_time >= #{param.updateTimeStart} + + + AND t.update_time <= #{param.updateTimeEnd} + + ORDER BY t.id DESC + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/org/mapper/OrgMapper.xml b/src/main/java/com/newyetai/usercenter/org/mapper/OrgMapper.xml new file mode 100644 index 0000000..b12263c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/mapper/OrgMapper.xml @@ -0,0 +1,164 @@ + + + + + + update xs_org + set + update_by = #{param.operateUserId}, + update_time = now(), + org_logo = #{param.orgLogo}, + company_size = #{param.companySize}, + address_code = #{param.addressCode}, + business_license = #{param.businessLicense}, + credit_code = #{param.creditCode}, + address_name = #{param.addressName}, + registered_address = #{param.registeredAddress}, + trade = #{param.trade}, + description = #{param.description}, + enable = #{param.enable} + where id = #{param.id} and deleted = 0 + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/com/newyetai/usercenter/org/mapper/OrgRelationMapper.xml b/src/main/java/com/newyetai/usercenter/org/mapper/OrgRelationMapper.xml new file mode 100644 index 0000000..2dc6e97 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/mapper/OrgRelationMapper.xml @@ -0,0 +1,50 @@ + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/org/mapstruct/ImportDetailOrgConvert.java b/src/main/java/com/newyetai/usercenter/org/mapstruct/ImportDetailOrgConvert.java new file mode 100644 index 0000000..e01dbd1 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/mapstruct/ImportDetailOrgConvert.java @@ -0,0 +1,28 @@ +package com.newyetai.usercenter.org.mapstruct; + +import com.newyetai.usercenter.org.entity.ImportDetailOrg; +import com.newyetai.usercenter.org.dto.ImportDetailOrgDTO; +import com.newyetai.usercenter.org.dto.ImportDetailOrgOperatorDTO; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 机构导入表 + * + * @author guixinman + * @since 1.0.0 2024-06-12 + */ +@Mapper +public interface ImportDetailOrgConvert { + ImportDetailOrgConvert INSTANCE = Mappers.getMapper(ImportDetailOrgConvert.class); + + ImportDetailOrg convert(ImportDetailOrgDTO dto); + + ImportDetailOrgDTO convert(ImportDetailOrg entity); + + ImportDetailOrg convert(ImportDetailOrgOperatorDTO dto); + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/org/mapstruct/OrgMapMapper.java b/src/main/java/com/newyetai/usercenter/org/mapstruct/OrgMapMapper.java new file mode 100644 index 0000000..c6b511f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/mapstruct/OrgMapMapper.java @@ -0,0 +1,35 @@ +package com.newyetai.usercenter.org.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.newyetai.usercenter.org.dto.OrgCreateDTO; +import com.newyetai.usercenter.org.dto.OrgDTO; +import com.newyetai.usercenter.org.entity.Org; + +/** + * @author sr on 2024-04-18 + */ +@Mapper +public interface OrgMapMapper { + + OrgMapMapper INSTANCE = + Mappers.getMapper(OrgMapMapper.class); + + /** + * @param orgDto + * @return + * @author sr on 2024-04-18 + */ + Org toEntity( + OrgDTO orgDto); + + /** + * @param orgCreateDTO + * @return + * @author sr on 2024-04-18 + */ + Org toEntity(OrgCreateDTO orgCreateDTO); + + +} diff --git a/src/main/java/com/newyetai/usercenter/org/mapstruct/OrgRelationMapMapper.java b/src/main/java/com/newyetai/usercenter/org/mapstruct/OrgRelationMapMapper.java new file mode 100644 index 0000000..2126276 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/mapstruct/OrgRelationMapMapper.java @@ -0,0 +1,40 @@ +package com.newyetai.usercenter.org.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.newyetai.usercenter.org.dto.OrgRelationCreateDTO; +import com.newyetai.usercenter.org.dto.OrgRelationDTO; +import com.newyetai.usercenter.org.entity.OrgRelation; +import com.newyetai.usercenter.org.dto.OrgRelationModifyDTO; + +/** + * @author sr on 2022-05-25 + */ +@Mapper +public interface OrgRelationMapMapper { + + OrgRelationMapMapper INSTANCE = + Mappers.getMapper(OrgRelationMapMapper.class); + + /** + * dto to entity + * + * @param orgRelationDto + * @return + * @author sr on 2022-05-25 + */ + OrgRelation toEntity( + OrgRelationDTO orgRelationDto); + + + /** + * @param orgRelationCreateDTO + * @return + * @author sr on 2022-05-25 + */ + OrgRelation toEntity(OrgRelationCreateDTO orgRelationCreateDTO); + + OrgRelation to(OrgRelationModifyDTO orgRelationModifyDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/org/service/ImportDetailOrgService.java b/src/main/java/com/newyetai/usercenter/org/service/ImportDetailOrgService.java new file mode 100644 index 0000000..e178087 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/service/ImportDetailOrgService.java @@ -0,0 +1,70 @@ +package com.newyetai.usercenter.org.service; + +import org.springframework.validation.annotation.Validated; + +import javax.validation.Valid; +import javax.validation.groups.Default; + +import java.util.List; + +import com.newyetai.usercenter.org.dto.*; + +/** + * 机构导入表 + * + * @author guixinman + * @since 1.0.0 2024-06-12 + */ +@Validated(Default.class) +public interface ImportDetailOrgService { + + /** + * 机构导入表 - 创建 + * + * @param operatorDto 操作dto + * @return {@link ImportDetailOrgDTO} + */ + ImportDetailOrgDTO create(@Valid ImportDetailOrgOperatorDTO operatorDto); + + /** + * 机构导入表 - 修改 + * + * @param operatorDto 操作dto + * @return {@link ImportDetailOrgDTO} + */ + ImportDetailOrgDTO modify(@Valid ImportDetailOrgOperatorDTO operatorDto); + + /** + * 机构导入表 - 删除 + * + * @param id id + * @return {@link ImportDetailOrgDTO} + */ + ImportDetailOrgDTO delete(Long id); + + /** + * 机构导入表 - 根据ID查询单个 + * + * @param id id + * @return {@link ImportDetailOrgDTO} + */ + ImportDetailOrgDTO findById(Long id); + + /** + * 机构导入表 - 列表查询 + * + * @param queryDTO 列表查询dto + * @return {@link List}<{@link ImportDetailOrgDTO}> + */ + List list(ImportDetailOrgQueryDTO queryDTO); + + /** + * 机构导入表 - 分页查询 + * + * @param queryDTO 分页查询dto + * @return {@link ImportDetailOrgDTO} + */ + List page(ImportDetailOrgPageQueryDTO queryDTO); + + void batchCreate(List importDetailOrgDTOS); +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/org/service/OrgRelationService.java b/src/main/java/com/newyetai/usercenter/org/service/OrgRelationService.java new file mode 100644 index 0000000..ac156f1 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/service/OrgRelationService.java @@ -0,0 +1,67 @@ +package com.newyetai.usercenter.org.service; + +import java.util.List; + +import javax.validation.Valid; + +import com.newyetai.usercenter.org.dto.OrgRelationQueryDTO; +import com.newyetai.usercenter.org.dto.OrgRelationQueryOrgDTO; +import com.newyetai.usercenter.org.dto.OrgRelationModifyDTO; +import com.newyetai.usercenter.org.dto.OrgRelationCreateDTO; +import com.newyetai.usercenter.org.dto.OrgRelationDTO; + +/** + * 机构关系表 + * + * @author sr on 2022-05-25 + */ +public interface OrgRelationService { + + /** + * 新增 + * + * @param orgRelationOperateDTO + * @return + * @author sr on 2022-05-25 + */ + Long create(@Valid OrgRelationCreateDTO orgRelationCreateDTO); + + /** + * 修改 + * + * @param orgRelationModifyDTO + * @author sr on 2022-05-25 + */ + void modify(OrgRelationModifyDTO orgRelationModifyDTO); + + /** + * 查询 + * + * @param orgRelationQueryDTO + * @return + * @author sr on 2022-05-25 + */ + List list(OrgRelationQueryDTO orgRelationQueryDTO); + + /** + * 分页查询 + * + * @param orgRelationQueryDTO + * @return + * @author sr on 2022-05-25 + */ + void page(OrgRelationQueryDTO orgRelationQueryDTO); + + /** + * 单个查询 + * + * @param orgRelationQueryDTO + * @return + * @author sr on 2022-05-25 + */ + OrgRelationDTO find(OrgRelationQueryDTO orgRelationQueryDTO); + + void pageOrg(OrgRelationQueryOrgDTO orgRelationQueryOrgDTO); + + +} diff --git a/src/main/java/com/newyetai/usercenter/org/service/OrgService.java b/src/main/java/com/newyetai/usercenter/org/service/OrgService.java new file mode 100644 index 0000000..ba72bb5 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/service/OrgService.java @@ -0,0 +1,70 @@ +package com.newyetai.usercenter.org.service; + +import java.util.List; +import java.util.Set; + +import javax.validation.Valid; +import javax.validation.groups.Default; + +import org.springframework.validation.annotation.Validated; + +import com.newyetai.usercenter.org.dto.OrgCreateDTO; +import com.newyetai.usercenter.org.dto.OrgDTO; +import com.newyetai.usercenter.org.dto.OrgModifyDTO; +import com.newyetai.usercenter.org.dto.OrgQueryDTO; +import com.newyetai.usercenter.org.dto.UcOpenOrgPartQueryDTO; +import com.newyetai.usercenter.org.dto.UcOrgInfoReqDTO; +import com.newyetai.usercenter.org.dto.UcOrgInfoResDTO; +import com.newyetai.usercenter.org.dto.UcOrgPartInfoDTO; +import com.newyetai.usercenter.org.dto.UcOrgPartQueryDTO; + +@Validated(Default.class) +public interface OrgService { + + Long create(@Valid OrgCreateDTO orgCreateDTO); + + List list(OrgQueryDTO orgQueryDTO); + void page(OrgQueryDTO orgQueryDTO); + OrgDTO find(OrgQueryDTO orgQueryDTO); + + void modify(OrgModifyDTO orgModifyDTO); + + /** + * 获取所有子级机构id+自己 + */ + Set childrenOrgIdList(Long parentId); + + + + /** + * 企业信息 + * + * @param reqDTO 点播dto + * @return {@link UcOrgInfoResDTO} + */ + UcOrgInfoResDTO info(@Valid UcOrgInfoReqDTO reqDTO); + + /** + * 页面 + * + * @param queryDTO 查询dto + * @return {@link UcOrgPartInfoDTO} + */ + List orgPartInfoList(UcOrgPartQueryDTO queryDTO); + + /** + * 找到所有组织 + * + * @return {@link List}<{@link UcOrgProductInfoDTO}> + */ + List findAllOrg(); + + /** + * @description: 开放接口--查询机构部分的信息 + * @return: + * @author: guixinman + * @param: 产品编号 + */ + List openOrgPartInfoList(UcOpenOrgPartQueryDTO queryDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/org/service/impl/ImportDetailOrgExcelListener.java b/src/main/java/com/newyetai/usercenter/org/service/impl/ImportDetailOrgExcelListener.java new file mode 100644 index 0000000..74c0869 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/service/impl/ImportDetailOrgExcelListener.java @@ -0,0 +1,66 @@ +package com.newyetai.usercenter.org.service.impl; + +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.event.AnalysisEventListener; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.usercenter.org.dto.ImportDetailOrgListenerDTO; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @description: + * @author: guixinman + * @create: 2024-06-12 15:35 + **/ +public class ImportDetailOrgExcelListener extends AnalysisEventListener { + + private List dtos; + private Map headMap = new HashMap<>(); + + public ImportDetailOrgExcelListener() { + this.dtos = new ArrayList<>(); + } + + + @Override + public void invoke(ImportDetailOrgListenerDTO data, AnalysisContext analysisContext) { + dtos.add(data); + } + + @Override + public void doAfterAllAnalysed(AnalysisContext analysisContext) { + + } + + @Override + public void invokeHeadMap(Map headMap, AnalysisContext context) { + this.headMap = headMap; + if (headMap.isEmpty()) { + throw new BusinessException("导入模板表头有误"); + } + + if (headMap.size() != 12) { + throw new BusinessException("导入模板表头有误"); + } + Assert.isTrue(headMap.get(0).toString().contains("机构名称"), "导入模板表头有误"); + Assert.isTrue(headMap.get(1).toString().contains("机构类型"), "导入模板表头有误"); + Assert.isTrue(headMap.get(2).toString().contains("招聘岗位类型"), "导入模板表头有误"); + Assert.isTrue(headMap.get(3).toString().contains("管理员姓名"), "导入模板表头有误"); + Assert.isTrue(headMap.get(4).toString().contains("管理员手机号"), "导入模板表头有误"); + Assert.isTrue(headMap.get(5).toString().contains("统一社会信用代码"), "导入模板表头有误"); + Assert.isTrue(headMap.get(6).toString().contains("注册地址"), "导入模板表头有误"); + Assert.isTrue(headMap.get(7).toString().contains("企业规模"), "导入模板表头有误"); + Assert.isTrue(headMap.get(8).toString().contains("所属行业"), "导入模板表头有误"); + Assert.isTrue(headMap.get(9).toString().contains("企业经营地址"), "导入模板表头有误"); + Assert.isTrue(headMap.get(10).toString().contains("机构简介"), "导入模板表头有误"); + Assert.isTrue(headMap.get(11).toString().contains("上级机构"), "导入模板表头有误"); + } + + public List getDtos() { + return dtos; + } +} diff --git a/src/main/java/com/newyetai/usercenter/org/service/impl/ImportDetailOrgProvider.java b/src/main/java/com/newyetai/usercenter/org/service/impl/ImportDetailOrgProvider.java new file mode 100644 index 0000000..ef28a87 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/service/impl/ImportDetailOrgProvider.java @@ -0,0 +1,400 @@ +package com.newyetai.usercenter.org.service.impl; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; + +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.read.builder.ExcelReaderBuilder; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.newyetai.common.dto.ExportHeadDetailInfoDTO; +import com.newyetai.common.dto.ExportHeadInfoDTO; +import com.newyetai.common.easyexcel.ExcelUtil; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.component.commonimport.constant.ImportDetailStatusEnum; +import com.newyetai.component.commonimport.constant.ImportStatusEnum; +import com.newyetai.component.commonimport.constant.ImportTypeEnum; +import com.newyetai.component.commonimport.dto.ImportDetailPageDTO; +import com.newyetai.component.commonimport.dto.ImportMainDTO; +import com.newyetai.component.commonimport.dto.ImportMainQueryDTO; +import com.newyetai.component.commonimport.dto.ImportMainUpdateDTO; +import com.newyetai.component.commonimport.service.ImportMainService; +import com.newyetai.component.commonimport.service.impl.AbstractCommonImportProvider; +import com.newyetai.component.dict.util.DictUtils; +import com.newyetai.component.file.entity.FileRecord; +import com.newyetai.component.file.service.FileRecordService; +import com.newyetai.recruit.position.dto.ImportDetailPositionExportDTO; +import com.newyetai.recruit.position.dto.ImportDetailPositionListenerDTO; +import com.newyetai.recruit.position.service.impl.ImportPositionExcelListener; +import com.newyetai.recruit.talent.service.ImportDetailTalentService; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.org.dao.OrgMapper; +import com.newyetai.usercenter.org.dto.ImportDetailOrgDTO; +import com.newyetai.usercenter.org.dto.ImportDetailOrgExecuteDTO; +import com.newyetai.usercenter.org.dto.ImportDetailOrgExportDTO; +import com.newyetai.usercenter.org.dto.ImportDetailOrgListenerDTO; +import com.newyetai.usercenter.org.dto.ImportDetailOrgOperatorDTO; +import com.newyetai.usercenter.org.dto.ImportDetailOrgPageQueryDTO; +import com.newyetai.usercenter.org.dto.OrgCreateDTO; +import com.newyetai.usercenter.org.dto.OrgQueryDTO; +import com.newyetai.usercenter.org.entity.ImportDetailOrg; +import com.newyetai.usercenter.org.entity.Org; +import com.newyetai.usercenter.org.service.ImportDetailOrgService; +import com.newyetai.usercenter.org.service.OrgService; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.InputStream; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + + +import javax.annotation.Resource; + +import lombok.extern.slf4j.Slf4j; + +/** + * @description: + * @author: guixinman + * @create: 2024-06-12 13:45 + **/ +@Service +@Slf4j +public class ImportDetailOrgProvider extends AbstractCommonImportProvider { + + @Autowired + private ImportMainService importMainService; + + @Autowired + private FileRecordService fileRecordService; + + @Autowired + private ImportDetailOrgService importDetailOrgService; + + @Autowired + private OrgService orgService; + + @Resource + private OrgMapper orgMapper; + + + public ImportDetailOrgProvider(ImportMainService imprImportMainService) { + super(imprImportMainService); + } + + @Override + public String getType() { + return ImportTypeEnum.ORG.getType(); + } + + @Override + public Page pageDetail(ImportDetailPageDTO importDetailPageDTO) { + ImportDetailOrgPageQueryDTO queryDTO = new ImportDetailOrgPageQueryDTO(); + BeanUtils.copyProperties(importDetailPageDTO, queryDTO); + queryDTO.setType(null); + importDetailOrgService.page(queryDTO); + return queryDTO.getPageResult(); + } + + @Override + public void importDetailExport(ImportDetailPageDTO importDetailPageDTO) { + ImportDetailOrgPageQueryDTO queryDTO = new ImportDetailOrgPageQueryDTO(); + BeanUtils.copyProperties(importDetailPageDTO, queryDTO); + queryDTO.setType(null); + queryDTO.disablePage(); + List list = importDetailOrgService.page(queryDTO); + + List exportDTOList = list.stream().map(dto -> { + ImportDetailOrgExportDTO exportDTO = JsonUtils.toObject(dto.getDataJson(), ImportDetailOrgExportDTO.class); + exportDTO.setRemark(dto.getRemark()); + exportDTO.setFailReason(dto.getFailReason()); + return exportDTO; + }).collect(Collectors.toList()); + + if (org.springframework.util.CollectionUtils.isEmpty(exportDTOList)) { + return; + } + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); + String commonImportDetailStatus = DictUtils.getCodeNameMap("common_import_detail_status").get(String.valueOf(importDetailPageDTO.getDetailStatus())); + String fileName = "机构导入" + ( StringUtils.isNotBlank(commonImportDetailStatus) ? commonImportDetailStatus : "") + "明细导出" + "(" + formatter.format(LocalDateTime.now()) + ")"; + + ExportHeadInfoDTO infoDTO = ExportHeadInfoDTO.builder() + .fileName(fileName) + .build(); + List heads = infoDTO.getHeads(); + heads.add(ExportHeadDetailInfoDTO.builder().head("机构名称").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("机构类型").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("招聘岗位类型").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("管理员姓名").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("手机号").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("统一社会信用代码").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("注册地址").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("规模").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("所属行业").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("机构描述").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("任务地点全称").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("上级机构名称").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("失败原因").build()); + heads.add(ExportHeadDetailInfoDTO.builder().head("备注").build()); + + List datas = Lists.newArrayList(); + for (ImportDetailOrgExportDTO dto : exportDTOList) { + List objects = Lists.newArrayList(); + datas.add(objects); + objects.add(dto.getOrgName()); + objects.add(dto.getType()); + objects.add(dto.getRecruitPositionType()); + objects.add(dto.getRealName()); + objects.add(dto.getPhone()); + objects.add(dto.getCreditCode()); + objects.add(dto.getRegisteredAddress()); + objects.add(dto.getCompanySize()); + objects.add(dto.getTrade()); + objects.add(dto.getDescription()); + objects.add(dto.getAddressName()); + objects.add(dto.getParentOrgName()); + objects.add(dto.getFailReason()); + objects.add(dto.getRemark()); + + } + infoDTO.setDatas(datas); + + ExcelUtil.dynamicExportTemplate(infoDTO); + + } + + @Override + public List analy(Long mainId) { + // 解析文件+明细 + ImportMainDTO importMainDTO = importMainService.find(ImportMainQueryDTO.builder().id(mainId).build()); + Assert.notNull(importMainDTO, "未查询到导入的数据"); + FileRecord fileRecord; + try { + fileRecord = fileRecordService.find(FileRecord.builder().fileCode(importMainDTO.getFileCode()).build()); + } catch (Exception e) { + log.info("导入文件异常,", e); + fileRecord = null; + } + Assert.notNull(fileRecord, "上传文件不存在"); + + try (InputStream is = fileRecordService.getFile(importMainDTO.getFileCode())) { + ImportDetailOrgExcelListener listener = new ImportDetailOrgExcelListener(); + ExcelReaderBuilder reader = EasyExcel.read(is, ImportDetailOrgListenerDTO.class, listener); + reader.sheet().doRead(); + List dtos = listener.getDtos(); + Assert.isTrue(!dtos.isEmpty(), "导入文件无有效数据"); + return dtos; + } catch (Exception e) { + throw new BusinessException(e.getMessage()); + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void checkAndSave(Long mainId, List detailCreateDtos) { + //更改状态为校验中 + ImportMainUpdateDTO updateDto = ImportMainUpdateDTO.builder().id(mainId) + .oldStatusSet(Sets.newHashSet(ImportStatusEnum.INIT.getStatus())) + .newStatus(ImportStatusEnum.CHECKING.getStatus()) + .build(); + importMainService.modify(updateDto); + + List importDetailOrgDTOS = new ArrayList<>(); + for (ImportDetailOrgListenerDTO detailCreateDto : detailCreateDtos) { + ImportDetailOrgDTO importDetailOrgDTO = new ImportDetailOrgDTO(); + + this.checkAndFill(importDetailOrgDTO, detailCreateDto); + + if (StringUtils.isNotBlank(importDetailOrgDTO.getFailReason())) { + importDetailOrgDTO.setDetailStatus(ImportDetailStatusEnum.CHECK_FAIL.getStatus()); + } else { + importDetailOrgDTO.setDetailStatus(ImportDetailStatusEnum.CHECK_SUCCESS.getStatus()); + } + importDetailOrgDTO.setMainId(mainId); + importDetailOrgDTO.setOrgId(UserContextHolder.getExistLoginOrgId()); + importDetailOrgDTOS.add(importDetailOrgDTO); + } + + importDetailOrgService.batchCreate(importDetailOrgDTOS); + super.finishCheck(mainId, importDetailOrgDTOS); + } + + private void checkAndFill(ImportDetailOrgDTO importDetailOrgDTO, ImportDetailOrgListenerDTO importDetailOrgListenerDTO) { + BeanUtils.copyProperties(importDetailOrgListenerDTO, importDetailOrgDTO); + importDetailOrgDTO.setDataJson(JsonUtils.toJsonString(importDetailOrgListenerDTO)); + + if (StringUtils.isBlank(importDetailOrgDTO.getOrgName())) { + importDetailOrgDTO.appendFailMsg("机构名称不能为空"); + } else { + if (importDetailOrgDTO.getOrgName().length() > 32) { + importDetailOrgDTO.appendFailMsg("机构名称超过最大限制长度"); + importDetailOrgDTO.setOrgName(null); + } else { + Org org = orgMapper.selectOne(new LambdaQueryWrapper().eq(Org::getDeleted, false).eq(Org::getOrgName, importDetailOrgDTO.getOrgName())); + if (Objects.nonNull(org)) { + importDetailOrgDTO.appendFailMsg("机构已存在"); + } + } + + } + + if (StringUtils.isBlank(importDetailOrgDTO.getType())) { + importDetailOrgDTO.appendFailMsg("机构类型不能为空"); + } else { + String orgType = DictUtils.getNameCodeMap("org_type").get(importDetailOrgDTO.getType()); + if (StringUtils.isBlank(orgType)) { + importDetailOrgDTO.appendFailMsg("机构类型未匹配到"); + importDetailOrgDTO.setType(null); + }else { + importDetailOrgDTO.setType(orgType); + } + } + + if (StringUtils.isBlank(importDetailOrgDTO.getRecruitPositionType())) { + importDetailOrgDTO.appendFailMsg("招聘岗位类型不能为空"); + } else { + String recruitPositionType = DictUtils.getNameCodeMap("recruit_position_type").get(importDetailOrgDTO.getRecruitPositionType()); + if (StringUtils.isBlank(recruitPositionType)) { + importDetailOrgDTO.appendFailMsg("招聘岗位类型未匹配到"); + importDetailOrgDTO.setRecruitPositionType(null); + }else { + importDetailOrgDTO.setRecruitPositionType(recruitPositionType); + } + + } + + if (StringUtils.isBlank(importDetailOrgDTO.getRealName())) { + importDetailOrgDTO.appendFailMsg("管理员姓名不能为空"); + } else if (importDetailOrgDTO.getRealName().length() > 32) { + importDetailOrgDTO.appendFailMsg("管理员姓名超过最大限制长度"); + importDetailOrgDTO.setRealName(null); + } + + if (StringUtils.isBlank(importDetailOrgDTO.getPhone())) { + importDetailOrgDTO.appendFailMsg("管理员手机号不能为空"); + } else if (importDetailOrgDTO.getPhone().length() > 32) { + importDetailOrgDTO.appendFailMsg("管理员手机号超过最大限制长度"); + importDetailOrgDTO.setPhone(null); + } + + if (StringUtils.isBlank(importDetailOrgDTO.getCreditCode())) { + importDetailOrgDTO.appendFailMsg("统一社会信用代码不能为空"); + } else if (importDetailOrgDTO.getCreditCode().length() > 64) { + importDetailOrgDTO.appendFailMsg("统一社会信用代码超过最大限制长度"); + importDetailOrgDTO.setCreditCode(null); + } + + if (StringUtils.isBlank(importDetailOrgDTO.getRegisteredAddress())) { + importDetailOrgDTO.appendFailMsg("注册地址不能为空"); + } else if (importDetailOrgDTO.getRegisteredAddress().length() > 128) { + importDetailOrgDTO.appendFailMsg("注册地址超过最大限制长度"); + importDetailOrgDTO.setRegisteredAddress(null); + } + + if (StringUtils.isBlank(importDetailOrgDTO.getCompanySize())) { + importDetailOrgDTO.appendFailMsg("企业规模不能为空"); + } else { + String companySize = DictUtils.getNameCodeMap("company_size").get(importDetailOrgDTO.getCompanySize()); + if (StringUtils.isBlank(companySize)) { + importDetailOrgDTO.appendFailMsg("企业规模未匹配到"); + importDetailOrgDTO.setCompanySize(null); + }else { + importDetailOrgDTO.setCompanySize(companySize); + } + } + + if (StringUtils.isNotBlank(importDetailOrgDTO.getTrade())) { + String industryType = DictUtils.getNameCodeMap("industry_type").get(importDetailOrgDTO.getTrade()); + if (StringUtils.isBlank(industryType)) { + importDetailOrgDTO.appendFailMsg("所属行业未匹配到"); + importDetailOrgDTO.setTrade(null); + }else { + importDetailOrgDTO.setTrade(industryType); + } + } + + if (StringUtils.isBlank(importDetailOrgDTO.getAddressName())) { + importDetailOrgDTO.appendFailMsg("企业所在地不能为空"); + } else if (importDetailOrgDTO.getAddressName().length() > 128) { + importDetailOrgDTO.appendFailMsg("企业所在地超过最大限制长度"); + importDetailOrgDTO.setAddressName(null); + } + + if (StringUtils.isNotBlank(importDetailOrgDTO.getDescription())) { + if (importDetailOrgDTO.getDescription().length() > 1024) { + importDetailOrgDTO.appendFailMsg("机构简介超过最大限制长度"); + importDetailOrgDTO.setDescription(null); + } + } + + if (StringUtils.isNotBlank(importDetailOrgDTO.getParentOrgName())) { + if (importDetailOrgDTO.getParentOrgName().length() > 32) { + importDetailOrgDTO.appendFailMsg("上级机构超过最大限制长度"); + importDetailOrgDTO.setParentOrgName(null); + }else { + Org org = orgMapper.selectOne(new LambdaQueryWrapper().eq(Org::getDeleted, false).eq(Org::getOrgName, importDetailOrgDTO.getParentOrgName())); + if (Objects.isNull(org)) { + importDetailOrgDTO.appendFailMsg("上级机构未匹配到"); + importDetailOrgDTO.setParentOrgName(null); + } + } + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public Long execute(ImportDetailOrgExecuteDTO executeDto) { + Long mainId = executeDto.getMainId(); + Assert.notNull(mainId, "参数异常"); + + ImportMainDTO importMainDTO = importMainService.find(ImportMainQueryDTO.builder().id(mainId).build()); + Assert.notNull(importMainDTO, "未查询到导入数据"); + ImportDetailOrgPageQueryDTO queryDTO = new ImportDetailOrgPageQueryDTO(); + queryDTO.disablePage(); + queryDTO.setMainId(mainId); + queryDTO.setDetailStatus(ImportDetailStatusEnum.CHECK_SUCCESS.getStatus()); + List importDetailOrgDTOS = importDetailOrgService.page(queryDTO); + + if (CollectionUtils.isEmpty(importDetailOrgDTOS)) { + throw new BusinessException("未查询到成功的明细数据"); + } + + for (ImportDetailOrgDTO importDetailOrgDTO : importDetailOrgDTOS) { + + OrgCreateDTO orgCreateDTO = new OrgCreateDTO(); + BeanUtils.copyProperties(importDetailOrgDTO, orgCreateDTO); + + orgCreateDTO.setAddressCode("31"); + + //文本填写上级机构名称,不填则上级机构为当前导入机构,填则根据填写的名称匹配系统机构,匹配不上做失败记录处理。 + if (StringUtils.isBlank(importDetailOrgDTO.getParentOrgName())) { + orgCreateDTO.setParentId(UserContextHolder.getExistLoginOrgId()); + }else { + Org org = orgMapper.selectOne(new LambdaQueryWrapper().eq(Org::getDeleted, false).eq(Org::getOrgName, importDetailOrgDTO.getParentOrgName())); + if (Objects.nonNull(org)) { + orgCreateDTO.setParentId(org.getId()); + } + } + + Long orgId = orgService.create(orgCreateDTO); + + ImportDetailOrgOperatorDTO importDetailOrgOperatorDTO = new ImportDetailOrgOperatorDTO(); + BeanUtils.copyProperties(importDetailOrgDTO, importDetailOrgOperatorDTO); + importDetailOrgOperatorDTO.setExtraDetailId(orgId); + importDetailOrgService.modify(importDetailOrgOperatorDTO); + } + + return null; + } +} diff --git a/src/main/java/com/newyetai/usercenter/org/service/impl/ImportDetailOrgServiceImpl.java b/src/main/java/com/newyetai/usercenter/org/service/impl/ImportDetailOrgServiceImpl.java new file mode 100644 index 0000000..43c6139 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/service/impl/ImportDetailOrgServiceImpl.java @@ -0,0 +1,101 @@ +package com.newyetai.usercenter.org.service.impl; + +import lombok.extern.slf4j.Slf4j; + +import com.newyetai.recruit.position.entity.ImportDetailPosition; +import com.newyetai.usercenter.org.entity.ImportDetailOrg; +import com.newyetai.usercenter.org.dto.*; +import com.newyetai.usercenter.org.dao.ImportDetailOrgMapper; +import com.newyetai.usercenter.org.mapstruct.ImportDetailOrgConvert; +import com.newyetai.usercenter.org.service.ImportDetailOrgService; + +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.common.util.UserContextHolder; + +import javax.annotation.Resource; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * 机构导入表 + * + * @author guixinman + * @since 1.0.0 2024-06-12 + */ +@Slf4j +@Service +public class ImportDetailOrgServiceImpl implements ImportDetailOrgService { + + @Resource + private ImportDetailOrgMapper importDetailOrgMapper; + + @Override + public ImportDetailOrgDTO create(ImportDetailOrgOperatorDTO operatorDto) { + ImportDetailOrg importDetailOrg = ImportDetailOrgConvert.INSTANCE.convert(operatorDto); + importDetailOrgMapper.saveEntity(importDetailOrg); + return ImportDetailOrgConvert.INSTANCE.convert(importDetailOrg); + } + + @Override + public ImportDetailOrgDTO modify(ImportDetailOrgOperatorDTO operatorDto) { + ImportDetailOrgDTO importDetailOrgDto = this.findById(operatorDto.getId()); + if (Objects.isNull(importDetailOrgDto)) { + return null; + } + ImportDetailOrg importDetailOrg = ImportDetailOrgConvert.INSTANCE.convert(operatorDto); + importDetailOrgMapper.updateEntitySelective(importDetailOrg); + return this.findById(operatorDto.getId()); + } + + @Override + public ImportDetailOrgDTO delete(Long id) { + ImportDetailOrgDTO importDetailOrgDto = this.findById(id); + if (Objects.isNull(importDetailOrgDto)) { + return null; + } + ImportDetailOrg importDetailOrg = ImportDetailOrg.builder().build(); + importDetailOrg.setId(id); + importDetailOrgMapper.deleteEntity(importDetailOrg, UserContextHolder.getLoginUserId()); + return importDetailOrgDto; + } + + @Override + public ImportDetailOrgDTO findById(Long id) { + ImportDetailOrg importDetailOrg = importDetailOrgMapper.getById(id); + if (Objects.isNull(importDetailOrg)) { + return null; + } + return ImportDetailOrgConvert.INSTANCE.convert(importDetailOrg); + } + + @Override + public List list(ImportDetailOrgQueryDTO queryDTO) { + return importDetailOrgMapper.list(queryDTO); + } + + @Override + public List page(ImportDetailOrgPageQueryDTO queryDTO) { + return importDetailOrgMapper.page(queryDTO); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void batchCreate(List importDetailOrgDTOS) { + if (CollectionUtils.isEmpty(importDetailOrgDTOS)) { + return; + } + + List importDetailOrgs= importDetailOrgDTOS.stream().map(dto -> { + ImportDetailOrg importDetailOrg = new ImportDetailOrg(); + BeanUtils.copyProperties(dto, importDetailOrg); + return importDetailOrg; + }).collect(Collectors.toList()); + + importDetailOrgMapper.saveEntites(importDetailOrgs); + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/org/service/impl/OrgRelationServiceImpl.java b/src/main/java/com/newyetai/usercenter/org/service/impl/OrgRelationServiceImpl.java new file mode 100644 index 0000000..5440685 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/service/impl/OrgRelationServiceImpl.java @@ -0,0 +1,106 @@ +package com.newyetai.usercenter.org.service.impl; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.usercenter.constants.OrgConstants; +import com.newyetai.usercenter.org.constant.OrgTypeConstants; +import com.newyetai.usercenter.org.dao.OrgRelationMapper; +import com.newyetai.usercenter.org.service.OrgRelationService; +import com.newyetai.usercenter.org.dto.OrgRelationQueryDTO; +import com.newyetai.usercenter.org.dto.OrgRelationQueryOrgDTO; +import com.newyetai.usercenter.org.dto.OrgQueryDTO; +import com.newyetai.usercenter.org.dto.OrgRelationCreateDTO; +import com.newyetai.usercenter.org.dto.OrgRelationDTO; +import com.newyetai.usercenter.org.dto.OrgRelationModifyDTO; +import com.newyetai.usercenter.org.entity.Org; +import com.newyetai.usercenter.org.entity.OrgRelation; +import com.newyetai.usercenter.org.mapstruct.OrgMapMapper; +import com.newyetai.usercenter.org.mapstruct.OrgRelationMapMapper; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.frame.redis.dto.LockDTO; +import com.newyetai.frame.redis.redisson.RedissonUtils; +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.ListUtil; + +/** + * @author sr on 2022-05-25 + */ +@Service +public class OrgRelationServiceImpl implements OrgRelationService { + + @Autowired + private OrgRelationMapper orgRelationMapper; + + + public static LockDTO getLockDTO(Long orgId) { + Assert.notNull(orgId, "机构id不能为空"); + return LockDTO.builder().methodName("orgrelation").tryLockWaitTime(0L) + .arg(orgId.toString()) + .failMsg("该机构关系正在被操作") + .build(); + } + + @Override + @Transactional + public Long create(OrgRelationCreateDTO orgRelationCreateDTO) { + Long orgId = orgRelationCreateDTO.getOrgId(); + Integer platformCode = orgRelationCreateDTO.getPlatformCode(); + OrgRelationDTO existDto = this.find(OrgRelationQueryDTO.builder().orgId(orgId).platformCode(platformCode).build()); + if (existDto != null) { + return existDto.getId(); + } + Long parentId = orgRelationCreateDTO.getParentId(); + if (parentId == null) { + parentId = OrgConstants.PLATFORM_ORG_ID; + orgRelationCreateDTO.setParentId(parentId); + } + OrgRelation orgRelation = OrgRelationMapMapper.INSTANCE.toEntity(orgRelationCreateDTO); + OrgRelationDTO parentOrgRelation = this.find(OrgRelationQueryDTO.builder().orgId(parentId) + .platformCode(platformCode).build()); + Assert.notNull(parentOrgRelation, "上级机构信息有误"); + String path = String.join(CommonConstants.COMMA, parentOrgRelation.getPath(), + orgRelationCreateDTO.getOrgId().toString()); + orgRelation.setPath(path); + orgRelationMapper.saveEntity(orgRelation); + return orgRelation.getId(); + } + + @Override + @Transactional + public void modify(OrgRelationModifyDTO orgRelationModifyDTO) { + Long id = orgRelationModifyDTO.getId(); + OrgRelation existOrgRelation = orgRelationMapper.getById(id); + Assert.notNull(existOrgRelation, "机构关系不存在"); + List children = this + .list(OrgRelationQueryDTO.builder().id(id).upOrgId(existOrgRelation.getOrgId()).build()); + Assert.isTrue(children.isEmpty(), "存在下级机构,不支持修改"); + orgRelationMapper.updateEntitySelective(OrgRelationMapMapper.INSTANCE.to(orgRelationModifyDTO)); + } + + @Override + public List list(OrgRelationQueryDTO orgRelationQueryDTO) { + orgRelationQueryDTO.disablePage(); + return orgRelationMapper.listOrgRelationDTO(orgRelationQueryDTO); + } + + @Override + public void page(OrgRelationQueryDTO orgRelationQueryDTO) { + orgRelationMapper.listOrgRelationDTO(orgRelationQueryDTO); + } + + @Override + public OrgRelationDTO find(OrgRelationQueryDTO orgRelationQueryDTO) { + List orgRelationDTOs = this.list(orgRelationQueryDTO); + return ListUtil.first(orgRelationDTOs); + } + + @Override + public void pageOrg(OrgRelationQueryOrgDTO orgRelationQueryOrgDTO) { + orgRelationMapper.listOrg(orgRelationQueryOrgDTO); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/org/service/impl/OrgServiceImpl.java b/src/main/java/com/newyetai/usercenter/org/service/impl/OrgServiceImpl.java new file mode 100644 index 0000000..389ff27 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/org/service/impl/OrgServiceImpl.java @@ -0,0 +1,225 @@ +package com.newyetai.usercenter.org.service.impl; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.newyetai.codegenerator.util.CodeUtils; +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.constant.SystemCodeEnum; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.EnvironmentUtils; +import com.newyetai.common.util.ListUtil; +import com.newyetai.common.util.TreeHelper; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.frame.redis.dto.LockDTO; +import com.newyetai.frame.redis.redisson.RedissonUtils; +import com.newyetai.recruit.company.dao.HrCompanyMapper; +import com.newyetai.recruit.company.dto.HrCompanyDTO; +import com.newyetai.recruit.company.entity.HrCompany; +import com.newyetai.recruit.company.enums.HrCompanyEnum; +import com.newyetai.recruit.company.service.IHrCompanyService; +import com.newyetai.recruit.position.entity.PositionAudit; +import com.newyetai.usercenter.common.constant.CodeTypeEnum; +import com.newyetai.usercenter.enums.OrgTypeEnum; +import com.newyetai.usercenter.org.dao.OrgMapper; +import com.newyetai.usercenter.org.dto.OrgCreateDTO; +import com.newyetai.usercenter.org.dto.OrgDTO; +import com.newyetai.usercenter.org.dto.OrgModifyDTO; +import com.newyetai.usercenter.org.dto.OrgQueryDTO; +import com.newyetai.usercenter.org.dto.OrgRelationCreateDTO; +import com.newyetai.usercenter.org.dto.UcOpenOrgPartQueryDTO; +import com.newyetai.usercenter.org.dto.UcOrgInfoReqDTO; +import com.newyetai.usercenter.org.dto.UcOrgInfoResDTO; +import com.newyetai.usercenter.org.dto.UcOrgPartInfoDTO; +import com.newyetai.usercenter.org.dto.UcOrgPartQueryDTO; +import com.newyetai.usercenter.org.entity.Org; +import com.newyetai.usercenter.org.mapstruct.OrgMapMapper; +import com.newyetai.usercenter.org.service.OrgRelationService; +import com.newyetai.usercenter.org.service.OrgService; +import com.newyetai.usercenter.permissionpackage.service.UcPermissionOrganizationService; +import com.newyetai.usercenter.user.dto.OrgUserCreateDTO; +import com.newyetai.usercenter.user.service.UserService; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class OrgServiceImpl implements OrgService { + + @Autowired + private OrgMapper orgMapper; + + @Autowired + private UcPermissionOrganizationService permissionOrganizationService; + + @Autowired + private UserService userService; + + @Autowired + private OrgRelationService orgRelationService; + + @Autowired + private HrCompanyMapper companyMapper; + + public static LockDTO getLockDTO(String orgName) { + Assert.notNull(orgName, "机构名称不能为空"); + return LockDTO.builder().methodName("org").tryLockWaitTime(0L) + .arg(orgName) + .failMsg("该机构正在被操作") + .build(); + } + + private void initCreateOrg(Org org) { + org.setOrgCode(CodeUtils.getCode(CodeTypeEnum.ORG.getCodeParam())); + org.setEnable(Boolean.TRUE); + org.setActivated(Boolean.FALSE); + + } + + @Override + @Transactional + public Long create(OrgCreateDTO orgCreateDTO) { + OrgTypeEnum orgTypeEnum = OrgTypeEnum.findByType(orgCreateDTO.getType()); + Assert.notNull(orgTypeEnum, "机构类型有误"); + Assert.isTrue(orgTypeEnum != OrgTypeEnum.ORG_TYPE_PLATFORM, "该机构类型不支持创建"); + String orgName = orgCreateDTO.getOrgName(); + Long orgId = RedissonUtils.lockAndSave(getLockDTO(orgName), + () -> this.find(OrgQueryDTO.builder().orgName(orgName).build()), () -> { + Org org = + OrgMapMapper.INSTANCE.toEntity(orgCreateDTO); + initCreateOrg(org); + orgMapper.saveEntity(org); + return org.getId(); + }, "该机构名称已存在"); + // 创建管理员用户 + userService.createOrgUser(OrgUserCreateDTO.builder().orgId(orgId).phone(orgCreateDTO.getPhone()).realName(orgCreateDTO.getRealName()) + .administrator(Boolean.TRUE).build()); + + Integer orgType = Integer.valueOf(orgCreateDTO.getType()); + // 分配权限包 + permissionOrganizationService.saveOrgByType(orgId, orgType); + // orgrelation上下级 + orgRelationService.create(OrgRelationCreateDTO.builder().orgId(orgId).orgType(orgType) + .platformCode(EnvironmentUtils.getSystemCode()).parentId(orgCreateDTO.getParentId()).build()); + // 用工企业类型-创建自己默认的用工企业 + if (orgTypeEnum == OrgTypeEnum.ORG_TYPE_SIMPLE || orgTypeEnum == OrgTypeEnum.ORG_TYPE_HR) { + companyMapper.saveEntity(HrCompany.builder().orgId(orgId).companyName(orgName) + .companyType(HrCompanyEnum.SELF.getType()).build()); + } + return orgId; + } + + @Override + public List list(OrgQueryDTO orgQueryDTO) { + orgQueryDTO.disablePage(); + return orgMapper.listOrgDTO(orgQueryDTO); + } + + @Override + public void page(OrgQueryDTO orgQueryDTO) { + //小程序有匿名的需要调用。不做权限 + if (Objects.nonNull(UserContextHolder.getLoginOrgId())) { + if (!CommonConstants.PLATFORM_ORG_ID.equals(UserContextHolder.getLoginOrgId())) { + //指定了id就查指定的id + if (Objects.isNull(orgQueryDTO.getId())) { + orgQueryDTO.setOrgIds(this.childrenOrgIdList(UserContextHolder.getLoginOrgId())); + } + } + } + orgMapper.listOrgDTO(orgQueryDTO); + } + + @Override + public OrgDTO find(OrgQueryDTO orgQueryDTO) { + return ListUtil.first(this.list(orgQueryDTO)); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void modify(OrgModifyDTO orgModifyDTO) { + orgMapper.modifyByOrgId(orgModifyDTO); + HrCompany hrCompany = companyMapper.selectOne(new LambdaQueryWrapper() + .eq(HrCompany::getDeleted, false) + .eq(HrCompany::getCompanyType, HrCompanyEnum.SELF.getType()) + .eq(HrCompany::getOrgId, orgModifyDTO.getId()) + ); + if (Objects.nonNull(hrCompany)) { + hrCompany.setCompanyLogo(orgModifyDTO.getOrgLogo()); + companyMapper.updateEntity(hrCompany); + } + + } + + @Override + public Set childrenOrgIdList(Long parentId) { + OrgQueryDTO orgQueryDTO = new OrgQueryDTO(); + List list = this.list(orgQueryDTO); + Set orgIds = TreeHelper.childrenNodeIds(parentId, list); + orgIds.add(parentId); + return orgIds; + } + + // ***********************************分隔符*********************************************** + + @Override + public UcOrgInfoResDTO info(UcOrgInfoReqDTO reqDTO) { + return orgMapper.info(reqDTO); + } + + + @Override + public List orgPartInfoList(UcOrgPartQueryDTO queryDTO) { + return orgMapper.orgPartInfoList(queryDTO); + } + + @Override + public List findAllOrg() { + return orgMapper.findAllOrg(); + } + + @Override + public List openOrgPartInfoList(UcOpenOrgPartQueryDTO queryDTO) { + //sql不分组,代码分组 + List ucOrgPartInfoDTOS = orgMapper.openOrgPartInfoList(queryDTO); + + if (CollectionUtils.isNotEmpty(ucOrgPartInfoDTOS)) { + LinkedHashMap> ucOrgPartInfoDTOMap = + ucOrgPartInfoDTOS.stream().collect(Collectors.groupingBy(UcOrgPartInfoDTO::getOrgId, + LinkedHashMap::new, Collectors.toList())); + List ucOrgPartInfoList = new ArrayList<>(); + + for (Long orgId : ucOrgPartInfoDTOMap.keySet()) { + List dtos = ucOrgPartInfoDTOMap.get(orgId); + + UcOrgPartInfoDTO ucOrgPartInfoDTO = new UcOrgPartInfoDTO(); + ucOrgPartInfoDTO.setOrgId(orgId); + ucOrgPartInfoDTO.setOrgName(dtos.get(0).getOrgName()); + ucOrgPartInfoDTO.setBankAccount(dtos.get(0).getBankAccount()); + ucOrgPartInfoDTO.setBankName(dtos.get(0).getBankName()); + ucOrgPartInfoDTO.setPhone(dtos.get(0).getPhone()); + List categoryNames = + dtos.stream().filter(map -> StringUtils.isNotBlank(map.getCategoryName())) + .map(dto -> dto.getCategoryName()).collect(Collectors.toList()); + ucOrgPartInfoDTO.setCategoryNames(categoryNames); + ucOrgPartInfoList.add(ucOrgPartInfoDTO); + } + return ucOrgPartInfoList; + } + + return ucOrgPartInfoDTOS; + } + + + +} diff --git a/src/main/java/com/newyetai/usercenter/permissionpackage/constants/PermissionPackageConstants.java b/src/main/java/com/newyetai/usercenter/permissionpackage/constants/PermissionPackageConstants.java new file mode 100644 index 0000000..a48c07a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/permissionpackage/constants/PermissionPackageConstants.java @@ -0,0 +1,22 @@ +package com.newyetai.usercenter.permissionpackage.constants; + +/** + * @author : yzq + * create at: 2020/9/14 17:47 + * @description: 权限包常量类 + */ +public class PermissionPackageConstants { + + /** + * 权限包状态:1.有效 2.无效 + **/ + + public static final Integer PERMISSION_PACKAGE_STATUS_NOT_INVALID = 1; + + /** + * 权限包状态:1.有效 2.无效 + **/ + + public static final Integer PERMISSION_PACKAGE_STATUS_INVALID = 2; + +} diff --git a/src/main/java/com/newyetai/usercenter/permissionpackage/controller/UcPermissionPackageController.java b/src/main/java/com/newyetai/usercenter/permissionpackage/controller/UcPermissionPackageController.java new file mode 100644 index 0000000..00f435d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/permissionpackage/controller/UcPermissionPackageController.java @@ -0,0 +1,179 @@ +package com.newyetai.usercenter.permissionpackage.controller; + +import java.util.List; +import java.util.Set; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.validation.Check; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.cache.SecurityCacheUtils; +import com.newyetai.usercenter.permissionpackage.dto.PackageResourcesDTO; +import com.newyetai.usercenter.permissionpackage.dto.PackageResourcesOperateDTO; +import com.newyetai.usercenter.permissionpackage.dto.PackageResourcesPageQueryDTO; +import com.newyetai.usercenter.permissionpackage.dto.PermissionOrganizeDTO; +import com.newyetai.usercenter.permissionpackage.dto.PermissionOrganizePageQueryDTO; +import com.newyetai.usercenter.permissionpackage.dto.PermissionPackageDTO; +import com.newyetai.usercenter.permissionpackage.dto.PermissionPackageOperateDTO; +import com.newyetai.usercenter.permissionpackage.dto.PermissionPackagePageQueryDTO; +import com.newyetai.usercenter.permissionpackage.service.UcPermissionOrganizationService; +import com.newyetai.usercenter.permissionpackage.service.UcPermissionPackageService; +import com.newyetai.usercenter.permissionpackage.service.UcPermissionResourceService; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; + +/** + * 权限包操作 + * + * @author yzq + */ +@Api(tags = "权限包操作") +@RestController +@RequestMapping("/permission_package") +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class UcPermissionPackageController { + + private final UcPermissionPackageService ucPermissionPackageService; + + private final UcPermissionResourceService ucPermissionResourceService; + + private final UcPermissionOrganizationService ucPermissionOrganizationService; + + @ApiOperation("创建权限包") + @PostMapping("/create") + public AlitaResult createPermissionPackage(@Validated(Create.class) + @RequestBody PermissionPackageDTO permissionPackageDTO) { + ucPermissionPackageService.createPermissionPackage(permissionPackageDTO); + SecurityCacheUtils.flushAll(); + return AlitaResult.success(permissionPackageDTO); + } + + @ApiOperation("修改权限包") + @PostMapping("/update") + public AlitaResult updatePermissionPackage( + @Validated(Update.class) @RequestBody PermissionPackageDTO permissionPackageDTO) { + ucPermissionPackageService.updatePermissionPackage(permissionPackageDTO); + SecurityCacheUtils.flushAll(); + return AlitaResult.success(permissionPackageDTO); + } + + @ApiOperation("删除权限包") + @DeleteMapping("/delete/{id}") + public AlitaResult deletePermissionPackageDTO(@PathVariable("id") Long id) { + ucPermissionPackageService.removePermissionPackage(id); + SecurityCacheUtils.flushAll(); + return AlitaResult.success(Boolean.TRUE); + } + + @ApiOperation("查询权限包列表") + @GetMapping("/list") + public AlitaResult> PermissionPackageList( + @Validated PermissionPackagePageQueryDTO permissionPackagePageQueryDTO) { + return AlitaResult + .success(ucPermissionPackageService.list(permissionPackagePageQueryDTO)); + } + + @ApiOperation("查询权限包分页列表") + @GetMapping("/page") + public AlitaResult> pagePermissionPackageList( + @Validated PermissionPackagePageQueryDTO permissionPackagePageQueryDTO) { + ucPermissionPackageService.page(permissionPackagePageQueryDTO); + return AlitaResult.success(permissionPackagePageQueryDTO.getPageResult()); + } + + @ApiOperation("查询权限包下的菜单资源") + @GetMapping("/url_list") + public AlitaResult urlList( + @RequestParam(name = "permissionPackageId", required = + true) Long permissionPackageId, @RequestParam(name = "platformCode", required = + true) Integer platformCode) { + return AlitaResult + .success(ucPermissionResourceService.urlList(permissionPackageId, platformCode)); + } + + @ApiOperation("保存权限包下的菜单资源分配") + @PostMapping("/update_url_list") + public AlitaResult updateUrlList( + @Validated(Update.class) @RequestBody + PermissionPackageOperateDTO permissionPackageOperateDTO) { + ucPermissionResourceService.updateUrlList(permissionPackageOperateDTO); + ucPermissionResourceService.cleanUrlCompentAndInterface(permissionPackageOperateDTO.getPermissionPackageId()); + SecurityCacheUtils.flushAll(); + return AlitaResult.success(permissionPackageOperateDTO); + } + + @ApiOperation("查询对应菜单下组件/接口列表") + @GetMapping("/url_component_list") + public AlitaResult> urlComponentList( + @Validated(Check.class) + PackageResourcesPageQueryDTO packageResourcesPageQueryDTO) { + ucPermissionResourceService.urlComponentList(packageResourcesPageQueryDTO); + return AlitaResult.success(packageResourcesPageQueryDTO.getPageResult()); + } + + @ApiOperation("保存对应菜单下组件/接口列表") + @PostMapping("/save_url_component_list") + public AlitaResult> saveUrlResourcesOperateDTO( + @Validated(Create.class) @RequestBody PackageResourcesDTO packageResourcesDTO) { + ucPermissionResourceService.saveUrlComponentList(packageResourcesDTO); + SecurityCacheUtils.flushAll(); + return AlitaResult.success(packageResourcesDTO.getPackageResourcesOperateDTOList()); + } + + @ApiOperation("查询对应权限包下可分配的机构信息") + @GetMapping("/can_be_allocated_org_list") + public AlitaResult> canBeAllocatedOrgList( + @Validated PermissionOrganizePageQueryDTO permissionOrganizePageQueryDTO) { + ucPermissionOrganizationService.canBeAllocatedOrgList(permissionOrganizePageQueryDTO); + return AlitaResult.success(permissionOrganizePageQueryDTO.getPageResult()); + } + + @ApiOperation("查询对应权限包下已分配的机构信息") + @GetMapping("/allocated_org_list") + public AlitaResult> allocatedOrgList( + @Validated PermissionOrganizePageQueryDTO permissionOrganizePageQueryDTO) { + ucPermissionOrganizationService.allocatedOrgList(permissionOrganizePageQueryDTO); + return AlitaResult.success(permissionOrganizePageQueryDTO.getPageResult()); + } + + @ApiOperation("新增机构分配信息") + @PostMapping("/save_org_list") + public AlitaResult saveOrgList( + @Validated(Create.class) @RequestBody List permissionOrganizeDTOList) { + ucPermissionOrganizationService.saveOrgList(permissionOrganizeDTOList); + return AlitaResult.success(); + } + + @ApiOperation("删除机构分配信息") + @DeleteMapping("/remove_allocated_org/{id}") + public AlitaResult removeAllocatedOrg(@PathVariable("id") Long id) { + ucPermissionOrganizationService.removeAllocatedOrg(id); + SecurityCacheUtils.flushAll(); + return AlitaResult.success(Boolean.TRUE); + } + + @ApiOperation("删除机构分配信息列表") + @PostMapping("/remove_allocated_org_list") + public AlitaResult removeAllocatedOrgList(@RequestBody + Set permissionOrganizeId) { + ucPermissionOrganizationService.removeAllocatedOrgList(permissionOrganizeId); + SecurityCacheUtils.flushAll(); + return AlitaResult.success(Boolean.TRUE); + } + + +} diff --git a/src/main/java/com/newyetai/usercenter/permissionpackage/dao/PermissionPackageMapper.java b/src/main/java/com/newyetai/usercenter/permissionpackage/dao/PermissionPackageMapper.java new file mode 100644 index 0000000..d548048 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/permissionpackage/dao/PermissionPackageMapper.java @@ -0,0 +1,18 @@ +package com.newyetai.usercenter.permissionpackage.dao; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.usercenter.permissionpackage.dto.PermissionPackageDTO; +import com.newyetai.usercenter.permissionpackage.dto.PermissionPackagePageQueryDTO; +import com.newyetai.usercenter.permissionpackage.entity.PermissionPackage; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + * @author : yzq create at: 2020/9/7 17:35 + * @description: 权限包 + */ +public interface PermissionPackageMapper extends MyMapper { + + List listPermissionPackage( + @Param("param") PermissionPackagePageQueryDTO permissionPackagePageQueryDTO); +} diff --git a/src/main/java/com/newyetai/usercenter/permissionpackage/dao/PermissionPackageOrgMapper.java b/src/main/java/com/newyetai/usercenter/permissionpackage/dao/PermissionPackageOrgMapper.java new file mode 100644 index 0000000..434f440 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/permissionpackage/dao/PermissionPackageOrgMapper.java @@ -0,0 +1,21 @@ +package com.newyetai.usercenter.permissionpackage.dao; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.usercenter.permissionpackage.dto.PermissionOrganizeDTO; +import com.newyetai.usercenter.permissionpackage.dto.PermissionOrganizePageQueryDTO; +import com.newyetai.usercenter.permissionpackage.entity.PermissionOrganization; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + * @author : yzq create at: 2020/9/7 17:35 + * @description: 权限包机构关系 + */ +public interface PermissionPackageOrgMapper extends MyMapper { + + List canBeAllocatedOrgList( + @Param("param") PermissionOrganizePageQueryDTO permissionOrganizePageQueryDTO); + + List allocatedOrgList( + @Param("param") PermissionOrganizePageQueryDTO permissionOrganizePageQueryDTO); +} diff --git a/src/main/java/com/newyetai/usercenter/permissionpackage/dao/PermissionResourceMapper.java b/src/main/java/com/newyetai/usercenter/permissionpackage/dao/PermissionResourceMapper.java new file mode 100644 index 0000000..0f69cee --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/permissionpackage/dao/PermissionResourceMapper.java @@ -0,0 +1,41 @@ +package com.newyetai.usercenter.permissionpackage.dao; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.usercenter.permissionpackage.dto.PackageResourcesOperateDTO; +import com.newyetai.usercenter.permissionpackage.dto.PackageResourcesPageQueryDTO; +import com.newyetai.usercenter.permissionpackage.entity.PermissionResources; +import com.newyetai.usercenter.resource.dto.UrlDTO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; +import java.util.Set; + +/** + * @author : yzq create at: 2020/9/7 17:35 + * @description: 权限包 + */ +public interface PermissionResourceMapper extends MyMapper { + + /** + * 查询已经选择的菜单 + * + * @return + */ + List findSelectdUrl(@Param("permissionPackageId") Long permissionPackageId); + + + List urlComponentList( + @Param("param") PackageResourcesPageQueryDTO packageResourcesPageQueryDTO); + + List urlInterfaceList( + @Param("param") PackageResourcesPageQueryDTO packageResourcesPageQueryDTO); + + void removeAllUrlResourcesById(@Param("permissionPackageId") Long permissionPackageId); + + void refreshComponentResourcesInfo(@Param("permissionPackageId") Long permissionPackageId); + + void refreshUrlResourcesInfo(@Param("permissionPackageId") Long permissionPackageId); + + void removeUrlResources(Set removeResourceIds, Long permissionPackageId,Long usrId, + Integer resourceType); +} diff --git a/src/main/java/com/newyetai/usercenter/permissionpackage/dto/PackageResourcesDTO.java b/src/main/java/com/newyetai/usercenter/permissionpackage/dto/PackageResourcesDTO.java new file mode 100644 index 0000000..6d93adf --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/permissionpackage/dto/PackageResourcesDTO.java @@ -0,0 +1,25 @@ +package com.newyetai.usercenter.permissionpackage.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + + +/** + * @author leijiaping + */ +@ApiModel("权限包资源保存DTO") +@Data +@NoArgsConstructor +@AllArgsConstructor +public class PackageResourcesDTO extends PackageResourcesPageQueryDTO implements Serializable { + + @ApiModelProperty("权限包ID不能为空") + private List packageResourcesOperateDTOList; + +} + diff --git a/src/main/java/com/newyetai/usercenter/permissionpackage/dto/PackageResourcesOperateDTO.java b/src/main/java/com/newyetai/usercenter/permissionpackage/dto/PackageResourcesOperateDTO.java new file mode 100644 index 0000000..2379e25 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/permissionpackage/dto/PackageResourcesOperateDTO.java @@ -0,0 +1,61 @@ +package com.newyetai.usercenter.permissionpackage.dto; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; +import com.newyetai.usercenter.constants.SecurityValidateConstants; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; + + +/** + * @author yzq + */ +@ApiModel("权限包资源操作DTO") +@Data +@NoArgsConstructor +@AllArgsConstructor +public class PackageResourcesOperateDTO extends BaseDTO implements Serializable { + + private static final long serialVersionUID = -4203821389531547990L; + + @ApiModelProperty("权限包ID") + @NotNull(message = SecurityValidateConstants.PERMISSION_PACKAGE_ID_NULL, groups = {Create.class}) + private Long permissionPackageId; + + @ApiModelProperty("资源ID") + @NotNull(message = SecurityValidateConstants.COMPONENT_URL_ID_NULL, groups = {Create.class}) + private Long resourceId; + + @ApiModelProperty("资源类型 1.菜单 2.组件 3.接口") + @NotNull(message = SecurityValidateConstants.RESOURCE_TYPE_NULL, groups = {Create.class}) + private Integer resourceType; + + @ApiModelProperty("组件/接口名称") + private String name; + + @ApiModelProperty("接口地址") + private String link; + + @ApiModelProperty("组件编码") + private String code; + + @ApiModelProperty("描述") + private String description; + + @ApiModelProperty("平台编码") + private Integer platformCode; + + @ApiModelProperty("是否授权") + @NotNull(message = SecurityValidateConstants.PERMISSION_SELECTED_FLAG_NULL, groups = { + Create.class, Update.class}) + private Boolean selected; + +} + diff --git a/src/main/java/com/newyetai/usercenter/permissionpackage/dto/PackageResourcesPageQueryDTO.java b/src/main/java/com/newyetai/usercenter/permissionpackage/dto/PackageResourcesPageQueryDTO.java new file mode 100644 index 0000000..34c46ce --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/permissionpackage/dto/PackageResourcesPageQueryDTO.java @@ -0,0 +1,49 @@ +package com.newyetai.usercenter.permissionpackage.dto; + +import com.newyetai.common.dto.PageQueryDTO; +import com.newyetai.common.validation.Check; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.constants.SecurityValidateConstants; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; + + +/** + * @author yzq + */ +@ApiModel("权限包资源查询DTO") +@Data +@NoArgsConstructor +@AllArgsConstructor +public class PackageResourcesPageQueryDTO extends PageQueryDTO + implements + Serializable { + + private static final long serialVersionUID = -4203821389531547990L; + + @ApiModelProperty("权限包ID不能为空") + @NotNull(message = SecurityValidateConstants.PERMISSION_PACKAGE_ID_NULL, groups = {Check.class}) + private Long permissionPackageId; + + @ApiModelProperty("父菜单Id") + @NotNull(message = SecurityValidateConstants.URL_PARENT_ID_NULL, groups = {Check.class}) + private Long urlId; + + @ApiModelProperty("资源类型 1.菜单 2.组件 3.接口") + @NotNull(message = SecurityValidateConstants.RESOURCE_TYPE_NULL, groups = {Check.class}) + private Integer resourceType; + + @ApiModelProperty("是否选中") + private Boolean selected; + +} + diff --git a/src/main/java/com/newyetai/usercenter/permissionpackage/dto/PermissionOrgCreateDTO.java b/src/main/java/com/newyetai/usercenter/permissionpackage/dto/PermissionOrgCreateDTO.java new file mode 100644 index 0000000..05d753b --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/permissionpackage/dto/PermissionOrgCreateDTO.java @@ -0,0 +1,31 @@ +package com.newyetai.usercenter.permissionpackage.dto; + +import java.util.Set; + +import javax.validation.constraints.NotNull; + +import com.newyetai.common.dto.BaseOperateDTO; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class PermissionOrgCreateDTO extends BaseOperateDTO{ + + @ApiModelProperty("权限包ID") + @NotNull(message = "权限包ID不能为空") + private Long permissionPackageId; + + @ApiModelProperty("分配机构ID") + @NotNull(message = "分配机构ID不能为空") + private Set allocationOrgIds; + +} diff --git a/src/main/java/com/newyetai/usercenter/permissionpackage/dto/PermissionOrganizeDTO.java b/src/main/java/com/newyetai/usercenter/permissionpackage/dto/PermissionOrganizeDTO.java new file mode 100644 index 0000000..34cef51 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/permissionpackage/dto/PermissionOrganizeDTO.java @@ -0,0 +1,48 @@ +package com.newyetai.usercenter.permissionpackage.dto; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.common.validation.Create; +import com.newyetai.usercenter.constants.SecurityValidateConstants; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; + + +/** + * @author yzq + */ +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +@SuperBuilder +public class PermissionOrganizeDTO extends BaseDTO implements Serializable { + + private static final long serialVersionUID = 7381062994217834327L; + + @ApiModelProperty("权限包ID") + @NotNull(message = SecurityValidateConstants.PERMISSION_PACKAGE_ID_NULL, groups = + {Create.class}) + private Long permissionPackageId; + + @ApiModelProperty("分配机构ID") + @NotNull(message = SecurityValidateConstants.PERMISSION_ORG_ID_NULL, groups = + {Create.class}) + private Long allocationOrgId; + + @ApiModelProperty("机构编号") + private String orgCode; + + @ApiModelProperty("机构名称") + private String orgName; + + @ApiModelProperty("机构类型") + private Integer orgType; + +} diff --git a/src/main/java/com/newyetai/usercenter/permissionpackage/dto/PermissionOrganizePageQueryDTO.java b/src/main/java/com/newyetai/usercenter/permissionpackage/dto/PermissionOrganizePageQueryDTO.java new file mode 100644 index 0000000..d594071 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/permissionpackage/dto/PermissionOrganizePageQueryDTO.java @@ -0,0 +1,42 @@ +package com.newyetai.usercenter.permissionpackage.dto; + +import com.newyetai.common.dto.PageQueryDTO; +import com.newyetai.usercenter.constants.SecurityValidateConstants; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.Set; + + +/** + * @author yzq + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class PermissionOrganizePageQueryDTO extends PageQueryDTO implements + Serializable { + + private static final long serialVersionUID = -1920827611245718163L; + @ApiModelProperty("权限包ID") + @NotNull(message = SecurityValidateConstants.PERMISSION_PACKAGE_ID_NULL) + private Long permissionPackageId; + + @ApiModelProperty("机构编号") + private String orgCode; + + @ApiModelProperty("机构名称") + private String orgName; + + @ApiModelProperty("机构类型") + private Integer orgType; + + @ApiModelProperty("分配机构ID集合") + private Set allocationOrgIds; +} diff --git a/src/main/java/com/newyetai/usercenter/permissionpackage/dto/PermissionPackageDTO.java b/src/main/java/com/newyetai/usercenter/permissionpackage/dto/PermissionPackageDTO.java new file mode 100644 index 0000000..5c4bef5 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/permissionpackage/dto/PermissionPackageDTO.java @@ -0,0 +1,60 @@ +package com.newyetai.usercenter.permissionpackage.dto; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.common.validation.Check; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; +import com.newyetai.usercenter.constants.SecurityValidateConstants; +import com.newyetai.usercenter.enums.OrgTypeEnum; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.SuperBuilder; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +/** + * @author yzq + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +@ApiModel("权限包DTO") +@SuperBuilder +public class PermissionPackageDTO extends BaseDTO { + + private static final long serialVersionUID = -3829431820106387725L; + + + @ApiModelProperty("权限包名称") + @NotEmpty(message = SecurityValidateConstants.PERMISSION_PACKAGE_NAME_NULL, groups = + {Create.class}) + private String permissionPackageName; + + @ApiModelProperty("权限包类型:参考{@link OrgTypeEnum}") + @NotNull(message = SecurityValidateConstants.PERMISSION_PACKAGE_TYPE_NULL, groups = + {Create.class}) + private Integer permissionPackageType; + + @ApiModelProperty("状态 1.有效 2.失效") + private Integer status; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("应用编码 1.业务系统 2.运营中台 3.用户中心 4.支付系统 5.在线培训 6.转发器 7.风控 8.网关 9.发号器 10.基础框架") + @NotNull(message = SecurityValidateConstants.PLATFORM_CODE_EMPTY, groups = + {Create.class}) + private Integer platformCode; + + @ApiModelProperty("是否授权") + private Boolean selected; + + @ApiModelProperty("分配机构关系表Id") + private Long permissionOrganizeId; + +} diff --git a/src/main/java/com/newyetai/usercenter/permissionpackage/dto/PermissionPackageOperateDTO.java b/src/main/java/com/newyetai/usercenter/permissionpackage/dto/PermissionPackageOperateDTO.java new file mode 100644 index 0000000..abef898 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/permissionpackage/dto/PermissionPackageOperateDTO.java @@ -0,0 +1,42 @@ +package com.newyetai.usercenter.permissionpackage.dto; + +import com.newyetai.common.validation.Update; +import com.newyetai.usercenter.constants.SecurityValidateConstants; +import com.newyetai.usercenter.resource.dto.UrlDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.List; + + +/** + * @author yzq + * 权限包 + */ +@ApiModel("权限包树DTO") +@Data +@NoArgsConstructor +@AllArgsConstructor +public class PermissionPackageOperateDTO implements Serializable { + + private static final long serialVersionUID = -3116840853887604199L; + + @ApiModelProperty("权限包ID") + @NotNull(message = SecurityValidateConstants.PERMISSION_PACKAGE_ID_NULL, groups = {Update.class}) + private Long permissionPackageId; + + @ApiModelProperty("平台编码") + private Integer platformCode; + + @ApiModelProperty("菜单资源树") + List urlDTOs; + + @ApiModelProperty("已分配的菜单资源Id列表") + List selectedResourceIdList; + +} diff --git a/src/main/java/com/newyetai/usercenter/permissionpackage/dto/PermissionPackagePageQueryDTO.java b/src/main/java/com/newyetai/usercenter/permissionpackage/dto/PermissionPackagePageQueryDTO.java new file mode 100644 index 0000000..6ff51ba --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/permissionpackage/dto/PermissionPackagePageQueryDTO.java @@ -0,0 +1,42 @@ +package com.newyetai.usercenter.permissionpackage.dto; + +import com.newyetai.common.dto.PageQueryDTO; +import com.newyetai.usercenter.constants.SecurityValidateConstants; +import com.newyetai.usercenter.enums.OrgTypeEnum; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; + +/** + * @author yzq + */ +@ApiModel("权限包查询DTO") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class PermissionPackagePageQueryDTO extends PageQueryDTO { + + private static final long serialVersionUID = 3308348258162338939L; + + @ApiModelProperty("权限包名称") + private String permissionPackageName; + + /** 权限包类型:参考{@link OrgTypeEnum} **/ + @ApiModelProperty("权限包类型") + private Integer permissionPackageType; + + @ApiModelProperty("应用编码 1.业务系统 2.运营中台 3.用户中心 4.支付系统 5.在线培训 6.转发器 7.风控 8.网关 9.发号器 10.基础框架") + @NotNull(message = SecurityValidateConstants.PLATFORM_CODE_EMPTY) + private Integer platformCode; + + @ApiModelProperty("机构Id") + private Long orgId; + +} diff --git a/src/main/java/com/newyetai/usercenter/permissionpackage/entity/PermissionOrganization.java b/src/main/java/com/newyetai/usercenter/permissionpackage/entity/PermissionOrganization.java new file mode 100644 index 0000000..04f4e90 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/permissionpackage/entity/PermissionOrganization.java @@ -0,0 +1,50 @@ +package com.newyetai.usercenter.permissionpackage.entity; + +import java.util.Date; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author : yzq create at: 2020/9/3 15:52 + * @description: 权限包-机构关系表 + */ +@TableName("xs_permission_organization") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Data +public class PermissionOrganization extends BaseEntity { + + + private static final long serialVersionUID = -1017315735785518362L; + /** + * 权限包ID + **/ + private Long permissionPackageId; + + /** + * 分配机构orgId + **/ + private Long allocationOrgId; + + /** + * 备注 + **/ + private String remark; + + @Builder + public PermissionOrganization(Long id, Boolean deleted, Long createBy, Date createTime, + Long updateBy, Date updateTime, Long proxyBy, Long permissionsPackageId, Long allocationOrgId, String remark) { + super(id, deleted, createBy, createTime, updateBy, updateTime, proxyBy); + this.permissionPackageId = permissionsPackageId; + this.allocationOrgId = allocationOrgId; + this.remark = remark; + } +} diff --git a/src/main/java/com/newyetai/usercenter/permissionpackage/entity/PermissionPackage.java b/src/main/java/com/newyetai/usercenter/permissionpackage/entity/PermissionPackage.java new file mode 100644 index 0000000..8c880fe --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/permissionpackage/entity/PermissionPackage.java @@ -0,0 +1,66 @@ +package com.newyetai.usercenter.permissionpackage.entity; + +import java.util.Date; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; +import com.newyetai.usercenter.enums.OrgTypeEnum; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author : yzq create at: 2020/9/3 15:52 + * @description: 标准权限包 + */ +@TableName("xs_permission_package") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Data +public class PermissionPackage extends BaseEntity { + + + private static final long serialVersionUID = 3822862490863266305L; + + + /** + * 权限包名称 + **/ + private String permissionPackageName; + + /** + * 应用编码 + */ + private Integer platformCode; + + /** + * 权限包类型:参考{@link OrgTypeEnum} + **/ + private Integer permissionPackageType; + + /** + * 状态 1.有效 2.失效 + **/ + private Integer status; + + /** + * 备注 + **/ + private String remark; + + @Builder + public PermissionPackage(Long id, Boolean deleted, Long createBy, Date createTime, + Long updateBy, Date updateTime, Long proxyBy, String permissionPackageName, + Integer platformCode, Integer permissionPackageType, Integer status, String remark) { + super(id, deleted, createBy, createTime, updateBy, updateTime, proxyBy); + this.permissionPackageName = permissionPackageName; + this.platformCode = platformCode; + this.permissionPackageType = permissionPackageType; + this.status = status; + this.remark = remark; + } +} diff --git a/src/main/java/com/newyetai/usercenter/permissionpackage/entity/PermissionResources.java b/src/main/java/com/newyetai/usercenter/permissionpackage/entity/PermissionResources.java new file mode 100644 index 0000000..21c76f3 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/permissionpackage/entity/PermissionResources.java @@ -0,0 +1,57 @@ +package com.newyetai.usercenter.permissionpackage.entity; + +import java.util.Date; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author : yzq create at: 2020/9/3 15:52 + * @description: 权限包-资源关系表 + */ +@TableName("xs_permission_resources") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Data +public class PermissionResources extends BaseEntity { + + + private static final long serialVersionUID = 617520887852396742L; + /** + * 权限包Id + **/ + private Long permissionPackageId; + + /** + * 资源ID + **/ + private Long resourceId; + + /** + * 类型 1.菜单 2.组件 3.接口 + **/ + private Integer resourceType; + + /** + * 备注 + **/ + private String remark; + + @Builder + public PermissionResources(Long id, Boolean deleted, Long createBy, Date createTime, + Long updateBy, Date updateTime, Long proxyBy, Long permissionPackageId, + Long resourceId, Integer resourceType, String remark) { + super(id, deleted, createBy, createTime, updateBy, updateTime, proxyBy); + this.permissionPackageId = permissionPackageId; + this.resourceId = resourceId; + this.resourceType = resourceType; + this.remark = remark; + } +} diff --git a/src/main/java/com/newyetai/usercenter/permissionpackage/mapper/PermissionPackageMapper.xml b/src/main/java/com/newyetai/usercenter/permissionpackage/mapper/PermissionPackageMapper.xml new file mode 100644 index 0000000..ae0558d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/permissionpackage/mapper/PermissionPackageMapper.xml @@ -0,0 +1,44 @@ + + + + + diff --git a/src/main/java/com/newyetai/usercenter/permissionpackage/mapper/PermissionPackageOrgMapper.xml b/src/main/java/com/newyetai/usercenter/permissionpackage/mapper/PermissionPackageOrgMapper.xml new file mode 100644 index 0000000..c196529 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/permissionpackage/mapper/PermissionPackageOrgMapper.xml @@ -0,0 +1,81 @@ + + + + + + + diff --git a/src/main/java/com/newyetai/usercenter/permissionpackage/mapper/PermissionResourceMapper.xml b/src/main/java/com/newyetai/usercenter/permissionpackage/mapper/PermissionResourceMapper.xml new file mode 100644 index 0000000..c3b3faf --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/permissionpackage/mapper/PermissionResourceMapper.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + UPDATE + xs_permission_resources + SET + deleted = 1 + WHERE + deleted = 0 + AND resource_type = 1 + AND permission_package_id= #{permissionPackageId} + + + + UPDATE + xs_permission_package t1 + INNER JOIN xs_permission_resources t2 ON + t2.permission_package_id = t1.id + AND t2.deleted = 0 + AND t2.resource_type = 2 + LEFT JOIN xs_component t3 ON + t3.id = t2.resource_id + AND t3.deleted = 0 + LEFT JOIN xs_permission_resources t4 ON + t4.permission_package_id=t1.id + AND t4.resource_id=t3.url_id + AND t4.resource_type=1 + AND t4.deleted=0 + SET t2.deleted=1 + WHERE t1.deleted=0 AND t4.id IS NULL AND t1.id=#{permissionPackageId} + + + + UPDATE + xs_permission_package t1 + INNER JOIN xs_permission_resources t2 ON + t2.permission_package_id = t1.id + AND t2.deleted = 0 + AND t2.resource_type = 3 + LEFT JOIN xs_url t3 ON + t3.id = t2.resource_id + AND t3.deleted = 0 + LEFT JOIN xs_permission_resources t4 ON + t4.permission_package_id=t1.id + AND t4.resource_id=t3.parent_id + AND t4.resource_type=1 + AND t4.deleted=0 + SET t2.deleted=1 + WHERE t1.deleted=0 AND t4.id IS NULL AND t1.id=#{permissionPackageId} + + + + + UPDATE + xs_permission_resources t + SET + t.deleted = 1, + t.update_by = #{usrId}, + t.update_time = now() + WHERE + t.deleted = 0 + AND t.permission_package_id = #{permissionPackageId} + + AND t.resource_id IN + + #{resourceId} + + + AND t.resource_type = #{resourceType} + + diff --git a/src/main/java/com/newyetai/usercenter/permissionpackage/mapstruct/PermissionPackageMapMapper.java b/src/main/java/com/newyetai/usercenter/permissionpackage/mapstruct/PermissionPackageMapMapper.java new file mode 100644 index 0000000..76dfc69 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/permissionpackage/mapstruct/PermissionPackageMapMapper.java @@ -0,0 +1,40 @@ +package com.newyetai.usercenter.permissionpackage.mapstruct; + +import com.newyetai.usercenter.permissionpackage.dto.PackageResourcesOperateDTO; +import com.newyetai.usercenter.permissionpackage.dto.PermissionOrganizeDTO; +import com.newyetai.usercenter.permissionpackage.entity.PermissionOrganization; +import com.newyetai.usercenter.permissionpackage.entity.PermissionResources; +import java.util.List; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + + +/** + * @author yzq + */ +@Mapper +public interface PermissionPackageMapMapper { + + PermissionPackageMapMapper INSTANCE = + Mappers.getMapper(PermissionPackageMapMapper.class); + + /** + * 批量转换PermissionResources + * + * @param packageResourcesOperateDTOList + * @return + */ + List toResourcesEntityList( + List packageResourcesOperateDTOList); + + /** + * 批量转换PermissionOrganization + * + * @param permissionOrganizeDTOList + * @return + */ + List toOrganizationEntityList( + List permissionOrganizeDTOList); + + +} diff --git a/src/main/java/com/newyetai/usercenter/permissionpackage/service/UcPermissionOrganizationService.java b/src/main/java/com/newyetai/usercenter/permissionpackage/service/UcPermissionOrganizationService.java new file mode 100644 index 0000000..dee49ac --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/permissionpackage/service/UcPermissionOrganizationService.java @@ -0,0 +1,80 @@ +package com.newyetai.usercenter.permissionpackage.service; + +import java.util.List; +import java.util.Set; + +import javax.validation.Valid; + +import com.newyetai.usercenter.permissionpackage.dto.PermissionOrgCreateDTO; +import com.newyetai.usercenter.permissionpackage.dto.PermissionOrganizeDTO; +import com.newyetai.usercenter.permissionpackage.dto.PermissionOrganizePageQueryDTO; + +/** + * @author : yzq create at: 2020/9/3 16:54 + * @description: 权限包接口 + */ +public interface UcPermissionOrganizationService { + + /** + * 根据机构类型保存机构权限包 + * @param orgId + * @param orgType + * @author sr on 2024-04-19 + */ + void saveOrgByType(Long orgId, Integer orgType); + + void create(@Valid PermissionOrgCreateDTO permissionOrgCreateDTO); + + + + + + + /** + * 查询对应权限包下所有可以被选择的机构信息 + * + * @param permissionOrganizePageQueryDTO + * @return + */ + List canBeAllocatedOrgList( + PermissionOrganizePageQueryDTO permissionOrganizePageQueryDTO); + + /** + * 查询对应权限包下的分配的机构信息 + * + * @param permissionOrganizePageQueryDTO + * @return + */ + List allocatedOrgList( + PermissionOrganizePageQueryDTO permissionOrganizePageQueryDTO); + + /** + * 保存机构分配信息 + * + * @param permissionOrganizeDTOList + * @return + */ + void saveOrgList(List permissionOrganizeDTOList); + + /** + * 删除机构分配信息 + * + * @param id + * @return + */ + void removeAllocatedOrg(Long id); + + void removeAllocatedOrgList(Set ids); + + + + + + + + + + +} + + diff --git a/src/main/java/com/newyetai/usercenter/permissionpackage/service/UcPermissionPackageService.java b/src/main/java/com/newyetai/usercenter/permissionpackage/service/UcPermissionPackageService.java new file mode 100644 index 0000000..95bf43a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/permissionpackage/service/UcPermissionPackageService.java @@ -0,0 +1,60 @@ +package com.newyetai.usercenter.permissionpackage.service; + + +import com.newyetai.usercenter.permissionpackage.dto.PermissionPackageDTO; +import com.newyetai.usercenter.permissionpackage.dto.PermissionPackageOperateDTO; +import com.newyetai.usercenter.permissionpackage.dto.PermissionPackagePageQueryDTO; +import java.util.List; + +/** + * @author : yzq create at: 2020/9/3 16:54 + * @description: 权限包接口 + */ +public interface UcPermissionPackageService { + + /** + * 分页查询权限包列表 + */ + void page( + PermissionPackagePageQueryDTO permissionPackagePageQueryDTO); + + /** + * 查询权限包列表 + */ + List list( + PermissionPackagePageQueryDTO permissionPackagePageQueryDTO); + + PermissionPackageDTO findOne(PermissionPackagePageQueryDTO permissionPackagePageQueryDTO); + + + + + + + + + /** + * 新增权限包 + */ + void createPermissionPackage(PermissionPackageDTO permissionPackageDTO); + + /** + * 修改权限包 + */ + void updatePermissionPackage(PermissionPackageDTO permissionPackageDTO); + + /** + * 删除权限包 + */ + void removePermissionPackage(Long id); + + + + + + PermissionPackageOperateDTO urlList(PermissionPackageDTO permissionPackageDTO); + + +} + + diff --git a/src/main/java/com/newyetai/usercenter/permissionpackage/service/UcPermissionResourceService.java b/src/main/java/com/newyetai/usercenter/permissionpackage/service/UcPermissionResourceService.java new file mode 100644 index 0000000..b39f2d8 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/permissionpackage/service/UcPermissionResourceService.java @@ -0,0 +1,51 @@ +package com.newyetai.usercenter.permissionpackage.service; + +import com.newyetai.usercenter.permissionpackage.dto.PackageResourcesDTO; +import com.newyetai.usercenter.permissionpackage.dto.PackageResourcesOperateDTO; +import com.newyetai.usercenter.permissionpackage.dto.PackageResourcesPageQueryDTO; +import com.newyetai.usercenter.permissionpackage.dto.PermissionPackageOperateDTO; +import java.util.List; + +/** + * @author : yzq create at: 2020/9/3 16:54 + * @description: 权限包资源明细接口 + */ +public interface UcPermissionResourceService { + + /** + * 查询权限包下的菜单资源 + * + * @param permissionPackageId + * @param platformCode + * @return + */ + PermissionPackageOperateDTO urlList( + Long permissionPackageId, Integer platformCode); + + /** + * 变更权限包下的菜单资源 + * + * @param permissionPackageOperateDTO + */ + void updateUrlList(PermissionPackageOperateDTO permissionPackageOperateDTO); + + /** + * 查询对应菜单下组件接口列表 + * + * @param packageResourcesPageQueryDTO + * @return + */ + List urlComponentList( + PackageResourcesPageQueryDTO packageResourcesPageQueryDTO); + + /** + * 更新菜单下的相关资源 + * + * @param packageResourcesDTO + */ + void saveUrlComponentList(PackageResourcesDTO packageResourcesDTO); + + + void cleanUrlCompentAndInterface(Long permissionPackageId); +} + diff --git a/src/main/java/com/newyetai/usercenter/permissionpackage/service/impl/UcPermissionOrganizationServiceImpl.java b/src/main/java/com/newyetai/usercenter/permissionpackage/service/impl/UcPermissionOrganizationServiceImpl.java new file mode 100644 index 0000000..f0495e0 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/permissionpackage/service/impl/UcPermissionOrganizationServiceImpl.java @@ -0,0 +1,143 @@ +package com.newyetai.usercenter.permissionpackage.service.impl; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.EnvironmentUtils; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.usercenter.cache.SecurityCacheUtils; +import com.newyetai.usercenter.constants.SecurityConstants; +import com.newyetai.usercenter.permissionpackage.dao.PermissionPackageOrgMapper; +import com.newyetai.usercenter.permissionpackage.dto.PermissionOrgCreateDTO; +import com.newyetai.usercenter.permissionpackage.dto.PermissionOrganizeDTO; +import com.newyetai.usercenter.permissionpackage.dto.PermissionOrganizePageQueryDTO; +import com.newyetai.usercenter.permissionpackage.dto.PermissionPackageDTO; +import com.newyetai.usercenter.permissionpackage.dto.PermissionPackagePageQueryDTO; +import com.newyetai.usercenter.permissionpackage.entity.PermissionOrganization; +import com.newyetai.usercenter.permissionpackage.mapstruct.PermissionPackageMapMapper; +import com.newyetai.usercenter.permissionpackage.service.UcPermissionOrganizationService; +import com.newyetai.usercenter.permissionpackage.service.UcPermissionPackageService; + +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; + +/** + * @author : yzq create at: 2020/9/9 19:55 + * @description: 权限包机构实现类 + */ +@Service +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +@ConditionalOnProperty(name = SecurityConstants.PROP_KEY_SECURITY_USELOCAL, havingValue = "true", matchIfMissing = true) +public class UcPermissionOrganizationServiceImpl implements UcPermissionOrganizationService { + + private final PermissionPackageOrgMapper permissionPackageOrgMapper; + + private final UcPermissionPackageService permissionPackageService; + + @Override + @Transactional + public void saveOrgByType(Long orgId, Integer orgType) { + PermissionPackageDTO permissionPackageDTO = + permissionPackageService.findOne(PermissionPackagePageQueryDTO.builder() + .platformCode(EnvironmentUtils.getSystemCode()) + .permissionPackageType(orgType).build()); + Long permissionPackageId = permissionPackageDTO.getId(); + List permissions = Lists.newArrayList(PermissionOrganizeDTO.builder() + .permissionPackageId(permissionPackageId).allocationOrgId(orgId).build()); + this.saveOrgList(permissions); + } + + @Override + @Transactional + public void create(PermissionOrgCreateDTO permissionOrgCreateDTO) { + Set orgIds = permissionOrgCreateDTO.getAllocationOrgIds(); + Long permissionsPackageId = permissionOrgCreateDTO.getPermissionPackageId(); + Assert.notEmpty(orgIds, "请传入有效的机构信息"); + List existOrgs = this.allocatedOrgList(PermissionOrganizePageQueryDTO.builder() + .permissionPackageId(permissionsPackageId) + .allocationOrgIds(orgIds).build()); + Set checkOrgIds = orgIds; + if (!existOrgs.isEmpty()) { + Set allocatedOrgSet = + existOrgs.stream().map(PermissionOrganizeDTO::getAllocationOrgId) + .collect(Collectors.toSet()); + checkOrgIds = orgIds.stream().filter(orgId -> !allocatedOrgSet + .contains(orgId)).collect(Collectors.toSet()); + } + if (checkOrgIds.isEmpty()) { + return ; + } + List permissionOrganizationList = orgIds + .stream().map(orgId -> PermissionOrganization.builder() + .permissionsPackageId(permissionsPackageId).allocationOrgId(orgId).build()) + .collect(Collectors.toList()); + permissionPackageOrgMapper.saveEntites(permissionOrganizationList); + SecurityCacheUtils.flushSystemOrgs(null, checkOrgIds); + } + + +//***********************************分隔符*********************************************** + + + + + + @Override + @Transactional(rollbackFor = Exception.class) + public List canBeAllocatedOrgList( + PermissionOrganizePageQueryDTO permissionOrganizePageQueryDTO) { + return permissionPackageOrgMapper.canBeAllocatedOrgList(permissionOrganizePageQueryDTO); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public List allocatedOrgList( + PermissionOrganizePageQueryDTO permissionOrganizePageQueryDTO) { + return permissionPackageOrgMapper.allocatedOrgList(permissionOrganizePageQueryDTO); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void saveOrgList( + List permissionOrganizeDTOList) { + Assert.notEmpty(permissionOrganizeDTOList, "请传入有效的机构信息"); + Set orgIds = permissionOrganizeDTOList.stream().map(d -> d.getAllocationOrgId()) + .collect(Collectors.toSet()); + this.create(PermissionOrgCreateDTO.builder() + .permissionPackageId(permissionOrganizeDTOList.get(0).getPermissionPackageId()) + .allocationOrgIds(orgIds).build()); + } + + + + @Override + @Transactional(rollbackFor = Exception.class) + public void removeAllocatedOrg(Long id) { + Assert.isTrue( + permissionPackageOrgMapper.deleteEntity(PermissionOrganization.builder().id(id).build(), + UserContextHolder.getLoginUserId()) == 1, + "取消分配机构失败"); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void removeAllocatedOrgList(Set ids) { + Assert.isTrue(!CollectionUtils.isEmpty(ids), + "请传入有效的机构"); + List permissionOrganizationList = + ids.stream().map(id -> PermissionOrganization.builder().id(id).build()) + .collect(Collectors.toList()); + permissionPackageOrgMapper + .deleteEntites(permissionOrganizationList, UserContextHolder.getExistLoginUserId()); + } + + +} diff --git a/src/main/java/com/newyetai/usercenter/permissionpackage/service/impl/UcPermissionPackageServiceImpl.java b/src/main/java/com/newyetai/usercenter/permissionpackage/service/impl/UcPermissionPackageServiceImpl.java new file mode 100644 index 0000000..64136ab --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/permissionpackage/service/impl/UcPermissionPackageServiceImpl.java @@ -0,0 +1,112 @@ +package com.newyetai.usercenter.permissionpackage.service.impl; + +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.ListUtil; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.usercenter.constants.SecurityConstants; +import com.newyetai.usercenter.permissionpackage.dao.PermissionPackageMapper; +import com.newyetai.usercenter.permissionpackage.dao.PermissionPackageOrgMapper; +import com.newyetai.usercenter.permissionpackage.dto.PermissionOrganizeDTO; +import com.newyetai.usercenter.permissionpackage.dto.PermissionOrganizePageQueryDTO; +import com.newyetai.usercenter.permissionpackage.dto.PermissionPackageDTO; +import com.newyetai.usercenter.permissionpackage.dto.PermissionPackageOperateDTO; +import com.newyetai.usercenter.permissionpackage.dto.PermissionPackagePageQueryDTO; +import com.newyetai.usercenter.permissionpackage.entity.PermissionOrganization; +import com.newyetai.usercenter.permissionpackage.entity.PermissionPackage; +import com.newyetai.usercenter.permissionpackage.service.UcPermissionOrganizationService; +import com.newyetai.usercenter.permissionpackage.service.UcPermissionPackageService; +import com.newyetai.usercenter.utils.PermissionPackageUtils; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * @author : yzq create at: 2020/9/7 17:20 + * @description: 权限包实现类 + */ +@Service +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +@ConditionalOnProperty(name = SecurityConstants.PROP_KEY_SECURITY_USELOCAL, havingValue = "true", matchIfMissing = true) +public class UcPermissionPackageServiceImpl implements UcPermissionPackageService { + + private final PermissionPackageMapper permissionPackageMapper; + + private final PermissionPackageOrgMapper permissionPackageOrgMapper; + + @Override + public void page( + PermissionPackagePageQueryDTO permissionPackagePageQueryDTO) { + permissionPackageMapper.listPermissionPackage(permissionPackagePageQueryDTO); + } + + @Override + public List list( + PermissionPackagePageQueryDTO permissionPackagePageQueryDTO) { + permissionPackagePageQueryDTO.disablePage(); + return permissionPackageMapper.listPermissionPackage(permissionPackagePageQueryDTO); + } + + @Override + public PermissionPackageDTO findOne(PermissionPackagePageQueryDTO permissionPackagePageQueryDTO) { + List permissionPackageDTOs = list(permissionPackagePageQueryDTO); + Assert.isTrue(permissionPackageDTOs.size() == 1, "未找到唯一匹配的权限包"); + return ListUtil.first(permissionPackageDTOs); + } + + +//***********************************分隔符*********************************************** + + + + @Override + @Transactional(rollbackFor = Exception.class) + public void createPermissionPackage(PermissionPackageDTO permissionPackageDTO) { + //校验唯一性 + List packageList = + permissionPackageMapper.listPermissionPackage(PermissionPackagePageQueryDTO.builder() + .permissionPackageName(permissionPackageDTO.getPermissionPackageName()) + .platformCode(permissionPackageDTO.getPlatformCode()) + .permissionPackageType(permissionPackageDTO.getPermissionPackageType()) + .build()); + Assert.isTrue(CollectionUtils.isEmpty(packageList), "该应用下已存在同名权限包"); + PermissionPackage permissionPackage = + PermissionPackageUtils.toCreatePermissionPackage(permissionPackageDTO); + permissionPackageMapper.saveEntity(permissionPackage, UserContextHolder.getLoginUserId()); + permissionPackageDTO.setId(permissionPackage.getId()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updatePermissionPackage(PermissionPackageDTO permissionPackageDTO) { + PermissionPackage permissionPackage = + PermissionPackageUtils.toCreatePermissionPackage(permissionPackageDTO); + permissionPackage.setId(permissionPackageDTO.getId()); + Assert.isTrue(permissionPackageMapper.updateEntitySelective(permissionPackage, + UserContextHolder.getLoginUserId()) == 1 + , "更新权限包失败"); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void removePermissionPackage(Long id) { + //已分配的权限包不能删除 + boolean exists = permissionPackageOrgMapper + .existsEntity(PermissionOrganization.builder().permissionsPackageId(id).build()); + Assert.isTrue(!exists, + "该权限包已分配机构,不能删除"); + Assert.isTrue(permissionPackageMapper.deleteEntity(PermissionPackage.builder().id(id).build(), + UserContextHolder.getLoginUserId()) == 1, + "删除权限包失败"); + } + + + @Override + @Transactional(rollbackFor = Exception.class) + public PermissionPackageOperateDTO urlList(PermissionPackageDTO permissionPackageDTO) { + return null; + } +} diff --git a/src/main/java/com/newyetai/usercenter/permissionpackage/service/impl/UcPermissionResourceServiceImpl.java b/src/main/java/com/newyetai/usercenter/permissionpackage/service/impl/UcPermissionResourceServiceImpl.java new file mode 100644 index 0000000..3c8f034 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/permissionpackage/service/impl/UcPermissionResourceServiceImpl.java @@ -0,0 +1,180 @@ +package com.newyetai.usercenter.permissionpackage.service.impl; + +import com.google.common.collect.Lists; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.usercenter.authority.constants.PermissionConstants; +import com.newyetai.usercenter.constants.SecurityConstants; +import com.newyetai.usercenter.enums.ResourceType; +import com.newyetai.usercenter.permissionpackage.dao.PermissionPackageMapper; +import com.newyetai.usercenter.permissionpackage.dao.PermissionResourceMapper; +import com.newyetai.usercenter.permissionpackage.dto.PackageResourcesDTO; +import com.newyetai.usercenter.permissionpackage.dto.PackageResourcesOperateDTO; +import com.newyetai.usercenter.permissionpackage.dto.PackageResourcesPageQueryDTO; +import com.newyetai.usercenter.permissionpackage.dto.PermissionPackageOperateDTO; +import com.newyetai.usercenter.permissionpackage.entity.PermissionPackage; +import com.newyetai.usercenter.permissionpackage.entity.PermissionResources; +import com.newyetai.usercenter.permissionpackage.mapstruct.PermissionPackageMapMapper; +import com.newyetai.usercenter.permissionpackage.service.UcPermissionResourceService; +import com.newyetai.usercenter.resource.dto.UrlDTO; +import com.newyetai.usercenter.resource.dto.UrlPageQueryDTO; +import com.newyetai.usercenter.resource.service.UcUrlService; +import lombok.RequiredArgsConstructor; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * @author : yzq create at: 2020/9/7 17:20 + * @description: 权限包实现类 + */ +@Service +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +@ConditionalOnProperty(name = SecurityConstants.PROP_KEY_SECURITY_USELOCAL, havingValue = "true", matchIfMissing = true) +public class UcPermissionResourceServiceImpl implements UcPermissionResourceService { + + private final PermissionResourceMapper permissionResourceMapper; + + private final UcUrlService ucUrlService; + + private final PermissionPackageMapper permissionPackageMapper; + + + @Override + @Transactional(rollbackFor = Exception.class) + public PermissionPackageOperateDTO urlList( + Long permissionPackageId, Integer platformCode) { + //查询权限包 + PermissionPackage permissionPackage = + permissionPackageMapper.getById(permissionPackageId); + if (permissionPackage == null) { + return null; + } + //查询该应用下的所有菜单资源 + PermissionPackageOperateDTO permissionOperateDTO = new PermissionPackageOperateDTO(); + UrlPageQueryDTO urlPageQueryDTO = new UrlPageQueryDTO(); + urlPageQueryDTO.setPlatformCode(platformCode); + urlPageQueryDTO.setTree(Boolean.TRUE); + urlPageQueryDTO.setNeedPage(Boolean.FALSE); + permissionOperateDTO.setUrlDTOs(ucUrlService.list(urlPageQueryDTO)); + //查询已选择的菜单资源 + permissionOperateDTO.setPermissionPackageId(permissionPackageId); + permissionOperateDTO.setPlatformCode(platformCode); + List selectedUrlList = + permissionResourceMapper.findSelectdUrl(permissionPackageId); + if (CollectionUtils.isNotEmpty(selectedUrlList)) { + permissionOperateDTO.setSelectedResourceIdList( + selectedUrlList.stream().map(UrlDTO::getId).collect(Collectors.toList())); + } + return permissionOperateDTO; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateUrlList(PermissionPackageOperateDTO permissionPackageOperateDTO) { + Long permissionPackageId = permissionPackageOperateDTO.getPermissionPackageId(); + //本次所选菜单 + List selectedResourceIdList =permissionPackageOperateDTO.getSelectedResourceIdList(); + if(CollectionUtils.isEmpty(selectedResourceIdList)){ + //删除原本权限包-菜单资源信息 + permissionResourceMapper + .removeAllUrlResourcesById(permissionPackageId); + return; + } + //原本已分配的菜单 + List originalUrlList = + permissionResourceMapper.findSelectdUrl(permissionPackageId); + Set originalUrlSet= + originalUrlList.stream().map(UrlDTO::getId).collect(Collectors.toSet()); + //过滤出需要删除的(原本已存在,不在本次所选菜单中) + Set removeList=originalUrlSet.stream().filter(resourceId ->!selectedResourceIdList.contains(resourceId)).collect(Collectors.toSet()); + if(CollectionUtils.isNotEmpty(removeList)){ + permissionResourceMapper.removeUrlResources(removeList, + permissionPackageId,UserContextHolder.getLoginUserId(),Integer.valueOf(ResourceType.RESOURCE_MENU_TYPE.getType())); + } + //过滤出本次新增的(本次所选菜单存在,原本不存在) + selectedResourceIdList.removeAll(originalUrlSet); + //重新插入已选择的菜单信息 + List permissionResources = Lists.newArrayList(); + selectedResourceIdList.forEach(urlId -> { + permissionResources.add( + PermissionResources.builder().permissionPackageId(permissionPackageId).resourceType( + Integer.valueOf(ResourceType.RESOURCE_MENU_TYPE.getType())) + .resourceId(urlId).build()); + }); + permissionResourceMapper + .saveEntites(permissionResources, UserContextHolder.getExistLoginUserId()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public List urlComponentList( + PackageResourcesPageQueryDTO packageResourcesPageQueryDTO) { + Integer resourceType = packageResourcesPageQueryDTO.getResourceType(); + if (PermissionConstants.RESOURCE_TYPE_COMPONENT.equals(resourceType.toString())) { + return permissionResourceMapper.urlComponentList(packageResourcesPageQueryDTO); + } + return permissionResourceMapper.urlInterfaceList(packageResourcesPageQueryDTO); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void saveUrlComponentList(PackageResourcesDTO packageResourcesDTO) { + List packageResourcesOperateDTOList = packageResourcesDTO + .getPackageResourcesOperateDTOList(); + /* Assert.isTrue(CollectionUtils.isNotEmpty(packageResourcesOperateDTOList), + "请传入需要保存或者需要取消的组件/接口数据");*/ + // 获取原来已有的 + packageResourcesDTO.setNeedPage(false); + List permissionResourcesList = this + .urlComponentList(packageResourcesDTO); + Set oldResourceIdSet = permissionResourcesList.stream() + .map(PackageResourcesOperateDTO::getResourceId) + .collect(Collectors.toSet()); + + // 获取新增的资源,顺便将旧的列表中移出已存在的资源 + List selectedList = packageResourcesOperateDTOList.stream() + .filter(packageResourcesOperateDTO -> { + Long newResourceId = packageResourcesOperateDTO.getResourceId(); + boolean exist = oldResourceIdSet.contains(newResourceId); + // 移出已存在的资源 + if (exist) { + oldResourceIdSet.remove(newResourceId); + } + return !exist; + }) + .collect(Collectors.toList()); + + // 新增(在新的中排除老的就是新增的) + if (CollectionUtils.isNotEmpty(selectedList)) { + permissionResourceMapper + .saveEntites(PermissionPackageMapMapper.INSTANCE.toResourcesEntityList(selectedList), + UserContextHolder.getLoginUserId()); + } + + // 删除(将老的中排除新增的就是要删除的) + List removeList = permissionResourcesList.stream() + .filter(permissionResource -> oldResourceIdSet.contains(permissionResource.getResourceId())) + .collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(removeList)) { + permissionResourceMapper + .deleteEntites(PermissionPackageMapMapper.INSTANCE.toResourcesEntityList(removeList), + UserContextHolder.getLoginUserId()); + } + } + + @Override + public void cleanUrlCompentAndInterface(Long permissionPackageId) { + //将未勾选的菜单下的组件记录删除 + permissionResourceMapper.refreshComponentResourcesInfo(permissionPackageId); + //将未勾选的菜单下的接口记录删除 + permissionResourceMapper.refreshUrlResourcesInfo(permissionPackageId); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/query/RoleQuery.java b/src/main/java/com/newyetai/usercenter/query/RoleQuery.java new file mode 100644 index 0000000..074d93e --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/query/RoleQuery.java @@ -0,0 +1,46 @@ +package com.newyetai.usercenter.query; + +import com.newyetai.common.dto.PageQueryDTO; +import com.newyetai.usercenter.constants.RoleConstants; +import com.newyetai.usercenter.dto.RoleDTO; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Builder.Default; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author: Jerry.li + * @description: 角色查询 + * @create: 2020-06-16 16:36 + **/ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class RoleQuery extends PageQueryDTO { + + /** **/ + private static final long serialVersionUID = 7563793746636237744L; + + private String roleName; + + /** + * 平台编码 + */ + private Integer platformCode; + + private Long userId; + /** + * 角色类型:1-业务角色 + */ + @Default + private String roleType = RoleConstants.ROLE_TYPE_BUSINESS; + + private String standardType; + private Long orgId; + + private Boolean enabled; + +} diff --git a/src/main/java/com/newyetai/usercenter/query/RoleStandardTypeQuery.java b/src/main/java/com/newyetai/usercenter/query/RoleStandardTypeQuery.java new file mode 100644 index 0000000..f769fe9 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/query/RoleStandardTypeQuery.java @@ -0,0 +1,37 @@ +package com.newyetai.usercenter.query; + +import com.newyetai.common.dto.PageQueryDTO; +import com.newyetai.tkmybatis.pojo.Page; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author Jerry.li + * @description 企业联系信息查询实体 + * @date 2020/3/27 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +public class RoleStandardTypeQuery extends PageQueryDTO { + + private static final long serialVersionUID = 910664153838006438L; + + /** + * 编码 + **/ + private String roleCode; + /** + * 名称 + **/ + private String name; + /** + * 平台编码 + **/ + private String platformCode; + +} diff --git a/src/main/java/com/newyetai/usercenter/query/UserQuery.java b/src/main/java/com/newyetai/usercenter/query/UserQuery.java new file mode 100644 index 0000000..3333136 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/query/UserQuery.java @@ -0,0 +1,211 @@ +//package com.newyetai.usercenter.query; +// +//import com.newyetai.common.annotation.trimAndUpper.TrimAndUpper; +//import com.newyetai.tkmybatis.pojo.Page; +//import com.newyetai.usercenter.enums.AuthStatu; +//import com.newyetai.usercenter.enums.UserType; +//import io.swagger.annotations.ApiModelProperty; +//import lombok.*; +//import org.springframework.format.annotation.DateTimeFormat; +// +//import java.util.Date; +//import java.util.List; +// +///** +// * @author Jerry.li +// * @description 用户查询实体 +// * @date 2020/3/26 +// */ +//@EqualsAndHashCode(callSuper = true) +//@Data +//@AllArgsConstructor +//@NoArgsConstructor +//public class UserQuery extends BaseQuery { +// +// private static final long serialVersionUID = 8645219985888896094L; +// +// /** +// * 用户ID +// */ +// private Long userId; +// /** +// * 用户姓名 +// */ +// @TrimAndUpper(TrimAndUpper.ExecuteType.TRIM) +// private String username; +// /** +// * 机构类型 +// */ +// private UserType userType; +// +// /** +// * 用户正式姓名姓名 +// */ +// @TrimAndUpper(TrimAndUpper.ExecuteType.TRIM) +// private String realName; +// +// /** +// * 身份证 +// */ +// @TrimAndUpper(TrimAndUpper.ExecuteType.TRIM) +// private String cardNo; +// +// /** +// * 身份证集合 +// */ +// private List cardNos; +// +// /** +// * 手机号 +// */ +// @TrimAndUpper(TrimAndUpper.ExecuteType.TRIM) +// private String phone; +// +// /** +// * 角色类型 2:销售 +// */ +// private String standardType; +// +// /** +// * 机构名称 +// */ +// @TrimAndUpper(TrimAndUpper.ExecuteType.TRIM) +// private String orgName; +// +// /** +// * 角色Id +// */ +// private Long roleId; +// +// /** +// * 角色名称 +// */ +// private String roleName; +// +// /** +// * 查询来源:"userInfo":用户管理页面 +// */ +// private String queryType; +// +// /** +// * 认证状态 (弃用 现在使用 authenticated) +// */ +// @Deprecated +// private AuthStatu authStatu; +// +// /** +// * 是否实名 +// */ +// private Boolean authenticated; +// +// /** +// * 身份证上传状态 cardIdStatus 1.已上传 2.未上传 +// */ +// private Integer cardInfoStatus; +// +// +// /** +// * 合同签署状态 1.已签约 2.未签约 3.已过期 +// */ +// private Integer contractStatus; +// +// /** +// * 需要忽略的机构信息 +// */ +// private List ignoreOrgIds; +// +// /** +// * 是否来自中台页面查询 +// */ +// private Boolean settlementPageQuery; +// +// /** +// * 当前登录机构Id +// */ +// private Long loginOrgId; +// +// /** +// * 是否启用 +// */ +// private Boolean enabled; +// +// /** +// * 手机号绑定状态 +// */ +// private Boolean phoneBinding; +// +// /** +// * 是否注销 +// */ +// private Boolean cancelled; +// /** +// * 中文名称 +// */ +// private String chineseName; +// /** +// * 邮箱 +// */ +// @TrimAndUpper(TrimAndUpper.ExecuteType.TRIM) +// private String email; +// +// /** +// * 用户状态 +// */ +// private Integer userStatus; +// +// @ApiModelProperty("完成时间起") +// @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") +// private Date createTimeStart; +// +// @ApiModelProperty("完成时间止") +// @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") +// private Date createTimeEnd; +// +// /** +// * 系统编码 用于区分来源 +// */ +// private Integer code; +// +// /** +// * 人像是否上传 (1 未上传 2 已上传) +// */ +// private Integer userFaceStatus; +// +// @Builder +// public UserQuery(Integer pageNo, Integer pageSize, Boolean needPage, +// Page pageResult, Long orgId, Long userId, String username, +// UserType userType, String realName, String cardNo, String phone, String standardType, +// String orgName, Long roleId, String roleName, String queryType, +// AuthStatu authStatu, Integer cardInfoStatus, Integer contractStatus, +// List ignoreOrgIds, Boolean settlementPageQuery, Long loginOrgId, +// Boolean enabled, Boolean cancelled, String chineseName, String email, Integer userStatus, +// Date createTimeStart, Date createTimeEnd, Integer code, Integer userFaceStatus) { +// super(pageNo, pageSize, needPage, pageResult, orgId); +// this.userId = userId; +// this.username = username; +// this.userType = userType; +// this.realName = realName; +// this.cardNo = cardNo; +// this.phone = phone; +// this.standardType = standardType; +// this.orgName = orgName; +// this.roleId = roleId; +// this.roleName = roleName; +// this.queryType = queryType; +// this.authStatu = authStatu; +// this.cardInfoStatus = cardInfoStatus; +// this.contractStatus = contractStatus; +// this.ignoreOrgIds = ignoreOrgIds; +// this.settlementPageQuery = settlementPageQuery; +// this.loginOrgId = loginOrgId; +// this.enabled = enabled; +// this.cancelled = cancelled; +// this.chineseName = chineseName; +// this.email = email; +// this.userStatus = userStatus; +// this.createTimeStart=createTimeStart; +// this.createTimeEnd=createTimeEnd; +// this.code = code; +// this.userFaceStatus = userFaceStatus; +// } +//} diff --git a/src/main/java/com/newyetai/usercenter/query/UserRelationCreateDTO.java b/src/main/java/com/newyetai/usercenter/query/UserRelationCreateDTO.java new file mode 100644 index 0000000..333b91a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/query/UserRelationCreateDTO.java @@ -0,0 +1,47 @@ +package com.newyetai.usercenter.query; + +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @Author dylanyuan + * @Date 2021/2/23 6:13 下午 + * @Version 1.0 + */ +@Data +@NoArgsConstructor +public class UserRelationCreateDTO implements Serializable { + + @ApiModelProperty("用户ID") + @NotNull(message = "用户ID不能为空", groups = {Create.class, Update.class}) + private Long userId; + + @ApiModelProperty("上级用户ID") + @NotNull(message = "上级ID不能为空", groups = {Create.class, Update.class}) + private Long upperUserId; + + @ApiModelProperty("平台编码") + @NotEmpty(message = "平台编码不能为空") + private String platformCode; + + @Builder + public UserRelationCreateDTO( + @NotNull(message = "用户ID不能为空", groups = {Create.class, + Update.class}) Long userId, + @NotNull(message = "上级ID不能为空", groups = {Create.class, + Update.class}) Long upperUserId, + @NotEmpty(message = "平台编码不能为空") String platformCode) { + this.userId = userId; + this.upperUserId = upperUserId; + this.platformCode = platformCode; + } +} diff --git a/src/main/java/com/newyetai/usercenter/query/UserRelationQuery.java b/src/main/java/com/newyetai/usercenter/query/UserRelationQuery.java new file mode 100644 index 0000000..163ccda --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/query/UserRelationQuery.java @@ -0,0 +1,41 @@ +package com.newyetai.usercenter.query; + +import com.newyetai.common.dto.PageQueryDTO; +import com.newyetai.tkmybatis.pojo.Page; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author Jerry.li + * @description 企业联系信息查询实体 + * @date 2020/3/27 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +public class UserRelationQuery extends PageQueryDTO { + + private static final long serialVersionUID = 910664153838006438L; + + @ApiModelProperty("用户ID") + private Long userId; + + @ApiModelProperty("上级用户ID") + private Long upperUserId; + + @ApiModelProperty("平台编码") + private String platformCode; + + @ApiModelProperty("中文名称") + private String chineseName; + + @ApiModelProperty("手机号") + private String phone; + + +} diff --git a/src/main/java/com/newyetai/usercenter/resource/controller/UcComponentController.java b/src/main/java/com/newyetai/usercenter/resource/controller/UcComponentController.java new file mode 100644 index 0000000..cccfa82 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/resource/controller/UcComponentController.java @@ -0,0 +1,70 @@ +package com.newyetai.usercenter.resource.controller; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.constants.SecurityConstants; +import com.newyetai.usercenter.resource.dto.ComponentDTO; +import com.newyetai.usercenter.resource.dto.ComponentPageQueryDTO; +import com.newyetai.usercenter.resource.service.UcComponentService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 组件操作 + * + * @author sr on 2019-11-05 + */ +@Api(tags = "组件操作") +@RestController +@RequestMapping("/component") +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +//TODO 目前只有本地引用,需提供cloud调用,然后放开注释 +@ConditionalOnProperty(name = SecurityConstants.PROP_KEY_SECURITY_USELOCAL, havingValue = "true", matchIfMissing = true) +public class UcComponentController { + + private final UcComponentService componentService; + + @ApiOperation("创建组件") + @PostMapping("/create") + public AlitaResult createComponent( + @Validated(Create.class) @RequestBody ComponentDTO componentDTO) { + return AlitaResult.success(componentService.creatComponent(componentDTO)); + } + + @ApiOperation("修改组件") + @PostMapping("/update") + public AlitaResult updateComponent( + @Validated(Update.class) @RequestBody ComponentDTO componentDTO) { + return AlitaResult.success(componentService.updateComponent(componentDTO)); + } + + @ApiOperation("删除组件") + @DeleteMapping("/delete/{id}") + public AlitaResult deleteComponent(@PathVariable("id") Long componentId) { + componentService.deleteComponent(componentId); + return AlitaResult.success(true); + } + + @ApiOperation("组件列表") + @GetMapping("/list") + public AlitaResult> list(@Validated ComponentPageQueryDTO queryDTO) { + queryDTO.setNeedPage(false); + return AlitaResult.success(componentService.list(queryDTO)); + } + + @ApiOperation("组件分页列表") + @GetMapping("/page") + public AlitaResult> page(@Validated ComponentPageQueryDTO queryDTO) { + componentService.list(queryDTO); + return AlitaResult.success(queryDTO.getPageResult()); + } +} diff --git a/src/main/java/com/newyetai/usercenter/resource/controller/UcResourceController.java b/src/main/java/com/newyetai/usercenter/resource/controller/UcResourceController.java new file mode 100644 index 0000000..6c51ea2 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/resource/controller/UcResourceController.java @@ -0,0 +1,73 @@ +package com.newyetai.usercenter.resource.controller; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.common.validation.Update; +import com.newyetai.security.service.IResourceSecurityService; +import com.newyetai.usercenter.authority.dto.PermissionOperateDTO; +import com.newyetai.usercenter.cache.SecurityCacheUtils; +import com.newyetai.usercenter.resource.dto.UrlDTO; +import com.newyetai.usercenter.resource.service.UcResourceService; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +/** + * @author sr on 2020-09-08 + */ +@RestController +@RequestMapping("/resource") +@Api(tags = "资源操作(菜单+组件)") +public class UcResourceController { + + @Autowired + private IResourceSecurityService iResourceSecurityService; + + @Autowired + private UcResourceService ucResourceService; + + @ApiOperation("获取当前用户资源列表") + @GetMapping("/list") + public AlitaResult> list(@RequestParam("systemCode") Integer systemCode, + @RequestParam(name = "roleId", required = false) Long roleId) { + if (null != roleId) { + return AlitaResult.success(iResourceSecurityService.listResource(systemCode, UserContextHolder.getLoginUser(), roleId)); + } + return AlitaResult.success(iResourceSecurityService.listResource(systemCode, UserContextHolder.getLoginUser())); + } + + @ApiOperation("设置角色权限(业务角色)") + @PostMapping("/permission/business") + public AlitaResult saveBusinessPermission( + @Validated(Update.class) @RequestBody PermissionOperateDTO permissionDTO) { + ucResourceService.saveBusinessPermission(UserContextHolder.getLoginOrgId(), permissionDTO, + UserContextHolder.getExistLoginUserId()); + return AlitaResult.success(true); + } + + @ApiOperation("获取当前用户资源列表") + @GetMapping("/flush_current_org") + public AlitaResult flushCurrentOrg(@RequestParam("systemCode") Integer systemCode) { + SecurityCacheUtils.flushSystemOrg(systemCode, UserContextHolder.getLoginOrgId()); + return AlitaResult.success(true); + } + + @ApiOperation("获取当前用户资源列表") + @GetMapping("/flush_all") + public AlitaResult flushAll() { + SecurityCacheUtils.flushAll(); + return AlitaResult.success(true); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/resource/controller/UcUrlController.java b/src/main/java/com/newyetai/usercenter/resource/controller/UcUrlController.java new file mode 100644 index 0000000..5246720 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/resource/controller/UcUrlController.java @@ -0,0 +1,89 @@ +package com.newyetai.usercenter.resource.controller; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.util.EnumUtil; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.authority.dto.PermissionOperateDTO; +import com.newyetai.usercenter.constants.SecurityConstants; +import com.newyetai.usercenter.resource.dto.UrlDTO; +import com.newyetai.usercenter.resource.dto.UrlPageQueryDTO; +import com.newyetai.usercenter.resource.enums.UrlTypeEnum; +import com.newyetai.usercenter.resource.service.UcUrlService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 菜单操作 + * + * @author sr on 2019-11-05 + */ +@Api(tags = "菜单操作") +@RestController +@RequestMapping("/url") +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +//TODO 目前只有本地引用,需提供cloud调用,然后放开注释 +@ConditionalOnProperty(name = SecurityConstants.PROP_KEY_SECURITY_USELOCAL, havingValue = "true", matchIfMissing = true) +public class UcUrlController { + + private final UcUrlService urlService; + + @ApiOperation("创建菜单") + @PostMapping("/create") + public AlitaResult createUrl(@Validated(Create.class) @RequestBody UrlDTO urlDTO) { + UrlTypeEnum urlTypeEnum = EnumUtil.resolve(UrlTypeEnum::getType, urlDTO.getType()); + if (urlTypeEnum == null) { + return AlitaResult.error("资源类型错误"); + } + if (UrlTypeEnum.INTERFACE.equals(urlTypeEnum) && StringUtils.isEmpty(urlDTO.getLink())) { + return AlitaResult.error("接口地址不能为空"); + } + return AlitaResult.success(urlService.creatUrl(urlDTO)); + } + + + @ApiOperation("修改菜单") + @PostMapping("/update") + public AlitaResult updateUrl(@Validated(Update.class) @RequestBody UrlDTO urlDTO) { + return AlitaResult.success(urlService.updateUrl(urlDTO)); + } + + @ApiOperation("删除菜单") + @DeleteMapping("/delete/{id}") + public AlitaResult deleteUrl(@PathVariable Long id) { + urlService.deleteUrl(id); + return AlitaResult.success(true); + } + + @ApiOperation("菜单列表") + @GetMapping("/list") + public AlitaResult> list(@Validated UrlPageQueryDTO query) { + query.setNeedPage(false); + return AlitaResult.success(urlService.list(query)); + } + + @ApiOperation("菜单分页列表") + @GetMapping("/page") + public AlitaResult> page(@Validated UrlPageQueryDTO query) { + urlService.list(query); + return AlitaResult.success(query.getPageResult()); + } + + @ApiOperation("获取全部可分配菜单列表") + @GetMapping("/get_all_menu_list/{roleId}/{platformCode}") + public AlitaResult getAllMenuList(@PathVariable Long roleId, + @PathVariable Integer platformCode) { + return urlService.queryAllMenuList(roleId, platformCode); + } + + +} diff --git a/src/main/java/com/newyetai/usercenter/resource/dao/UcComponentMapper.java b/src/main/java/com/newyetai/usercenter/resource/dao/UcComponentMapper.java new file mode 100644 index 0000000..ccf88b9 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/resource/dao/UcComponentMapper.java @@ -0,0 +1,38 @@ +package com.newyetai.usercenter.resource.dao; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.usercenter.resource.dto.ComponentDTO; +import com.newyetai.usercenter.resource.dto.ComponentPageQueryDTO; +import com.newyetai.usercenter.resource.entity.Component; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** + * 组件mapper + * + * @author sr on 2019-10-15 + */ +public interface UcComponentMapper extends MyMapper { + + /** + * 获取所有组件 + * + * @return + * @author sr on 2019-11-05 + */ + @Select("select * from xs_component where deleted = 0") + List findAll(); + + /** + * 查询组件列表 + * + * @param queryDTO + * @return + */ + List list(@Param("param") ComponentPageQueryDTO queryDTO); + + + List listComponentDTO(@Param("systemCode") Integer systemCode, @Param("orgId") Long orgId); +} diff --git a/src/main/java/com/newyetai/usercenter/resource/dao/UcUrlMapper.java b/src/main/java/com/newyetai/usercenter/resource/dao/UcUrlMapper.java new file mode 100644 index 0000000..d858b9c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/resource/dao/UcUrlMapper.java @@ -0,0 +1,68 @@ +package com.newyetai.usercenter.resource.dao; + +import java.util.List; +import java.util.Set; + +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.usercenter.resource.dto.UrlDTO; +import com.newyetai.usercenter.resource.dto.UrlPageQueryDTO; +import com.newyetai.usercenter.resource.entity.Url; + +/** + * 菜单 + * @author sr on 2019-10-15 + */ +public interface UcUrlMapper extends MyMapper{ + + String BEAN_ID = "security.urlMapper"; + + /** + * 查询所有菜单列表 + * + * @return + * @author sr on 2019-11-05 + */ + @Select("select * from xs_url where deleted = 0 and platform_code = #{platformCode} order by resource_order") + List findAll(Integer platformCode); + + /** + * 查询所有菜单 + * + * @return + */ + List findAllUrl(Integer platformCode, Long orgId); + + + /** + * 查询所有一级菜单列表 + * + * @param menuQuery 查询条件 + */ +// List selectAllParentMenuList(@Param("param") MenuQuery menuQuery, Page page); + + /** + * 查询所有二级菜单列表 + * @param parentIdList 一级菜单ID + */ + List selectAllChildMenuList(@Param("parentIdList") List parentIdList); + + /** + * 根据Id查询父级ID + * + * @param resourceIds + * @return + */ + Set selectParentIdByResourceIds(@Param("resourceIds") List resourceIds); + + /**************************** 下面的是最新方法 , 上面的逐步删除 *******************************/ + + List list(@Param("param") UrlPageQueryDTO urlQueryDTO); + + int batchDeleted(@Param("urlIds") Set urlIds); + + List listUrlDTO(@Param("systemCode") Integer systemCode, @Param("orgId") Long orgId); + +} diff --git a/src/main/java/com/newyetai/usercenter/resource/dto/ComponentDTO.java b/src/main/java/com/newyetai/usercenter/resource/dto/ComponentDTO.java new file mode 100644 index 0000000..8723ba2 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/resource/dto/ComponentDTO.java @@ -0,0 +1,69 @@ +package com.newyetai.usercenter.resource.dto; + +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.Optional; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +import org.springframework.security.access.ConfigAttribute; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.newyetai.common.validation.Create; +import com.newyetai.usercenter.dto.Resource; +import com.newyetai.usercenter.dto.ResourceDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2019-10-15 + */ +@ApiModel("组件") +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class ComponentDTO extends ResourceDTO implements Resource{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("菜单id") + @NotNull(message = "组件所属菜单id不能为空", groups = {Create.class}) + private Long urlId; + + @ApiModelProperty("组件编码") + @NotEmpty(message = "组件不能为空", groups = {Create.class}) + private String code; + + @ApiModelProperty("组件名称") + private String name; + + @ApiModelProperty("平台编码") + @NotNull(message = "平台编码不能为空", groups = {Create.class}) + private Integer platformCode; + + private List attributes; + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTime; + + + @Override + public List getAttributes() { + return Optional.ofNullable(attributes).orElse(Collections.emptyList()); + } + + + +} + diff --git a/src/main/java/com/newyetai/usercenter/resource/dto/ComponentPageQueryDTO.java b/src/main/java/com/newyetai/usercenter/resource/dto/ComponentPageQueryDTO.java new file mode 100644 index 0000000..052db2f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/resource/dto/ComponentPageQueryDTO.java @@ -0,0 +1,30 @@ +package com.newyetai.usercenter.resource.dto; + +import com.newyetai.common.dto.PageQueryDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; + +/** + * @author chenyun + * @description + * @date 2020/9/3 10:29 + */ +@ApiModel("菜单查询") +@Data +@NoArgsConstructor +@AllArgsConstructor +public class ComponentPageQueryDTO extends PageQueryDTO { + private static final long serialVersionUID = 573525736440675929L; + + /** + * 菜单Id + */ + @NotNull(message = "菜单ID不能为空") + @ApiModelProperty("菜单ID") + private Long urlId; +} diff --git a/src/main/java/com/newyetai/usercenter/resource/dto/UrlDTO.java b/src/main/java/com/newyetai/usercenter/resource/dto/UrlDTO.java new file mode 100644 index 0000000..d9ffa68 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/resource/dto/UrlDTO.java @@ -0,0 +1,120 @@ +package com.newyetai.usercenter.resource.dto; + +import java.util.Date; +import java.util.List; +import java.util.Optional; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import org.springframework.data.annotation.Transient; +import org.springframework.security.access.ConfigAttribute; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.google.common.collect.Lists; +import com.newyetai.common.util.TreeNode; +import com.newyetai.common.validation.Create; +import com.newyetai.usercenter.dto.Resource; +import com.newyetai.usercenter.dto.ResourceDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2019-10-15 + */ +@ApiModel("菜单") +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class UrlDTO extends ResourceDTO implements Resource, TreeNode { + private static final long serialVersionUID = 3185997122725142996L; + + @ApiModelProperty("资源名称(如果是按钮,从数据字典表取名称)") + @NotBlank(message = "菜单名称不能为空", groups = {Create.class}) + private String name; + + @ApiModelProperty("链接") + private String link; + + @ApiModelProperty("资源图标") + private String icon; + + @ApiModelProperty("对应的父资源ID,一级资源=0") + private Long parentId; + + @ApiModelProperty("排序") + private Integer resourceOrder; + + @ApiModelProperty("是否可见") + private Boolean visible; + + @ApiModelProperty("描述") + private String description; + + @ApiModelProperty("资源类型 1:菜单 2:接口") + @NotNull(message = "资源类型不能为空", groups = {Create.class}) + private Integer type; + + @ApiModelProperty("所属平台") + @NotNull(message = "平台编码不能为空", groups = {Create.class}) + private Integer platformCode; + + @ApiModelProperty("是否删除: 0-否 1-是") + private Integer deleted; + + @ApiModelProperty("创建时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTime; + + private List children = Lists.newArrayList(); + + private List components = Lists.newArrayList(); + + public List getChildren() { + if (this.children == null) { + this.children = Lists.newArrayList(); + } + return this.children; + } + + public void setChildren(List children) { + this.children = children; + } + + public List getComponents() { + return components; + } + + + @Transient + private List attributes; + + @Override + public List getAttributes() { + return Optional.ofNullable(attributes).orElse(Lists.newArrayList()); + } + + @Override + public void addChildren(UrlDTO node) { + List urlDTOS = Optional.ofNullable(getChildren()) + .orElse(Lists.newArrayList()); + urlDTOS.add(node); + setChildren(urlDTOS); + } + + public Long getParentId() { + return Optional.ofNullable(parentId).orElse(0L); + } + + public Boolean getVisible() { + return Optional.ofNullable(visible).orElse(Boolean.TRUE); + } +} diff --git a/src/main/java/com/newyetai/usercenter/resource/dto/UrlPageQueryDTO.java b/src/main/java/com/newyetai/usercenter/resource/dto/UrlPageQueryDTO.java new file mode 100644 index 0000000..286cb84 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/resource/dto/UrlPageQueryDTO.java @@ -0,0 +1,39 @@ +package com.newyetai.usercenter.resource.dto; + +import com.newyetai.common.dto.PageQueryDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Optional; + +/** + * @author chenyun + * @description + * @date 2020/9/3 10:29 + */ +@ApiModel("菜单查询") +@Data +@NoArgsConstructor +@AllArgsConstructor +public class UrlPageQueryDTO extends PageQueryDTO { + private static final long serialVersionUID = 573525736440675929L; + + @ApiModelProperty("平台编码") + private Integer platformCode; + + @ApiModelProperty("是否需要树形结构,默认不是树形") + private Boolean tree; + + @ApiModelProperty("资源类型 1:菜单 2:接口") + private Integer type; + + @ApiModelProperty("对应的父资源ID,一级资源=0") + private Long parentId; + + public Boolean getTree() { + return Optional.ofNullable(tree).orElse(Boolean.FALSE); + } +} diff --git a/src/main/java/com/newyetai/usercenter/resource/entity/Component.java b/src/main/java/com/newyetai/usercenter/resource/entity/Component.java new file mode 100644 index 0000000..e89aa60 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/resource/entity/Component.java @@ -0,0 +1,62 @@ +package com.newyetai.usercenter.resource.entity; + +import java.util.Date; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * 组件 + * + * @author sr on 2019-10-10 + */ +@TableName("xs_component") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Data +public class Component extends BaseEntity { + + /** + * + **/ + private static final long serialVersionUID = 6157400267849631575L; + + /** + * 菜单id + **/ + private Long urlId; + + /** + * 组件编码 + **/ + private String code; + + /** + * 组件名称 + **/ + private String name; + + /** + * 平台编码 + */ + private Integer platformCode; + + + @Builder + public Component(Long id, Boolean deleted, Long createBy, Date createTime, Long updateBy, + Date updateTime, Long proxyBy, Long urlId, String code, String name, Integer platformCode) { + super(id, deleted, createBy, createTime, updateBy, updateTime, proxyBy); + this.urlId = urlId; + this.code = code; + this.name = name; + this.platformCode = platformCode; + } + +} diff --git a/src/main/java/com/newyetai/usercenter/resource/entity/Url.java b/src/main/java/com/newyetai/usercenter/resource/entity/Url.java new file mode 100644 index 0000000..0466801 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/resource/entity/Url.java @@ -0,0 +1,86 @@ +package com.newyetai.usercenter.resource.entity; + +import java.util.Date; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author chenyun + * @description 菜单资源表 + * @date 2020/9/2 16:20 + */ +@Data +@TableName("xs_url") +@NoArgsConstructor +@AllArgsConstructor +public class Url extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 资源名称(如果是按钮,从数据字典表取名称) + **/ + private String name; + + /** + * 链接 + **/ + private String link; + + /** + * 资源图标 + **/ + private String icon; + + /** + * 对应的父资源ID,一级资源=0 + **/ + private Long parentId; + + /** + * 排序 + **/ + private Integer resourceOrder; + + /** + * 是否可见 + **/ + private Boolean visible; + + /** + * 描述 + **/ + private String description; + + /** + * 所属平台 + */ + private Integer platformCode; + + /** + * 资源类型 1:菜单 2:接口 + */ + private Integer type; + + @Builder + public Url(Long id, Boolean deleted, Long createBy, Date createTime, Long updateBy, + Date updateTime, Long proxyBy, String name, String link, String icon, Long parentId, + Integer resourceOrder, Boolean visible, String description, Integer platformCode, + Integer type) { + super(id, deleted, createBy, createTime, updateBy, updateTime, proxyBy); + this.name = name; + this.link = link; + this.icon = icon; + this.parentId = parentId; + this.resourceOrder = resourceOrder; + this.visible = visible; + this.description = description; + this.platformCode = platformCode; + this.type = type; + } +} diff --git a/src/main/java/com/newyetai/usercenter/resource/enums/UrlTypeEnum.java b/src/main/java/com/newyetai/usercenter/resource/enums/UrlTypeEnum.java new file mode 100644 index 0000000..c23f15d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/resource/enums/UrlTypeEnum.java @@ -0,0 +1,36 @@ +package com.newyetai.usercenter.resource.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.newyetai.mybatis.handle.BaseEnum; + +/** + * xs_url type 枚举类 + */ +public enum UrlTypeEnum implements BaseEnum { + + MENU(1, "菜单"), + INTERFACE(2, "接口"); + + @EnumValue + private Integer type; + + private String desc; + + UrlTypeEnum(Integer type, String desc) { + this.type = type; + this.desc = desc; + } + + public Integer getType() { + return type; + } + + public String getDesc() { + return desc; + } + + @Override + public Integer getValue() { + return this.type; + } +} diff --git a/src/main/java/com/newyetai/usercenter/resource/mapper/UcComponentMapper.xml b/src/main/java/com/newyetai/usercenter/resource/mapper/UcComponentMapper.xml new file mode 100644 index 0000000..de7f208 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/resource/mapper/UcComponentMapper.xml @@ -0,0 +1,40 @@ + + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/resource/mapper/UcUrlMapper.xml b/src/main/java/com/newyetai/usercenter/resource/mapper/UcUrlMapper.xml new file mode 100644 index 0000000..ebf8f36 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/resource/mapper/UcUrlMapper.xml @@ -0,0 +1,123 @@ + + + + + SELECT + id, + name, + link, + icon, + parent_id, + resource_order, + type, + visible, + description, + deleted, + create_time, + platform_code + FROM + xs_url + + + + + + + + + + + + update xs_url set deleted = 1 + where id in + + #{urlId} + + AND deleted = 0 + + + + + diff --git a/src/main/java/com/newyetai/usercenter/resource/mapstruct/ResourceMapMapper.java b/src/main/java/com/newyetai/usercenter/resource/mapstruct/ResourceMapMapper.java new file mode 100644 index 0000000..ca6f882 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/resource/mapstruct/ResourceMapMapper.java @@ -0,0 +1,31 @@ +package com.newyetai.usercenter.resource.mapstruct; + +import com.newyetai.usercenter.authority.dto.PermissionDTO; +import com.newyetai.usercenter.authority.entity.Permission; +import com.newyetai.usercenter.resource.dto.ComponentDTO; +import com.newyetai.usercenter.resource.dto.UrlDTO; +import com.newyetai.usercenter.resource.entity.Component; +import com.newyetai.usercenter.resource.entity.Url; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * @author sr on 2020-08-27 + */ +@Mapper +public interface ResourceMapMapper { + + ResourceMapMapper instance = Mappers.getMapper(ResourceMapMapper.class); + + @Mapping(target = "deleted", expression = "java(Boolean.TRUE.equals(url.getDeleted())?1:0)") + UrlDTO exchange(Url url); + + ComponentDTO exchange(Component component); + + Component exchange(ComponentDTO componentDTO); + + List exchange(List permissionDTOList); +} diff --git a/src/main/java/com/newyetai/usercenter/resource/service/UcComponentService.java b/src/main/java/com/newyetai/usercenter/resource/service/UcComponentService.java new file mode 100644 index 0000000..81fd183 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/resource/service/UcComponentService.java @@ -0,0 +1,42 @@ +package com.newyetai.usercenter.resource.service; + +import com.newyetai.usercenter.resource.dto.ComponentDTO; +import com.newyetai.usercenter.resource.dto.ComponentPageQueryDTO; + +import java.util.List; + + +/** + * 组件权限服务接口 + * + * @author on 2019-11-05 + */ +public interface UcComponentService { + + /** + * 新增组件 + * + * @param componentDTO + * @author sr on 2019-10-15 + */ + ComponentDTO creatComponent(ComponentDTO componentDTO); + + /** + * 修改组件 + * + * @param componentDTO + * @author sr on 2019-10-15 + */ + ComponentDTO updateComponent(ComponentDTO componentDTO); + + /** + * 删除组件 + * + * @param componentId + * @author sr on 2019-10-15 + */ + ComponentDTO deleteComponent(Long componentId); + + + List list(ComponentPageQueryDTO queryDTO); +} diff --git a/src/main/java/com/newyetai/usercenter/resource/service/UcResourceService.java b/src/main/java/com/newyetai/usercenter/resource/service/UcResourceService.java new file mode 100644 index 0000000..4f5c82b --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/resource/service/UcResourceService.java @@ -0,0 +1,20 @@ +package com.newyetai.usercenter.resource.service; + +import com.newyetai.usercenter.authority.dto.PermissionOperateDTO; + +/** + * 所有资源service + * @author sr on 2019-10-16 + */ +public interface UcResourceService { + + /** + * 保存业务角色权限 + * @param orgId + * @param permissionDTO + * @param operateUserId + * @author sr on 2019-10-17 + */ + void saveBusinessPermission(Long orgId, PermissionOperateDTO permissionDTO, Long operateUserId); + +} diff --git a/src/main/java/com/newyetai/usercenter/resource/service/UcUrlService.java b/src/main/java/com/newyetai/usercenter/resource/service/UcUrlService.java new file mode 100644 index 0000000..33fd903 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/resource/service/UcUrlService.java @@ -0,0 +1,72 @@ +package com.newyetai.usercenter.resource.service; + +import com.newyetai.common.AlitaResult; +import com.newyetai.usercenter.authority.dto.PermissionDTO; +import com.newyetai.usercenter.authority.dto.PermissionOperateDTO; +import com.newyetai.usercenter.authority.dto.PermissionPageQueryDTO; +import com.newyetai.usercenter.authority.dto.PermissionResourcesDTO; +import com.newyetai.usercenter.resource.dto.UrlDTO; +import com.newyetai.usercenter.resource.dto.UrlPageQueryDTO; + +import java.util.List; + + +/** + * 菜单服务接口 + * + * @author on 2019-11-05 + */ +public interface UcUrlService { + + /** + * 新增菜单 + * + * @param urlDTO + * @author sr on 2019-10-15 + */ + UrlDTO creatUrl(UrlDTO urlDTO); + + /** + * 修改菜单 + * + * @param urlDTO + * @author sr on 2019-10-15 + */ + UrlDTO updateUrl(UrlDTO urlDTO); + + /** + * 删除菜单 + * + * @param urlId + * @author sr on 2019-10-15 + */ + UrlDTO deleteUrl(Long urlId); + + /** + * 查询角色可分配的所有菜单列表 + * + * @return + */ + AlitaResult queryAllMenuList(Long roleId, Integer platformCode); + + + /** + * 资源列表 + * + * @param queryDTO + * @return + */ + List list(UrlPageQueryDTO queryDTO); + + + /** + * 查询角色/菜单下对应的组件或接口 + * + * @param permissionPageQueryDTO @return + * @return + */ + List queryAllResourceList( + PermissionPageQueryDTO permissionPageQueryDTO); + + void saveUrlResourcesOperateDTO(PermissionResourcesDTO permissionResourcesDTO); +} diff --git a/src/main/java/com/newyetai/usercenter/resource/service/impl/UcComponentServiceImpl.java b/src/main/java/com/newyetai/usercenter/resource/service/impl/UcComponentServiceImpl.java new file mode 100644 index 0000000..5a81b84 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/resource/service/impl/UcComponentServiceImpl.java @@ -0,0 +1,63 @@ +package com.newyetai.usercenter.resource.service.impl; + +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.usercenter.cache.SecurityCacheUtils; +import com.newyetai.usercenter.constants.SecurityConstants; +import com.newyetai.usercenter.resource.dao.UcComponentMapper; +import com.newyetai.usercenter.resource.dto.ComponentDTO; +import com.newyetai.usercenter.resource.dto.ComponentPageQueryDTO; +import com.newyetai.usercenter.resource.entity.Component; +import com.newyetai.usercenter.resource.mapstruct.ResourceMapMapper; +import com.newyetai.usercenter.resource.service.UcComponentService; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 组件 + * + * @author sr on 2019-10-15 + */ +@Service +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +//TODO 目前只有本地引用,需提供cloud调用,然后放开注释 +@ConditionalOnProperty(name = SecurityConstants.PROP_KEY_SECURITY_USELOCAL, havingValue = "true", matchIfMissing = true) +public class UcComponentServiceImpl implements UcComponentService { + + private final UcComponentMapper ucComponentMapper; + + @Override + public ComponentDTO creatComponent(ComponentDTO componentDTO) { + Component component = ResourceMapMapper.instance.exchange(componentDTO); + ucComponentMapper.saveEntity(component, UserContextHolder.getExistLoginSuperiorId()); + SecurityCacheUtils.flushAll(); + return ResourceMapMapper.instance.exchange(component); + } + + @Override + public ComponentDTO updateComponent(ComponentDTO componentDTO) { + Component component = ResourceMapMapper.instance.exchange(componentDTO); + Assert.isTrue(ucComponentMapper.updateEntitySelective(component, UserContextHolder.getExistLoginSuperiorId()) == 1 + , "更新组件失败"); + SecurityCacheUtils.flushAll(); + return ResourceMapMapper.instance.exchange(component); + } + + @Override + public ComponentDTO deleteComponent(Long componentId) { + Component component = Component.builder().id(componentId).build(); + Assert.isTrue(ucComponentMapper.deleteEntity(component, UserContextHolder.getExistLoginSuperiorId()) == 1, + "删除组件失败"); + SecurityCacheUtils.flushAll(); + return ResourceMapMapper.instance.exchange(component); + } + + @Override + public List list(ComponentPageQueryDTO queryDTO) { + return ucComponentMapper.list(queryDTO); + } +} diff --git a/src/main/java/com/newyetai/usercenter/resource/service/impl/UcResourceServiceImpl.java b/src/main/java/com/newyetai/usercenter/resource/service/impl/UcResourceServiceImpl.java new file mode 100644 index 0000000..65bad11 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/resource/service/impl/UcResourceServiceImpl.java @@ -0,0 +1,190 @@ +package com.newyetai.usercenter.resource.service.impl; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.google.common.collect.Lists; +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.exception.util.ExceptionUtils; +import com.newyetai.usercenter.authority.constants.PermissionConstants; +import com.newyetai.usercenter.authority.dao.UcPermissionMapper; +import com.newyetai.usercenter.authority.dao.UcRoleMapper; +import com.newyetai.usercenter.authority.dto.PermissionOperateDTO; +import com.newyetai.usercenter.authority.entity.Permission; +import com.newyetai.usercenter.cache.SecurityCacheEvict; +import com.newyetai.usercenter.constants.RoleConstants; +import com.newyetai.usercenter.constants.SecurityExceptionMsg; +import com.newyetai.usercenter.dto.ResourceDTO; +import com.newyetai.usercenter.resource.dao.UcComponentMapper; +import com.newyetai.usercenter.resource.dao.UcUrlMapper; +import com.newyetai.usercenter.resource.dto.ComponentDTO; +import com.newyetai.usercenter.resource.dto.UrlDTO; +import com.newyetai.usercenter.resource.service.UcResourceService; +import com.newyetai.usercenter.utils.PermissionUtils; + +/** + * 所有资源 + * + * @author sr on 2019-10-16 + */ +@Service +public class UcResourceServiceImpl implements UcResourceService { + + @Autowired + private UcComponentMapper ucComponentMapper; + + @Autowired + private UcUrlMapper ucUrlMapper; + + @Autowired + private UcPermissionMapper permissionMapper; + + @Autowired + private UcRoleMapper roleMapper; + + @Override + @Transactional(rollbackFor = RuntimeException.class) + @SecurityCacheEvict + public void saveBusinessPermission(Long orgId, PermissionOperateDTO permissionDTO, Long operateUserId) { + Long roleId = permissionDTO.getRoleId(); + checkRoleType(orgId, roleId, RoleConstants.ROLE_TYPE_BUSINESS); + dealResourceIds(roleId, permissionDTO.getResourceIds(), operateUserId); + } + + /** + * 校验对应机构下是否有对应角色 + * @param orgId + * @param roleId + * @param roleType + * @author sr on 2019-10-17 + */ + private void checkRoleType(Long orgId, Long roleId, String roleType) { + int num = roleMapper.existRole(orgId, roleId, roleType); + ExceptionUtils.throwBusinessException(num == 0, SecurityExceptionMsg.ORG_ROLE_NOT_EXIST); + } + + /** + * 根据给定权限资源id列表重新分配权限 + * @param operateUserId + * @author sr on 2019-10-21 + */ + private void dealResourceIds(Long roleId, List resourceIdStrings, Long operateUserId){ + // 获取roleId已存在的权限 + List permissions = permissionMapper.findByRoleId(roleId); + + Map permissionMap = permissions.stream() + .collect(Collectors.toMap(p -> StringUtils.join(p.getResourceType(), CommonConstants.UNDERLINE, p.getResourceId()), p -> p, (p1, p2) -> p1)); + + List createPermissions = Lists.newArrayList(); + List deletePermissions = null; + + resourceIdStrings.forEach(resourceIdString -> { + String[] resourceArray = resourceIdString.split(CommonConstants.UNDERLINE); + String resourceType = resourceArray[0]; + Long resourceId = Long.valueOf(resourceArray[1]); + Permission permission = permissionMap.get(resourceIdString); + if (permission == null) { + // 新增 + createPermissions.add(PermissionUtils.createPermission(roleId, resourceType, resourceId)); + return ; + } + // 不变 + permissionMap.remove(resourceIdString); + }); + // 删除 + deletePermissions = Lists.newArrayList(permissionMap.values()); + if (CollectionUtils.isNotEmpty(deletePermissions)) { + permissionMapper.deleteEntites(deletePermissions, operateUserId); + } + permissionMapper.saveEntites(createPermissions, operateUserId); + } + + + /** + * 处理前端传入角色权限树,变更已存在角色权限 + * @param permissionDTO + * @param operateUserId + * @author sr on 2019-10-17 + */ + @SuppressWarnings("unused") + private void dealResource(PermissionOperateDTO permissionDTO, Long operateUserId) { + Long roleId = permissionDTO.getRoleId(); + List urlDTOs = permissionDTO.getUrlDTOs(); + // 获取roleId已存在的权限 + List permissions = permissionMapper.findByRoleId(roleId); + + Map permissionMap = permissions.stream() + .collect(Collectors.toMap(p -> StringUtils.join(p.getResourceType(), CommonConstants.UNDERLINE, p.getResourceId()), p -> p)); + + List createPermissions = Lists.newArrayList(); + List deletePermissions = Lists.newArrayList(); + urlDTOs.stream().forEach(urlDTO -> dealUrlDTO(roleId, urlDTO, permissionMap, createPermissions, deletePermissions)); + permissionMapper.saveEntites(createPermissions, operateUserId); + permissionMapper.deleteEntites(deletePermissions, operateUserId); + + } + + /** + * 处理菜单权限(包含自己,子菜单,子组件) + * @param roleId + * @param urlDTO + * @param permissionMap + * @param createPermissions + * @param deletePermissions + * @author sr on 2019-10-17 + */ + private void dealUrlDTO(Long roleId, UrlDTO urlDTO, Map permissionMap, List createPermissions, List deletePermissions) { + // 处理当前菜单 + dealResource(roleId, urlDTO, permissionMap, createPermissions, deletePermissions); + List components = urlDTO.getComponents(); + // 处理组件 + if (CollectionUtils.isNotEmpty(components)) { + components.forEach(component -> dealResource(roleId, component, permissionMap, createPermissions, deletePermissions)); + } + // 处理子菜单 + List childrenUrlDTOs = urlDTO.getChildren(); + if (CollectionUtils.isEmpty(childrenUrlDTOs)) { + return ; + } + childrenUrlDTOs.stream().forEach(childrenUrlDTO -> dealUrlDTO(roleId, urlDTO, permissionMap, createPermissions, deletePermissions)); + } + + /** + * 处理单个资源权限(菜单/组件) + * @param roleId + * @param resourceDTO + * @param permissionMap + * @param createPermissions + * @param deletePermissions + * @author sr on 2019-10-17 + */ + private void dealResource(Long roleId, ResourceDTO resourceDTO, Map permissionMap, List createPermissions, List deletePermissions) { + String resourceType = null; + if (resourceDTO instanceof UrlDTO) { + resourceType = PermissionConstants.RESOURCE_TYPE_URL; + } else if (resourceDTO instanceof ComponentDTO) { + resourceType = PermissionConstants.RESOURCE_TYPE_COMPONENT; + } else { + return; + } + Long resourceId = resourceDTO.getId(); + Boolean selected = resourceDTO.getSelected(); + String key = StringUtils.join(resourceType, CommonConstants.UNDERLINE, resourceId); + Permission permission = permissionMap.get(key); + if (permission != null && !Boolean.TRUE.equals(selected)) { + // 删除 + deletePermissions.add(permission); + } else if (permission == null && Boolean.TRUE.equals(selected)) { + // 新增 + createPermissions.add(PermissionUtils.createPermission(roleId, PermissionConstants.RESOURCE_TYPE_COMPONENT, resourceId)); + } + } + +} diff --git a/src/main/java/com/newyetai/usercenter/resource/service/impl/UcUrlServiceImpl.java b/src/main/java/com/newyetai/usercenter/resource/service/impl/UcUrlServiceImpl.java new file mode 100644 index 0000000..e3c8d23 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/resource/service/impl/UcUrlServiceImpl.java @@ -0,0 +1,186 @@ +package com.newyetai.usercenter.resource.service.impl; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.constant.SystemCodeEnum; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.exception.util.ExceptionUtils; +import com.newyetai.common.util.TreeHelper; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.usercenter.authority.constants.PermissionConstants; +import com.newyetai.usercenter.authority.dao.UcPermissionMapper; +import com.newyetai.usercenter.authority.dto.PermissionDTO; +import com.newyetai.usercenter.authority.dto.PermissionOperateDTO; +import com.newyetai.usercenter.authority.dto.PermissionPageQueryDTO; +import com.newyetai.usercenter.authority.dto.PermissionResourcesDTO; +import com.newyetai.usercenter.cache.SecurityCacheUtils; +import com.newyetai.usercenter.constants.SecurityConstants; +import com.newyetai.usercenter.resource.dao.UcUrlMapper; +import com.newyetai.usercenter.resource.dto.UrlDTO; +import com.newyetai.usercenter.resource.dto.UrlPageQueryDTO; +import com.newyetai.usercenter.resource.entity.Url; +import com.newyetai.usercenter.resource.mapstruct.ResourceMapMapper; +import com.newyetai.usercenter.resource.service.UcUrlService; +import com.newyetai.usercenter.utils.UrlUtils; +import lombok.RequiredArgsConstructor; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * 菜单 + * + * @author sr on 2019-10-15 + */ +@Service +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +//TODO 目前只有本地引用,需提供cloud调用,然后放开注释 +@ConditionalOnProperty(name = SecurityConstants.PROP_KEY_SECURITY_USELOCAL, havingValue = "true", matchIfMissing = true) +public class UcUrlServiceImpl implements UcUrlService { + + private final UcUrlMapper ucUrlMapper; + + private final UcPermissionMapper ucPermissionMapper; + + @Override + public UrlDTO creatUrl(UrlDTO urlDTO) { + Url url = UrlUtils.toCreateUrl(urlDTO); + ucUrlMapper.saveEntity(url, UserContextHolder.getExistLoginSuperiorId()); + SecurityCacheUtils.flushAll(); + return ResourceMapMapper.instance.exchange(url); + } + + @Override + public UrlDTO updateUrl(UrlDTO urlDTO) { + Url url = UrlUtils.toUpdateUrl(urlDTO); + Assert.isTrue( + ucUrlMapper.updateEntity(url, UserContextHolder.getExistLoginSuperiorId()) == 1, + "更新菜单失败"); + SecurityCacheUtils.flushAll(); + return ResourceMapMapper.instance.exchange(url); + } + + @Override + @Transactional(rollbackFor = RuntimeException.class) + public UrlDTO deleteUrl(Long urlId) { + Url history = ucUrlMapper.getById(urlId); + ExceptionUtils.throwBusinessException(history == null || history.getDeleted(), "菜单已被删除"); + + Url url = Url.builder().id(urlId).build(); + ExceptionUtils.throwBusinessException( + ucUrlMapper.deleteEntity(url, UserContextHolder.getExistLoginSuperiorId()) != 1, "删除菜单失败"); + + // 递归删除子菜单 + Integer platformCode = history.getPlatformCode(); + Arrays.stream(SystemCodeEnum.values()) + .filter(systemCodeEnum -> systemCodeEnum.getCode().equals(platformCode)) + .findFirst() + .orElseThrow(() -> new RuntimeException("菜单应用码异常")); + + UrlPageQueryDTO urlQueryDTO = new UrlPageQueryDTO(); + urlQueryDTO.setNeedPage(false); + urlQueryDTO.setPlatformCode(platformCode); + List list = ucUrlMapper.list(urlQueryDTO); + if (CollectionUtils.isNotEmpty(list)) { + Set childrenNodeIds = TreeHelper.childrenNodeIds(urlId, list); + if (!childrenNodeIds.isEmpty()) { + ucUrlMapper.batchDeleted(childrenNodeIds); + } + } + SecurityCacheUtils.flushAll(); + return ResourceMapMapper.instance.exchange(url); + } + + @Override + public AlitaResult queryAllMenuList(Long roleId, Integer platformCode) { + PermissionOperateDTO permissionDTO = new PermissionOperateDTO(); + permissionDTO.setUrlDTOs(TreeHelper.buildTree(0L, ucUrlMapper.findAllUrl(platformCode, + UserContextHolder.getLoginOrgId()))); + //查询已分配的资源列表 + Set tempResourceIdSet = ucPermissionMapper.findResourceIdByRoleId(roleId, 1); + permissionDTO.setResourceIdList(new ArrayList<>(tempResourceIdSet)); + return AlitaResult.success(permissionDTO); + } + + @Override + public List list(UrlPageQueryDTO urlQueryDTO) { + List list = ucUrlMapper.list(urlQueryDTO); + if (Boolean.TRUE.equals(urlQueryDTO.getTree())) { + return TreeHelper.buildTree(0L, list); + } + return list; + } + + @Override + public List queryAllResourceList( + PermissionPageQueryDTO permissionPageQueryDTO) { + if (PermissionConstants.RESOURCE_TYPE_COMPONENT + .equals(permissionPageQueryDTO.getResourceType())) { + return + ucPermissionMapper.urlComponentList(permissionPageQueryDTO + ); + } else if (PermissionConstants.RESOURCE_TYPE_INTERFACE + .equals(permissionPageQueryDTO.getResourceType())) { + return ucPermissionMapper.urlInterfaceList(permissionPageQueryDTO); + } + return null; + } + + @Override + public void saveUrlResourcesOperateDTO(PermissionResourcesDTO permissionResourcesDTO) { + List permissionDTOList = permissionResourcesDTO + .getPermissionDTOList(); + // 获取原来已有的 + permissionResourcesDTO.setOrgId(UserContextHolder.getLoginOrgId()); + permissionResourcesDTO.setNeedPage(false); + permissionResourcesDTO.setSelected(Boolean.TRUE); + List originalPermissionDTOList = this + .queryAllResourceList(permissionResourcesDTO); + Set oldResourceIdSet = originalPermissionDTOList.stream() + .map(PermissionDTO::getResourceId) + .collect(Collectors.toSet()); + + // 获取新增的资源,顺便将旧的列表中移出已存在的资源 + if(CollectionUtils.isNotEmpty(permissionDTOList)){ + List selectedList = permissionDTOList.stream() + .filter(permissionDTO -> { + permissionDTO.setAttribute("ROLE_" + permissionDTO.getRoleId()); + Long newResourceId = permissionDTO.getResourceId(); + boolean exist = oldResourceIdSet.contains(newResourceId); + // 移出已存在的资源 + if (exist) { + oldResourceIdSet.remove(newResourceId); + }else{ + permissionDTO.setId(null); + } + return !exist; + }) + .collect(Collectors.toList()); + + // 新增(在新的中排除老的就是新增的) + if (CollectionUtils.isNotEmpty(selectedList)) { + ucPermissionMapper + .saveEntites(ResourceMapMapper.instance.exchange(selectedList), + UserContextHolder.getLoginUserId()); + } + } + + // 删除(将老的中排除新增的就是要删除的) + List removeList = originalPermissionDTOList.stream() + .filter(permissionDTO -> oldResourceIdSet.contains(permissionDTO.getResourceId())) + .collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(removeList)) { + ucPermissionMapper + .deleteEntites(ResourceMapMapper.instance.exchange(removeList), + UserContextHolder.getLoginUserId()); + } + + } +} diff --git a/src/main/java/com/newyetai/usercenter/searchHistory/controller/SearchHistoryController.java b/src/main/java/com/newyetai/usercenter/searchHistory/controller/SearchHistoryController.java new file mode 100644 index 0000000..fa7e926 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/searchHistory/controller/SearchHistoryController.java @@ -0,0 +1,45 @@ +package com.newyetai.usercenter.searchHistory.controller; + +import com.newyetai.common.AlitaResult; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.searchHistory.dto.SearchHistoryCreateDTO; +import com.newyetai.usercenter.searchHistory.dto.SearchHistoryInfoDTO; +import com.newyetai.usercenter.searchHistory.dto.SearchHistoryPageQueryDTO; +import com.newyetai.usercenter.searchHistory.service.SearchHistoryService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +/** + * @author czy on 2021-03-25 + */ +@RestController +@RequestMapping("search_history") +@Api(tags = "搜索记录") +public class SearchHistoryController { + + @Autowired + private SearchHistoryService searchHistoryService; + + @PostMapping("/create") + @ApiOperation("创建") + public AlitaResult create(@RequestBody SearchHistoryCreateDTO createDTO) { + searchHistoryService.create(createDTO); + return AlitaResult.success(); + } + + @GetMapping("/page") + @ApiOperation("列表") + public AlitaResult> page(SearchHistoryPageQueryDTO pageQueryDTO) { + searchHistoryService.page(pageQueryDTO); + return AlitaResult.success(pageQueryDTO.getPageResult()); + } + + @PostMapping("/clean_all") + @ApiOperation("删除") + public AlitaResult cleanAll() { + searchHistoryService.cleanAll(); + return AlitaResult.success(); + } +} diff --git a/src/main/java/com/newyetai/usercenter/searchHistory/dao/SearchHistoryMapper.java b/src/main/java/com/newyetai/usercenter/searchHistory/dao/SearchHistoryMapper.java new file mode 100644 index 0000000..910cf87 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/searchHistory/dao/SearchHistoryMapper.java @@ -0,0 +1,22 @@ +package com.newyetai.usercenter.searchHistory.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.newyetai.usercenter.searchHistory.dto.SearchHistoryInfoDTO; +import com.newyetai.usercenter.searchHistory.dto.SearchHistoryPageQueryDTO; +import com.newyetai.usercenter.searchHistory.entity.SearchHistory; + +import java.util.List; + + +/** + * 搜索历史映射器 + * + * @author Carlye + * @date 2021/10/22 + */ +public interface SearchHistoryMapper extends BaseMapper { + + + List page(SearchHistoryPageQueryDTO queryDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/searchHistory/dto/SearchHistoryCreateDTO.java b/src/main/java/com/newyetai/usercenter/searchHistory/dto/SearchHistoryCreateDTO.java new file mode 100644 index 0000000..12ec641 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/searchHistory/dto/SearchHistoryCreateDTO.java @@ -0,0 +1,40 @@ +package com.newyetai.usercenter.searchHistory.dto; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +import com.newyetai.common.dto.BaseDTO; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + + +/** + * 搜索历史记录 + * + * @author Carlye + * @date 2021/10/22 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Data +public class SearchHistoryCreateDTO extends BaseDTO{ + + + private static final long serialVersionUID = -4903984190748073753L; + /** + * 搜索内容 + */ + @NotEmpty(message = "搜索内容不能为空") + private String context; + + /** + * 搜索类目 1:招聘系统搜索记录 + */ + @NotNull(message = "搜索类目不能为空") + private Integer type; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/searchHistory/dto/SearchHistoryInfoDTO.java b/src/main/java/com/newyetai/usercenter/searchHistory/dto/SearchHistoryInfoDTO.java new file mode 100644 index 0000000..4e5d0d8 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/searchHistory/dto/SearchHistoryInfoDTO.java @@ -0,0 +1,37 @@ +package com.newyetai.usercenter.searchHistory.dto; + +import com.newyetai.common.dto.BaseDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + + +/** + * 搜索历史记录 + * + * @author Carlye + * @date 2021/10/22 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel("搜索历史记录") +public class SearchHistoryInfoDTO extends BaseDTO{ + + private static final long serialVersionUID = 4107885503029801211L; + /** + * 搜索内容 + */ + @ApiModelProperty("搜索内容") + private String context; + + + @ApiModelProperty("搜索次数") + private Integer count; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/searchHistory/dto/SearchHistoryPageQueryDTO.java b/src/main/java/com/newyetai/usercenter/searchHistory/dto/SearchHistoryPageQueryDTO.java new file mode 100644 index 0000000..dc05d7c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/searchHistory/dto/SearchHistoryPageQueryDTO.java @@ -0,0 +1,42 @@ +package com.newyetai.usercenter.searchHistory.dto; + +import com.newyetai.common.dto.PageQueryDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + + +/** + * 搜索历史记录 + * + * @author Carlye + * @date 2021/10/22 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel("搜索历史记录 - 查询DTO") +public class SearchHistoryPageQueryDTO extends PageQueryDTO { + + private static final long serialVersionUID = 6186970573776391657L; + + /** + * 搜索内容 + */ + @ApiModelProperty("搜索内容") + private String context; + + /** + * 搜索类目 1:招聘系统搜索记录 + */ + @ApiModelProperty("搜索类目") + private Integer type; + + private Long userId; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/searchHistory/entity/SearchHistory.java b/src/main/java/com/newyetai/usercenter/searchHistory/entity/SearchHistory.java new file mode 100644 index 0000000..71fdd2d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/searchHistory/entity/SearchHistory.java @@ -0,0 +1,46 @@ +package com.newyetai.usercenter.searchHistory.entity; + +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + + +/** + * 搜索历史记录 + * + * @author Carlye + * @date 2021/10/22 + */ +@TableName("xs_search_history") +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Data +public class SearchHistory extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 3512068172003223792L; + + /** + * 搜索内容 + */ + private String context; + + /** + * 搜索类目 1:招聘系统搜索记录 + */ + private Integer type; + + /** + * 用户ID + */ + private Long userId; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/searchHistory/enums/SearchHistoryTypeEnum.java b/src/main/java/com/newyetai/usercenter/searchHistory/enums/SearchHistoryTypeEnum.java new file mode 100644 index 0000000..e513f1d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/searchHistory/enums/SearchHistoryTypeEnum.java @@ -0,0 +1,38 @@ +package com.newyetai.usercenter.searchHistory.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.newyetai.mybatis.handle.BaseEnum; + + +/** + * 关联类型枚举 + * + * @author Carlye + * @date 2021/01/21 + */ +public enum SearchHistoryTypeEnum implements BaseEnum { + POST(1, "招聘系统搜索记录"); + + @EnumValue + private final Integer type; + + private final String desc; + + SearchHistoryTypeEnum(Integer type, String desc) { + this.type = type; + this.desc = desc; + } + + public Integer getType() { + return type; + } + + public String getDesc() { + return desc; + } + + @Override + public Integer getValue() { + return type; + } +} diff --git a/src/main/java/com/newyetai/usercenter/searchHistory/mapper/SearchHistoryMapper.xml b/src/main/java/com/newyetai/usercenter/searchHistory/mapper/SearchHistoryMapper.xml new file mode 100644 index 0000000..10c931e --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/searchHistory/mapper/SearchHistoryMapper.xml @@ -0,0 +1,20 @@ + + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/searchHistory/service/SearchHistoryService.java b/src/main/java/com/newyetai/usercenter/searchHistory/service/SearchHistoryService.java new file mode 100644 index 0000000..664626d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/searchHistory/service/SearchHistoryService.java @@ -0,0 +1,42 @@ +package com.newyetai.usercenter.searchHistory.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.newyetai.usercenter.searchHistory.dto.SearchHistoryCreateDTO; +import com.newyetai.usercenter.searchHistory.dto.SearchHistoryInfoDTO; +import com.newyetai.usercenter.searchHistory.dto.SearchHistoryPageQueryDTO; +import com.newyetai.usercenter.searchHistory.entity.SearchHistory; +import org.springframework.validation.annotation.Validated; + +import javax.validation.Valid; +import javax.validation.groups.Default; +import java.util.List; + +/** + * 搜索历史记录服务 + * + * @author Carlye + * @date 2021/10/22 + */ +@Validated(Default.class) +public interface SearchHistoryService extends IService { + + /** + * 新建搜索记录 + * + * @param createDTO 创建dto + */ + void create(@Valid SearchHistoryCreateDTO createDTO); + + /** + * 分页查询搜索记录 + * + * @param queryDTO 查询dto + * @return {@link List}<{@link SearchHistoryInfoDTO}> + */ + List page(SearchHistoryPageQueryDTO queryDTO); + + /** + * 清楚所有的搜搜记录 + */ + void cleanAll(); +} diff --git a/src/main/java/com/newyetai/usercenter/searchHistory/service/impl/SearchHistoryServiceImpl.java b/src/main/java/com/newyetai/usercenter/searchHistory/service/impl/SearchHistoryServiceImpl.java new file mode 100644 index 0000000..7142f1f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/searchHistory/service/impl/SearchHistoryServiceImpl.java @@ -0,0 +1,47 @@ +package com.newyetai.usercenter.searchHistory.service.impl; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.usercenter.searchHistory.dao.SearchHistoryMapper; +import com.newyetai.usercenter.searchHistory.dto.SearchHistoryCreateDTO; +import com.newyetai.usercenter.searchHistory.dto.SearchHistoryInfoDTO; +import com.newyetai.usercenter.searchHistory.dto.SearchHistoryPageQueryDTO; +import com.newyetai.usercenter.searchHistory.entity.SearchHistory; +import com.newyetai.usercenter.searchHistory.service.SearchHistoryService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Slf4j +@Service +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class SearchHistoryServiceImpl extends ServiceImpl implements SearchHistoryService { + + + @Override + public void create(SearchHistoryCreateDTO createDTO) { + save(SearchHistory.builder().context(createDTO.getContext()).type(createDTO.getType()).userId(UserContextHolder.getExistLoginUserId()).build()); + } + + @Override + public List page(SearchHistoryPageQueryDTO queryDTO) { + queryDTO.setUserId(UserContextHolder.getExistLoginUserId()); + return getBaseMapper().page(queryDTO); + } + + @Override + public void cleanAll() { + update(Wrappers.lambdaUpdate() + .set(SearchHistory::getDeleted,true) + .set(SearchHistory::getUpdateBy,UserContextHolder.getExistLoginUserId()) + .set(SearchHistory::getUpdateTime, DateUtil.date()) + .eq(SearchHistory::getUserId,UserContextHolder.getExistLoginUserId()) + .eq(SearchHistory::getDeleted,false) + ); + } +} diff --git a/src/main/java/com/newyetai/usercenter/service/AuthService.java b/src/main/java/com/newyetai/usercenter/service/AuthService.java new file mode 100644 index 0000000..9d74fb3 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/service/AuthService.java @@ -0,0 +1,4 @@ +package com.newyetai.usercenter.service; + +public interface AuthService { +} diff --git a/src/main/java/com/newyetai/usercenter/service/UcDictionaryService.java b/src/main/java/com/newyetai/usercenter/service/UcDictionaryService.java new file mode 100644 index 0000000..3b83b02 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/service/UcDictionaryService.java @@ -0,0 +1,85 @@ +package com.newyetai.usercenter.service; + +import com.newyetai.common.AlitaResult; +import com.newyetai.component.dict.dto.DictDTO; +import com.newyetai.component.dict.dto.DictDetailDTO; +import com.newyetai.component.dict.dto.DictDetailQueryDTO; +import com.newyetai.component.dict.dto.DictQueryDTO; +import com.newyetai.component.dict.service.DictDetailService; +import com.newyetai.component.dict.service.DictService; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author: Jerry.li + * @description: 数据字典服务 + * @create: 2020-06-18 14:19 + **/ +@Slf4j +@Service +public class UcDictionaryService { + + @Autowired + private DictService dictService; + + @Autowired + private DictDetailService dictDetailService; + + + /** + * 新增或者修改字典数据 + * + * @param dictDTO + * @param operateUserId + * @return + */ + public AlitaResult editDictionary(DictDTO dictDTO, Long operateUserId) { + if (null == dictDTO.getId()) { + return AlitaResult.success(dictService.createDict(dictDTO, operateUserId)); + } else { + return AlitaResult.success(dictService.modifyDict(dictDTO, operateUserId)); + } + } + + /** + * 新增或者修改字典数据详情 + * + * @param detailDTO + * @param operateUserId + * @return + */ + public AlitaResult editDictionaryDetail(DictDetailDTO detailDTO, Long operateUserId) { + if (null == detailDTO.getId()) { + dictDetailService.createDictDetail(detailDTO, operateUserId); + } else { + dictDetailService.modifyDictDetail(detailDTO, operateUserId); + } + return AlitaResult.success(true); + } + + /** + * 分页查询数据字典列表 + * + * @return + */ + public void pageDictionaryList(DictQueryDTO query) { + query.setDictCode(StringUtils.trim(query.getDictCode())); + query.setDictName(StringUtils.trim(query.getDictName())); + dictService.page(query); + } + + /** + * 查询数据字典详情列表 + * + * @param detailQueryDTO + * @return + */ + public List getDictDetailList(DictDetailQueryDTO detailQueryDTO) { + return dictDetailService.list(detailQueryDTO); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/service/UcRoleStandardTypeService.java b/src/main/java/com/newyetai/usercenter/service/UcRoleStandardTypeService.java new file mode 100644 index 0000000..41e1d4f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/service/UcRoleStandardTypeService.java @@ -0,0 +1,16 @@ +package com.newyetai.usercenter.service; + +import java.util.List; + +import com.newyetai.usercenter.dto.RoleStandardTypeDTO; +import com.newyetai.usercenter.query.RoleStandardTypeQuery; + +/** + * @Author dylanyuan + * @Date 2021/2/19 2:21 下午 + * @Version 1.0 + */ +public interface UcRoleStandardTypeService { + + List page(RoleStandardTypeQuery query); +} diff --git a/src/main/java/com/newyetai/usercenter/service/UcSmsService.java b/src/main/java/com/newyetai/usercenter/service/UcSmsService.java new file mode 100644 index 0000000..874a674 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/service/UcSmsService.java @@ -0,0 +1,43 @@ +package com.newyetai.usercenter.service; + +import com.newyetai.common.AlitaResult; +import com.newyetai.usercenter.enums.SmsScenesEnum; + +/** + * @author chenyun + * @description 短信验证码 + * @date 2020/8/26 14:23 + */ +public interface UcSmsService { + + + /** + * 发送手机验证码 + * + * @param smsScenesEnum + * @param phone + * @return + */ + AlitaResult sendPhoneCode(SmsScenesEnum smsScenesEnum, String phone); + + /** + * 校验手机验证码 + * + * @param smsScenesEnum + * @param phone + * @param code + * @return + */ + AlitaResult checkPhoneCode(SmsScenesEnum smsScenesEnum, String phone, String code); + + /** + * 使用手机验证码 + * + * @param smsScenesEnum + * @param phone 手机号 + * @param code 验证码 + * @return + */ + AlitaResult usePhoneCode(SmsScenesEnum smsScenesEnum, String phone, String code); + +} diff --git a/src/main/java/com/newyetai/usercenter/service/impl/UcRoleStandardTypeServiceImpl.java b/src/main/java/com/newyetai/usercenter/service/impl/UcRoleStandardTypeServiceImpl.java new file mode 100644 index 0000000..2108b4f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/service/impl/UcRoleStandardTypeServiceImpl.java @@ -0,0 +1,30 @@ +package com.newyetai.usercenter.service.impl; + +import com.newyetai.usercenter.dao.XsRoleStandardTypeMapper; +import com.newyetai.usercenter.dto.RoleStandardTypeDTO; +import com.newyetai.usercenter.entity.RoleStandardType; +import com.newyetai.usercenter.query.RoleStandardTypeQuery; +import com.newyetai.usercenter.service.UcRoleStandardTypeService; +import java.util.List; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * @Author dylanyuan + * @Date 2021/2/19 2:21 下午 + * @Version 1.0 + */ +@Slf4j +@Service +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class UcRoleStandardTypeServiceImpl implements UcRoleStandardTypeService { + + private final XsRoleStandardTypeMapper xsRoleStandardTypeMapper; + + @Override + public List page(RoleStandardTypeQuery query) { + return xsRoleStandardTypeMapper.page(query); + } +} diff --git a/src/main/java/com/newyetai/usercenter/sys/constant/DomainSettingConstant.java b/src/main/java/com/newyetai/usercenter/sys/constant/DomainSettingConstant.java new file mode 100644 index 0000000..1a22e47 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/constant/DomainSettingConstant.java @@ -0,0 +1,13 @@ +package com.newyetai.usercenter.sys.constant; + +/** + * @description: + * @author: guixinman + * @create: 2024-05-20 15:57 + **/ +public interface DomainSettingConstant { + + Integer QUICK = 3; + + Integer BANNER = 2; +} diff --git a/src/main/java/com/newyetai/usercenter/sys/controller/DomainAnonController.java b/src/main/java/com/newyetai/usercenter/sys/controller/DomainAnonController.java new file mode 100644 index 0000000..598a1d5 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/controller/DomainAnonController.java @@ -0,0 +1,39 @@ +package com.newyetai.usercenter.sys.controller; + +import com.newyetai.common.AlitaResult; +import com.newyetai.usercenter.dto.DomainSettingReqDTO; +import com.newyetai.usercenter.dto.DomainSettingResDTO; +import com.newyetai.usercenter.sys.service.DomainSettingService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + * @author sr on 2021-05-24 + */ +@RestController +@RequestMapping("/anon") +@Api(tags = "域名") +public class DomainAnonController { + + @Autowired + private DomainSettingService domainSettingService; + + @ApiOperation(value = "域名配置查询", notes = "域名配置查询") + @GetMapping("/domain_setting/list") + public AlitaResult> list(DomainSettingReqDTO reqDTO) { + return AlitaResult.success(domainSettingService.list(reqDTO)); + } + + @ApiOperation(value = "清理缓存", notes = "清理缓存") + @GetMapping("/domain_setting/clean_cache") + public AlitaResult cleanCache() { + domainSettingService.cleanCache(); + return AlitaResult.success(); + } +} diff --git a/src/main/java/com/newyetai/usercenter/sys/controller/DomainAuthController.java b/src/main/java/com/newyetai/usercenter/sys/controller/DomainAuthController.java new file mode 100644 index 0000000..c56f71c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/controller/DomainAuthController.java @@ -0,0 +1,58 @@ +package com.newyetai.usercenter.sys.controller; + +import com.newyetai.common.AlitaResult; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.sys.dto.DomainAuthDTO; +import com.newyetai.usercenter.sys.dto.DomainAuthOperateDTO; +import com.newyetai.usercenter.sys.dto.DomainAuthQueryDTO; +import com.newyetai.usercenter.sys.service.DomainAuthService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Set; + +/** + * @author sr on 2021-05-24 + */ +@RestController +@RequestMapping("domain_auth") +@Api(tags = "域名授权") +public class DomainAuthController { + + @Autowired + private DomainAuthService domainAuthService; + + @PostMapping("/link") + @ApiOperation("关联") + public AlitaResult> link(@RequestBody DomainAuthOperateDTO domainAuthOperateDTO) { + return AlitaResult.success(domainAuthService.link(domainAuthOperateDTO)); + } + + @PostMapping("/cancel_link") + @ApiOperation("取消关联") + public AlitaResult> cancelLink(@RequestBody DomainAuthOperateDTO domainAuthOperateDTO) { + return AlitaResult.success(domainAuthService.cancelLink(domainAuthOperateDTO)); + } + + @GetMapping("/page") + @ApiOperation("分页查询") + public AlitaResult> page(DomainAuthQueryDTO domainAuthQueryDTO) { + domainAuthService.list(domainAuthQueryDTO); + return AlitaResult.success(domainAuthQueryDTO.getPageResult()); + } + + @GetMapping("/not_link_list") + @ApiOperation("分页查询未关联的引用列表") + public AlitaResult> notLinkList(DomainAuthQueryDTO domainAuthQueryDTO) { + domainAuthService.notLinkList(domainAuthQueryDTO); + return AlitaResult.success(domainAuthQueryDTO.getPageResult()); + } + + +} diff --git a/src/main/java/com/newyetai/usercenter/sys/controller/DomainController.java b/src/main/java/com/newyetai/usercenter/sys/controller/DomainController.java new file mode 100644 index 0000000..c03c8d9 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/controller/DomainController.java @@ -0,0 +1,65 @@ +package com.newyetai.usercenter.sys.controller; + +import com.newyetai.common.AlitaResult; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.sys.dto.DomainDTO; +import com.newyetai.usercenter.sys.dto.DomainOperateDTO; +import com.newyetai.usercenter.sys.dto.DomainQueryDTO; +import com.newyetai.usercenter.sys.service.DomainService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.Set; + +/** + * @author sr on 2021-05-24 + */ +@RestController +@Api(tags = "域名") +public class DomainController { + + @Autowired + private DomainService domainService; + + @PostMapping("domain/create") + @ApiOperation("创建") + public AlitaResult create(@RequestBody DomainOperateDTO domainOperateDTO){ + return AlitaResult.success(domainService.create(domainOperateDTO)); + } + + @PutMapping("domain/modify") + @ApiOperation("修改") + public AlitaResult modify(@RequestBody DomainOperateDTO domainOperateDTO){ + domainService.modify(domainOperateDTO); + return AlitaResult.success(true); + } + + @GetMapping("domain/detail/{id}") + @ApiOperation("详情") + public AlitaResult detail(@PathVariable Long id){ + return AlitaResult.success(domainService.detail(id)); + } + + @DeleteMapping("domain/remove/{id}") + @ApiOperation("删除") + public AlitaResult remove(@PathVariable Long id){ + domainService.remove(id); + return AlitaResult.success(true); + } + + @GetMapping("domain/page") + @ApiOperation("分页查询") + public AlitaResult> page(DomainQueryDTO domainQueryDTO){ + domainService.page(domainQueryDTO); + return AlitaResult.success(domainQueryDTO.getPageResult()); + } + + @GetMapping("/anon/domain/list_org_id") + @ApiOperation("获取请求相关机构列表") + public AlitaResult> listOrgId(){ + return domainService.listOrgId(); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/sys/controller/DomainSettingController.java b/src/main/java/com/newyetai/usercenter/sys/controller/DomainSettingController.java new file mode 100644 index 0000000..b14d340 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/controller/DomainSettingController.java @@ -0,0 +1,106 @@ +package com.newyetai.usercenter.sys.controller; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; +import com.newyetai.usercenter.dto.DomainSettingOperateDTO; +import com.newyetai.usercenter.dto.DomainSettingReqDTO; +import com.newyetai.usercenter.dto.DomainSettingResDTO; +import com.newyetai.usercenter.sys.dto.DomainSettingBannerOperateDTO; +import com.newyetai.usercenter.sys.dto.DomainSettingQuickOperateDTO; +import com.newyetai.usercenter.sys.service.DomainSettingService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @author sr on 2021-05-24 + */ +@RestController +@RequestMapping("/domain_setting") +@Api(tags = "域名配置") +public class DomainSettingController { + + @Autowired + private DomainSettingService domainSettingService; + + @PostMapping("/create") + @ApiOperation("创建") + public AlitaResult create(@RequestBody DomainSettingOperateDTO domainOperateDTO){ + return AlitaResult.success(domainSettingService.create(domainOperateDTO)); + } + + @PutMapping("/modify") + @ApiOperation("修改") + public AlitaResult modify(@RequestBody DomainSettingOperateDTO domainOperateDTO){ + domainSettingService.modify(domainOperateDTO); + return AlitaResult.success(true); + } + + @DeleteMapping("/remove/{id}") + @ApiOperation("删除") + public AlitaResult remove(@PathVariable Long id) { + domainSettingService.remove(id); + return AlitaResult.success(true); + } + + @GetMapping("/list/no_cache") + @ApiOperation("列表查询(没有缓存)") + public AlitaResult> listNoCache(DomainSettingReqDTO reqDTO) { + return AlitaResult.success(domainSettingService.listNoCache(reqDTO)); + } + + @PostMapping("/quick/create") + @ApiOperation("快捷入口") + public AlitaResult quickCreate(@RequestBody DomainSettingQuickOperateDTO quickCreateDTO){ + return AlitaResult.success(domainSettingService.quickCreate(quickCreateDTO)); + } + @PutMapping("/quick/modify") + @ApiOperation("快捷入口") + public AlitaResult quickModify(@RequestBody @Validated(Update.class) DomainSettingQuickOperateDTO quickModifyDTO){ + domainSettingService.quickModify(quickModifyDTO); + return AlitaResult.success(); + } + + @DeleteMapping("/quick/delete") + @ApiOperation("快捷入口") + public AlitaResult quickDelete(@RequestParam("id") String id){ + domainSettingService.quickDelete(id); + return AlitaResult.success(); + } + + @GetMapping("/quick/list") + @ApiOperation("快捷入口查看") + public AlitaResult> quickList(){ + return AlitaResult.success(domainSettingService.quickList()); + } + + @PostMapping("/banner/create") + @ApiOperation("banner创建") + public AlitaResult bannerCreate(@RequestBody DomainSettingBannerOperateDTO bannerOperateDTO){ + return AlitaResult.success(domainSettingService.bannerCreate(bannerOperateDTO)); + } + @PutMapping("/banner/modify") + @ApiOperation("banner修改") + public AlitaResult bannerModify(@RequestBody @Validated(Update.class) DomainSettingBannerOperateDTO bannerOperateDTO){ + domainSettingService.bannerModify(bannerOperateDTO); + return AlitaResult.success(); + } + + @GetMapping("/banner/list") + @ApiOperation("banner查看") + public AlitaResult> bannerList(){ + return AlitaResult.success(domainSettingService.bannerList()); + } + + @DeleteMapping("/banner/delete") + @ApiOperation("banner") + public AlitaResult bannerDelete(@RequestParam("id") String id){ + domainSettingService.bannerDelete(id); + return AlitaResult.success(); + } +} diff --git a/src/main/java/com/newyetai/usercenter/sys/controller/FaqController.java b/src/main/java/com/newyetai/usercenter/sys/controller/FaqController.java new file mode 100644 index 0000000..2187113 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/controller/FaqController.java @@ -0,0 +1,72 @@ +package com.newyetai.usercenter.sys.controller; + +import com.newyetai.common.validation.Create; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.PathVariable; + +import com.newyetai.common.validation.Update; +import com.newyetai.common.AlitaResult; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.sys.dto.FaqQueryDTO; +import com.newyetai.usercenter.sys.service.FaqService; +import com.newyetai.usercenter.sys.dto.FaqDTO; +import com.newyetai.usercenter.sys.dto.FaqOperateDTO; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +/** + * @author sr on 2021-05-24 + */ +@RestController +@Api(tags = "常见问题表") +public class FaqController { + + @Autowired + private FaqService faqService; + + @PostMapping("/faq/create") + @ApiOperation("创建") + public AlitaResult create( + @Validated(Create.class) @RequestBody FaqOperateDTO faqOperateDTO){ + return AlitaResult.success(faqService.create(faqOperateDTO)); + } + + @PutMapping("/faq/modify") + @ApiOperation("修改") + public AlitaResult modify( + @Validated(Update.class) @RequestBody FaqOperateDTO faqOperateDTO){ + faqService.modify(faqOperateDTO); + return AlitaResult.success(true); + } + + @DeleteMapping("/faq/remove/{id}") + @ApiOperation("删除") + public AlitaResult remove(@PathVariable Long id){ + faqService.remove(id); + return AlitaResult.success(true); + } + + @GetMapping("/anon/faq/page") + @ApiOperation("分页查询") + public AlitaResult> page(FaqQueryDTO faqQueryDTO){ + faqService.list(faqQueryDTO); + return AlitaResult.success(faqQueryDTO.getPageResult()); + } + + @GetMapping("/anon/faq/{id}") + @ApiOperation("获取单个") + AlitaResult get(@PathVariable Long id){ + return AlitaResult.success(faqService.get(id)); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/sys/controller/FaqFileController.java b/src/main/java/com/newyetai/usercenter/sys/controller/FaqFileController.java new file mode 100644 index 0000000..7fc4b1f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/controller/FaqFileController.java @@ -0,0 +1,40 @@ +package com.newyetai.usercenter.sys.controller; + +import com.newyetai.common.AlitaResult; +import com.newyetai.usercenter.sys.dto.FaqFileDTO; +import com.newyetai.usercenter.sys.dto.FaqFileQueryDTO; +import com.newyetai.usercenter.sys.service.FaqFileService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@Api(tags = "常见问题表") +public class FaqFileController { + + @Autowired + private FaqFileService faqFileService; + + @GetMapping("/anon/faq_file/list") + @ApiOperation("查询常见问题附件列表") + public AlitaResult> list(FaqFileQueryDTO queryDTO) { + return AlitaResult.success(faqFileService.list(queryDTO)); + } + + @PostMapping("/faq_file/create") + @ApiOperation("创建常见问题附件") + public AlitaResult create(@RequestBody FaqFileDTO operateDTO) { + return AlitaResult.success(faqFileService.create(operateDTO)); + } + + @DeleteMapping("/faq_file/delete/{id}") + @ApiOperation("根据文件Id删除常见问题附件") + public AlitaResult delete(@PathVariable Long id) { + faqFileService.delete(id); + return AlitaResult.success(); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/sys/controller/FeedbackController.java b/src/main/java/com/newyetai/usercenter/sys/controller/FeedbackController.java new file mode 100644 index 0000000..ab26736 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/controller/FeedbackController.java @@ -0,0 +1,66 @@ +package com.newyetai.usercenter.sys.controller; + +import com.newyetai.common.validation.Create; +import com.newyetai.usercenter.sys.dto.FeedbackDTO; +import com.newyetai.usercenter.sys.dto.FeedbackOperateDTO; +import com.newyetai.usercenter.sys.dto.FeedbackQueryDTO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.PathVariable; + +import com.newyetai.common.validation.Update; +import com.newyetai.common.AlitaResult; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.sys.service.FeedbackService; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +/** + * @author sr on 2021-05-24 + */ +@RestController +@RequestMapping("/anon/feedback") +@Api(tags = "反馈表") +public class FeedbackController { + + @Autowired + private FeedbackService feedbackService; + + @PostMapping("/create") + @ApiOperation("创建") + public AlitaResult create( + @Validated(Create.class) @RequestBody FeedbackOperateDTO feedbackOperateDTO){ + return AlitaResult.success(feedbackService.create(feedbackOperateDTO)); + } + + @PutMapping("/modify") + @ApiOperation("修改") + public AlitaResult modify( + @Validated(Update.class) @RequestBody FeedbackOperateDTO feedbackOperateDTO){ + feedbackService.modify(feedbackOperateDTO); + return AlitaResult.success(true); + } + + @DeleteMapping("/remove/{id}") + @ApiOperation("删除") + public AlitaResult remove(@PathVariable Long id){ + feedbackService.remove(id); + return AlitaResult.success(true); + } + + @GetMapping("/page") + @ApiOperation("分页查询") + public AlitaResult> page(FeedbackQueryDTO feedbackQueryDTO){ + feedbackService.list(feedbackQueryDTO); + return AlitaResult.success(feedbackQueryDTO.getPageResult()); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/sys/controller/PlatformController.java b/src/main/java/com/newyetai/usercenter/sys/controller/PlatformController.java new file mode 100644 index 0000000..2730dfd --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/controller/PlatformController.java @@ -0,0 +1,65 @@ +package com.newyetai.usercenter.sys.controller; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.validation.Update; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.sys.dto.PlatformDTO; +import com.newyetai.usercenter.sys.dto.PlatformOperateDTO; +import com.newyetai.usercenter.sys.dto.PlatformPageQueryDTO; +import com.newyetai.usercenter.sys.dto.PlatformQueryDTO; +import com.newyetai.usercenter.sys.service.PlatformService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @author sr on 2021-05-24 + */ +@RestController +@RequestMapping("platform") +@Api(tags = "系统应用") +public class PlatformController { + + @Autowired + private PlatformService platformService; + + @PostMapping("/create") + @ApiOperation("创建") + public AlitaResult create( + @Validated @RequestBody PlatformOperateDTO platformOperateDTO){ + return AlitaResult.success(platformService.create(platformOperateDTO)); + } + + @PutMapping("/modify") + @ApiOperation("修改") + public AlitaResult modify( + @Validated(Update.class) @RequestBody PlatformOperateDTO platformOperateDTO){ + platformService.modify(platformOperateDTO); + return AlitaResult.success(true); + } + + @DeleteMapping("/remove/{id}") + @ApiOperation("删除") + public AlitaResult remove(@PathVariable Long id) { + platformService.remove(id); + return AlitaResult.success(true); + } + + @GetMapping("list") + @ApiOperation("列表查询") + public AlitaResult> list(PlatformQueryDTO queryDTO) { + return AlitaResult.success(platformService.list(queryDTO)); + } + + @GetMapping("/page") + @ApiOperation("分页查询") + public AlitaResult> page(PlatformPageQueryDTO platformPageQueryDTO) { + platformService.page(platformPageQueryDTO); + return AlitaResult.success(platformPageQueryDTO.getPageResult()); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/sys/dao/DomainAuthMapper.java b/src/main/java/com/newyetai/usercenter/sys/dao/DomainAuthMapper.java new file mode 100644 index 0000000..708744e --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/dao/DomainAuthMapper.java @@ -0,0 +1,28 @@ +package com.newyetai.usercenter.sys.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.newyetai.usercenter.sys.dto.DomainAuthDTO; +import com.newyetai.usercenter.sys.dto.DomainAuthQueryDTO; +import com.newyetai.usercenter.sys.entity.DomainAuth; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 域名授权 + * + * @author sr on 2021-05-24 + */ +public interface DomainAuthMapper extends BaseMapper { + + /** + * 查询 + * + * @param domainAuthQueryDTO + * @return + * @author sr on 2021-05-24 + */ + List listDomainAuthDTO(@Param("param") DomainAuthQueryDTO domainAuthQueryDTO); + + List notLinkList(@Param("param") DomainAuthQueryDTO domainAuthQueryDTO); +} diff --git a/src/main/java/com/newyetai/usercenter/sys/dao/DomainMapper.java b/src/main/java/com/newyetai/usercenter/sys/dao/DomainMapper.java new file mode 100644 index 0000000..4d88d67 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/dao/DomainMapper.java @@ -0,0 +1,28 @@ +package com.newyetai.usercenter.sys.dao; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.usercenter.sys.dto.DomainDTO; +import com.newyetai.usercenter.sys.dto.DomainQueryDTO; +import com.newyetai.usercenter.sys.entity.Domain; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 域名 + * + * @author sr on 2021-05-24 + */ +public interface DomainMapper extends MyMapper { + + /** + * 查询 + * + * @param domainQueryDTO + * @return + * @author sr on 2021-05-24 + */ + List listDomainDTO(@Param("param") DomainQueryDTO domainQueryDTO); + + DomainDTO selectByDomainOrIp(@Param("domainOrIp") String domainOrIp); +} diff --git a/src/main/java/com/newyetai/usercenter/sys/dao/DomainSettingMapper.java b/src/main/java/com/newyetai/usercenter/sys/dao/DomainSettingMapper.java new file mode 100644 index 0000000..82377e4 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/dao/DomainSettingMapper.java @@ -0,0 +1,25 @@ +package com.newyetai.usercenter.sys.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.usercenter.dto.DomainSettingReqDTO; +import com.newyetai.usercenter.dto.DomainSettingResDTO; +import com.newyetai.usercenter.sys.entity.DomainSetting; + + +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 域名配置表 Mapper 接口 + *

+ * + * @author Carlye + * @since 2021-06-17 + */ +public interface DomainSettingMapper extends MyMapper { + + List list(@Param("param") DomainSettingReqDTO reqDTO); +} diff --git a/src/main/java/com/newyetai/usercenter/sys/dao/FaqFileMapper.java b/src/main/java/com/newyetai/usercenter/sys/dao/FaqFileMapper.java new file mode 100644 index 0000000..3c4abb6 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/dao/FaqFileMapper.java @@ -0,0 +1,26 @@ +package com.newyetai.usercenter.sys.dao; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.usercenter.sys.dto.FaqFileDTO; +import com.newyetai.usercenter.sys.dto.FaqFileQueryDTO; +import com.newyetai.usercenter.sys.entity.FaqFile; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 常见问题附件表 + * + */ +public interface FaqFileMapper extends MyMapper { + + /** + * 查询 + * + * @param faqQueryDTO + * @return + * @author sr on 2021-05-24 + */ + List filePage(@Param("param") FaqFileQueryDTO faqQueryDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/sys/dao/FaqMapper.java b/src/main/java/com/newyetai/usercenter/sys/dao/FaqMapper.java new file mode 100644 index 0000000..116a97c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/dao/FaqMapper.java @@ -0,0 +1,28 @@ +package com.newyetai.usercenter.sys.dao; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.newyetai.usercenter.sys.dto.FaqDTO; +import com.newyetai.usercenter.sys.dto.FaqQueryDTO; +import com.newyetai.usercenter.sys.entity.Faq; +import com.newyetai.tkmybatis.mybatis.MyMapper; + +/** + * 常见问题表 + * + * @author sr on 2021-05-24 + */ +public interface FaqMapper extends MyMapper { + + /** + * 查询 + * + * @param faqQueryDTO + * @return + * @author sr on 2021-05-24 + */ + List listFaqDTO(@Param("param") FaqQueryDTO faqQueryDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/sys/dao/FeedbackMapper.java b/src/main/java/com/newyetai/usercenter/sys/dao/FeedbackMapper.java new file mode 100644 index 0000000..99f9dad --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/dao/FeedbackMapper.java @@ -0,0 +1,28 @@ +package com.newyetai.usercenter.sys.dao; + +import java.util.List; + +import com.newyetai.usercenter.sys.dto.FeedbackDTO; +import com.newyetai.usercenter.sys.dto.FeedbackQueryDTO; +import org.apache.ibatis.annotations.Param; + +import com.newyetai.usercenter.sys.entity.Feedback; +import com.newyetai.tkmybatis.mybatis.MyMapper; + +/** + * 反馈表 + * + * @author sr on 2021-05-24 + */ +public interface FeedbackMapper extends MyMapper { + + /** + * 查询 + * + * @param feedbackQueryDTO + * @return + * @author sr on 2021-05-24 + */ + List listFeedbackDTO(@Param("param") FeedbackQueryDTO feedbackQueryDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/sys/dao/PlatformMapper.java b/src/main/java/com/newyetai/usercenter/sys/dao/PlatformMapper.java new file mode 100644 index 0000000..55f07c1 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/dao/PlatformMapper.java @@ -0,0 +1,35 @@ +package com.newyetai.usercenter.sys.dao; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.usercenter.sys.dto.PlatformDTO; +import com.newyetai.usercenter.sys.dto.PlatformPageQueryDTO; +import com.newyetai.usercenter.sys.dto.PlatformQueryDTO; +import com.newyetai.usercenter.sys.entity.Platform; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 系统应用 + * + * @author sr on 2021-05-24 + */ +public interface PlatformMapper extends MyMapper { + + /** + * 查询 + * + * @param platformPageQueryDTO + * @return + * @author sr on 2021-05-24 + */ + List page(@Param("param") PlatformPageQueryDTO platformPageQueryDTO); + + /** + * 列表 + * + * @param queryDTO 查询dto + * @return {@link List}<{@link PlatformDTO}> + */ + List list(@Param("param") PlatformQueryDTO queryDTO); +} diff --git a/src/main/java/com/newyetai/usercenter/sys/dto/DomainAuthDTO.java b/src/main/java/com/newyetai/usercenter/sys/dto/DomainAuthDTO.java new file mode 100644 index 0000000..27d16ae --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/dto/DomainAuthDTO.java @@ -0,0 +1,41 @@ +package com.newyetai.usercenter.sys.dto; + +import com.newyetai.common.dto.OrgBaseDTO; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2021-05-24 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@ApiModel(description = "域名授权") +public class DomainAuthDTO extends OrgBaseDTO { + + /** **/ + private static final long serialVersionUID = 1L; + /** 域名id */ + private Long domainId ; + /** 授权类型标识 */ + private Integer authTypeCode ; + /** 授权客户端id */ + private Long authClientId ; + /** + * 授权类型名称 + */ + private String authTypeName; + /** + * 授权应用名称 + */ + private String clientName; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/sys/dto/DomainAuthOperateDTO.java b/src/main/java/com/newyetai/usercenter/sys/dto/DomainAuthOperateDTO.java new file mode 100644 index 0000000..29cc9c7 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/dto/DomainAuthOperateDTO.java @@ -0,0 +1,46 @@ +package com.newyetai.usercenter.sys.dto; + +import com.newyetai.common.dto.BaseOperateDTO; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.Set; + +/** + * @author sr on 2021-05-24 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "域名授权操作") +public class DomainAuthOperateDTO extends BaseOperateDTO implements Serializable{ + + + private static final long serialVersionUID = -2610902048033082892L; + @ApiModelProperty("id") + @NotNull(message = "id不能为空", groups = {Update.class}) + private Long id; + + /** 域名id */ + @ApiModelProperty("域名id") + @NotNull( + message = "域名id不能为空", + groups = {Create.class, Update.class}) + private Long domainId; + /** 授权客户端id */ + @ApiModelProperty("授权客户端id") + @NotNull(message = "授权客户端id不能为空",groups = {Create.class,Update.class}) + private Set authClientIds ; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/sys/dto/DomainAuthQueryDTO.java b/src/main/java/com/newyetai/usercenter/sys/dto/DomainAuthQueryDTO.java new file mode 100644 index 0000000..70eaa64 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/dto/DomainAuthQueryDTO.java @@ -0,0 +1,29 @@ +package com.newyetai.usercenter.sys.dto; + +import com.newyetai.common.dto.PageQueryDTO; +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 sr on 2021-05-24 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "域名授权查询条件") +public class DomainAuthQueryDTO extends PageQueryDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("域名id") + private Long domainId; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/sys/dto/DomainDTO.java b/src/main/java/com/newyetai/usercenter/sys/dto/DomainDTO.java new file mode 100644 index 0000000..af967e0 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/dto/DomainDTO.java @@ -0,0 +1,34 @@ +package com.newyetai.usercenter.sys.dto; + +import com.newyetai.common.dto.OrgBaseDTO; +import io.swagger.annotations.ApiModel; +import lombok.*; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2021-05-24 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@ApiModel(description = "域名") +public class DomainDTO extends OrgBaseDTO{ + + /** **/ + private static final long serialVersionUID = 1L; + /** 平台编码 */ + private Integer platformCode ; + /** 域名 */ + private String domainName ; + /** ip:port */ + private String ipPort ; + /** 是否公共 */ + private Boolean publiced ; + + /** + * 机构名称 + */ + private String orgName; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/sys/dto/DomainOperateDTO.java b/src/main/java/com/newyetai/usercenter/sys/dto/DomainOperateDTO.java new file mode 100644 index 0000000..744d5fa --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/dto/DomainOperateDTO.java @@ -0,0 +1,61 @@ +package com.newyetai.usercenter.sys.dto; + +import com.newyetai.common.dto.BaseOperateDTO; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +/** + * @author sr on 2021-05-24 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "域名操作") +public class DomainOperateDTO extends BaseOperateDTO implements Serializable { + + /** + * + **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @NotNull(message = "id不能为空", groups = {Update.class}) + private Long id; + + /** + * 平台编码 + */ + @NotNull(message = "平台不能为空", groups = {Create.class}) + private Integer platformCode; + /** + * 域名 + */ + @NotEmpty(message = "域名不能为空", groups = {Create.class}) + private String domainName; + /** + * ip:port + */ + @NotEmpty(message = "ip端口不能为空", groups = {Create.class}) + private String ipPort; + /** + * 是否公共 + */ + @NotNull(message = "是否公共不能为空", groups = {Create.class}) + private Boolean publiced; + + /** + * 机构名称 + */ +// @NotNull(message = "所属机构不能为空", groups = {Create.class}) + private Long orgId; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/sys/dto/DomainQueryDTO.java b/src/main/java/com/newyetai/usercenter/sys/dto/DomainQueryDTO.java new file mode 100644 index 0000000..0f7078a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/dto/DomainQueryDTO.java @@ -0,0 +1,33 @@ +package com.newyetai.usercenter.sys.dto; + +import com.newyetai.common.dto.PageQueryDTO; +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 sr on 2021-05-24 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "域名查询条件") +public class DomainQueryDTO extends PageQueryDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + @ApiModelProperty("orgId") + private Long orgId; + @ApiModelProperty("域名或ip") + private String domainOrIp; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/sys/dto/DomainSettingBannerOperateDTO.java b/src/main/java/com/newyetai/usercenter/sys/dto/DomainSettingBannerOperateDTO.java new file mode 100644 index 0000000..003c8ee --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/dto/DomainSettingBannerOperateDTO.java @@ -0,0 +1,30 @@ +package com.newyetai.usercenter.sys.dto; + +import com.newyetai.common.validation.Update; + +import java.io.Serializable; + +import javax.validation.constraints.NotBlank; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Builder; +import lombok.Data; + +/** + * @description: BannerDTO + * @author: guixinman + * @create: 2024-05-20 15:03 + **/ +@Data +@Builder +public class DomainSettingBannerOperateDTO implements Serializable { + + @NotBlank(message = "id不能为空",groups = Update.class) + private String id; + + @ApiModelProperty("图标") + private String icon; + + @ApiModelProperty("链接") + private String link; +} diff --git a/src/main/java/com/newyetai/usercenter/sys/dto/DomainSettingQuickOperateDTO.java b/src/main/java/com/newyetai/usercenter/sys/dto/DomainSettingQuickOperateDTO.java new file mode 100644 index 0000000..ee44966 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/dto/DomainSettingQuickOperateDTO.java @@ -0,0 +1,39 @@ +package com.newyetai.usercenter.sys.dto; + +import com.newyetai.common.validation.Update; + +import java.io.Serializable; + +import javax.validation.constraints.NotBlank; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Builder; +import lombok.Data; + +/** + * @description: BannerDTO + * @author: guixinman + * @create: 2024-05-20 15:03 + **/ +@Data +@Builder +public class DomainSettingQuickOperateDTO implements Serializable { + + @NotBlank(message = "id不能为空",groups = Update.class) + private String id; + + @ApiModelProperty("描述") + private String remark; + + @ApiModelProperty("图标") + private String icon; + + @ApiModelProperty("标题") + private String title; + + @ApiModelProperty("链接") + private String link; + + @ApiModelProperty("排序") + private int sort; +} diff --git a/src/main/java/com/newyetai/usercenter/sys/dto/FaqDTO.java b/src/main/java/com/newyetai/usercenter/sys/dto/FaqDTO.java new file mode 100644 index 0000000..319aec3 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/dto/FaqDTO.java @@ -0,0 +1,38 @@ +package com.newyetai.usercenter.sys.dto; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.common.dto.OrgBaseDTO; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2021-05-24 + */ +/** @EqualsAndHashCode(callSuper = true) */ +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +@Data +@ApiModel(description = "常见问题表") +public class FaqDTO extends BaseDTO { + + /** **/ + private static final long serialVersionUID = 1L; + + /** 主键 */ + private Long id; + /** 排序字段 */ + private Integer faqOrder; + /** 类型 */ + private String faqType; + /** 问题 */ + private String question ; + /** 回答 */ + private String answer ; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/sys/dto/FaqFileDTO.java b/src/main/java/com/newyetai/usercenter/sys/dto/FaqFileDTO.java new file mode 100644 index 0000000..2e28a11 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/dto/FaqFileDTO.java @@ -0,0 +1,45 @@ +package com.newyetai.usercenter.sys.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; + +@ApiModel("常见问题附件DTO") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class FaqFileDTO implements Serializable { + + + private static final long serialVersionUID = 8851173648134487125L; + + @ApiModelProperty("主键") + private Long id; + + @ApiModelProperty("文件名称") + private String fileName; + + @ApiModelProperty("文件编码") + private String fileCode; + + @ApiModelProperty("文件后缀") + private String fileSuffix; + + @ApiModelProperty("文件描述") + private String description; + + @ApiModelProperty("排序") + private Integer sort; + + @ApiModelProperty("问题ID") + private Long questionId; + + + +} diff --git a/src/main/java/com/newyetai/usercenter/sys/dto/FaqFileQueryDTO.java b/src/main/java/com/newyetai/usercenter/sys/dto/FaqFileQueryDTO.java new file mode 100644 index 0000000..3445e7a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/dto/FaqFileQueryDTO.java @@ -0,0 +1,21 @@ +package com.newyetai.usercenter.sys.dto; + +import com.newyetai.common.dto.PageQueryDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +@EqualsAndHashCode(callSuper = true) +@ApiModel("常见问题附件查询DTO") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class FaqFileQueryDTO extends PageQueryDTO { + + private static final long serialVersionUID = -6211701785572927530L; + + @ApiModelProperty("常见问题ID") + private Long questionId; + +} diff --git a/src/main/java/com/newyetai/usercenter/sys/dto/FaqOperateDTO.java b/src/main/java/com/newyetai/usercenter/sys/dto/FaqOperateDTO.java new file mode 100644 index 0000000..5057e22 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/dto/FaqOperateDTO.java @@ -0,0 +1,47 @@ +package com.newyetai.usercenter.sys.dto; + +import java.io.Serializable; + +import com.newyetai.common.validation.Create; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import io.swagger.annotations.ApiModel; +import javax.validation.constraints.NotNull; +import com.newyetai.common.validation.Update; + +import com.newyetai.common.dto.BaseOperateDTO; + +/** + * @author sr on 2021-05-24 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "常见问题表操作") +public class FaqOperateDTO extends BaseOperateDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @NotNull(message = "id不能为空", groups = {Update.class}) + private Long id; + + /** 排序字段 */ + private Integer faqOrder; + /** 类型 */ + @NotNull(message = "类型不能为空", groups = {Create.class, Update.class}) + private String faqType; + /** 问题 */ + @NotNull(message = "问题不能为空", groups = {Create.class, Update.class}) + private String question ; + /** 回答 */ + @NotNull(message = "回答不能为空", groups = {Create.class, Update.class}) + private String answer ; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/sys/dto/FaqQueryDTO.java b/src/main/java/com/newyetai/usercenter/sys/dto/FaqQueryDTO.java new file mode 100644 index 0000000..fe79797 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/dto/FaqQueryDTO.java @@ -0,0 +1,51 @@ +package com.newyetai.usercenter.sys.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.newyetai.common.annotation.trimAndUpper.TrimAndUpper; +import com.newyetai.common.dto.PageQueryDTO; + +import org.springframework.format.annotation.DateTimeFormat; + +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; +import java.util.Date; + +/** + * @author sr on 2021-05-24 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "常见问题表查询条件") +public class FaqQueryDTO extends PageQueryDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + + /** 问题 */ + @TrimAndUpper(TrimAndUpper.ExecuteType.TRIM) + private String question ; + /** 平台类型 */ + private String faqType; + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/sys/dto/FeedbackDTO.java b/src/main/java/com/newyetai/usercenter/sys/dto/FeedbackDTO.java new file mode 100644 index 0000000..7de9647 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/dto/FeedbackDTO.java @@ -0,0 +1,48 @@ +package com.newyetai.usercenter.sys.dto; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.common.dto.OrgBaseDTO; + +import io.swagger.annotations.ApiModel; +import lombok.*; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2021-05-24 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@ApiModel(description = "反馈表") +public class FeedbackDTO extends BaseDTO { + + /** + * + **/ + private static final long serialVersionUID = 1L; + + /** + * 类型 + */ + private String type; + /** + * 用户id + */ + private Long userId; + /** + * 用户昵称 + */ + private String nickname; + /** + * 手机号 + */ + private String phone; + /** + * 反馈内容 + */ + private String content; + + private String sourceType; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/sys/dto/FeedbackOperateDTO.java b/src/main/java/com/newyetai/usercenter/sys/dto/FeedbackOperateDTO.java new file mode 100644 index 0000000..7228270 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/dto/FeedbackOperateDTO.java @@ -0,0 +1,60 @@ +package com.newyetai.usercenter.sys.dto; + +import com.newyetai.common.dto.BaseOperateDTO; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; +import com.newyetai.common.validation.annotation.Phone; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; + +import java.io.Serializable; + +/** + * @author sr on 2021-05-24 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "反馈表操作") +public class FeedbackOperateDTO extends BaseOperateDTO implements Serializable { + + /** + * + **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @NotNull(message = "id不能为空", groups = {Update.class}) + private Long id; + + /** + * 类型 + */ + private String type; + /** + * 用户id + */ + private Long userId; + /** + * 手机号 + */ + @Phone(groups = {Create.class, Update.class}) + private String phone; + + /** + * 反馈内容 + */ + private String content; + + private String sourceType; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/sys/dto/FeedbackQueryDTO.java b/src/main/java/com/newyetai/usercenter/sys/dto/FeedbackQueryDTO.java new file mode 100644 index 0000000..d30f662 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/dto/FeedbackQueryDTO.java @@ -0,0 +1,54 @@ +package com.newyetai.usercenter.sys.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.newyetai.common.dto.PageQueryDTO; + +import org.springframework.format.annotation.DateTimeFormat; + +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; +import java.util.Date; + +/** + * @author sr on 2021-05-24 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "反馈表查询条件") +public class FeedbackQueryDTO extends PageQueryDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + + /** 类型 */ + private String type ; + /** 用户昵称 */ + private String nickname ; + /** 手机号 */ + private String phone ; + + + @ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeStart; + + @ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTimeEnd; + + private String sourceType; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/sys/dto/PlatformDTO.java b/src/main/java/com/newyetai/usercenter/sys/dto/PlatformDTO.java new file mode 100644 index 0000000..f9135c6 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/dto/PlatformDTO.java @@ -0,0 +1,39 @@ +package com.newyetai.usercenter.sys.dto; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.common.dto.OrgBaseDTO; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2021-05-24 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@ApiModel(description = "系统应用") +public class PlatformDTO extends BaseDTO { + + /** **/ + private static final long serialVersionUID = 1L; + + /** 平台编码 */ + private Integer platformCode ; + /** 名称 */ + private String name ; + /** 全称 */ + private String fullName ; + /** 简称 */ + private String shortName ; + /** 是否业务系统 */ + private Boolean business ; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/sys/dto/PlatformOperateDTO.java b/src/main/java/com/newyetai/usercenter/sys/dto/PlatformOperateDTO.java new file mode 100644 index 0000000..6f1fd5a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/dto/PlatformOperateDTO.java @@ -0,0 +1,33 @@ +package com.newyetai.usercenter.sys.dto; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import io.swagger.annotations.ApiModel; +import javax.validation.constraints.NotNull; +import com.newyetai.common.validation.Update; + +import com.newyetai.common.dto.BaseOperateDTO; + +/** + * @author sr on 2021-05-24 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "系统应用操作") +public class PlatformOperateDTO extends BaseOperateDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @NotNull(message = "id不能为空", groups = {Update.class}) + private Long id; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/sys/dto/PlatformPageQueryDTO.java b/src/main/java/com/newyetai/usercenter/sys/dto/PlatformPageQueryDTO.java new file mode 100644 index 0000000..ed304a6 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/dto/PlatformPageQueryDTO.java @@ -0,0 +1,31 @@ +package com.newyetai.usercenter.sys.dto; + +import com.newyetai.common.dto.PageQueryDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import java.io.Serializable; + +/** + * @author sr on 2021-05-24 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@EqualsAndHashCode(callSuper = true) +@ApiModel(description = "系统应用查询条件") +public class PlatformPageQueryDTO extends PageQueryDTO implements Serializable { + + /** + * + **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("是否业务系统") + private Boolean business; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/sys/dto/PlatformQueryDTO.java b/src/main/java/com/newyetai/usercenter/sys/dto/PlatformQueryDTO.java new file mode 100644 index 0000000..3d4c147 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/dto/PlatformQueryDTO.java @@ -0,0 +1,32 @@ +package com.newyetai.usercenter.sys.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 sr on 2021-05-24 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "系统应用查询条件") +public class PlatformQueryDTO implements Serializable { + + /** + * + **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("是否业务系统") + private Boolean business; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/sys/entity/Domain.java b/src/main/java/com/newyetai/usercenter/sys/entity/Domain.java new file mode 100644 index 0000000..a3fe197 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/entity/Domain.java @@ -0,0 +1,36 @@ +package com.newyetai.usercenter.sys.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.OrgBaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 域名 + * + * @author sr on 2021-05-24 + */ +@TableName("uc_domain") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +public class Domain extends OrgBaseEntity { + + /** **/ + private static final long serialVersionUID = 1L; + /** 平台编码 */ + private Integer platformCode ; + /** 域名 */ + private String domainName ; + /** ip:port */ + private String ipPort ; + /** 是否公共 */ + private Boolean publiced ; + +} diff --git a/src/main/java/com/newyetai/usercenter/sys/entity/DomainAuth.java b/src/main/java/com/newyetai/usercenter/sys/entity/DomainAuth.java new file mode 100644 index 0000000..8f4189c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/entity/DomainAuth.java @@ -0,0 +1,35 @@ +package com.newyetai.usercenter.sys.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 域名授权 + * + * @author sr on 2021-05-24 + */ +@TableName("uc_domain_auth") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +public class DomainAuth extends BaseEntity { + + /** **/ + private static final long serialVersionUID = 1L; + + /** 域名id */ + private Long domainId ; + /** 授权类型标识 */ + private Integer authTypeCode ; + /** 授权客户端id */ + private Long authClientId ; + +} diff --git a/src/main/java/com/newyetai/usercenter/sys/entity/DomainSetting.java b/src/main/java/com/newyetai/usercenter/sys/entity/DomainSetting.java new file mode 100644 index 0000000..0a58e2a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/entity/DomainSetting.java @@ -0,0 +1,47 @@ +package com.newyetai.usercenter.sys.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; +import lombok.*; +import lombok.experimental.Accessors; + +/** + *

+ * 域名配置表 + *

+ * + * @author Carlye + * @since 2021-06-17 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@TableName("uc_domain_setting") +public class DomainSetting extends BaseEntity { + + + private static final long serialVersionUID = 8042528746194876802L; + /** + * 域名id + */ + private Long domainId; + + /** + * 类型 + */ + private Integer type; + + /** + * 配置数据 + */ + private String data; + + /** + * 备注 + */ + private String remark; + +} diff --git a/src/main/java/com/newyetai/usercenter/sys/entity/Faq.java b/src/main/java/com/newyetai/usercenter/sys/entity/Faq.java new file mode 100644 index 0000000..01a184b --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/entity/Faq.java @@ -0,0 +1,37 @@ +package com.newyetai.usercenter.sys.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 常见问题表 + * + * @author sr on 2021-05-24 + */ +@TableName("uc_faq") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +public class Faq extends BaseEntity { + + /** **/ + private static final long serialVersionUID = 1L; + + /** 排序字段 */ + private Integer faqOrder; + /** 类型 */ + private String faqType; + /** 问题 */ + private String question ; + /** 回答 */ + private String answer ; + +} diff --git a/src/main/java/com/newyetai/usercenter/sys/entity/FaqFile.java b/src/main/java/com/newyetai/usercenter/sys/entity/FaqFile.java new file mode 100644 index 0000000..f1d769f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/entity/FaqFile.java @@ -0,0 +1,53 @@ +package com.newyetai.usercenter.sys.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 常见问题 文件 + */ +@TableName("uc_faq_file") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +public class FaqFile extends BaseEntity { + + private static final long serialVersionUID = -1L; + /** + * 常见问题ID + */ + private Long questionId; + + /** + * 文件名称 + */ + private String fileName; + + /** + * 文件编码 + */ + private String fileCode; + + /** + * 文件后缀 + */ + private String fileSuffix; + + /** + * 排序 + */ + private Integer sort; + + /** + * 描述 + */ + private String description; +} diff --git a/src/main/java/com/newyetai/usercenter/sys/entity/Feedback.java b/src/main/java/com/newyetai/usercenter/sys/entity/Feedback.java new file mode 100644 index 0000000..7890ee8 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/entity/Feedback.java @@ -0,0 +1,53 @@ +package com.newyetai.usercenter.sys.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; +import com.newyetai.common.validation.annotation.Phone; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 反馈表 + * + * @author sr on 2021-05-24 + */ +@TableName("uc_feedback") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +public class Feedback extends BaseEntity { + + /** + * + **/ + private static final long serialVersionUID = 1L; + + /** + * 类型 + */ + private String type; + /** + * 用户id + */ + private Long userId; + /** + * 手机号 + */ + + @Phone(groups = {Create.class, Update.class}) + private String phone; + /** + * 反馈内容 + */ + private String content; + + private String sourceType; +} diff --git a/src/main/java/com/newyetai/usercenter/sys/entity/Platform.java b/src/main/java/com/newyetai/usercenter/sys/entity/Platform.java new file mode 100644 index 0000000..451b74a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/entity/Platform.java @@ -0,0 +1,39 @@ +package com.newyetai.usercenter.sys.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 系统应用 + * + * @author sr on 2021-05-24 + */ +@TableName("uc_platform") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +public class Platform extends BaseEntity { + + /** **/ + private static final long serialVersionUID = 1L; + + /** 平台编码 */ + private Integer platformCode ; + /** 名称 */ + private String name ; + /** 全称 */ + private String fullName ; + /** 简称 */ + private String shortName ; + /** 是否业务系统 */ + private Boolean business ; + +} diff --git a/src/main/java/com/newyetai/usercenter/sys/mapper/DomainAuthMapper.xml b/src/main/java/com/newyetai/usercenter/sys/mapper/DomainAuthMapper.xml new file mode 100644 index 0000000..26281e9 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/mapper/DomainAuthMapper.xml @@ -0,0 +1,43 @@ + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/sys/mapper/DomainMapper.xml b/src/main/java/com/newyetai/usercenter/sys/mapper/DomainMapper.xml new file mode 100644 index 0000000..faae941 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/mapper/DomainMapper.xml @@ -0,0 +1,33 @@ + + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/sys/mapper/DomainSettingMapper.xml b/src/main/java/com/newyetai/usercenter/sys/mapper/DomainSettingMapper.xml new file mode 100644 index 0000000..ca9296d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/mapper/DomainSettingMapper.xml @@ -0,0 +1,34 @@ + + + + + + diff --git a/src/main/java/com/newyetai/usercenter/sys/mapper/FaqFileMapper.xml b/src/main/java/com/newyetai/usercenter/sys/mapper/FaqFileMapper.xml new file mode 100644 index 0000000..a33cef6 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/mapper/FaqFileMapper.xml @@ -0,0 +1,14 @@ + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/sys/mapper/FaqMapper.xml b/src/main/java/com/newyetai/usercenter/sys/mapper/FaqMapper.xml new file mode 100644 index 0000000..4dfee6f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/mapper/FaqMapper.xml @@ -0,0 +1,27 @@ + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/sys/mapper/FeedbackMapper.xml b/src/main/java/com/newyetai/usercenter/sys/mapper/FeedbackMapper.xml new file mode 100644 index 0000000..d1c1752 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/mapper/FeedbackMapper.xml @@ -0,0 +1,38 @@ + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/sys/mapper/PlatformMapper.xml b/src/main/java/com/newyetai/usercenter/sys/mapper/PlatformMapper.xml new file mode 100644 index 0000000..2616b49 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/mapper/PlatformMapper.xml @@ -0,0 +1,32 @@ + + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/sys/mapstruct/DomainAuthMapMapper.java b/src/main/java/com/newyetai/usercenter/sys/mapstruct/DomainAuthMapMapper.java new file mode 100644 index 0000000..c6299be --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/mapstruct/DomainAuthMapMapper.java @@ -0,0 +1,37 @@ +package com.newyetai.usercenter.sys.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.newyetai.usercenter.sys.dto.DomainAuthDTO; +import com.newyetai.usercenter.sys.entity.DomainAuth; +import com.newyetai.usercenter.sys.dto.DomainAuthOperateDTO; + +/** + * @author sr on 2021-05-24 + */ +@Mapper +public interface DomainAuthMapMapper { + + DomainAuthMapMapper INSTANCE = + Mappers.getMapper(DomainAuthMapMapper.class); + + /** + * dto to entity + * + * @param domainAuthDto + * @return + * @author sr on 2021-05-24 + */ + DomainAuth toEntity( + DomainAuthDTO domainAuthDto); + + + /** + * @param domainAuthOperateDTO + * @return + * @author sr on 2021-05-24 + */ + DomainAuth toEntity(DomainAuthOperateDTO domainAuthOperateDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/sys/mapstruct/DomainMapMapper.java b/src/main/java/com/newyetai/usercenter/sys/mapstruct/DomainMapMapper.java new file mode 100644 index 0000000..d3ce7c9 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/mapstruct/DomainMapMapper.java @@ -0,0 +1,43 @@ +package com.newyetai.usercenter.sys.mapstruct; + +import com.newyetai.usercenter.dto.DomainSettingOperateDTO; +import com.newyetai.usercenter.sys.entity.DomainSetting; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.newyetai.usercenter.sys.dto.DomainDTO; +import com.newyetai.usercenter.sys.entity.Domain; +import com.newyetai.usercenter.sys.dto.DomainOperateDTO; + +/** + * @author sr on 2021-05-24 + */ +@Mapper +public interface DomainMapMapper { + + DomainMapMapper INSTANCE = + Mappers.getMapper(DomainMapMapper.class); + + /** + * dto to entity + * + * @param domainDto + * @return + * @author sr on 2021-05-24 + */ + Domain toEntity( + DomainDTO domainDto); + + + /** + * @param domainOperateDTO + * @return + * @author sr on 2021-05-24 + */ + Domain toEntity(DomainOperateDTO domainOperateDTO); + + DomainSetting exchange(DomainSettingOperateDTO operateDTO); + + DomainDTO exchange(Domain domain); + +} diff --git a/src/main/java/com/newyetai/usercenter/sys/mapstruct/FaqFileMapMapper.java b/src/main/java/com/newyetai/usercenter/sys/mapstruct/FaqFileMapMapper.java new file mode 100644 index 0000000..2d0d57c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/mapstruct/FaqFileMapMapper.java @@ -0,0 +1,16 @@ +package com.newyetai.usercenter.sys.mapstruct; + +import com.newyetai.usercenter.sys.dto.FaqFileDTO; +import com.newyetai.usercenter.sys.entity.FaqFile; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface FaqFileMapMapper { + + FaqFileMapMapper INSTANCE = Mappers.getMapper(FaqFileMapMapper.class); + + FaqFile toEntity(FaqFileDTO dto); + + FaqFileDTO toDTO(FaqFile file); +} diff --git a/src/main/java/com/newyetai/usercenter/sys/mapstruct/FaqMapMapper.java b/src/main/java/com/newyetai/usercenter/sys/mapstruct/FaqMapMapper.java new file mode 100644 index 0000000..465a294 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/mapstruct/FaqMapMapper.java @@ -0,0 +1,40 @@ +package com.newyetai.usercenter.sys.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.newyetai.usercenter.sys.dto.FaqDTO; +import com.newyetai.usercenter.sys.entity.Faq; +import com.newyetai.usercenter.sys.dto.FaqOperateDTO; + +/** + * @author sr on 2021-05-24 + */ +@Mapper +public interface FaqMapMapper { + + FaqMapMapper INSTANCE = + Mappers.getMapper(FaqMapMapper.class); + + /** + * dto to entity + * + * @param faqDto + * @return + * @author sr on 2021-05-24 + */ + Faq toEntity( + FaqDTO faqDto); + + + /** + * @param faqOperateDTO + * @return + * @author sr on 2021-05-24 + */ + Faq toEntity(FaqOperateDTO faqOperateDTO); + + + FaqDTO toDTO(Faq faq); + +} diff --git a/src/main/java/com/newyetai/usercenter/sys/mapstruct/FeedbackMapMapper.java b/src/main/java/com/newyetai/usercenter/sys/mapstruct/FeedbackMapMapper.java new file mode 100644 index 0000000..7d1cb4e --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/mapstruct/FeedbackMapMapper.java @@ -0,0 +1,37 @@ +package com.newyetai.usercenter.sys.mapstruct; + +import com.newyetai.usercenter.sys.dto.FeedbackDTO; +import com.newyetai.usercenter.sys.dto.FeedbackOperateDTO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.newyetai.usercenter.sys.entity.Feedback; + +/** + * @author sr on 2021-05-24 + */ +@Mapper +public interface FeedbackMapMapper { + + FeedbackMapMapper INSTANCE = + Mappers.getMapper(FeedbackMapMapper.class); + + /** + * dto to entity + * + * @param feedbackDto + * @return + * @author sr on 2021-05-24 + */ + Feedback toEntity( + FeedbackDTO feedbackDto); + + + /** + * @param feedbackOperateDTO + * @return + * @author sr on 2021-05-24 + */ + Feedback toEntity(FeedbackOperateDTO feedbackOperateDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/sys/mapstruct/PlatformMapMapper.java b/src/main/java/com/newyetai/usercenter/sys/mapstruct/PlatformMapMapper.java new file mode 100644 index 0000000..4f87f53 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/mapstruct/PlatformMapMapper.java @@ -0,0 +1,37 @@ +package com.newyetai.usercenter.sys.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.newyetai.usercenter.sys.dto.PlatformDTO; +import com.newyetai.usercenter.sys.entity.Platform; +import com.newyetai.usercenter.sys.dto.PlatformOperateDTO; + +/** + * @author sr on 2021-05-24 + */ +@Mapper +public interface PlatformMapMapper { + + PlatformMapMapper INSTANCE = + Mappers.getMapper(PlatformMapMapper.class); + + /** + * dto to entity + * + * @param platformDto + * @return + * @author sr on 2021-05-24 + */ + Platform toEntity( + PlatformDTO platformDto); + + + /** + * @param platformOperateDTO + * @return + * @author sr on 2021-05-24 + */ + Platform toEntity(PlatformOperateDTO platformOperateDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/sys/service/DomainAuthService.java b/src/main/java/com/newyetai/usercenter/sys/service/DomainAuthService.java new file mode 100644 index 0000000..3e95e84 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/service/DomainAuthService.java @@ -0,0 +1,60 @@ +package com.newyetai.usercenter.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.newyetai.common.validation.Create; +import com.newyetai.usercenter.sys.dto.DomainAuthDTO; +import com.newyetai.usercenter.sys.dto.DomainAuthOperateDTO; +import com.newyetai.usercenter.sys.dto.DomainAuthQueryDTO; +import com.newyetai.usercenter.sys.entity.DomainAuth; +import org.springframework.validation.annotation.Validated; + +import javax.validation.Valid; +import java.util.List; +import java.util.Set; + +/** + * 域名授权 + * + * @author sr on 2021-05-24 + */ +@Validated +public interface DomainAuthService extends IService { + + /** + * 新增 + * + * @param domainAuthOperateDTO + * @return + * @author sr on 2021-05-24 + */ + @Validated(Create.class) + Set link(@Valid DomainAuthOperateDTO domainAuthOperateDTO); + + /** + * 删除 + * + * @param domainAuthOperateDTO + * @author sr on 2021-05-24 + */ + @Validated(Create.class) + Set cancelLink(@Valid DomainAuthOperateDTO domainAuthOperateDTO); + + /** + * 查询 + * + * @param domainAuthQueryDTO + * @return + * @author sr on 2021-05-24 + */ + List list(DomainAuthQueryDTO domainAuthQueryDTO); + + /** + * 查询 + * + * @param domainAuthQueryDTO + * @return + * @author sr on 2021-05-24 + */ + List notLinkList(DomainAuthQueryDTO domainAuthQueryDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/sys/service/DomainService.java b/src/main/java/com/newyetai/usercenter/sys/service/DomainService.java new file mode 100644 index 0000000..ed33282 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/service/DomainService.java @@ -0,0 +1,93 @@ +package com.newyetai.usercenter.sys.service; + +import java.util.List; + +import javax.validation.Valid; +import javax.validation.groups.Default; + +import org.springframework.validation.annotation.Validated; + +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; +import com.newyetai.usercenter.sys.dto.DomainDTO; +import com.newyetai.usercenter.sys.dto.DomainOperateDTO; +import com.newyetai.usercenter.sys.dto.DomainQueryDTO; + +/** + * 域名 + * + * @author sr on 2021-05-24 + */ +@Validated(Default.class) +public interface DomainService extends IDomainOrgService{ + + /** + * 新增 + * + * @param domainOperateDTO + * @return + * @author sr on 2021-05-24 + */ + @Validated(Create.class) + Long create(@Valid DomainOperateDTO domainOperateDTO); + + /** + * 修改 + * + * @param domainOperateDTO + * @author sr on 2021-05-24 + */ + @Validated(Update.class) + void modify(@Valid DomainOperateDTO domainOperateDTO); + + /** + * 删除 + * + * @param id + * @author sr on 2021-05-24 + */ + void remove(Long id); + + /** + * 查询 + * + * @param domainQueryDTO + * @return + * @author sr on 2021-05-24 + */ + List list(DomainQueryDTO domainQueryDTO); + + /** + * 分页查询 + * @param domainQueryDTO + * @author sr on 2022-02-28 + */ + void page(DomainQueryDTO domainQueryDTO); + + /** + * 查询单个(无异常) + * @param domainQueryDTO + * @return + * @author sr on 2022-02-28 + */ + DomainDTO findOne(DomainQueryDTO domainQueryDTO); + + /** + * 查询当前请求host对应系统编码 + * + * @return + * @author sr on 2021-11-16 + */ + Integer findPlatformCode(); + Integer findPlatformCode(String domainOrIp); + + /** + * 细节 + * + * @param id id + * @return {@link DomainDTO} + */ + DomainDTO detail(Long id); + + +} diff --git a/src/main/java/com/newyetai/usercenter/sys/service/DomainSettingService.java b/src/main/java/com/newyetai/usercenter/sys/service/DomainSettingService.java new file mode 100644 index 0000000..325c4d2 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/service/DomainSettingService.java @@ -0,0 +1,79 @@ +package com.newyetai.usercenter.sys.service; + + +import com.baomidou.mybatisplus.extension.service.IService; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; +import com.newyetai.usercenter.dto.DomainSettingOperateDTO; +import com.newyetai.usercenter.dto.DomainSettingReqDTO; +import com.newyetai.usercenter.dto.DomainSettingResDTO; +import com.newyetai.usercenter.sys.dto.DomainSettingBannerOperateDTO; +import com.newyetai.usercenter.sys.dto.DomainSettingQuickOperateDTO; +import com.newyetai.usercenter.sys.entity.DomainSetting; + +import org.springframework.validation.annotation.Validated; + +import javax.validation.Valid; + +import java.util.List; + +/** + * 域设置服务 + * + * @author Carlye + * @date 2021/08/02 + */ +@Validated +public interface DomainSettingService extends IService { + + /** + * 新增 + * + * @param domainOperateDTO + * @return + * @author sr on 2021-05-24 + */ + @Validated(Create.class) + Long create(@Valid DomainSettingOperateDTO domainOperateDTO); + + /** + * 修改 + * + * @param domainOperateDTO + * @author sr on 2021-05-24 + */ + @Validated(Update.class) + void modify(@Valid DomainSettingOperateDTO domainOperateDTO); + + /** + * 删除 + * + * @param id + * @author sr on 2021-05-24 + */ + void remove(Long id); + + List list(@Valid DomainSettingReqDTO reqDTO); + + List listNoCache(DomainSettingReqDTO reqDTO); + + String findSettingData(DomainSettingReqDTO reqDTO); + + void cleanCache(); + + String quickCreate(DomainSettingQuickOperateDTO quickCreateOrModifyDTO); + + void quickModify(DomainSettingQuickOperateDTO quickCreateOrModifyDTO); + + List quickList(); + + String bannerCreate(DomainSettingBannerOperateDTO bannerOperateDTO); + + void bannerModify(DomainSettingBannerOperateDTO bannerOperateDTO); + + List bannerList(); + + void quickDelete(String id); + + void bannerDelete(String id); +} diff --git a/src/main/java/com/newyetai/usercenter/sys/service/FaqFileService.java b/src/main/java/com/newyetai/usercenter/sys/service/FaqFileService.java new file mode 100644 index 0000000..98eb6b3 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/service/FaqFileService.java @@ -0,0 +1,21 @@ +package com.newyetai.usercenter.sys.service; + +import com.newyetai.usercenter.sys.dto.FaqFileDTO; +import com.newyetai.usercenter.sys.dto.FaqFileQueryDTO; +import com.newyetai.usercenter.sys.entity.FaqFile; + +import java.util.List; + +/** + * 常见问题表 + * + */ +public interface FaqFileService { + + List list(FaqFileQueryDTO queryDTO); + + FaqFileDTO create(FaqFileDTO queryDTO) ; + + void delete(Long id) ; + +} diff --git a/src/main/java/com/newyetai/usercenter/sys/service/FaqService.java b/src/main/java/com/newyetai/usercenter/sys/service/FaqService.java new file mode 100644 index 0000000..84897b2 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/service/FaqService.java @@ -0,0 +1,56 @@ +package com.newyetai.usercenter.sys.service; + +import java.util.List; + +import com.newyetai.usercenter.sys.dto.FaqQueryDTO; +import com.newyetai.usercenter.sys.dto.FaqOperateDTO; +import com.newyetai.usercenter.sys.dto.FaqDTO; + +/** + * 常见问题表 + * + * @author sr on 2021-05-24 + */ +public interface FaqService { + + /** + * 新增 + * + * @param faqOperateDTO + * @return + * @author sr on 2021-05-24 + */ + Long create(FaqOperateDTO faqOperateDTO); + + /** + * 修改 + * + * @param faqOperateDTO + * @author sr on 2021-05-24 + */ + void modify(FaqOperateDTO faqOperateDTO); + + /** + * 删除 + * + * @param id + * @author sr on 2021-05-24 + */ + void remove(Long id); + + /** + * 查询 + * + * @param faqQueryDTO + * @return + * @author sr on 2021-05-24 + */ + List list(FaqQueryDTO faqQueryDTO); + + /** + * 获取单个 + * @param id + * @return + */ + FaqDTO get(Long id); +} diff --git a/src/main/java/com/newyetai/usercenter/sys/service/FeedbackService.java b/src/main/java/com/newyetai/usercenter/sys/service/FeedbackService.java new file mode 100644 index 0000000..ed85117 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/service/FeedbackService.java @@ -0,0 +1,50 @@ +package com.newyetai.usercenter.sys.service; + +import com.newyetai.usercenter.sys.dto.FeedbackDTO; +import com.newyetai.usercenter.sys.dto.FeedbackOperateDTO; +import com.newyetai.usercenter.sys.dto.FeedbackQueryDTO; + +import java.util.List; + +/** + * 反馈表 + * + * @author sr on 2021-05-24 + */ +public interface FeedbackService { + + /** + * 新增 + * + * @param feedbackOperateDTO + * @return + * @author sr on 2021-05-24 + */ + Long create(FeedbackOperateDTO feedbackOperateDTO); + + /** + * 修改 + * + * @param feedbackOperateDTO + * @author sr on 2021-05-24 + */ + void modify(FeedbackOperateDTO feedbackOperateDTO); + + /** + * 删除 + * + * @param id + * @author sr on 2021-05-24 + */ + void remove(Long id); + + /** + * 查询 + * + * @param feedbackQueryDTO + * @return + * @author sr on 2021-05-24 + */ + List list(FeedbackQueryDTO feedbackQueryDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/sys/service/IDomainOrgService.java b/src/main/java/com/newyetai/usercenter/sys/service/IDomainOrgService.java new file mode 100644 index 0000000..10161a2 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/service/IDomainOrgService.java @@ -0,0 +1,16 @@ +package com.newyetai.usercenter.sys.service; + +import java.util.Set; + +import com.newyetai.common.AlitaResult; + +public interface IDomainOrgService { + + /** + * 获取请求相关机构列表 + * @return + * @author sr on 2022-02-28 + */ + AlitaResult> listOrgId(); + +} diff --git a/src/main/java/com/newyetai/usercenter/sys/service/PlatformService.java b/src/main/java/com/newyetai/usercenter/sys/service/PlatformService.java new file mode 100644 index 0000000..fc61581 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/service/PlatformService.java @@ -0,0 +1,59 @@ +package com.newyetai.usercenter.sys.service; + +import com.newyetai.usercenter.sys.dto.PlatformDTO; +import com.newyetai.usercenter.sys.dto.PlatformOperateDTO; +import com.newyetai.usercenter.sys.dto.PlatformPageQueryDTO; +import com.newyetai.usercenter.sys.dto.PlatformQueryDTO; + +import java.util.List; + +/** + * 系统应用 + * + * @author sr on 2021-05-24 + */ +public interface PlatformService { + + /** + * 新增 + * + * @param platformOperateDTO + * @return + * @author sr on 2021-05-24 + */ + Long create(PlatformOperateDTO platformOperateDTO); + + /** + * 修改 + * + * @param platformOperateDTO + * @author sr on 2021-05-24 + */ + void modify(PlatformOperateDTO platformOperateDTO); + + /** + * 删除 + * + * @param id + * @author sr on 2021-05-24 + */ + void remove(Long id); + + /** + * 列表 + * + * @param queryDTO 查询dto + * @return {@link List}<{@link PlatformDTO}> + */ + List list(PlatformQueryDTO queryDTO); + + /** + * 查询 + * + * @param platformPageQueryDTO + * @return + * @author sr on 2021-05-24 + */ + List page(PlatformPageQueryDTO platformPageQueryDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/sys/service/impl/DomainAuthServiceImpl.java b/src/main/java/com/newyetai/usercenter/sys/service/impl/DomainAuthServiceImpl.java new file mode 100644 index 0000000..553113a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/service/impl/DomainAuthServiceImpl.java @@ -0,0 +1,94 @@ +package com.newyetai.usercenter.sys.service.impl; + +import java.util.List; +import java.util.Objects; +import java.util.Set; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.google.common.collect.Sets; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.usercenter.auth.dto.AuthClientDTO; +import com.newyetai.usercenter.auth.dto.AuthClientQueryDTO; +import com.newyetai.usercenter.auth.service.AuthClientService; +import com.newyetai.usercenter.sys.dao.DomainAuthMapper; +import com.newyetai.usercenter.sys.dto.DomainAuthDTO; +import com.newyetai.usercenter.sys.dto.DomainAuthOperateDTO; +import com.newyetai.usercenter.sys.dto.DomainAuthQueryDTO; +import com.newyetai.usercenter.sys.entity.DomainAuth; +import com.newyetai.usercenter.sys.service.DomainAuthService; + +import cn.hutool.core.date.DateUtil; + +/** + * @author sr on 2021-05-24 + */ +@Service +public class DomainAuthServiceImpl extends ServiceImpl implements DomainAuthService { + + @Autowired + private AuthClientService authClientService; + + @Override + public Set link(DomainAuthOperateDTO domainAuthOperateDTO) { + Set res = Sets.newHashSet(); + for (Long authClientId : domainAuthOperateDTO.getAuthClientIds()) { + DomainAuth domainAuth = getOne(Wrappers.lambdaQuery() + .eq(DomainAuth::getDomainId,domainAuthOperateDTO.getDomainId()) + .eq(DomainAuth::getAuthClientId,authClientId) + .eq(DomainAuth::getDeleted,false) + ); + if (Objects.isNull(domainAuth)){ + AuthClientDTO authClient = authClientService + .findAuthClientDTO(AuthClientQueryDTO.builder().id(authClientId).build()); + Assert.notNull(authClient,"s授权客户端不存在"); + DomainAuth build = DomainAuth.builder() + .authClientId(authClientId) + .domainId(domainAuthOperateDTO.getDomainId()) + .authTypeCode(authClient.getAuthTypeCode()) + .build(); + save(build); + res.add(build.getId()); + }else { + res.add(domainAuth.getId()); + } + } + return res; + } + + @Override + public Set cancelLink(DomainAuthOperateDTO domainAuthOperateDTO) { + Set res = Sets.newHashSet(); + for (Long authClientId : domainAuthOperateDTO.getAuthClientIds()) { + DomainAuth domainAuth = getOne(Wrappers.lambdaQuery() + .eq(DomainAuth::getDomainId,domainAuthOperateDTO.getDomainId()) + .eq(DomainAuth::getAuthClientId,authClientId) + .eq(DomainAuth::getDeleted,false) + ); + Assert.notNull(domainAuth,"关联授权不存在"); + + update(Wrappers.lambdaUpdate() + .set(DomainAuth::getDeleted, true) + .set(DomainAuth::getUpdateBy, UserContextHolder.getExistLoginUserId()) + .set(DomainAuth::getUpdateTime, DateUtil.date()) + .eq(DomainAuth::getId,domainAuth.getId())); + res.add(domainAuth.getId()); + } + return res; + } + + + @Override + public List list(DomainAuthQueryDTO domainAuthQueryDTO) { + return getBaseMapper().listDomainAuthDTO(domainAuthQueryDTO); + } + + @Override + public List notLinkList(DomainAuthQueryDTO domainAuthQueryDTO) { + return getBaseMapper().notLinkList(domainAuthQueryDTO); + } +} diff --git a/src/main/java/com/newyetai/usercenter/sys/service/impl/DomainServiceImpl.java b/src/main/java/com/newyetai/usercenter/sys/service/impl/DomainServiceImpl.java new file mode 100644 index 0000000..962abd3 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/service/impl/DomainServiceImpl.java @@ -0,0 +1,99 @@ +package com.newyetai.usercenter.sys.service.impl; + +import com.google.common.collect.Sets; +import com.newyetai.common.AlitaResult; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.ListUtil; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.security.util.HostContextHolder; +import com.newyetai.usercenter.sys.dao.DomainMapper; +import com.newyetai.usercenter.sys.dto.DomainDTO; +import com.newyetai.usercenter.sys.dto.DomainOperateDTO; +import com.newyetai.usercenter.sys.dto.DomainQueryDTO; +import com.newyetai.usercenter.sys.entity.Domain; +import com.newyetai.usercenter.sys.mapstruct.DomainMapMapper; +import com.newyetai.usercenter.sys.service.DomainService; +import com.newyetai.usercenter.sys.util.DomainUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Set; + +/** + * @author sr on 2021-05-24 + */ +@Service +public class DomainServiceImpl implements DomainService { + + @Autowired + private DomainMapper domainMapper; + + @Override + public Long create(DomainOperateDTO domainOperateDTO) { + if (!Boolean.TRUE.equals(domainOperateDTO.getPubliced())) { + Assert.notNull(domainOperateDTO.getOrgId(), "所属机构不能为空"); + } + Domain domain = DomainMapMapper.INSTANCE.toEntity(domainOperateDTO); + domainMapper.saveEntity(domain); + return domain.getId(); + } + + @Override + public void modify(DomainOperateDTO domainOperateDTO) { + Domain oldDomain = domainMapper.getById(domainOperateDTO.getId()); + Assert.notNull(oldDomain, "域名配置不存在"); + domainMapper.updateEntitySelective(DomainMapMapper.INSTANCE.toEntity(domainOperateDTO)); + } + + @Override + public void remove(Long id) { + domainMapper.deleteEntity(Domain.builder().id(id).build(), + UserContextHolder.getLoginUserId()); + } + + @Override + public List list(DomainQueryDTO domainQueryDTO) { + domainQueryDTO.disablePage(); + return domainMapper.listDomainDTO(domainQueryDTO); + } + + @Override + public void page(DomainQueryDTO domainQueryDTO) { + domainMapper.listDomainDTO(domainQueryDTO); + } + + @Override + public DomainDTO findOne(DomainQueryDTO domainQueryDTO) { + List domainDTOs = list(domainQueryDTO); + Assert.isTrue(!domainDTOs.isEmpty(), "请求host配置信息异常,请联系管理员"); + return ListUtil.first(domainDTOs); + } + + @Override + public Integer findPlatformCode() { + return this.findPlatformCode(null); + } + @Override + public Integer findPlatformCode(String domainOrIp) { + return findOne(DomainQueryDTO.builder() + .domainOrIp(DomainUtils.getOrDefault(domainOrIp)).build()).getPlatformCode(); + } + + @Override + public DomainDTO detail(Long id) { + return this.findOne(DomainQueryDTO.builder().id(id).build()); + } + + @Override + public AlitaResult> listOrgId() { + DomainDTO domainDTO = findOne(DomainQueryDTO.builder() + .domainOrIp(HostContextHolder.getHost()).build()); + Long orgId = domainDTO.getOrgId(); + Set orgIds = Sets.newHashSet(); + if (Boolean.FALSE.equals(domainDTO.getPubliced())) { + orgIds.add(orgId); + } + return AlitaResult.success(orgIds); + } +} diff --git a/src/main/java/com/newyetai/usercenter/sys/service/impl/DomainSettingServiceImpl.java b/src/main/java/com/newyetai/usercenter/sys/service/impl/DomainSettingServiceImpl.java new file mode 100644 index 0000000..8301fb1 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/service/impl/DomainSettingServiceImpl.java @@ -0,0 +1,323 @@ +package com.newyetai.usercenter.sys.service.impl; + + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import javax.annotation.Resource; + +import org.apache.commons.compress.utils.Lists; +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.exception.util.UUIDUtils; +import com.newyetai.common.util.ListUtil; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.security.util.HostContextHolder; +import com.newyetai.usercenter.dto.DomainSettingOperateDTO; +import com.newyetai.usercenter.dto.DomainSettingReqDTO; +import com.newyetai.usercenter.dto.DomainSettingResDTO; +import com.newyetai.usercenter.sys.constant.DomainSettingConstant; +import com.newyetai.usercenter.sys.dao.DomainMapper; +import com.newyetai.usercenter.sys.dao.DomainSettingMapper; +import com.newyetai.usercenter.sys.dto.DomainDTO; +import com.newyetai.usercenter.sys.dto.DomainQueryDTO; +import com.newyetai.usercenter.sys.dto.DomainSettingBannerOperateDTO; +import com.newyetai.usercenter.sys.dto.DomainSettingQuickOperateDTO; +import com.newyetai.usercenter.sys.entity.DomainSetting; +import com.newyetai.usercenter.sys.mapstruct.DomainMapMapper; +import com.newyetai.usercenter.sys.service.DomainService; +import com.newyetai.usercenter.sys.service.DomainSettingService; +import com.newyetai.usercenter.sys.util.DomainUtils; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONUtil; +import lombok.extern.slf4j.Slf4j; + +/** + * 域设置服务 + * + * @author Carlye + * @date 2021/08/02 + */ +@Slf4j +@Service +public class DomainSettingServiceImpl extends ServiceImpl implements DomainSettingService { + + @Resource + private DomainMapper domainMapper; + @Autowired + private DomainService domainService; + + @Override + public Long create(DomainSettingOperateDTO domainOperateDTO) { + DomainSetting domain = DomainMapMapper.INSTANCE.exchange(domainOperateDTO); + baseMapper.saveEntity(domain); + DomainSettingServiceImpl domainSettingService = (DomainSettingServiceImpl) AopContext.currentProxy(); + domainSettingService.cleanCache(); + return domain.getId(); + } + + @Override + public void modify(DomainSettingOperateDTO domainOperateDTO) { + DomainSetting domainSetting = getOne(Wrappers.lambdaUpdate() + .eq(DomainSetting::getDeleted, false) + .eq(DomainSetting::getId, domainOperateDTO.getId()) + ); + Assert.notNull(domainSetting, "配置不存在"); + DomainSetting domain = DomainMapMapper.INSTANCE.exchange(domainOperateDTO); + baseMapper.updateEntitySelective(domain); + DomainSettingServiceImpl domainSettingService = (DomainSettingServiceImpl) AopContext.currentProxy(); + domainSettingService.cleanCache(); + } + + @Override + public void remove(Long id) { + DomainSetting domainSetting = getOne(Wrappers.lambdaUpdate() + .eq(DomainSetting::getDeleted, false) + .eq(DomainSetting::getId, id) + ); + Assert.notNull(domainSetting, "配置不存在"); + update(Wrappers.lambdaUpdate() + .set(DomainSetting::getDeleted, true) + .set(DomainSetting::getUpdateBy, UserContextHolder.getExistLoginUserId()) + .set(DomainSetting::getUpdateTime, DateUtil.date()) + .eq(DomainSetting::getId, id)); + DomainSettingServiceImpl domainSettingService = (DomainSettingServiceImpl) AopContext.currentProxy(); + domainSettingService.cleanCache(); + } + + @Override + public List list(DomainSettingReqDTO reqDTO) { + Long domainId = reqDTO.getDomainId(); + if (Objects.isNull(domainId)) { + String domainOrIp = DomainUtils.getOrDefault(reqDTO.getDomainOrIp()); + DomainDTO domainDTO = domainMapper.selectByDomainOrIp(domainOrIp); + if (Objects.isNull(domainDTO)) { + return Lists.newArrayList(); + } + domainId = domainDTO.getId(); + } + DomainSettingReqDTO reqDTO1 = new DomainSettingReqDTO(); + reqDTO1.setDomainId(domainId); + //查询缓存 + DomainSettingServiceImpl domainSettingServiceProxy = (DomainSettingServiceImpl) AopContext.currentProxy(); + List domainSettingResDTOS = domainSettingServiceProxy.listByCache(reqDTO1); + + if (CollectionUtils.isNotEmpty(reqDTO.getTypes())) { + return domainSettingResDTOS.stream().filter(d -> reqDTO.getTypes().contains(d.getType())).collect(Collectors.toList()); + } + return domainSettingResDTOS; + } + + @Cacheable(value = "domain_setting", key = " #reqDTO.toString() ") + public List listByCache(DomainSettingReqDTO reqDTO) { + return getBaseMapper().list(reqDTO); + } + + public List listNoCache(DomainSettingReqDTO reqDTO) { + return getBaseMapper().list(reqDTO); + } + + @Override + @CacheEvict(value = "domain_setting", allEntries = true) + public void cleanCache() { + //doNothing + } + + @Override + public String findSettingData(DomainSettingReqDTO reqDTO) { + List settings = ((DomainSettingService) AopContext.currentProxy()).list(reqDTO); + if (settings.isEmpty()) { + return null; + } + Assert.isTrue(settings.size() == 1, "查询到多个匹配配置,请检查数据"); + return ListUtil.first(settings).getData(); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public String quickCreate(DomainSettingQuickOperateDTO quickCreateDTO) { + + DomainDTO domainDTO = domainService.findOne(DomainQueryDTO.builder() + .domainOrIp(HostContextHolder.getHost()).build()); + + String uuid = UUIDUtils.generateUUID(); + quickCreateDTO.setId(uuid); + + List list = this.list(DomainSettingReqDTO.builder().type(DomainSettingConstant.QUICK).build()); + DomainSettingResDTO first = ListUtil.first(list); + + DomainSettingServiceImpl domainSettingService = (DomainSettingServiceImpl) AopContext.currentProxy(); + + JSONArray jsonArray = new JSONArray(); + jsonArray.add(quickCreateDTO); + + if (Objects.isNull(first)) { + domainSettingService.create(DomainSettingOperateDTO.builder() + .domainId(domainDTO.getId()) + .type(DomainSettingConstant.QUICK) + .remark(quickCreateDTO.getRemark()) + .data(JSONUtil.toJsonStr(jsonArray)) + .build()); + }else { + List domainSettingQuickOperateDTOS = JSONUtil.toList(first.getData(), DomainSettingQuickOperateDTO.class); + domainSettingQuickOperateDTOS.add(quickCreateDTO); + first.setData(JSONUtil.toJsonStr(domainSettingQuickOperateDTOS)); + DomainSettingOperateDTO modifyDto = new DomainSettingOperateDTO(); + BeanUtils.copyProperties(first,modifyDto); + domainSettingService.modify(modifyDto); + } + return uuid; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void quickModify(DomainSettingQuickOperateDTO quickModifyDTO) { + List list = this.list(DomainSettingReqDTO.builder().type(DomainSettingConstant.QUICK).build()); + DomainSettingResDTO first = ListUtil.first(list); + if (Objects.isNull(first)) { + return; + } + DomainSettingServiceImpl domainSettingService = (DomainSettingServiceImpl) AopContext.currentProxy(); + + List resultList = JSONUtil.toList(first.getData(), DomainSettingQuickOperateDTO.class); + for (DomainSettingQuickOperateDTO modifyDTO : resultList) { + if (StringUtils.equals(quickModifyDTO.getId(),modifyDTO.getId())) { + BeanUtils.copyProperties(quickModifyDTO,modifyDTO); + } + } + DomainSettingOperateDTO modifyDto = new DomainSettingOperateDTO(); + BeanUtils.copyProperties(first,modifyDto); + modifyDto.setData(JSONUtil.toJsonStr(resultList)); + domainSettingService.modify(modifyDto); + } + + @Override + public List quickList() { + List list = this.list(DomainSettingReqDTO.builder().type(DomainSettingConstant.QUICK).build()); + DomainSettingResDTO first = ListUtil.first(list); + if (Objects.isNull(first)) { + return new ArrayList<>(); + } + List resultList = JSONUtil.toList(first.getData(), DomainSettingQuickOperateDTO.class); + resultList = resultList.stream().sorted(Comparator.comparing(DomainSettingQuickOperateDTO::getSort)).collect(Collectors.toList()); + return resultList; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public String bannerCreate(DomainSettingBannerOperateDTO bannerOperateDTO) { + + DomainDTO domainDTO = domainService.findOne(DomainQueryDTO.builder() + .domainOrIp(HostContextHolder.getHost()).build()); + + String uuid = UUIDUtils.generateUUID(); + bannerOperateDTO.setId(uuid); + + List list = this.list(DomainSettingReqDTO.builder().type(DomainSettingConstant.BANNER).build()); + DomainSettingResDTO first = ListUtil.first(list); + + DomainSettingServiceImpl domainSettingService = (DomainSettingServiceImpl) AopContext.currentProxy(); + + JSONArray jsonArray = new JSONArray(); + jsonArray.add(bannerOperateDTO); + + if (Objects.isNull(first)) { + domainSettingService.create(DomainSettingOperateDTO.builder() + .domainId(domainDTO.getId()) + .type(DomainSettingConstant.BANNER) + .data(JSONUtil.toJsonStr(jsonArray)) + .build()); + }else { + List domainSettingBannerOperateDTOS = JSONUtil.toList(first.getData(), DomainSettingBannerOperateDTO.class); + domainSettingBannerOperateDTOS.add(bannerOperateDTO); + first.setData(JSONUtil.toJsonStr(domainSettingBannerOperateDTOS)); + DomainSettingOperateDTO modifyDto = new DomainSettingOperateDTO(); + BeanUtils.copyProperties(first,modifyDto); + domainSettingService.modify(modifyDto); + } + return uuid; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void bannerModify(DomainSettingBannerOperateDTO bannerOperateDTO) { + List list = this.list(DomainSettingReqDTO.builder().type(DomainSettingConstant.BANNER).build()); + DomainSettingResDTO first = ListUtil.first(list); + if (Objects.isNull(first)) { + return; + } + DomainSettingServiceImpl domainSettingService = (DomainSettingServiceImpl) AopContext.currentProxy(); + + List resultList = JSONUtil.toList(first.getData(), DomainSettingBannerOperateDTO.class); + for (DomainSettingBannerOperateDTO modifyDTO : resultList) { + if (StringUtils.equals(bannerOperateDTO.getId(),modifyDTO.getId())) { + BeanUtils.copyProperties(bannerOperateDTO,modifyDTO); + } + } + DomainSettingOperateDTO modifyDto = new DomainSettingOperateDTO(); + BeanUtils.copyProperties(first,modifyDto); + modifyDto.setData(JSONUtil.toJsonStr(resultList)); + domainSettingService.modify(modifyDto); + } + + @Override + public List bannerList() { + List list = this.list(DomainSettingReqDTO.builder().type(DomainSettingConstant.BANNER).build()); + DomainSettingResDTO first = ListUtil.first(list); + if (Objects.isNull(first)) { + return new ArrayList<>(); + } + List resultList = JSONUtil.toList(first.getData(), DomainSettingBannerOperateDTO.class); + return resultList; + } + + @Override + public void quickDelete(String id) { + List list = this.list(DomainSettingReqDTO.builder().type(DomainSettingConstant.QUICK).build()); + DomainSettingResDTO first = ListUtil.first(list); + if (Objects.isNull(first)) { + return; + } + DomainSettingServiceImpl domainSettingService = (DomainSettingServiceImpl) AopContext.currentProxy(); + + List resultList = JSONUtil.toList(first.getData(), DomainSettingQuickOperateDTO.class); + resultList = resultList.stream().filter(result -> !StringUtils.equals(result.getId(),id)).collect(Collectors.toList()); + DomainSettingOperateDTO modifyDto = new DomainSettingOperateDTO(); + BeanUtils.copyProperties(first,modifyDto); + modifyDto.setData(JSONUtil.toJsonStr(resultList)); + domainSettingService.modify(modifyDto); + } + + @Override + public void bannerDelete(String id) { + List list = this.list(DomainSettingReqDTO.builder().type(DomainSettingConstant.BANNER).build()); + DomainSettingResDTO first = ListUtil.first(list); + if (Objects.isNull(first)) { + return; + } + DomainSettingServiceImpl domainSettingService = (DomainSettingServiceImpl) AopContext.currentProxy(); + + List resultList = JSONUtil.toList(first.getData(), DomainSettingBannerOperateDTO.class); + resultList = resultList.stream().filter(result -> !StringUtils.equals(result.getId(),id)).collect(Collectors.toList()); + DomainSettingOperateDTO modifyDto = new DomainSettingOperateDTO(); + BeanUtils.copyProperties(first,modifyDto); + modifyDto.setData(JSONUtil.toJsonStr(resultList)); + domainSettingService.modify(modifyDto); + } +} diff --git a/src/main/java/com/newyetai/usercenter/sys/service/impl/FaqFileServiceImpl.java b/src/main/java/com/newyetai/usercenter/sys/service/impl/FaqFileServiceImpl.java new file mode 100644 index 0000000..7afdd50 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/service/impl/FaqFileServiceImpl.java @@ -0,0 +1,37 @@ +package com.newyetai.usercenter.sys.service.impl; + +import com.newyetai.usercenter.sys.dao.FaqFileMapper; +import com.newyetai.usercenter.sys.dto.FaqFileDTO; +import com.newyetai.usercenter.sys.dto.FaqFileQueryDTO; +import com.newyetai.usercenter.sys.entity.FaqFile; +import com.newyetai.usercenter.sys.mapstruct.FaqFileMapMapper; +import com.newyetai.usercenter.sys.service.FaqFileService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.Assert; + +import java.util.List; + +@Service +public class FaqFileServiceImpl implements FaqFileService { + + @Autowired + private FaqFileMapper faqFileMapper; + + @Override + public List list(FaqFileQueryDTO queryDTO){ + return faqFileMapper.filePage(queryDTO); + } + + @Override + public FaqFileDTO create(FaqFileDTO operateDTO) { + FaqFile file = FaqFileMapMapper.INSTANCE.toEntity(operateDTO); + faqFileMapper.saveEntity(file); + return FaqFileMapMapper.INSTANCE.toDTO(file); + } + + @Override + public void delete(Long id) { + faqFileMapper.deleteEntity(FaqFile.builder().id(id).build()); + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/sys/service/impl/FaqServiceImpl.java b/src/main/java/com/newyetai/usercenter/sys/service/impl/FaqServiceImpl.java new file mode 100644 index 0000000..73b562d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/service/impl/FaqServiceImpl.java @@ -0,0 +1,54 @@ +package com.newyetai.usercenter.sys.service.impl; + +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.usercenter.sys.dao.FaqMapper; +import com.newyetai.usercenter.sys.dto.FaqDTO; +import com.newyetai.usercenter.sys.dto.FaqOperateDTO; +import com.newyetai.usercenter.sys.dto.FaqQueryDTO; +import com.newyetai.usercenter.sys.entity.Faq; +import com.newyetai.usercenter.sys.mapstruct.FaqMapMapper; +import com.newyetai.usercenter.sys.service.FaqService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + * @author sr on 2021-05-24 + */ +@Service +public class FaqServiceImpl implements FaqService { + + @Autowired + private FaqMapper faqMapper; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long create(FaqOperateDTO faqOperateDTO) { + Faq faq = FaqMapMapper.INSTANCE.toEntity(faqOperateDTO); + faqMapper.saveEntity(faq); + return faq.getId(); + } + + @Override + public void modify(FaqOperateDTO faqOperateDTO) { + Faq faq = FaqMapMapper.INSTANCE.toEntity(faqOperateDTO); + faqMapper.updateEntitySelective(faq, UserContextHolder.getLoginUserId()); + } + + @Override + public void remove(Long id) { + faqMapper.deleteEntity(Faq.builder().id(id).build()); + } + + @Override + public List list(FaqQueryDTO faqQueryDTO) { + return faqMapper.listFaqDTO(faqQueryDTO); + } + + @Override + public FaqDTO get(Long id) { + return FaqMapMapper.INSTANCE.toDTO(faqMapper.getById(id)); + } +} diff --git a/src/main/java/com/newyetai/usercenter/sys/service/impl/FeedbackServiceImpl.java b/src/main/java/com/newyetai/usercenter/sys/service/impl/FeedbackServiceImpl.java new file mode 100644 index 0000000..2c09978 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/service/impl/FeedbackServiceImpl.java @@ -0,0 +1,63 @@ +package com.newyetai.usercenter.sys.service.impl; + +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.util.ExceptionUtils; +import com.newyetai.common.util.SensitiveWordUtils; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.usercenter.sys.dao.FeedbackMapper; +import com.newyetai.usercenter.sys.dto.FeedbackDTO; +import com.newyetai.usercenter.sys.dto.FeedbackOperateDTO; +import com.newyetai.usercenter.sys.dto.FeedbackQueryDTO; +import com.newyetai.usercenter.sys.entity.Feedback; +import com.newyetai.usercenter.sys.mapstruct.FeedbackMapMapper; +import com.newyetai.usercenter.sys.service.FeedbackService; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author sr on 2021-05-24 + */ +@Service +public class FeedbackServiceImpl implements FeedbackService { + + @Autowired + private FeedbackMapper feedbackMapper; + + @Override + public Long create(FeedbackOperateDTO feedbackOperateDTO) { + if (!SensitiveWordUtils.check(feedbackOperateDTO.getContent())) { + throw new BusinessException("非法反馈内容"); + } + + Feedback feedback = FeedbackMapMapper.INSTANCE.toEntity(feedbackOperateDTO); + if(feedback.getUserId() == null ){ + feedback.setUserId(UserContextHolder.getLoginUserId()); + } + ExceptionUtils.throwBusinessException( + StringUtils.isNotBlank(feedback.getContent()) && feedback.getContent().length() > 200 , + "反馈内容过长"); + + feedbackMapper.saveEntity(feedback); + return feedback.getId(); + } + + @Override + public void modify(FeedbackOperateDTO feedbackOperateDTO) { + Feedback feedback = FeedbackMapMapper.INSTANCE.toEntity(feedbackOperateDTO); + feedbackMapper.updateEntitySelective(feedback,UserContextHolder.getLoginUserId()); + } + + @Override + public void remove(Long id) { + feedbackMapper.deleteEntity(Feedback.builder().id(id).build()); + } + + @Override + public List list(FeedbackQueryDTO feedbackQueryDTO) { + return feedbackMapper.listFeedbackDTO(feedbackQueryDTO); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/sys/service/impl/PlatformServiceImpl.java b/src/main/java/com/newyetai/usercenter/sys/service/impl/PlatformServiceImpl.java new file mode 100644 index 0000000..a2d7ada --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/service/impl/PlatformServiceImpl.java @@ -0,0 +1,53 @@ +package com.newyetai.usercenter.sys.service.impl; + +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.usercenter.sys.dao.PlatformMapper; +import com.newyetai.usercenter.sys.dto.PlatformDTO; +import com.newyetai.usercenter.sys.dto.PlatformOperateDTO; +import com.newyetai.usercenter.sys.dto.PlatformPageQueryDTO; +import com.newyetai.usercenter.sys.dto.PlatformQueryDTO; +import com.newyetai.usercenter.sys.entity.Platform; +import com.newyetai.usercenter.sys.service.PlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author sr on 2021-05-24 + */ +@Service +public class PlatformServiceImpl implements PlatformService { + + @Autowired + private PlatformMapper platformMapper; + + @Override + public Long create(PlatformOperateDTO platformOperateDTO) { + // TODO Auto-generated method stub + return null; + } + + @Override + public void modify(PlatformOperateDTO platformOperateDTO) { + // TODO Auto-generated method stub + + } + + @Override + public void remove(Long id) { + platformMapper.deleteEntity(Platform.builder().id(id).build(), + UserContextHolder.getLoginUserId()); + } + + @Override + public List list(PlatformQueryDTO queryDTO) { + return platformMapper.list(queryDTO); + } + + @Override + public List page(PlatformPageQueryDTO platformPageQueryDTO) { + return platformMapper.page(platformPageQueryDTO); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/sys/util/DomainOrgUtils.java b/src/main/java/com/newyetai/usercenter/sys/util/DomainOrgUtils.java new file mode 100644 index 0000000..62ec841 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/util/DomainOrgUtils.java @@ -0,0 +1,26 @@ +package com.newyetai.usercenter.sys.util; + +import java.util.Set; + +import org.springframework.stereotype.Component; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.usercenter.sys.service.IDomainOrgService; + +@Component +public class DomainOrgUtils { + + private static IDomainOrgService domainOrgService; + + public DomainOrgUtils(IDomainOrgService domainOrgService) { + DomainOrgUtils.domainOrgService = domainOrgService; + } + + public static Set list(){ + AlitaResult> result = domainOrgService.listOrgId(); + Assert.isTrue(result.getSuccess(), result.getMsg()); + return result.getData(); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/sys/util/DomainUtils.java b/src/main/java/com/newyetai/usercenter/sys/util/DomainUtils.java new file mode 100644 index 0000000..9ecab57 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/sys/util/DomainUtils.java @@ -0,0 +1,15 @@ +package com.newyetai.usercenter.sys.util; + +import org.apache.commons.lang3.StringUtils; + +import com.newyetai.security.util.HostContextHolder; + +/** + * @author sr on 2021-05-24 + */ +public class DomainUtils { + + public static String getOrDefault(String domainOrIp) { + return StringUtils.isBlank(domainOrIp) ? HostContextHolder.getHost() : domainOrIp; + } +} diff --git a/src/main/java/com/newyetai/usercenter/tag/controller/AnonTagRelationshipController.java b/src/main/java/com/newyetai/usercenter/tag/controller/AnonTagRelationshipController.java new file mode 100644 index 0000000..123bf97 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/tag/controller/AnonTagRelationshipController.java @@ -0,0 +1,48 @@ +package com.newyetai.usercenter.tag.controller; + + +import com.newyetai.common.AlitaResult; +import com.newyetai.usercenter.tag.dto.TagRelationshipMapQueryDTO; +import com.newyetai.usercenter.tag.dto.TagRelationshipQueryDTO; +import com.newyetai.usercenter.tag.service.ITagRelationshipService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + *

+ * 前端控制器 + *

+ * + * @author Carlye + * @since 2021-01-21 + */ +@Api(tags = "标签关系信息") +@RestController +@RequestMapping("/anon/tag_relationship") +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class AnonTagRelationshipController { + + private final ITagRelationshipService tagRelationshipsService; + + @GetMapping("/source_id_map") + @ApiOperation("创建标签关系信息") + public AlitaResult>> sourceIdMap(TagRelationshipMapQueryDTO queryDTO) { + return AlitaResult.success(tagRelationshipsService.sourceIdMap(queryDTO)); + } + + @GetMapping("/source_ids") + @ApiOperation("查询source_id集合") + public AlitaResult> sourceIds(TagRelationshipQueryDTO queryDTO) { + return AlitaResult.success(tagRelationshipsService.sourceIds(queryDTO)); + } +} + diff --git a/src/main/java/com/newyetai/usercenter/tag/controller/TagController.java b/src/main/java/com/newyetai/usercenter/tag/controller/TagController.java new file mode 100644 index 0000000..bd9e2c6 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/tag/controller/TagController.java @@ -0,0 +1,89 @@ +package com.newyetai.usercenter.tag.controller; + + +import com.newyetai.common.AlitaResult; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.tag.dto.*; +import com.newyetai.usercenter.tag.service.ITagService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + *

+ * 标签表 前端控制器 + *

+ * + * @author Carlye + * @since 2021-01-21 + */ +@Api(tags = "标签信息") +@RestController +@RequestMapping("/tag") +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class TagController { + + private final ITagService tagService; + + /** + * 创建 + * + * @param tagDTO 标签dto + * @return {@link AlitaResult} + */ + @PostMapping("/create") + @ApiOperation("创建岗位信息") + public AlitaResult create(@RequestBody TagCreateDTO tagDTO) { + return AlitaResult.success(tagService.create(tagDTO)); + } + + /** + * 批量创建 + * + * @param tagDTO 标签dto + * @return {@link AlitaResult>} + */ + @PostMapping("/batch_create") + @ApiOperation("创建岗位信息") + public AlitaResult> batchCreate(@RequestBody TagBatchCreateDTO tagDTO) { + return AlitaResult.success(tagService.batchCreate(tagDTO)); + } + + /** + * 分页查询 + * + * @param pageQueryDTO 页面查询dto + * @return {@link AlitaResult>} + */ + @GetMapping("/list") + @ApiOperation("列表查询") + public AlitaResult> list(TagPageQueryDTO pageQueryDTO) { + pageQueryDTO.setNeedPage(Boolean.FALSE); + return AlitaResult.success(tagService.page(pageQueryDTO)); + } + + /** + * 分页查询 + * + * @param pageQueryDTO 页面查询dto + * @return {@link AlitaResult>} + */ + @GetMapping("/page") + @ApiOperation("分页查询") + public AlitaResult> page(TagPageQueryDTO pageQueryDTO) { + tagService.page(pageQueryDTO); + return AlitaResult.success(pageQueryDTO.getPageResult()); + } + + @PostMapping("/update") + @ApiOperation("更新") + public AlitaResult update(@RequestBody TagUpdateDTO updateDTO) { + tagService.update(updateDTO); + return AlitaResult.success(); + } +} + diff --git a/src/main/java/com/newyetai/usercenter/tag/controller/TagRelationshipController.java b/src/main/java/com/newyetai/usercenter/tag/controller/TagRelationshipController.java new file mode 100644 index 0000000..cd30d04 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/tag/controller/TagRelationshipController.java @@ -0,0 +1,39 @@ +package com.newyetai.usercenter.tag.controller; + + +import com.newyetai.common.AlitaResult; +import com.newyetai.usercenter.tag.dto.TagRelationshipDTO; +import com.newyetai.usercenter.tag.dto.TagRelationshipMapQueryDTO; +import com.newyetai.usercenter.tag.service.ITagRelationshipService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Map; + +/** + *

+ * 前端控制器 + *

+ * + * @author Carlye + * @since 2021-01-21 + */ +@Api(tags = "标签关系信息") +@RestController +@RequestMapping("/tag_relationship") +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class TagRelationshipController { + + private final ITagRelationshipService tagRelationshipsService; + + @PostMapping("/create") + @ApiOperation("创建标签关系信息") + public AlitaResult create(@RequestBody TagRelationshipDTO tagRelationshipDTO) { + return AlitaResult.success(tagRelationshipsService.create(tagRelationshipDTO)); + } +} + diff --git a/src/main/java/com/newyetai/usercenter/tag/dao/TagMapper.java b/src/main/java/com/newyetai/usercenter/tag/dao/TagMapper.java new file mode 100644 index 0000000..9c90925 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/tag/dao/TagMapper.java @@ -0,0 +1,21 @@ +package com.newyetai.usercenter.tag.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.newyetai.usercenter.tag.dto.TagDTO; +import com.newyetai.usercenter.tag.dto.TagPageQueryDTO; +import com.newyetai.usercenter.tag.entity.Tag; + +import java.util.List; + +/** + *

+ * 标签表 Mapper 接口 + *

+ * + * @author Carlye + * @since 2021-01-21 + */ +public interface TagMapper extends BaseMapper { + + List page(TagPageQueryDTO queryDTO); +} diff --git a/src/main/java/com/newyetai/usercenter/tag/dao/TagRelationshipMapper.java b/src/main/java/com/newyetai/usercenter/tag/dao/TagRelationshipMapper.java new file mode 100644 index 0000000..2cffdef --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/tag/dao/TagRelationshipMapper.java @@ -0,0 +1,31 @@ +package com.newyetai.usercenter.tag.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.newyetai.usercenter.tag.dto.HrOperatingPostDTO; +import com.newyetai.usercenter.tag.dto.TagRelationshipInfoDTO; +import com.newyetai.usercenter.tag.dto.TagRelationshipMapQueryDTO; +import com.newyetai.usercenter.tag.dto.TagRelationshipQueryDTO; +import com.newyetai.usercenter.tag.entity.TagRelationship; + +import java.util.List; +import java.util.Set; + +/** + *

+ * Mapper 接口 + *

+ * + * @author Carlye + * @since 2021-01-21 + */ +public interface TagRelationshipMapper extends BaseMapper { + + HrOperatingPostDTO findById(Long id); + + int updatePost(HrOperatingPostDTO postDTO); + + List sourceIdMap(TagRelationshipMapQueryDTO queryDTO); + + Set sourceIds(TagRelationshipQueryDTO queryDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/tag/dto/HrOperatingPostDTO.java b/src/main/java/com/newyetai/usercenter/tag/dto/HrOperatingPostDTO.java new file mode 100644 index 0000000..fba844d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/tag/dto/HrOperatingPostDTO.java @@ -0,0 +1,102 @@ +package com.newyetai.usercenter.tag.dto; + +import com.newyetai.common.entity.BaseEntity; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.math.BigDecimal; + +/** + *

+ * 招聘系统-岗位信息表 + *

+ * + * @author chenyun + * @since 2021-01-08 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@NoArgsConstructor +@AllArgsConstructor +public class HrOperatingPostDTO extends BaseEntity { + + private static final long serialVersionUID = -6380138352828899597L; + /** + * 机构ID + */ + private Long orgId; + + /** + * 公司ID (hr_company) + */ + private Long companyId; + + /** + * 岗位名称 + */ + private String postName; + + /** + * 岗位所在地 + */ + private String postLocation; + + /** + * 岗位薪酬福利单位 1:CNY + */ + private Integer postSalaryUnit; + + /** + * 岗位薪酬福利下限 + */ + private BigDecimal postSalaryLow; + + /** + * 岗位薪酬福利上限 + */ + private BigDecimal postSalaryUp; + + /** + * 岗位薪酬福利类型 1:日薪 2:月薪 3:年薪 99:面议 + */ + private Integer postSalaryType; + + /** + * 岗位招聘人数 + */ + private Integer postNumber; + + /** + * 岗位福利待遇 + */ + private String postBeneft; + + /** + * 岗位描述 + */ + private String postDescription; + + /** + * 岗位要求 + */ + private String postRequire; + + /** + * 状态 + */ + private Integer status; + + /** + * 关联岗位Id集合 + */ + private String affiliationPosts; + + /** + * 关联标签集合 + */ + private String affiliationTags; +} diff --git a/src/main/java/com/newyetai/usercenter/tag/dto/TagBatchCreateDTO.java b/src/main/java/com/newyetai/usercenter/tag/dto/TagBatchCreateDTO.java new file mode 100644 index 0000000..ce2d90f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/tag/dto/TagBatchCreateDTO.java @@ -0,0 +1,44 @@ +package com.newyetai.usercenter.tag.dto; + +import com.newyetai.common.entity.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +/** + *

+ * 标签表 + *

+ * + * @author Carlye + * @since 2021-01-21 + */ +@ApiModel("标签批量创建信息DTO") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +public class TagBatchCreateDTO extends BaseEntity { + private static final long serialVersionUID = 5250371091927498053L; + @ApiModelProperty("标签名称集合") + private String tagNames; + + @ApiModelProperty("标签业务分类 1:岗位福利待遇") + @NotNull(message = "标签类型不能为空") + private Integer tagType; + + @ApiModelProperty("关联到哪个表 1:hr_operating_post") + @NotNull(message = "关联表不能为空") + private Integer sourceType; + + @ApiModelProperty("关联ID") + @NotNull(message = "关联id不能为空") + private Long sourceId; + +} diff --git a/src/main/java/com/newyetai/usercenter/tag/dto/TagCreateDTO.java b/src/main/java/com/newyetai/usercenter/tag/dto/TagCreateDTO.java new file mode 100644 index 0000000..8a7a62a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/tag/dto/TagCreateDTO.java @@ -0,0 +1,43 @@ +package com.newyetai.usercenter.tag.dto; + +import com.newyetai.common.entity.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +/** + *

+ * 标签表 + *

+ * + * @author Carlye + * @since 2021-01-21 + */ +@ApiModel("标签信息创建DTO") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +public class TagCreateDTO extends BaseEntity { + private static final long serialVersionUID = 5250371091927498053L; + @ApiModelProperty("标签名称") + @NotEmpty(message = "标签名称不能为空") + private String tagName; + + @ApiModelProperty("标签业务分类 1:岗位福利待遇") + @NotNull(message = "标签类型不能为空") + private Integer tagType; + + @ApiModelProperty("关联到哪个表 1:hr_operating_post") + private Integer sourceType; + + @ApiModelProperty("关联ID") + private Long sourceId; + +} diff --git a/src/main/java/com/newyetai/usercenter/tag/dto/TagDTO.java b/src/main/java/com/newyetai/usercenter/tag/dto/TagDTO.java new file mode 100644 index 0000000..f122c89 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/tag/dto/TagDTO.java @@ -0,0 +1,37 @@ +package com.newyetai.usercenter.tag.dto; + +import com.newyetai.common.entity.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +/** + *

+ * 标签表 + *

+ * + * @author Carlye + * @since 2021-01-21 + */ +@ApiModel("标签信息DTO") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +public class TagDTO extends BaseEntity { + private static final long serialVersionUID = 5250371091927498053L; + @ApiModelProperty("标签名称") + @NotEmpty(message = "标签名称不能为空") + private String tagName; + + @ApiModelProperty("标签业务分类 1:岗位福利待遇") + @NotNull(message = "标签类型不能为空") + private Integer tagType; + +} diff --git a/src/main/java/com/newyetai/usercenter/tag/dto/TagPageQueryDTO.java b/src/main/java/com/newyetai/usercenter/tag/dto/TagPageQueryDTO.java new file mode 100644 index 0000000..54addfb --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/tag/dto/TagPageQueryDTO.java @@ -0,0 +1,33 @@ +package com.newyetai.usercenter.tag.dto; + +import com.newyetai.common.dto.PageQueryDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +/** + *

+ * 标签表 + *

+ * + * @author Carlye + * @since 2021-01-21 + */ +@ApiModel("标签查询DTO") +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +public class TagPageQueryDTO extends PageQueryDTO { + private static final long serialVersionUID = 5250371091927498053L; + @ApiModelProperty("标签名称") + private String tagName; + + @ApiModelProperty("标签业务分类 1-岗位福利待遇 2-技能") + private Integer tagType; +} diff --git a/src/main/java/com/newyetai/usercenter/tag/dto/TagRelationshipDTO.java b/src/main/java/com/newyetai/usercenter/tag/dto/TagRelationshipDTO.java new file mode 100644 index 0000000..37efeee --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/tag/dto/TagRelationshipDTO.java @@ -0,0 +1,42 @@ +package com.newyetai.usercenter.tag.dto; + +import com.newyetai.common.entity.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotNull; + +/** + *

+ * + *

+ * + * @author Carlye + * @since 2021-01-21 + */ +@ApiModel("标签关系信息DTO") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +public class TagRelationshipDTO extends BaseEntity { + + + private static final long serialVersionUID = -519594241373286878L; + + @ApiModelProperty("标签ID") + @NotNull(message = "标签ID不能为空") + private Long tagId; + + @ApiModelProperty("关联到哪个表 1:hr_operating_post") + @NotNull(message = "关联类型不能为空") + private Integer sourceType; + + @ApiModelProperty("关联ID") + @NotNull(message = "关联ID不能为空") + private Long sourceId; +} diff --git a/src/main/java/com/newyetai/usercenter/tag/dto/TagRelationshipInfoDTO.java b/src/main/java/com/newyetai/usercenter/tag/dto/TagRelationshipInfoDTO.java new file mode 100644 index 0000000..9991d4b --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/tag/dto/TagRelationshipInfoDTO.java @@ -0,0 +1,36 @@ +package com.newyetai.usercenter.tag.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @author Carlye + * @since 2021-01-21 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class TagRelationshipInfoDTO implements Serializable { + + private static final long serialVersionUID = 3725333598124945060L; + + private Long id; + + @ApiModelProperty("标签ID") + private String tagName; + + @ApiModelProperty("关联ID") + private Long sourceId; +} diff --git a/src/main/java/com/newyetai/usercenter/tag/dto/TagRelationshipMapQueryDTO.java b/src/main/java/com/newyetai/usercenter/tag/dto/TagRelationshipMapQueryDTO.java new file mode 100644 index 0000000..1bbce4a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/tag/dto/TagRelationshipMapQueryDTO.java @@ -0,0 +1,39 @@ +package com.newyetai.usercenter.tag.dto; + +import com.newyetai.common.entity.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotNull; +import java.util.Set; + +/** + *

+ * + *

+ * + * @author Carlye + * @since 2021-01-21 + */ +@ApiModel("标签关系信息DTO") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +public class TagRelationshipMapQueryDTO extends BaseEntity { + + + private static final long serialVersionUID = -519594241373286878L; + + @ApiModelProperty("关联到哪个表 1:hr_operating_post") + @NotNull(message = "关联类型不能为空") + private Integer sourceType; + + @ApiModelProperty("关联ID") + @NotNull(message = "关联ID不能为空") + private Set sourceIds; +} diff --git a/src/main/java/com/newyetai/usercenter/tag/dto/TagRelationshipQueryDTO.java b/src/main/java/com/newyetai/usercenter/tag/dto/TagRelationshipQueryDTO.java new file mode 100644 index 0000000..81742b5 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/tag/dto/TagRelationshipQueryDTO.java @@ -0,0 +1,38 @@ +package com.newyetai.usercenter.tag.dto; + +import com.newyetai.common.entity.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotNull; +import java.util.Set; + +/** + *

+ * + *

+ * + * @author Carlye + * @since 2021-01-21 + */ +@ApiModel("标签关系信息DTO") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +public class TagRelationshipQueryDTO extends BaseEntity { + + + private static final long serialVersionUID = -519594241373286878L; + + @ApiModelProperty("关联到哪个表 1:hr_operating_post") + @NotNull(message = "关联类型不能为空") + private Integer sourceType; + + @ApiModelProperty("标签名") + private Set tagNames; +} diff --git a/src/main/java/com/newyetai/usercenter/tag/dto/TagUpdateDTO.java b/src/main/java/com/newyetai/usercenter/tag/dto/TagUpdateDTO.java new file mode 100644 index 0000000..1c5c754 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/tag/dto/TagUpdateDTO.java @@ -0,0 +1,31 @@ +package com.newyetai.usercenter.tag.dto; + +import com.newyetai.common.entity.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotEmpty; + +/** + *

+ * 标签表 + *

+ * + * @author Carlye + * @since 2021-01-21 + */ +@ApiModel("标签信息修改DTO") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +public class TagUpdateDTO extends BaseEntity { + private static final long serialVersionUID = 5250371091927498053L; + @ApiModelProperty("标签名称") + @NotEmpty(message = "标签名称不能为空") + private String tagName; +} diff --git a/src/main/java/com/newyetai/usercenter/tag/entity/Tag.java b/src/main/java/com/newyetai/usercenter/tag/entity/Tag.java new file mode 100644 index 0000000..0298e6b --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/tag/entity/Tag.java @@ -0,0 +1,37 @@ +package com.newyetai.usercenter.tag.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; +import lombok.*; +import lombok.experimental.Accessors; + +/** + *

+ * 标签表 + *

+ * + * @author Carlye + * @since 2021-01-21 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@TableName("xs_tag") +public class Tag extends BaseEntity { + +private static final long serialVersionUID=1L; + + /** + * 标签名称 + */ + private String tagName; + + /** + * 标签业务分类 1:岗位福利待遇 2:技能标签 + */ + private Integer tagType; + +} diff --git a/src/main/java/com/newyetai/usercenter/tag/entity/TagRelationship.java b/src/main/java/com/newyetai/usercenter/tag/entity/TagRelationship.java new file mode 100644 index 0000000..55bf7b1 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/tag/entity/TagRelationship.java @@ -0,0 +1,41 @@ +package com.newyetai.usercenter.tag.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; +import lombok.*; +import lombok.experimental.Accessors; + +/** + *

+ * + *

+ * + * @author Carlye + * @since 2021-01-21 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@TableName("xs_tag_relationship") +public class TagRelationship extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * 标签表ID + */ + private Long tagId; + + /** + * 关联到哪个表 1:hr_operating_post + */ + private Integer sourceType; + + /** + * 关联ID + */ + private Long sourceId; +} diff --git a/src/main/java/com/newyetai/usercenter/tag/enums/SourceTypeEnum.java b/src/main/java/com/newyetai/usercenter/tag/enums/SourceTypeEnum.java new file mode 100644 index 0000000..ae60454 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/tag/enums/SourceTypeEnum.java @@ -0,0 +1,39 @@ +package com.newyetai.usercenter.tag.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.newyetai.mybatis.handle.BaseEnum; + + +/** + * 关联类型枚举 + * + * @author Carlye + * @date 2021/01/21 + */ +public enum SourceTypeEnum implements BaseEnum { + POST(1, "关联岗位"), + WORKSTATION(3,"关联零工驿站"); + + @EnumValue + private final Integer sourceType; + + private final String desc; + + SourceTypeEnum(Integer sourceType, String desc) { + this.sourceType = sourceType; + this.desc = desc; + } + + public Integer getSourceType() { + return sourceType; + } + + public String getDesc() { + return desc; + } + + @Override + public Integer getValue() { + return sourceType; + } +} diff --git a/src/main/java/com/newyetai/usercenter/tag/enums/TagTypeEnum.java b/src/main/java/com/newyetai/usercenter/tag/enums/TagTypeEnum.java new file mode 100644 index 0000000..0233330 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/tag/enums/TagTypeEnum.java @@ -0,0 +1,39 @@ +package com.newyetai.usercenter.tag.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.newyetai.mybatis.handle.BaseEnum; + + +/** + * 标签类型枚举 + * + * @author Carlye + * @date 2021/01/21 + */ +public enum TagTypeEnum implements BaseEnum { + POST(1, "岗位福利标签"), + WORKSTATION(3,"零工驿站标签"); + + @EnumValue + private final Integer tagType; + + private final String desc; + + TagTypeEnum(Integer tagType, String desc) { + this.tagType = tagType; + this.desc = desc; + } + + public Integer getTagType() { + return tagType; + } + + public String getDesc() { + return desc; + } + + @Override + public Integer getValue() { + return tagType; + } +} diff --git a/src/main/java/com/newyetai/usercenter/tag/mapper/TagMapper.xml b/src/main/java/com/newyetai/usercenter/tag/mapper/TagMapper.xml new file mode 100644 index 0000000..54f6f90 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/tag/mapper/TagMapper.xml @@ -0,0 +1,17 @@ + + + + + + diff --git a/src/main/java/com/newyetai/usercenter/tag/mapper/TagRelationshipMapper.xml b/src/main/java/com/newyetai/usercenter/tag/mapper/TagRelationshipMapper.xml new file mode 100644 index 0000000..40d7cb1 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/tag/mapper/TagRelationshipMapper.xml @@ -0,0 +1,56 @@ + + + + + update hr_operating_post + set update_time = now(), + update_by = 1, + affiliation_tags = #{affiliationTags} + where deleted = 0 + and id = #{id} + + + + + + diff --git a/src/main/java/com/newyetai/usercenter/tag/mapstruct/TagMapMapper.java b/src/main/java/com/newyetai/usercenter/tag/mapstruct/TagMapMapper.java new file mode 100644 index 0000000..e999e8c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/tag/mapstruct/TagMapMapper.java @@ -0,0 +1,30 @@ +package com.newyetai.usercenter.tag.mapstruct; + +import com.newyetai.usercenter.tag.dto.TagCreateDTO; +import com.newyetai.usercenter.tag.dto.TagDTO; +import com.newyetai.usercenter.tag.dto.TagRelationshipDTO; +import com.newyetai.usercenter.tag.entity.Tag; +import com.newyetai.usercenter.tag.entity.TagRelationship; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * @author sr on 2020-08-27 + */ +@Mapper +public interface TagMapMapper { + + TagMapMapper instance = Mappers.getMapper(TagMapMapper.class); + + + Tag exchange(TagDTO tagDTO); + + Tag exchange(TagCreateDTO tagDTO); + + TagDTO exchange(Tag tag); + + TagRelationship exchange(TagRelationshipDTO tagRelationshipDTO); + + TagRelationshipDTO exchange(TagRelationship tagRelationship); + +} diff --git a/src/main/java/com/newyetai/usercenter/tag/service/ITagRelationshipService.java b/src/main/java/com/newyetai/usercenter/tag/service/ITagRelationshipService.java new file mode 100644 index 0000000..798815d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/tag/service/ITagRelationshipService.java @@ -0,0 +1,60 @@ +package com.newyetai.usercenter.tag.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.newyetai.usercenter.tag.dto.TagBatchCreateDTO; +import com.newyetai.usercenter.tag.dto.TagRelationshipDTO; +import com.newyetai.usercenter.tag.dto.TagRelationshipMapQueryDTO; +import com.newyetai.usercenter.tag.dto.TagRelationshipQueryDTO; +import com.newyetai.usercenter.tag.entity.TagRelationship; +import org.springframework.validation.annotation.Validated; + +import javax.validation.Valid; +import javax.validation.groups.Default; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + *

+ * 服务类 + *

+ * + * @author Carlye + * @since 2021-01-21 + */ +@Validated(Default.class) +public interface ITagRelationshipService extends IService { + + + /** + * 创建标签关联关系 + * + * @param tagRelationshipDTO 标签dto的关系 + * @return {@link TagRelationshipDTO} + * @throws RuntimeException 运行时异常 + */ + TagRelationshipDTO create(@Valid TagRelationshipDTO tagRelationshipDTO) throws RuntimeException; + + + /** + * 删除标签关联关系 + * + */ + void deleted(TagBatchCreateDTO createDTO); + + /** + * 源id映射 + * + * @param queryDTO 查询dto + * @return {@link Map}<{@link Long}, {@link List}<{@link String}>> + */ + Map> sourceIdMap(TagRelationshipMapQueryDTO queryDTO); + + /** + * 查询资源ID集合 + * + * @param queryDTO 查询dto + * @return {@link Set}<{@link Long}> + */ + Set sourceIds(TagRelationshipQueryDTO queryDTO); +} diff --git a/src/main/java/com/newyetai/usercenter/tag/service/ITagService.java b/src/main/java/com/newyetai/usercenter/tag/service/ITagService.java new file mode 100644 index 0000000..a2b4d3c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/tag/service/ITagService.java @@ -0,0 +1,57 @@ +package com.newyetai.usercenter.tag.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.newyetai.usercenter.tag.dto.*; +import com.newyetai.usercenter.tag.entity.Tag; +import org.springframework.validation.annotation.Validated; + +import javax.validation.Valid; +import javax.validation.groups.Default; +import java.util.List; + +/** + *

+ * 标签表 服务类 + *

+ * + * @author Carlye + * @since 2021-01-21 + */ +@Validated(Default.class) +public interface ITagService extends IService { + + + /** + * 新建标签 + * + * @param tagDTO 标签dto + * @return {@link TagDTO} + */ + TagDTO create(@Valid TagCreateDTO tagDTO) throws RuntimeException; + + /** + * 批量创建 + * + * @param createDTO 创建dto + * @return {@link List} + * @throws RuntimeException 运行时异常 + */ + List batchCreate(@Valid TagBatchCreateDTO createDTO) throws RuntimeException; + + /** + * 分页查询 + * + * @param queryDTO 查询dto + * @return {@link List} + */ + List page(TagPageQueryDTO queryDTO); + + /** + * 更新 + * + * @param updateDTO 更新dto + * @return {@link TagDTO} + */ + void update(TagUpdateDTO updateDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/tag/service/impl/ITagRelationshipServiceImpl.java b/src/main/java/com/newyetai/usercenter/tag/service/impl/ITagRelationshipServiceImpl.java new file mode 100644 index 0000000..6b6d70c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/tag/service/impl/ITagRelationshipServiceImpl.java @@ -0,0 +1,96 @@ +package com.newyetai.usercenter.tag.service.impl; + +import cn.hutool.core.collection.CollUtil; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.newyetai.usercenter.tag.dao.TagRelationshipMapper; +import com.newyetai.usercenter.tag.dto.*; +import com.newyetai.usercenter.tag.entity.TagRelationship; +import com.newyetai.usercenter.tag.mapstruct.TagMapMapper; +import com.newyetai.usercenter.tag.service.ITagRelationshipService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.validation.Valid; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collector; +import java.util.stream.Collectors; + + +/** + *

+ * 服务实现类 + *

+ * + * @author Carlye + * @since 2021-01-21 + */ +@Slf4j +@Service +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class ITagRelationshipServiceImpl extends ServiceImpl implements ITagRelationshipService { + + @Override + @Transactional + public TagRelationshipDTO create(@Valid TagRelationshipDTO tagRelationshipDTO) throws RuntimeException { + TagRelationship exchange = TagMapMapper.instance.exchange(tagRelationshipDTO); + TagRelationship one = getOne(Wrappers.lambdaQuery() + .eq(TagRelationship::getTagId, tagRelationshipDTO.getTagId()) + .eq(TagRelationship::getSourceId, tagRelationshipDTO.getSourceId()) + .eq(TagRelationship::getSourceType, tagRelationshipDTO.getSourceType()) + ); + if (Objects.nonNull(one) && one.getDeleted()) { + update(Wrappers.lambdaUpdate().set(TagRelationship::getDeleted, Boolean.FALSE).eq(TagRelationship::getId, one.getId())); + return TagMapMapper.instance.exchange(one); + } + save(exchange); +// if (save(exchange) && tagRelationshipsDTO.getSourceType().equals(SourceTypeEnum.POST.getSourceType())) { +// //需要同步更新岗位表信息 +// HrOperatingPostDTO postDTO = getBaseMapper().findById(tagRelationshipsDTO.getSourceId()); +// String affiliationTags; +// Tag tag; +// if (Objects.nonNull(postDTO) && Objects.nonNull(tag = tagService.getById(tagRelationshipsDTO)) +// && StringUtils.isNotEmpty(affiliationTags = postDTO.getAffiliationTags()) +// && !affiliationTags.contains(tag.getTagName())) { +// affiliationTags = String.join(",", affiliationTags, tag.getTagName()); +// postDTO.setAffiliationTags(affiliationTags); +// getBaseMapper().updatePost(postDTO); +// } +// } + return TagMapMapper.instance.exchange(exchange); + } + + @Override + public void deleted(TagBatchCreateDTO createDTO) { + update(Wrappers.lambdaUpdate().set(TagRelationship::getDeleted, Boolean.TRUE) + .eq(TagRelationship::getSourceType, createDTO.getSourceType()) + .eq(TagRelationship::getSourceId, createDTO.getSourceId()) + ); + } + + @Override + public Map> sourceIdMap(TagRelationshipMapQueryDTO queryDTO) { + List relationshipInfoDTOS = getBaseMapper().sourceIdMap(queryDTO); + if (CollUtil.isEmpty(relationshipInfoDTOS)) { + return Maps.newHashMap(); + } + return relationshipInfoDTOS.stream().collect(Collectors.groupingBy(TagRelationshipInfoDTO::getSourceId, Collector.of(Lists::newArrayList, List::add, + (left, right) -> { + left.addAll(right); + return left; + }, (List list) -> list.stream().sorted((v1, v2) -> v2.getId().compareTo(v1.getId())).map(TagRelationshipInfoDTO::getTagName).collect(Collectors.toList())))); + } + + @Override + public Set sourceIds(TagRelationshipQueryDTO queryDTO) { + return getBaseMapper().sourceIds(queryDTO); + } +} diff --git a/src/main/java/com/newyetai/usercenter/tag/service/impl/ITagServiceImpl.java b/src/main/java/com/newyetai/usercenter/tag/service/impl/ITagServiceImpl.java new file mode 100644 index 0000000..988c488 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/tag/service/impl/ITagServiceImpl.java @@ -0,0 +1,134 @@ +package com.newyetai.usercenter.tag.service.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import javax.validation.Valid; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.usercenter.tag.dao.TagMapper; +import com.newyetai.usercenter.tag.dto.TagBatchCreateDTO; +import com.newyetai.usercenter.tag.dto.TagCreateDTO; +import com.newyetai.usercenter.tag.dto.TagDTO; +import com.newyetai.usercenter.tag.dto.TagPageQueryDTO; +import com.newyetai.usercenter.tag.dto.TagRelationshipDTO; +import com.newyetai.usercenter.tag.dto.TagUpdateDTO; +import com.newyetai.usercenter.tag.entity.Tag; +import com.newyetai.usercenter.tag.mapstruct.TagMapMapper; +import com.newyetai.usercenter.tag.service.ITagRelationshipService; +import com.newyetai.usercenter.tag.service.ITagService; + +import cn.hutool.core.date.DateUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + + +/** + *

+ * 标签表 服务实现类 + *

+ * + * @author Carlye + * @since 2021-01-21 + */ +@Slf4j +@Service +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class ITagServiceImpl extends ServiceImpl implements ITagService { + + private final ITagRelationshipService tagRelationshipsService; + + @Override + @Transactional + public TagDTO create(@Valid TagCreateDTO tagDTO) { + //查询历史是否存在相同标签 + List tags = list(Wrappers.lambdaQuery() + .eq(Tag::getTagType, tagDTO.getTagType()) + .eq(Tag::getTagName, tagDTO.getTagName())); + if (CollectionUtils.isNotEmpty(tags)) { + Tag tag = tags.get(0); + if (tag.getDeleted()) { + //更新已经删除的标签未 + update(Wrappers.lambdaUpdate().set(Tag::getDeleted, Boolean.FALSE).eq(Tag::getId, tag.getId())); + tag.setDeleted(Boolean.FALSE); + } + if (Objects.nonNull(tagDTO.getSourceType()) && Objects.nonNull(tagDTO.getSourceId())) { + //创建标签关系 + tagRelationshipsService.create(TagRelationshipDTO.builder().tagId(tag.getId()).sourceType(tagDTO.getSourceType()).sourceId(tagDTO.getSourceId()).build()); + } + return TagMapMapper.instance.exchange(tag); + } + //新增标签 + Tag exchange = TagMapMapper.instance.exchange(tagDTO); + save(exchange); + if (Objects.nonNull(tagDTO.getSourceType()) && Objects.nonNull(tagDTO.getSourceId())) { + //创建标签关系 + tagRelationshipsService.create(TagRelationshipDTO.builder().tagId(exchange.getId()).sourceType(tagDTO.getSourceType()).sourceId(tagDTO.getSourceId()).build()); + } + return TagMapMapper.instance.exchange(exchange); + } + + @Override + @Transactional + public List batchCreate(@Valid TagBatchCreateDTO createDTO) throws RuntimeException { + // 先删除关联关系 + tagRelationshipsService.deleted(createDTO); + // 后创建关联关系 + String tagNames = createDTO.getTagNames(); + if(StringUtils.isBlank(tagNames)){ + return new ArrayList<>(); + } + return Arrays.stream(tagNames.split(",")) + .map(tagName -> + ((ITagServiceImpl) AopContext.currentProxy()).create( + TagCreateDTO.builder() + .tagType(createDTO.getTagType()) + .tagName(tagName) + .sourceType(createDTO.getSourceType()) + .sourceId(createDTO.getSourceId()) + .build()) + ).collect(Collectors.toList()); + } + + @Override + public List page(TagPageQueryDTO queryDTO) { + return getBaseMapper().page(queryDTO); + } + + @Override + public void update(TagUpdateDTO updateDTO) { + Tag tag = getOne(Wrappers.lambdaQuery() + .eq(Tag::getDeleted, false) + .eq(Tag::getId, updateDTO.getId()) + ); + if (Objects.nonNull(tag)){ + if (Boolean.TRUE.equals(updateDTO.getDeleted())){ + update(Wrappers.lambdaUpdate() + .set(Tag::getDeleted,true) + .set(Tag::getUpdateBy, UserContextHolder.getExistLoginUserId()) + .set(Tag::getUpdateTime, DateUtil.now()) + .eq(Tag::getId,updateDTO.getId()) + ); + }else if (!StringUtils.equals(tag.getTagName(),updateDTO.getTagName())){ + update(Wrappers.lambdaUpdate() + .set(Tag::getTagName,updateDTO.getTagName()) + .set(Tag::getUpdateBy, UserContextHolder.getExistLoginUserId()) + .set(Tag::getUpdateTime, DateUtil.now()) + .eq(Tag::getId,updateDTO.getId()) + ); + } + } + } +} diff --git a/src/main/java/com/newyetai/usercenter/user/constant/UserBizAuthStatusEnum.java b/src/main/java/com/newyetai/usercenter/user/constant/UserBizAuthStatusEnum.java new file mode 100644 index 0000000..c490665 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/constant/UserBizAuthStatusEnum.java @@ -0,0 +1,21 @@ +package com.newyetai.usercenter.user.constant; + +/** + * 用户类型 + * @author czy on 2021-06-10 + */ +public enum UserBizAuthStatusEnum { + + PASS(1), NOT_PASS(2); + + private Integer type; + + UserBizAuthStatusEnum(Integer type) { + this.type = type; + } + + public Integer getType() { + return type; + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/constant/UserCancelConstants.java b/src/main/java/com/newyetai/usercenter/user/constant/UserCancelConstants.java new file mode 100644 index 0000000..f931689 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/constant/UserCancelConstants.java @@ -0,0 +1,17 @@ +package com.newyetai.usercenter.user.constant; + + +/** + * 用户取消常量 + * + * @author cheny + * @date 2023/03/07 + */ +public interface UserCancelConstants { + + /** + * 申请状态 1:已申请 2:已注销 + */ + Integer USER_CANCEL_STATUS_APPLY = 1; + Integer USER_CANCEL_STATUS_SUCCESS = 2; +} diff --git a/src/main/java/com/newyetai/usercenter/user/constant/UserConfigConstants.java b/src/main/java/com/newyetai/usercenter/user/constant/UserConfigConstants.java new file mode 100644 index 0000000..769014e --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/constant/UserConfigConstants.java @@ -0,0 +1,13 @@ +package com.newyetai.usercenter.user.constant; + +/** + * @author sr on 2021-08-12 + */ +public interface UserConfigConstants { + + /** 忽略初始密码 **/ + String IGNORE_INIT_PWD_CODE = "ignore_init_pwd"; + + + +} diff --git a/src/main/java/com/newyetai/usercenter/user/constant/UserIdentityPhotoConstants.java b/src/main/java/com/newyetai/usercenter/user/constant/UserIdentityPhotoConstants.java new file mode 100644 index 0000000..eec3503 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/constant/UserIdentityPhotoConstants.java @@ -0,0 +1,12 @@ +package com.newyetai.usercenter.user.constant; + +/** + * @author sr on 2021-05-24 + */ +public interface UserIdentityPhotoConstants { + + /**身份证图片认证状态 1.未认证 3.认证成功**/ + public static final Integer PHOTO_STATUS_NOT_AUTH = 1; + public static final Integer PHOTO_STATUS_SUCCESS = 3; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/constant/UserSourceEnum.java b/src/main/java/com/newyetai/usercenter/user/constant/UserSourceEnum.java new file mode 100644 index 0000000..fbbf929 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/constant/UserSourceEnum.java @@ -0,0 +1,30 @@ +package com.newyetai.usercenter.user.constant; + +/** + * 个人用户来源 + * @author fzp on 2022年3月8日14:55:13 + */ +public enum UserSourceEnum { + // ALITA_RECRUIT 13 = 1 + APPLET(1,"招聘微信小程序"), + // ALITA_TASK 1 = 2 + FLEXIBLE(2,"灵活就业微信小程序"), + FLEXIBLE_IMPORT(3,"灵活就业页面导入"); + + private Integer status; + private String name; + + UserSourceEnum(Integer status,String name) { + this.status = status; + this.name = name; + } + + public Integer getStatus() { + return status; + } + public String getName() { + return name; + } + + +} diff --git a/src/main/java/com/newyetai/usercenter/user/constant/UserStatusEnum.java b/src/main/java/com/newyetai/usercenter/user/constant/UserStatusEnum.java new file mode 100644 index 0000000..497a6ff --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/constant/UserStatusEnum.java @@ -0,0 +1,27 @@ +package com.newyetai.usercenter.user.constant; + +/** + * 用户类型 + * @author sr on 2021-05-31 + */ +public enum UserStatusEnum { + + /** 1待激活 **/ + INIT(1), + /** 2已激活 **/ + ACTIVE(2), + /** 3已注销 **/ + CLOSED(3); + + private Integer status; + + UserStatusEnum(Integer status) { + this.status = status; + } + + public Integer getStatus() { + return status; + } + + +} diff --git a/src/main/java/com/newyetai/usercenter/user/constant/UserTypeEnum.java b/src/main/java/com/newyetai/usercenter/user/constant/UserTypeEnum.java new file mode 100644 index 0000000..676bbb9 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/constant/UserTypeEnum.java @@ -0,0 +1,47 @@ +package com.newyetai.usercenter.user.constant; + +import java.util.Map; + +import com.google.common.collect.Maps; +import com.newyetai.common.exception.util.Assert; + +/** + * 用户类型 + * @author sr on 2021-05-31 + */ +public enum UserTypeEnum { + + /** 机构 **/ + ORG(1), + /** 个人 **/ + PERSON(2), + /** api机构用户 **/ + API_ORG(3); + + private static Map userTypeMap; + + static { + UserTypeEnum[] userTypeEnums = UserTypeEnum.values(); + userTypeMap = Maps.newHashMapWithExpectedSize(userTypeEnums.length); + for (UserTypeEnum userTypeEnum : userTypeEnums) { + userTypeMap.put(userTypeEnum.getType(), userTypeEnum); + } + } + + private Integer type; + + UserTypeEnum(Integer type) { + this.type = type; + } + + public Integer getType() { + return type; + } + + public static UserTypeEnum one(Integer userType) { + UserTypeEnum userTypeEnum = userTypeMap.get(userType); + Assert.notNull(userTypeEnum, "用户类型异常"); + return userTypeEnum; + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/consumer/FourFactorVerifyStatusUpdateHandler.java b/src/main/java/com/newyetai/usercenter/user/consumer/FourFactorVerifyStatusUpdateHandler.java new file mode 100644 index 0000000..b8f344e --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/consumer/FourFactorVerifyStatusUpdateHandler.java @@ -0,0 +1,62 @@ +package com.newyetai.usercenter.user.consumer; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.newyetai.alitaforward.verification.dto.FourFactorVerificationDTO; +import com.newyetai.common.constant.AuthStatusEnum; +import com.newyetai.usercenter.user.dto.AuthenticateUserDTO; +import com.newyetai.usercenter.user.dto.UserBankAccountCreateReqDTO; +import com.newyetai.usercenter.user.service.UserBankAccountService; +import com.newyetai.usercenter.user.service.UserService; + +import cn.hutool.json.JSONUtil; +import lombok.extern.slf4j.Slf4j; + +/** + * @author czy + * @date 2021-07-01 + */ + +@Slf4j +@Component("fourFactorVerifyStatusUpdateHandler") +public class FourFactorVerifyStatusUpdateHandler { + + + @Autowired + private UserService userService; + + @Autowired + private UserBankAccountService userBankAccountService; + + public void onMessage(FourFactorVerificationDTO fourVerification) { + try { +// log.info("【MQ】四要素认证流程结束,回写用户信息,参数:{}", JSONUtil.toJsonStr(fourVerification)); + if (fourVerification == null) { + return; + } + // 四要素校验通过 + if (!AuthStatusEnum.AUTH_SUCCESS.getType().equals(fourVerification.getStatus())) { + return; + } + AuthenticateUserDTO authenticateUserDTO = AuthenticateUserDTO.builder() + .cardNo(fourVerification.getCardNo()) + .realName(fourVerification.getRealName()) + .build(); + Long userId = userService.createAndAuthenticatePersonUser(authenticateUserDTO); + //3.添加用户银行卡信息 + UserBankAccountCreateReqDTO accountCreateReqDTO = UserBankAccountCreateReqDTO.builder() + .userId(userId) + .cardNo(fourVerification.getCardNo()) + .accountName(fourVerification.getRealName()) + .accountNo(fourVerification.getBankAccountNo()) + .build(); + userBankAccountService.addBankAccount(accountCreateReqDTO); + } catch (Exception e) { + log.info("四要素认证流程结束,回写用户信息异常,", e); + } + + } + + +} diff --git a/src/main/java/com/newyetai/usercenter/user/consumer/PhoneThreeFactorVerifyStatusUpdateHandler.java b/src/main/java/com/newyetai/usercenter/user/consumer/PhoneThreeFactorVerifyStatusUpdateHandler.java new file mode 100644 index 0000000..6ad5ebd --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/consumer/PhoneThreeFactorVerifyStatusUpdateHandler.java @@ -0,0 +1,49 @@ +package com.newyetai.usercenter.user.consumer; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.newyetai.alitaforward.verification.dto.PhoneThreeFactorVerificationDTO; +import com.newyetai.alitaforward.verification.service.PhoneThreeFactorVerificationProvider; +import com.newyetai.common.constant.AuthStatusEnum; +import com.newyetai.mq.dto.TopicMqMessage; +import com.newyetai.usercenter.user.dto.AuthenticateUserDTO; +import com.newyetai.usercenter.user.service.UserService; + +import cn.hutool.json.JSONUtil; +import lombok.extern.slf4j.Slf4j; + +/** + * @author czy + * @date 2021-07-01 + */ + +@Slf4j +@Component("phoneThreeFactorVerifyStatusUpdateHandler") +public class PhoneThreeFactorVerifyStatusUpdateHandler { + + @Autowired + private UserService userService; + + public void onMessage(PhoneThreeFactorVerificationDTO threeVerification) { + // log.info("【MQ】手机三要素认证流程结束,回写用户信息,参数:{}", JSONUtil.toJsonStr(threeVerification)); + try { + if (threeVerification == null) { + return; + } + // 三要素校验通过 + if (!AuthStatusEnum.AUTH_SUCCESS.getType().equals(threeVerification.getStatus())) { + return; + } + AuthenticateUserDTO authenticateUserDTO = AuthenticateUserDTO.builder() + .cardNo(threeVerification.getCardNo()) + .realName(threeVerification.getRealName()) + .build(); + userService.createAndAuthenticatePersonUser(authenticateUserDTO); + } catch (Exception e) { + log.info("手机三要素认证流程结束,回写用户信息异常,", e); + } + + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/consumer/ThreeFactorVerifyStatusUpdateHandler.java b/src/main/java/com/newyetai/usercenter/user/consumer/ThreeFactorVerifyStatusUpdateHandler.java new file mode 100644 index 0000000..8ac65d8 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/consumer/ThreeFactorVerifyStatusUpdateHandler.java @@ -0,0 +1,64 @@ +package com.newyetai.usercenter.user.consumer; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.newyetai.alitaforward.verification.dto.ThreeFactorVerificationDTO; +import com.newyetai.alitaforward.verification.service.ThreeFactorVerificationProvider; +import com.newyetai.common.constant.AuthStatusEnum; +import com.newyetai.mq.dto.TopicMqMessage; +import com.newyetai.usercenter.user.dto.AuthenticateUserDTO; +import com.newyetai.usercenter.user.dto.UserBankAccountCreateReqDTO; +import com.newyetai.usercenter.user.service.UserBankAccountService; +import com.newyetai.usercenter.user.service.UserService; + +import cn.hutool.json.JSONUtil; +import lombok.extern.slf4j.Slf4j; + +/** + * @author czy + * @date 2021-07-01 + */ + +@Slf4j +@Component("threeFactorVerifyStatusUpdateHandler") +public class ThreeFactorVerifyStatusUpdateHandler { + + @Autowired + private UserService userService; + + @Autowired + private UserBankAccountService userBankAccountService; + + + public void onMessage(ThreeFactorVerificationDTO threeVerification) { + // log.info("【MQ】三要素认证流程结束,回写用户信息,参数:{}", JSONUtil.toJsonStr(threeVerification)); + try { + if (threeVerification == null) { + return; + } + // 三要素校验通过 + if (!AuthStatusEnum.AUTH_SUCCESS.getType().equals(threeVerification.getStatus())) { + return; + } + AuthenticateUserDTO authenticateUserDTO = AuthenticateUserDTO.builder() + .cardNo(threeVerification.getCardNo()) + .realName(threeVerification.getRealName()) + .build(); + Long userId = userService.createAndAuthenticatePersonUser(authenticateUserDTO); + //3.添加用户银行卡信息 + UserBankAccountCreateReqDTO accountCreateReqDTO = UserBankAccountCreateReqDTO.builder() + .userId(userId) + .accountName(threeVerification.getRealName()) + .accountNo(threeVerification.getBankAccountNo()) + .cardNo(threeVerification.getCardNo()) + .build(); + userBankAccountService.addBankAccount(accountCreateReqDTO); + } catch (Exception e) { + log.info("三要素认证流程结束,回写用户信息异常,", e); + } + + } + + +} diff --git a/src/main/java/com/newyetai/usercenter/user/controller/OrgUserController.java b/src/main/java/com/newyetai/usercenter/user/controller/OrgUserController.java new file mode 100644 index 0000000..385e868 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/controller/OrgUserController.java @@ -0,0 +1,57 @@ +package com.newyetai.usercenter.user.controller; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.common.validation.Create; +import com.newyetai.security.jwt.JwtTokenUtils; +import com.newyetai.usercenter.user.dto.OrgUserInfoDTO; +import com.newyetai.usercenter.user.dto.OrgUserInfoQueryDTO; +import com.newyetai.usercenter.user.dto.OrgUserOperateDTO; +import com.newyetai.usercenter.user.login.dto.OrgDetailDTO; +import com.newyetai.usercenter.user.service.OrgUserService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @author sr on 2021-05-24 + */ +@RestController +@RequestMapping("org_user") +@Api(tags = "机构用户表") +public class OrgUserController { + + @Autowired + private OrgUserService orgUserService; + + @PostMapping("/create") + @ApiOperation("创建") + public AlitaResult create( + @Validated(Create.class) @RequestBody OrgUserOperateDTO orgUserOperateDTO) { + return AlitaResult.success(orgUserService.create(orgUserOperateDTO)); + } + + @GetMapping("/list") + @ApiOperation("查询机构用户信息列表") + public AlitaResult> list(OrgUserInfoQueryDTO queryDTO) { + return AlitaResult.success(orgUserService.list(queryDTO)); + } + + @GetMapping("/list_login_org") + @ApiOperation("查询登录用户所有机构列表") + public AlitaResult> listLoginOrg() { + return AlitaResult.success(orgUserService.listLoginOrgByUser(UserContextHolder.getExistLoginUserId(), null)); + } + + @GetMapping("/change_login_org") + @ApiOperation("修改登录用户机构") + public AlitaResult changeLoginOrg(@RequestParam Long orgId) { + JwtTokenUtils.changeToken(UserContextHolder.getExistLoginUserId(), orgId); + return AlitaResult.success(); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/controller/UserAuthController.java b/src/main/java/com/newyetai/usercenter/user/controller/UserAuthController.java new file mode 100644 index 0000000..d584777 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/controller/UserAuthController.java @@ -0,0 +1,66 @@ +package com.newyetai.usercenter.user.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.validation.annotation.Validated; + +import com.newyetai.common.validation.Update; +import com.newyetai.common.AlitaResult; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.user.dto.UserAuthQueryDTO; +import com.newyetai.usercenter.user.service.UserAuthService; +import com.newyetai.usercenter.user.dto.UserAuthDTO; +import com.newyetai.usercenter.user.dto.UserAuthOperateDTO; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +/** + * @author sr on 2021-05-24 + */ +@RestController +@RequestMapping("user_auth") +@Api(tags = "用户授权中间表") +public class UserAuthController { + + @Autowired + private UserAuthService userAuthService; + + @PostMapping("/create") + @ApiOperation("创建") + public AlitaResult create( + @Validated @RequestBody UserAuthOperateDTO userAuthOperateDTO){ + return AlitaResult.success(userAuthService.create(userAuthOperateDTO)); + } + + @PutMapping("/modify") + @ApiOperation("修改") + public AlitaResult modify( + @Validated(Update.class) @RequestBody UserAuthOperateDTO userAuthOperateDTO){ + userAuthService.modify(userAuthOperateDTO); + return AlitaResult.success(true); + } + + @DeleteMapping("/remove/{id}") + @ApiOperation("删除") + public AlitaResult remove(@PathVariable Long id){ + userAuthService.remove(id); + return AlitaResult.success(true); + } + + @GetMapping("/page") + @ApiOperation("分页查询") + public AlitaResult> page(UserAuthQueryDTO userAuthQueryDTO){ + userAuthService.page(userAuthQueryDTO); + return AlitaResult.success(userAuthQueryDTO.getPageResult()); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/controller/UserBankAccountController.java b/src/main/java/com/newyetai/usercenter/user/controller/UserBankAccountController.java new file mode 100644 index 0000000..397059f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/controller/UserBankAccountController.java @@ -0,0 +1,69 @@ +package com.newyetai.usercenter.user.controller; + +import java.util.List; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.usercenter.user.dto.UserBankAccountDTO; +import com.newyetai.usercenter.user.dto.UserBankAccountModifyDTO; +import com.newyetai.usercenter.user.dto.UserBankAccountQueryDTO; +import com.newyetai.usercenter.user.service.UserBankAccountService; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +/** + *

+ * 用户银行卡表 前端控制器 + *

+ * + * @author Carlye + * @since 2021-06-25 + */ +@RestController +@RequestMapping("/user/bank_account") +@Api(tags = "用户银行卡") +public class UserBankAccountController { + + @Autowired + private UserBankAccountService userBankAccountService; + + @ApiOperation("获取指定证件号与账户号的映射") + @GetMapping("/card_no/map") + public AlitaResult> queryBankAccountMap(@RequestParam("cardNos") List cardNos){ + return AlitaResult.success(userBankAccountService.queryBankAccountMap(cardNos)); + } + + @ApiOperation("列表查询") + @GetMapping("/list") + public AlitaResult> list(UserBankAccountQueryDTO userBankAccountQueryDTO){ + userBankAccountQueryDTO.setUserId(UserContextHolder.getExistLoginUserId()); + return AlitaResult.success(userBankAccountService.list(userBankAccountQueryDTO)); + } + + @ApiOperation("修改") + @PutMapping + public AlitaResult modify(@Validated @RequestBody UserBankAccountModifyDTO userBankAccountModifyDTO) { + userBankAccountService.modify(userBankAccountModifyDTO); + return AlitaResult.success(); + } + + @GetMapping("/{id}") + @ApiOperation("查询单个") + public AlitaResult get(@PathVariable Long id){ + return AlitaResult.success(userBankAccountService.get(id)); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/controller/UserCancelController.java b/src/main/java/com/newyetai/usercenter/user/controller/UserCancelController.java new file mode 100644 index 0000000..840578c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/controller/UserCancelController.java @@ -0,0 +1,55 @@ +package com.newyetai.usercenter.user.controller; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.user.dto.UserCancelApplyReqDTO; +import com.newyetai.usercenter.user.dto.UserCancelDTO; +import com.newyetai.usercenter.user.dto.UserCancelPageQueryDTO; +import com.newyetai.usercenter.user.service.UserCancelService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 用户取消控制器 + * + * @author cheny + * @date 2023/03/07 + */ +@RestController +@Api(tags = "用户注销") +@RequestMapping("user/cancel") +public class UserCancelController { + + @Autowired + private UserCancelService userCancelService; + + @PostMapping("apply") + @ApiOperation("用户注销申请") + public AlitaResult apply(@RequestBody @Validated UserCancelApplyReqDTO applyDTO) { + return AlitaResult.success(userCancelService.apply(applyDTO)); + } + + @GetMapping() + @ApiOperation("查询用户注销状态") + public AlitaResult find() { + Long existLoginUserId = UserContextHolder.getExistLoginUserId(); + return AlitaResult.success(userCancelService.find(UserCancelPageQueryDTO.builder().userId(existLoginUserId).build())); + } + + @PostMapping("agree/{userId}") + @ApiOperation("同意注销") + public AlitaResult agreeCancel(@PathVariable("userId") Long userId) { + return AlitaResult.success(userCancelService.agreeCancel(userId)); + } + + @GetMapping("page") + @ApiOperation("用户取消申请分页查询") + public AlitaResult> page(UserCancelPageQueryDTO queryDTO) { + userCancelService.page(queryDTO); + return AlitaResult.success(queryDTO.getPageResult()); + } +} diff --git a/src/main/java/com/newyetai/usercenter/user/controller/UserConfigController.java b/src/main/java/com/newyetai/usercenter/user/controller/UserConfigController.java new file mode 100644 index 0000000..8957cef --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/controller/UserConfigController.java @@ -0,0 +1,66 @@ +package com.newyetai.usercenter.user.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.user.dto.UserConfigDTO; +import com.newyetai.usercenter.user.dto.UserConfigOperateDTO; +import com.newyetai.usercenter.user.dto.UserConfigQueryDTO; +import com.newyetai.usercenter.user.service.UserConfigService; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +/** + * @author sr on 2021-08-12 + */ +@RestController +@RequestMapping("user_config") +@Api(tags = "用户配置") +public class UserConfigController { + + @Autowired + private UserConfigService userConfigService; + + @PostMapping("/create") + @ApiOperation("创建") + public AlitaResult create( + @Validated(Create.class) @RequestBody UserConfigOperateDTO userConfigOperateDTO){ + return AlitaResult.success(userConfigService.create(userConfigOperateDTO)); + } + + @PutMapping("/modify") + @ApiOperation("修改") + public AlitaResult modify( + @Validated(Update.class) @RequestBody UserConfigOperateDTO userConfigOperateDTO){ + userConfigService.modify(userConfigOperateDTO); + return AlitaResult.success(true); + } + + @DeleteMapping("/remove/{id}") + @ApiOperation("删除") + public AlitaResult remove(@PathVariable Long id){ + userConfigService.remove(id); + return AlitaResult.success(true); + } + + @GetMapping("/page") + @ApiOperation("分页查询") + public AlitaResult> page(UserConfigQueryDTO userConfigQueryDTO){ + userConfigService.list(userConfigQueryDTO); + return AlitaResult.success(userConfigQueryDTO.getPageResult()); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/controller/UserController.java b/src/main/java/com/newyetai/usercenter/user/controller/UserController.java new file mode 100644 index 0000000..774f50f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/controller/UserController.java @@ -0,0 +1,279 @@ +package com.newyetai.usercenter.user.controller; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.constant.SystemCodeEnum; +import com.newyetai.common.util.EnvironmentUtils; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.common.validation.Update; +import com.newyetai.security.dto.UserInfoDTO; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.dto.OrgUserEditDTO; +import com.newyetai.usercenter.dto.SuperResetPasswordDTO; +import com.newyetai.usercenter.user.constant.UserConfigConstants; +import com.newyetai.usercenter.user.dto.*; +import com.newyetai.usercenter.user.phone.constant.PhoneCodeProviderEnum; +import com.newyetai.usercenter.user.phone.dto.PhoneCodeSmsDTO; +import com.newyetai.usercenter.user.phone.util.PhoneCodeUtils; +import com.newyetai.usercenter.user.service.UserConfigService; +import com.newyetai.usercenter.user.service.UserService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Objects; +import java.util.Set; + +/** + * @author sr on 2021-05-24 + */ +@RestController +@Api(tags = "用户") +public class UserController { + + @Autowired + private UserService userService; + + @Autowired + private UserConfigService userConfigService; + + @PostMapping("user/modify") + @ApiOperation("编辑用户信息") + public AlitaResult modify( + @Validated(Update.class) @RequestBody UserOperateDTO userOperateDTO) { + userService.modify(userOperateDTO); + return AlitaResult.success(); + } + + @GetMapping("user/page") + @ApiOperation("分页查询") + public AlitaResult> page(UserQueryDTO userQueryDTO) { + userService.page(userQueryDTO); + return AlitaResult.success(userQueryDTO.getPageResult()); + } + + @GetMapping("user/list") + @ApiOperation("用户列表查询") + public AlitaResult> list(UserQueryDTO userQueryDTO) { + userQueryDTO.setNeedPage(false); + return AlitaResult.success(userService.list(userQueryDTO)); + } + + @GetMapping("user/get_by_id") + @ApiOperation("获取用户信息") + public AlitaResult getById(@RequestParam("userId") Long userId) { + return AlitaResult.success(userService.get(userId)); + } + + @GetMapping("user/find") + @ApiOperation("获取用户信息") + public AlitaResult find(UserQueryDTO userQueryDTO) { + return AlitaResult.success(userService.find(userQueryDTO)); + } + + @GetMapping("unac/user/get") + @ApiOperation("用户信息查询") + public AlitaResult get(@RequestParam(value = "userId",required = false) Long userId) { + userId = Objects.nonNull(userId) ? userId : UserContextHolder.getLoginUserId(); + return AlitaResult.success(userService.get(userId)); + } + + @GetMapping("anon/person_in_charge") + @ApiOperation("企业负责人查询") + public AlitaResult> personInCharge(@RequestParam("userIds") Set userIds) { + return AlitaResult.success(userService.personInCharge(userIds)); + } + + @PostMapping("user/create_person_user_by_card") + @ApiOperation("创建个人用户-证件") + public AlitaResult createPersonUser( + @Validated @RequestBody PersonUserCardCreateDTO personUserCardCreateDTO) { + return AlitaResult.success(userService.createPersonUser(personUserCardCreateDTO).getId()); + } + + @PostMapping("user/batch_create_person_user_by_card") + @ApiOperation("批量创建个人用户-证件") + public AlitaResult> createPersonUser( + @Validated @RequestBody List personUserCardCreateDTOs) { + return AlitaResult.success(userService.batchCreatePersonUser(personUserCardCreateDTOs)); + } + + @PostMapping("user/create_person_user_by_phone") + @ApiOperation("创建个人用户-手机号") + public AlitaResult createPersonUser( + @Validated @RequestBody PersonUserPhoneCreateDTO personUserPhoneCreateDTO) { + return AlitaResult.success(userService.modifyAndCreatePersonUser(personUserPhoneCreateDTO).getId()); + } + + + @PostMapping("user/create_org_user") + @ApiOperation("创建机构用户") + public AlitaResult createOrgUser(@Validated @RequestBody OrgUserCreateDTO orgUserCreateDTO) { + orgUserCreateDTO.setOrgId(UserContextHolder.getExistLoginOrgId()); + return AlitaResult.success(userService.createOrgUser(orgUserCreateDTO)); + } + + @PutMapping("user/modify_org_user") + @ApiOperation("修改机构用户") + public AlitaResult modifyOrgUser(@Validated @RequestBody OrgUserModifyDTO orgUserModifyDTO) { + //获取当前登录人的机构信息 + orgUserModifyDTO.setOrgId(UserContextHolder.getExistLoginOrgId()); + userService.modifyOrgUser(orgUserModifyDTO); + return AlitaResult.success(); + } + + @PostMapping("unac/user/init_user_password") + @ApiOperation("初始账号密码") + public AlitaResult initUserPassword( + @Validated @RequestBody InitUserPasswordDTO initUserPasswordDTO) { + userService.initUserPassword(initUserPasswordDTO); + return AlitaResult.success(); + } + + @PostMapping("unac/user/modify_username") + @ApiOperation("修改账号") + public AlitaResult modifyUsername(@RequestParam String username) { + userService.modifyUsername(username); + return AlitaResult.success(); + } + + @PostMapping("unac/user/modify_password") + @ApiOperation("修改密码") + public AlitaResult modifyPassword( + @Validated @RequestBody ModifyPasswordDTO modifyPasswordDTO) { + userService.modifyPassword(modifyPasswordDTO); + return AlitaResult.success(); + } + + @PostMapping("unac/user/bind_phone_sms/{phone}") + @ApiOperation("个人绑定手机号验证码") + public AlitaResult bindPhoneSms(@PathVariable String phone) { + PhoneCodeUtils.send(PhoneCodeSmsDTO.builder().providerType(PhoneCodeProviderEnum.PERSON_BIND_PHONE.getType()) + .phone(phone).build()); + return AlitaResult.success(); + } + + @PostMapping("unac/user/bind_phone") + @ApiOperation("(个人)绑定手机号") + public AlitaResult bindPhone(@Validated @RequestBody BindPhoneDTO bindPhoneDTO) { + userService.bindPersonPhone(bindPhoneDTO); + return AlitaResult.success(); + } + + @GetMapping("user/page/platform_user") + @ApiOperation("获取平台用户信息") + public AlitaResult> pagePlatformUser(PlatformUserInfoReqDTO reqDTO) { + userService.pagePlatformUser(reqDTO); + return AlitaResult.success(reqDTO.getPageResult()); + } + + @GetMapping("user/list/platform_user") + @ApiOperation("获取平台用户信息") + public AlitaResult> listPlatformUser(PlatformUserListQueryDTO reqDTO) { + return AlitaResult.success(userService.listPlatformUser(reqDTO)); + } + + @PostMapping("user/cancel") + @ApiOperation("注销用户信息") + public AlitaResult cancel(@RequestBody UserCancelReqDTO reqDTO) { + userService.userCancel(reqDTO); + return AlitaResult.success(); + } + + @PostMapping("anon/user/sms") + @ApiOperation("获取验证码-不同操作") + public AlitaResult sms(@Validated @RequestBody UserPhoneCodeSmsDTO userPhoneCodeSmsDTO) { + PhoneCodeUtils.send(userPhoneCodeSmsDTO); + return AlitaResult.success(); + } + + @ApiOperation("获取验证码-不同操作(带防水墙验证)") + @PostMapping("anon/user/sms_captcha") + public AlitaResult smsCaptcha( + @Validated @RequestBody UserPhoneCodeSmsCaptchaDTO userPhoneCodeSmsCaptchaDTO) { + PhoneCodeUtils.send(userPhoneCodeSmsCaptchaDTO); + return AlitaResult.success(); + } + + @PostMapping("anon/user/reset_pwd") + @ApiOperation("重置密码") + public AlitaResult resetPwd(@Validated @RequestBody ResetPwdDTO resetPwdDTO) { + userService.resetPwd(resetPwdDTO); + return AlitaResult.success(); + } + + @ApiOperation("获取当前登录人信息(机构用户)") + @GetMapping("anon/user/info") + public AlitaResult getLoginUserInfo() { + return AlitaResult.success(userService.findUserInfo(UserContextHolder.getLoginUserId(), + UserContextHolder.getLoginOrgId())); + } + + @PostMapping("unac/user/ignore_init_pwd") + @ApiOperation("忽略初始密码") + public AlitaResult ignoreInitPwd() { + userConfigService + .create(UserConfigOperateDTO.builder().userId(UserContextHolder.getExistLoginUserId()) + .configCode(UserConfigConstants.IGNORE_INIT_PWD_CODE) + .configValue(CommonConstants.CONFIG_TRUE).build()); + return AlitaResult.success(); + } + + @PostMapping("unac/user/reset_security_code") + @ApiOperation("重置安全码") + public AlitaResult resetSecurityCode(@Validated @RequestBody ResetSecurityCodeDTO resetSecurityCodeDTO) { + userService.resetSecurityCode(resetSecurityCodeDTO); + return AlitaResult.success(); + } + + + @PostMapping("user/check_security_code") + @ApiOperation("校验用户安全码信息") + public AlitaResult checkSecurityCode(@RequestBody CheckSecurityCodeReqDTO reqDTO) { + return AlitaResult.success(userService.checkSecurityCode(reqDTO)); + } + + @PostMapping("unac/user/change_phone") + @ApiOperation("换绑手机") + public AlitaResult changePhone(@Validated @RequestBody ChangePhoneDTO changePhoneDTO) { + userService.changePhone(changePhoneDTO); + return AlitaResult.success(); + } + + @ApiOperation("管理员修改企业用户信息") + @PostMapping("user/modify_org_user_info") + public AlitaResult modifyOrgUserInfo( + @RequestBody @Validated(Update.class) OrgUserEditDTO orgUserEditDTO) { + return AlitaResult.success(userService.modifyOrgUserInfo(orgUserEditDTO)); + } + + @ApiOperation("超级管理员重置企业用户密码") + @PostMapping("user/reset_org_user_pwd") + public AlitaResult resetOrgUserPassword(@Validated @RequestBody + SuperResetPasswordDTO resetPasswordDTO) { + return AlitaResult.success(userService.resetOrgUserPassword(resetPasswordDTO)); + } + + @PostMapping("user/exist_org_user") + @ApiOperation("验证机构用户是否存在") + public AlitaResult existOrgUser(@Validated @RequestBody OrgUserCreateDTO orgUserCreateDTO) { + return AlitaResult.success(userService.existOrgUser(orgUserCreateDTO)); + } + + @GetMapping("user/list_by_role") + @ApiOperation("通过角色信息查询用户列表") + public AlitaResult> listByRole(@Validated UserQueryByRoleDTO userQueryByRoleDTO) { + userQueryByRoleDTO.setOrgId(UserContextHolder.getLoginOrgId()); + userQueryByRoleDTO.setPlatformCode(EnvironmentUtils.getSystemCode()); + return AlitaResult.success(userService.listByRole(userQueryByRoleDTO)); + } + + @GetMapping("user/list_by_realName_or_phone") + @ApiOperation("通过姓名或手机号查询用户列表") + public AlitaResult> listByRealNameOrPhone(@RequestParam("realNames") Set realNames, @RequestParam("phones") Set phones) { + return AlitaResult.success(userService.listByRealNameOrPhone(realNames,phones)); + } +} diff --git a/src/main/java/com/newyetai/usercenter/user/controller/UserExtensionController.java b/src/main/java/com/newyetai/usercenter/user/controller/UserExtensionController.java new file mode 100644 index 0000000..61898b5 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/controller/UserExtensionController.java @@ -0,0 +1,59 @@ +package com.newyetai.usercenter.user.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.usercenter.user.dto.UserExtendStatusDTO; +import com.newyetai.usercenter.user.dto.UserExtensionDTO; +import com.newyetai.usercenter.user.dto.UserExtensionOperateDTO; +import com.newyetai.usercenter.user.service.UserExtensionService; +import com.newyetai.usercenter.user.service.UserService; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +/** + * @author sr on 2021-05-24 + */ +@RestController +@Api(tags = "用户扩展信息") +public class UserExtensionController { + + @Autowired + private UserService userService; + + @Autowired + private UserExtensionService userExtensionService; + + @GetMapping("user/extension/delete_user_file") + @ApiOperation("删除用户扩展信息简历附件") + public AlitaResult deleteUserFile(){ + userExtensionService.deleteUserFile(); + return AlitaResult.success(); + } + + @PostMapping("user/extension/edit") + @ApiOperation("编辑用户扩展信息") + public AlitaResult edit(@Validated @RequestBody UserExtensionOperateDTO userExtensionOperateDTO){ + return AlitaResult.success(userExtensionService.edit(userExtensionOperateDTO)); + } + + @GetMapping("/unac/user/extension/get") + @ApiOperation("编辑用户扩展信息") + public AlitaResult get(){ + return AlitaResult.success(userExtensionService.getByUserId(UserContextHolder.getLoginUserId())); + } + + @GetMapping("/unac/user/extend/status") + @ApiOperation("获取扩展状态") + public AlitaResult getUserExtendStatus() { + return AlitaResult.success(userService.getUserExtendStatus(UserContextHolder.getLoginUserId())); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/controller/UserIdentityPhotoController.java b/src/main/java/com/newyetai/usercenter/user/controller/UserIdentityPhotoController.java new file mode 100644 index 0000000..e93ad1d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/controller/UserIdentityPhotoController.java @@ -0,0 +1,92 @@ +package com.newyetai.usercenter.user.controller; + +import com.newyetai.common.validation.Create; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.validation.annotation.Validated; + +import com.newyetai.common.validation.Update; +import com.newyetai.common.AlitaResult; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.user.dto.UserIdentityPhotoQueryDTO; +import com.newyetai.usercenter.user.service.UserIdentityPhotoService; +import com.newyetai.usercenter.user.dto.UserIdentityPhotoInfoDTO; +import com.newyetai.usercenter.user.dto.UserIdentityPhotoDTO; +import com.newyetai.usercenter.user.dto.UserIdentityPhotoOperateDTO; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +/** + * @author sr on 2021-05-24 + */ +@RestController +@RequestMapping("user_identity_photo") +@Api(tags = "用户证件正反面") +public class UserIdentityPhotoController { + + @Autowired + private UserIdentityPhotoService userIdentityPhotoService; + + @PostMapping("/create") + @ApiOperation("创建") + public AlitaResult create( + @Validated(Create.class) @RequestBody UserIdentityPhotoOperateDTO userIdentityPhotoOperateDTO) { + return AlitaResult.success(userIdentityPhotoService.create(userIdentityPhotoOperateDTO)); + } + + @PutMapping("/modify") + @ApiOperation("修改") + public AlitaResult modify( + @Validated(Update.class) @RequestBody UserIdentityPhotoOperateDTO userIdentityPhotoOperateDTO) { + userIdentityPhotoService.modify(userIdentityPhotoOperateDTO); + return AlitaResult.success(true); + } + + @DeleteMapping("/remove/{id}") + @ApiOperation("删除") + public AlitaResult remove(@PathVariable Long id) { + userIdentityPhotoService.remove(id); + return AlitaResult.success(true); + } + + @GetMapping("/get/{userId}") + @ApiOperation("根据用户Id查询") + public AlitaResult getByUserId(@PathVariable Long userId) { + return AlitaResult.success(userIdentityPhotoService.getByUserId(userId)); + } + + @GetMapping("/page") + @ApiOperation("分页查询") + public AlitaResult> page( + UserIdentityPhotoQueryDTO userIdentityPhotoQueryDTO) { + userIdentityPhotoService.list(userIdentityPhotoQueryDTO); + return AlitaResult.success(userIdentityPhotoQueryDTO.getPageResult()); + } + + @GetMapping("/list") + @ApiOperation("列表查询") + public AlitaResult> list( + UserIdentityPhotoQueryDTO userIdentityPhotoQueryDTO) { + userIdentityPhotoQueryDTO.setNeedPage(false); + return AlitaResult.success(userIdentityPhotoService.list(userIdentityPhotoQueryDTO)); + } + + @GetMapping("/info") + @ApiOperation("查询详细信息") + public AlitaResult findInfo() { + return AlitaResult + .success(userIdentityPhotoService.findInfo(UserContextHolder.getExistLoginUserId())); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/controller/UserPostalInfoController.java b/src/main/java/com/newyetai/usercenter/user/controller/UserPostalInfoController.java new file mode 100644 index 0000000..cd72a9c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/controller/UserPostalInfoController.java @@ -0,0 +1,70 @@ +package com.newyetai.usercenter.user.controller; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.validation.Update; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.user.dto.UserPostalInfoDTO; +import com.newyetai.usercenter.user.dto.UserPostalInfoOperateDTO; +import com.newyetai.usercenter.user.dto.UserPostalInfoQueryDTO; +import com.newyetai.usercenter.user.service.UserPostalInfoService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @author fzp on 2022-01-19 + */ +@RestController +@RequestMapping("user_postal_info") +@Api(tags = "用户邮寄信息") +public class UserPostalInfoController { + + @Autowired + private UserPostalInfoService userPostalInfoService; + + @PostMapping("/create") + @ApiOperation("创建") + public AlitaResult create( + @Validated @RequestBody UserPostalInfoOperateDTO userPostalInfoOperateDTO){ + return AlitaResult.success(userPostalInfoService.create(userPostalInfoOperateDTO)); + } + + @PutMapping("/modify") + @ApiOperation("修改") + public AlitaResult modify( + @Validated(Update.class) @RequestBody UserPostalInfoOperateDTO userPostalInfoOperateDTO){ + userPostalInfoService.modify(userPostalInfoOperateDTO); + return AlitaResult.success(true); + } + + @DeleteMapping("/remove/{id}") + @ApiOperation("删除") + public AlitaResult remove(@PathVariable Long id){ + userPostalInfoService.remove(id); + return AlitaResult.success(true); + } + + @GetMapping("/list") + @ApiOperation("查询") + public AlitaResult> list(UserPostalInfoQueryDTO userPostalInfoQueryDTO){ + return AlitaResult.success(userPostalInfoService.list(userPostalInfoQueryDTO)); + } + + @GetMapping("/page") + @ApiOperation("分页查询") + public AlitaResult> page(UserPostalInfoQueryDTO userPostalInfoQueryDTO){ + userPostalInfoService.page(userPostalInfoQueryDTO); + return AlitaResult.success(userPostalInfoQueryDTO.getPageResult()); + } + + @GetMapping("/find/{id}") + @ApiOperation("查询单个") + public AlitaResult find(@PathVariable("id") Long id){ + return AlitaResult.success(userPostalInfoService.find(UserPostalInfoQueryDTO.builder().id(id).build())); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/controller/UserRegisterController.java b/src/main/java/com/newyetai/usercenter/user/controller/UserRegisterController.java new file mode 100644 index 0000000..ba6ec83 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/controller/UserRegisterController.java @@ -0,0 +1,55 @@ +package com.newyetai.usercenter.user.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.tkmybatis.pojo.Page; +import com.newyetai.usercenter.user.dto.UserRegisterCodeDTO; +import com.newyetai.usercenter.user.dto.UserRegisterCodeInfoDTO; +import com.newyetai.usercenter.user.dto.UserRegisterInfoDTO; +import com.newyetai.usercenter.user.dto.UserRegisterInfoQueryDTO; +import com.newyetai.usercenter.user.service.UserRegisterService; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +/** + * @author sr on 2021-11-16 + */ +@RestController +@RequestMapping("user_register") +@Api(tags = "用户注册信息") +public class UserRegisterController { + + @Autowired + private UserRegisterService userRegisterService; + + @PostMapping("/get_code") + @ApiOperation("获取(自己)邀请码") + public AlitaResult getCode( + @Validated @RequestBody UserRegisterCodeDTO userInvitationCreateCodeDTO){ + return AlitaResult.success(userRegisterService.getCode(userInvitationCreateCodeDTO)); + } + + @PostMapping("/up_get_code") + @ApiOperation("获取(指定)邀请码") + public AlitaResult upGetCode(@Validated @RequestBody UserRegisterCodeInfoDTO upUserRegisterCodeDTO){ + return AlitaResult.success(userRegisterService.getCode(upUserRegisterCodeDTO)); + } + + @GetMapping("/page_invitee_info") + @ApiOperation("分页查询受邀人信息") + public AlitaResult> pageInviteeInfo(UserRegisterInfoQueryDTO userRegisterInfoQueryDTO){ + userRegisterInfoQueryDTO.setInviterId(UserContextHolder.getExistLoginUserId()); + userRegisterService.page(userRegisterInfoQueryDTO); + return AlitaResult.success(userRegisterInfoQueryDTO.getPageResult()); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/controller/UserVerificationController.java b/src/main/java/com/newyetai/usercenter/user/controller/UserVerificationController.java new file mode 100644 index 0000000..518921a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/controller/UserVerificationController.java @@ -0,0 +1,96 @@ +package com.newyetai.usercenter.user.controller; + +import com.newyetai.common.AlitaResult; +import com.newyetai.usercenter.user.dto.RealNameTwoResponseDTO; +import com.newyetai.usercenter.user.dto.SuperRealNameTwoAuthDTO; +import com.newyetai.usercenter.user.dto.UserBankCardFourVerificationDTO; +import com.newyetai.usercenter.user.dto.UserBankCardThreeVerificationCreateDTO; +import com.newyetai.usercenter.user.dto.UserBankCardThreeVerificationDTO; +import com.newyetai.usercenter.user.dto.UserDTO; +import com.newyetai.usercenter.user.dto.UserPhoneThreeVerificationDTO; +import com.newyetai.usercenter.user.dto.UserRealNameTwoAuthCreateDTO; +import com.newyetai.usercenter.user.service.UserBankCardFourVerificationService; +import com.newyetai.usercenter.user.service.UserBankCardThreeVerificationService; +import com.newyetai.usercenter.user.service.UserPhoneThreeVerificationService; +import com.newyetai.usercenter.user.service.UserRealNameTwoVerificationService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author czy + * @date 2021-06-28 + */ +@RestController +@Api(tags = "用户要素认证") +public class UserVerificationController { + + @Autowired + private UserPhoneThreeVerificationService userPhoneThreeVerificationService; + @Autowired + private UserBankCardThreeVerificationService userBankCardThreeVerificationService; + @Autowired + private UserBankCardFourVerificationService userBankCardFourVerificationService; + @Autowired + private UserRealNameTwoVerificationService userRealNameTwoVerificationService; + + @PostMapping("/unac/user/verification/phone_three_factor") + @ApiOperation("三要素认证") + public AlitaResult userPhoneThreeFactorVerification( + @Validated @RequestBody UserPhoneThreeVerificationDTO userPhoneThreeVerificationDTO) { + return AlitaResult.success(userPhoneThreeVerificationService + .userThreeFactorVerification(userPhoneThreeVerificationDTO)); + } + + @GetMapping("/user/verification/phone_three_factor/find_last") + @ApiOperation("查询用户最新的三要素认证") + public AlitaResult phoneThreeFactorFindLast() { + return AlitaResult.success(userPhoneThreeVerificationService + .findLast()); + } + + @PostMapping("/unac/user/verification/three_factor") + @ApiOperation("三要素认证") + public AlitaResult userThreeFactorVerification( + @Validated @RequestBody UserBankCardThreeVerificationCreateDTO userBankCardThreeVerificationCreateDTO) { + return AlitaResult.success(userBankCardThreeVerificationService + .userThreeFactorVerification(userBankCardThreeVerificationCreateDTO)); + } + + @GetMapping("/user/verification/three_factor/find_last") + @ApiOperation("查询用户最新的三要素认证") + public AlitaResult threeFactorFindLast() { + return AlitaResult.success(userBankCardThreeVerificationService + .findLast()); + } + + @PostMapping("/unac/user/verification/four_factor") + @ApiOperation("四要素认证") + public AlitaResult userFourFactorVerification( + @RequestBody UserBankCardFourVerificationDTO userBankCardFourVerificationDTO) { + return AlitaResult.success(userBankCardFourVerificationService + .userFourFactorVerification(userBankCardFourVerificationDTO)); + } + + @PostMapping("/super/verification/two_factor") + @ApiOperation("上级认证并创建实名用户(非个人用户自己)") + public AlitaResult superTwoFactorVerification( + @Validated @RequestBody SuperRealNameTwoAuthDTO authDTO) { + return AlitaResult + .success(userRealNameTwoVerificationService.superAuth(authDTO)); + } + + @PostMapping("user/real_name_two_auth") + @ApiOperation("二要素实名认证") + public AlitaResult userRealNameTwoAuth( + @Validated @RequestBody UserRealNameTwoAuthCreateDTO createDTO) { + userRealNameTwoVerificationService.userRealNameTwoAuth(createDTO); + return AlitaResult.success(); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dao/OrgUserMapper.java b/src/main/java/com/newyetai/usercenter/user/dao/OrgUserMapper.java new file mode 100644 index 0000000..b2eca50 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dao/OrgUserMapper.java @@ -0,0 +1,57 @@ +package com.newyetai.usercenter.user.dao; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.usercenter.user.dto.OrgUserDTO; +import com.newyetai.usercenter.user.dto.OrgUserInfoDTO; +import com.newyetai.usercenter.user.dto.OrgUserInfoQueryDTO; +import com.newyetai.usercenter.user.dto.OrgUserQueryDTO; +import com.newyetai.usercenter.user.entity.OrgUser; +import com.newyetai.usercenter.user.login.dto.OrgDetailDTO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 机构用户表 + * + * @author sr on 2021-05-24 + */ +public interface OrgUserMapper extends MyMapper { + + /** + * 查询 + * + * @param orgUserQueryDTO + * @return + * @author sr on 2021-05-24 + */ + List listOrgUserDTO(@Param("param") OrgUserQueryDTO orgUserQueryDTO); + + /** + * 校验是否可创建管理员用户(机构下是否存在指定userId,是否存在其他管理员userId) + * @param orgId + * @param userId + * @return + * @author sr on 2021-06-10 + */ + Boolean checkCreateAdministratorUser(Long orgId, Long userId); + + /** + * 是否存在对应手机号机构用户 + * @param phone + * @return + * @author sr on 2021-06-17 + */ + boolean existOrgUser(String phone); + + /** + * 根据用户id获取机构信息 + * + * @param userId + * @return + * @author sr on 2019-11-05 + */ + List listLoginOrgByUser(@Param("userId") Long userId, @Param("orgId") Long orgId); + + List list(@Param("param") OrgUserInfoQueryDTO queryDTO); +} diff --git a/src/main/java/com/newyetai/usercenter/user/dao/UserAuthMapper.java b/src/main/java/com/newyetai/usercenter/user/dao/UserAuthMapper.java new file mode 100644 index 0000000..5637e31 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dao/UserAuthMapper.java @@ -0,0 +1,31 @@ +package com.newyetai.usercenter.user.dao; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.newyetai.usercenter.user.dto.UserAuthDTO; +import com.newyetai.usercenter.user.dto.UserAuthQueryDTO; +import com.newyetai.usercenter.user.entity.UserAuth; +import com.newyetai.tkmybatis.mybatis.MyMapper; + +/** + * 用户授权中间表 + * + * @author sr on 2021-05-24 + */ +public interface UserAuthMapper extends MyMapper { + + /** + * 查询 + * + * @param userAuthQueryDTO + * @return + * @author sr on 2021-05-24 + */ + List listUserAuthDTO(@Param("param") UserAuthQueryDTO userAuthQueryDTO); + + int mergeAuth(Long retainUserId, Long deletedUserId); + + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dao/UserBankAccountMapper.java b/src/main/java/com/newyetai/usercenter/user/dao/UserBankAccountMapper.java new file mode 100644 index 0000000..20bdaf4 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dao/UserBankAccountMapper.java @@ -0,0 +1,28 @@ +package com.newyetai.usercenter.user.dao; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.usercenter.user.dto.UserBankAccountDTO; +import com.newyetai.usercenter.user.dto.UserBankAccountModifyDTO; +import com.newyetai.usercenter.user.dto.UserBankAccountQueryDTO; +import com.newyetai.usercenter.user.entity.UcUserBankAccount; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import java.util.List; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Update; + +/** + *

+ * 用户银行卡表 Mapper 接口 + *

+ * + * @author Carlye + * @since 2021-06-25 + */ +public interface UserBankAccountMapper extends MyMapper { + + List queryByCardNos(List cardNos); + + List listUserBankAccountDTO(@Param("param") UserBankAccountQueryDTO userBankAccountQueryDTO); + + int modify(@Param("param") UserBankAccountModifyDTO userBankAccountModifyDTO); +} diff --git a/src/main/java/com/newyetai/usercenter/user/dao/UserBankCardFourVerificationMapper.java b/src/main/java/com/newyetai/usercenter/user/dao/UserBankCardFourVerificationMapper.java new file mode 100644 index 0000000..3b72d7e --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dao/UserBankCardFourVerificationMapper.java @@ -0,0 +1,31 @@ +package com.newyetai.usercenter.user.dao; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.usercenter.user.dto.UserBankAccountDTO; +import com.newyetai.usercenter.user.dto.UserBankCardFourVerificationDTO; +import com.newyetai.usercenter.user.dto.UserBankCardFourVerificationQueryDTO; +import com.newyetai.usercenter.user.dto.UserBankCardThreeVerificationDTO; +import com.newyetai.usercenter.user.dto.UserBankCardThreeVerificationQueryDTO; +import com.newyetai.usercenter.user.entity.UserBankCardFourVerification; +import com.newyetai.usercenter.user.entity.UserBankCardThreeVerification; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + * @author czy + * @date 2021-06-23 + */ +public interface UserBankCardFourVerificationMapper extends MyMapper { + + + /** + * 查询 + * + * @param userBankCardFourVerificationQueryDTO + * @return + * @author sr on 2021-08-04 + */ + List listUserBankCardFourVerificationDTO( + @Param("param") UserBankCardFourVerificationQueryDTO userBankCardFourVerificationQueryDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dao/UserBankCardThreeVerificationMapper.java b/src/main/java/com/newyetai/usercenter/user/dao/UserBankCardThreeVerificationMapper.java new file mode 100644 index 0000000..46845b2 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dao/UserBankCardThreeVerificationMapper.java @@ -0,0 +1,30 @@ +package com.newyetai.usercenter.user.dao; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.usercenter.user.dto.UserBankCardThreeVerificationDTO; +import com.newyetai.usercenter.user.dto.UserBankCardThreeVerificationQueryDTO; +import com.newyetai.usercenter.user.entity.UserBankCardThreeVerification; + +/** + * @author czy + * @date 2021-06-23 + */ +public interface UserBankCardThreeVerificationMapper + extends MyMapper { + + + /** + * 查询 + * + * @param userBankCardThreeVerificationQueryDTO + * @return + * @author sr on 2021-08-04 + */ + List listUserBankCardThreeVerificationDTO( + @Param("param") UserBankCardThreeVerificationQueryDTO userBankCardThreeVerificationQueryDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dao/UserCancelMapper.java b/src/main/java/com/newyetai/usercenter/user/dao/UserCancelMapper.java new file mode 100644 index 0000000..79fc3d6 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dao/UserCancelMapper.java @@ -0,0 +1,32 @@ +package com.newyetai.usercenter.user.dao; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.usercenter.user.dto.UserCancelDTO; +import com.newyetai.usercenter.user.dto.UserCancelPageQueryDTO; +import com.newyetai.usercenter.user.entity.UserCancel; +import org.apache.ibatis.annotations.Param; + +import java.math.BigDecimal; +import java.util.List; + + +/** + * 用户申请注销Mapper + * + * @author cheny + * @date 2023/03/07 + */ +public interface UserCancelMapper extends MyMapper { + + + List page(@Param("param") UserCancelPageQueryDTO queryDTO); + + /** + * 查询需要通知的数据 + * + * @return {@link List}<{@link UserCancelDTO}> + */ + List toNotify(); + + UserCancelDTO findNotifyInfo(Long userId); +} diff --git a/src/main/java/com/newyetai/usercenter/user/dao/UserConfigMapper.java b/src/main/java/com/newyetai/usercenter/user/dao/UserConfigMapper.java new file mode 100644 index 0000000..c8f0f9f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dao/UserConfigMapper.java @@ -0,0 +1,28 @@ +package com.newyetai.usercenter.user.dao; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.newyetai.usercenter.user.dto.UserConfigDTO; +import com.newyetai.usercenter.user.dto.UserConfigQueryDTO; +import com.newyetai.usercenter.user.entity.UserConfig; +import com.newyetai.tkmybatis.mybatis.MyMapper; + +/** + * 用户配置 + * + * @author sr on 2021-08-12 + */ +public interface UserConfigMapper extends MyMapper { + + /** + * 查询 + * + * @param userConfigQueryDTO + * @return + * @author sr on 2021-08-12 + */ + List listUserConfigDTO(@Param("param") UserConfigQueryDTO userConfigQueryDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dao/UserExtensionMapper.java b/src/main/java/com/newyetai/usercenter/user/dao/UserExtensionMapper.java new file mode 100644 index 0000000..fa6f284 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dao/UserExtensionMapper.java @@ -0,0 +1,23 @@ +package com.newyetai.usercenter.user.dao; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.usercenter.user.dto.UserDTO; +import com.newyetai.usercenter.user.dto.UserExtendStatusDTO; +import com.newyetai.usercenter.user.dto.UserExtensionDTO; +import com.newyetai.usercenter.user.dto.UserQueryDTO; +import com.newyetai.usercenter.user.entity.UserExtension; +import java.util.List; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +/** + * 用户扩展信息 + * + * @author czy on 2021-06-15 + */ +public interface UserExtensionMapper extends MyMapper { + + @Select("select * from uc_user_extension where deleted = 0 and user_id = #{userId}") + UserExtensionDTO getByUserId(@Param("userId") Long userId); + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dao/UserIdentityPhotoMapper.java b/src/main/java/com/newyetai/usercenter/user/dao/UserIdentityPhotoMapper.java new file mode 100644 index 0000000..c294042 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dao/UserIdentityPhotoMapper.java @@ -0,0 +1,31 @@ +package com.newyetai.usercenter.user.dao; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.newyetai.usercenter.user.dto.UserIdentityPhotoDTO; +import com.newyetai.usercenter.user.dto.UserIdentityPhotoQueryDTO; +import com.newyetai.usercenter.user.entity.UserIdentityPhoto; +import com.newyetai.tkmybatis.mybatis.MyMapper; +import org.apache.ibatis.annotations.Select; + +/** + * 用户证件正反面 + * + * @author sr on 2021-05-24 + */ +public interface UserIdentityPhotoMapper extends MyMapper { + + /** + * 查询 + * + * @param userIdentityPhotoQueryDTO + * @return + * @author sr on 2021-05-24 + */ + List listUserIdentityPhotoDTO(@Param("param") UserIdentityPhotoQueryDTO userIdentityPhotoQueryDTO); + + @Select("select * from uc_user_identity_photo where deleted=false and user_id=#{userId} limit 1") + UserIdentityPhotoDTO getByUserId(@Param("userId") Long userId); +} diff --git a/src/main/java/com/newyetai/usercenter/user/dao/UserMapper.java b/src/main/java/com/newyetai/usercenter/user/dao/UserMapper.java new file mode 100644 index 0000000..c42f369 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dao/UserMapper.java @@ -0,0 +1,184 @@ +package com.newyetai.usercenter.user.dao; + +import com.newyetai.security.dto.UserInfoDTO; +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.usercenter.user.dto.*; +import com.newyetai.usercenter.user.entity.User; +import com.newyetai.usercenter.user.login.dto.UserDetailDTO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; +import java.util.Set; + +/** + * 用户 + * + * @author sr on 2021-05-24 + */ +public interface UserMapper extends MyMapper { + + /** + * 查询 + * 用户注册表存在重复数据,取用户最开始注册平台的code + * @param userQueryDTO + * @return + * @author sr on 2021-05-24 + */ + List listUserDTO(@Param("param") UserQueryDTO userQueryDTO); + + /** + * 初始账号密码 + * + * @param username + * @param encodedPassword + * @param operateUserId + * @return + * @author sr on 2021-08-04 + */ + int initUserPassword(String username, String encodedPassword, Long operateUserId); + + /** + * 注销用户 + * + * @param userId 用户id + * @param operateUserId 操作用户id + * @return int + */ + int cancel(Long userId, Long operateUserId); + + /** + * 根据登录信息查询用户信息 + * + * @param userDetailQueryDto + * @return + */ + List listUserDetailDTO(@Param("param") UserDetailQueryDTO userDetailQueryDto); + + /** + * 根据授权信息查询用户信息 + * @param userAuthQueryDTO + * @return + * @author sr on 2021-06-28 + */ + List listAuthUserDetailDTO(@Param("param") UserAuthQueryDTO userAuthQueryDTO); + + /** + * 清理其他个人用户手机号 + * @param userId + * @return + * @author sr on 2021-07-01 + */ + int cleanOtherPersonUserPhone(Long userId, String phone); + + /** + * 实名个人用户 + * @param authenticateUserDTO + * @return + * @author sr on 2021-07-01 + */ + int authenticatePersonUser(@Param("param") AuthenticateUserDTO authenticateUserDTO); + + /** + * 修改绑定手机 + * @param userId + * @param phone 可以为空,但前提是用户手机号不为空 + * @return + * @author sr on 2021-07-02 + */ + int bindingPhone(Long userId, String phone); + + /** + * 获取指定用户的阔转状态(实名认证、证件正反面照上传、手机绑定、微信绑定状态) + * @param userId + * @return + * @author czy on 2021-06-10 + */ + UserExtendStatusDTO getUserExtendStatus(@Param("userId") Long userId); + + /** + * 将手机状态同步到选择的用户上 + * @param retainUserId + * @param phoneUserId + * @return + * @author sr on 2021-07-06 + */ + int mergeUser(Long retainUserId, Long phoneUserId); + + /** + * 页面平台用户 + * + * @param reqDTO 点播dto + * @return {@link List} + */ + List pagePlatformUser(@Param("param") PlatformUserInfoReqDTO reqDTO); + + /** + * 根据用户ID和机构ID查询用户信息 + * + * @param userId 用户id + * @param existLoginOrgId 存在登录org id + * @return {@link UserDTO} + */ + UserDTO getUserInfoByOrg(@Param("userId") Long userId,@Param("existLoginOrgId") Long existLoginOrgId); + + UserInfoDTO findUserInfo(@Param("userId") Long userId, @Param("orgId") Long orgId); + + /** + * 查询是否存在相同账号 + * + * @param username 账号 + * @return + */ + boolean existUsername(@Param("username") String username,@Param("userId") Long userId); + /** + * 更新用户信息 + * + * @param user + * @return + */ + int updateOrgUserById(User user); + + /** + * 超级管理员重置用户密码 + * + * @param userId + * @param password + * @param operateUserId + * @return + * @author sr on 2019-10-22 + */ + int updatePassword( + @Param("userId") Long userId, + @Param("password") String password, + @Param("operateUserId") Long operateUserId); + + /** + * 查询企业负责人信息 + * + * @param userIds 用户ID集合 + * @return + * @author sr on 2019-10-22 + */ + List personInCharge(@Param("userIds") Set userIds); + + /** + * 通过角色信息查询用户列表 + * @param userQueryByRoleDTO + * @return + * @author sr on 2022-05-25 + */ + List listByRole(@Param("param") UserQueryByRoleDTO userQueryByRoleDTO); + + /** + * 未激活用户,登录激活用户 + * + * @param userId + * @return + * @author sr on 2022-09-01 + */ + int loginActive(Long userId); + + List listPlatformUser(@Param("param") PlatformUserListQueryDTO queryDTO); + + List listByRealNameOrPhone(@Param("orgId") Long orgId, @Param("realNames") Set realNames, @Param("phones") Set phones); +} diff --git a/src/main/java/com/newyetai/usercenter/user/dao/UserPhoneThreeVerificationMapper.java b/src/main/java/com/newyetai/usercenter/user/dao/UserPhoneThreeVerificationMapper.java new file mode 100644 index 0000000..3b0a291 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dao/UserPhoneThreeVerificationMapper.java @@ -0,0 +1,29 @@ +package com.newyetai.usercenter.user.dao; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.usercenter.user.dto.UserPhoneThreeVerificationDTO; +import com.newyetai.usercenter.user.dto.UserPhoneThreeVerificationQueryDTO; +import com.newyetai.usercenter.user.entity.UserPhoneThreeVerification; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @author czy + * @date 2021-06-23 + */ +public interface UserPhoneThreeVerificationMapper + extends MyMapper { + + + /** + * 查询 + * + * @param userPhoneThreeVerificationQueryDTO + * @return + * @author sr on 2021-08-04 + */ + List listUserPhoneThreeVerificationDTO( + @Param("param") UserPhoneThreeVerificationQueryDTO userPhoneThreeVerificationQueryDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dao/UserPostalInfoMapper.java b/src/main/java/com/newyetai/usercenter/user/dao/UserPostalInfoMapper.java new file mode 100644 index 0000000..0b35e70 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dao/UserPostalInfoMapper.java @@ -0,0 +1,29 @@ +package com.newyetai.usercenter.user.dao; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.newyetai.usercenter.user.dto.UserPostalInfoDTO; +import com.newyetai.usercenter.user.dto.UserPostalInfoQueryDTO; +import com.newyetai.usercenter.user.entity.UserPostalInfo; +import com.newyetai.tkmybatis.mybatis.MyMapper; + +/** + * 用户邮寄信息 + * + * @author fzp on 2022-01-19 + */ +public interface UserPostalInfoMapper extends MyMapper { + + /** + * 查询 + * + * @param userPostalInfoQueryDTO + * @return + * @author fzp on 2022-01-19 + */ + List listUserPostalInfoDTO(@Param("param") UserPostalInfoQueryDTO userPostalInfoQueryDTO); + + void cancelDefaultedById(Long id,Long userId); +} diff --git a/src/main/java/com/newyetai/usercenter/user/dao/UserRealNameTwoVerificationMapper.java b/src/main/java/com/newyetai/usercenter/user/dao/UserRealNameTwoVerificationMapper.java new file mode 100644 index 0000000..fd22dc8 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dao/UserRealNameTwoVerificationMapper.java @@ -0,0 +1,12 @@ +package com.newyetai.usercenter.user.dao; + +import com.newyetai.tkmybatis.mybatis.MyMapper; +import com.newyetai.usercenter.user.entity.UserRealNameTwoVerification; + +/** + * @author fzp + * @date 2021年7月14日10:24:46 + */ +public interface UserRealNameTwoVerificationMapper extends MyMapper { + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dao/UserRegisterMapper.java b/src/main/java/com/newyetai/usercenter/user/dao/UserRegisterMapper.java new file mode 100644 index 0000000..48828d6 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dao/UserRegisterMapper.java @@ -0,0 +1,38 @@ +package com.newyetai.usercenter.user.dao; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.newyetai.usercenter.user.dto.UserRegisterDTO; +import com.newyetai.usercenter.user.dto.UserRegisterInfoDTO; +import com.newyetai.usercenter.user.dto.UserRegisterInfoQueryDTO; +import com.newyetai.usercenter.user.dto.UserRegisterQueryDTO; +import com.newyetai.usercenter.user.entity.UserRegister; +import com.newyetai.tkmybatis.mybatis.MyMapper; + +/** + * 用户注册表 + * + * @author sr on 2021-11-16 + */ +public interface UserRegisterMapper extends MyMapper { + + /** + * 查询 + * + * @param userRegisterQueryDTO + * @return + * @author sr on 2021-11-16 + */ + List listUserRegisterDTO(@Param("param") UserRegisterQueryDTO userRegisterQueryDTO); + + /** + * 查询注册详情 + * @param userRegisterQueryDTO + * @return + * @author sr on 2021-11-18 + */ + List listUserRegisterInfoDTO(@Param("param") UserRegisterInfoQueryDTO userRegisterInfoQueryDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/AuthenticateUserDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/AuthenticateUserDTO.java new file mode 100644 index 0000000..4c66141 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/AuthenticateUserDTO.java @@ -0,0 +1,45 @@ +package com.newyetai.usercenter.user.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotBlank; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.newyetai.common.validation.annotation.Expression; +import com.newyetai.common.validation.annotation.Phone; +import com.newyetai.common.validation.constants.ValidProviderEnum; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2021-07-01 + */ +@ApiModel("用户实名-认证已通过") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class AuthenticateUserDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 3807697853918276660L; + + @ApiModelProperty("姓名") + @Expression(type = ValidProviderEnum.REAL_NAME, message = "姓名不正确") + private String realName; + @ApiModelProperty("证件号") + @Expression(type = ValidProviderEnum.CARD_NO, message = "身份证号不正确") + private String cardNo; + @ApiModelProperty("手机号码") + @Phone(message = "手机号码格式不正确") + private String phone ; + @JsonIgnore + @ApiModelProperty("指定用户id(db使用更新用户实名状态;为空[认证成功通知]则根据身份证号查找对应用户实名,不为空则只更新指定id用户)") + private Long userId; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/BindPhoneDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/BindPhoneDTO.java new file mode 100644 index 0000000..f2846fa --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/BindPhoneDTO.java @@ -0,0 +1,22 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.usercenter.user.phone.constant.UserPhoneCodeOperateEnum; + +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.NoArgsConstructor; + +@ApiModel(description = "绑定手机号") +@Data +@NoArgsConstructor +public class BindPhoneDTO extends UserPhoneCodeDTO{ + + /** **/ + private static final long serialVersionUID = 1885543530652690308L; + + @Override + public String getOperateType() { + return UserPhoneCodeOperateEnum.BIND_PHONE.getOperate(); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/ChangePhoneDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/ChangePhoneDTO.java new file mode 100644 index 0000000..45eacb8 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/ChangePhoneDTO.java @@ -0,0 +1,22 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.usercenter.user.phone.constant.UserPhoneCodeOperateEnum; + +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.NoArgsConstructor; + +@ApiModel(description = "换绑手机号") +@Data +@NoArgsConstructor +public class ChangePhoneDTO extends UserPhoneCodeDTO{ + + /** **/ + private static final long serialVersionUID = 1885543530652690308L; + + @Override + public String getOperateType() { + return UserPhoneCodeOperateEnum.CHANGE_PHONE.getOperate(); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/ChangePhoneMqDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/ChangePhoneMqDTO.java new file mode 100644 index 0000000..cba7c7a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/ChangePhoneMqDTO.java @@ -0,0 +1,35 @@ +package com.newyetai.usercenter.user.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2021-09-13 + */ +@ApiModel(description = "换绑手机号mq消息") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class ChangePhoneMqDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = -3187518200627395525L; + + @ApiModelProperty("手机号码") + @NotBlank(message = "手机号码不能为空") + private String phone; + @ApiModelProperty("用户id") + @NotNull(message = "用户id不能为空") + private Long userId; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/CheckSecurityCodeReqDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/CheckSecurityCodeReqDTO.java new file mode 100644 index 0000000..5d6134d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/CheckSecurityCodeReqDTO.java @@ -0,0 +1,46 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.common.validation.util.ValidateUtils; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Pattern; +import java.io.Serializable; +import java.util.Objects; + + +/** + * 检查安全代码要求的dto + * + * @author Carlye + * @date 2021/08/09 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "校验用户安全码操作") +public class CheckSecurityCodeReqDTO implements Serializable { + + private static final long serialVersionUID = -4219278463333163768L; + @ApiModelProperty("用户ID,") + private Long userId; + + @ApiModelProperty("安全码") + @NotEmpty(message = "安全码不能为空") + @Pattern(regexp = ValidateUtils.SECURITY_CODE_PATTERN,message = "安全码不符合规则") + private String securityCode; + + public Long getUserId() { + if (Objects.isNull(userId)){ + userId = UserContextHolder.getLoginUserId(); + } + return userId; + } +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/user/dto/IUserPhoneCode.java b/src/main/java/com/newyetai/usercenter/user/dto/IUserPhoneCode.java new file mode 100644 index 0000000..e7bfcf3 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/IUserPhoneCode.java @@ -0,0 +1,11 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.usercenter.user.phone.dto.ICode; + +/** + * 用户短信验证码-验证 + * @author sr on 2021-09-02 + */ +public interface IUserPhoneCode extends IUserPhoneCodeSms, ICode { + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/IUserPhoneCodeSms.java b/src/main/java/com/newyetai/usercenter/user/dto/IUserPhoneCodeSms.java new file mode 100644 index 0000000..a07b5e2 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/IUserPhoneCodeSms.java @@ -0,0 +1,35 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.usercenter.user.phone.constant.UserPhoneCodeOperateEnum; +import com.newyetai.usercenter.user.phone.dto.IPhoneCodeSmsDTO; + +/** + * 用户短信验证码-发送 + * @author sr on 2021-09-02 + */ +public interface IUserPhoneCodeSms extends IPhoneCodeSmsDTO { + + /** + * 用户类型 + * @return + * @author sr on 2021-09-02 + */ + Integer getUserType(); + + /** + * 操作类型 + * {@link UserPhoneCodeOperateEnum} + * @return + * @author sr on 2021-09-02 + */ + String getOperateType(); + + /** + * 设置提供者类型 + * @param providerType + * @author sr on 2021-09-02 + */ + void setProviderType(String providerType); + + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/InitUserPasswordDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/InitUserPasswordDTO.java new file mode 100644 index 0000000..b7c7a8c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/InitUserPasswordDTO.java @@ -0,0 +1,37 @@ +package com.newyetai.usercenter.user.dto; + +import javax.validation.constraints.NotBlank; + +import com.newyetai.common.dto.BaseOperateDTO; +import com.newyetai.common.validation.annotation.Expression; +import com.newyetai.common.validation.constants.ValidProviderEnum; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@ApiModel(description = "初始设置账号密码") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InitUserPasswordDTO extends BaseOperateDTO { + + /** **/ + private static final long serialVersionUID = 8327018614562710138L; + + @ApiModelProperty("账号") + @NotBlank(message = "账号不能为空") + @Expression(type = ValidProviderEnum.USERNAME, message = "账号格式不正确") + private String username; + @ApiModelProperty("密码") + @Expression(type = ValidProviderEnum.PASSWORD, message = "密码格式不正确") + private String password; + @ApiModelProperty("二次确认密码") + @NotBlank(message = "二次确认密码不能为空") + private String rePassword; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/ModifyPasswordDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/ModifyPasswordDTO.java new file mode 100644 index 0000000..17bfa67 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/ModifyPasswordDTO.java @@ -0,0 +1,36 @@ +package com.newyetai.usercenter.user.dto; + +import javax.validation.constraints.NotBlank; + +import com.newyetai.common.dto.BaseOperateDTO; +import com.newyetai.common.validation.annotation.Expression; +import com.newyetai.common.validation.constants.ValidProviderEnum; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@ApiModel(description = "修改密码") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ModifyPasswordDTO extends BaseOperateDTO { + + /** **/ + private static final long serialVersionUID = 8327018614562710138L; + + @ApiModelProperty("原密码") + @Expression(type = ValidProviderEnum.PASSWORD, message = "密码格式不正确") + private String oldPassword; + @ApiModelProperty("新密码") + @Expression(type = ValidProviderEnum.PASSWORD, message = "密码格式不正确") + private String newPassword; + @ApiModelProperty("二次确认密码") + @NotBlank(message = "二次确认密码不能为空") + private String reNewPassword; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/OrgUserCreateDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/OrgUserCreateDTO.java new file mode 100644 index 0000000..80b771c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/OrgUserCreateDTO.java @@ -0,0 +1,53 @@ +package com.newyetai.usercenter.user.dto; + +import javax.validation.constraints.NotNull; + +import com.newyetai.common.dto.BaseOperateDTO; +import com.newyetai.common.validation.annotation.Expression; +import com.newyetai.common.validation.constants.ValidProviderEnum; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 机构内手机号唯一 + * @author sr on 2021-05-26 + */ +@ApiModel(description = "机构用户创建") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class OrgUserCreateDTO extends BaseOperateDTO{ + + /** **/ + private static final long serialVersionUID = 3741954861451945309L; + + @ApiModelProperty("昵称") + private String nickname; + + @ApiModelProperty("姓名") + private String realName; + + @ApiModelProperty("手机号") + @Expression(type = ValidProviderEnum.PHONE, message = "手机号格式不正确") + private String phone; + @ApiModelProperty("邮箱") + private String email; + @ApiModelProperty("机构id") +// @NotNull(message = "所属机构id不能为空") + private Long orgId; + @ApiModelProperty("是否管理员") + private Boolean administrator; + + + /** + * 微信二维码 + */ + @ApiModelProperty("微信二维码") + private String wechatQrCode; +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/OrgUserDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/OrgUserDTO.java new file mode 100644 index 0000000..c547b3c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/OrgUserDTO.java @@ -0,0 +1,32 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.dto.OrgBaseDTO; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2021-05-24 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@ApiModel(description = "机构用户表") +public class OrgUserDTO extends OrgBaseDTO{ + + /** **/ + private static final long serialVersionUID = 1L; + + /** 用户id */ + private Long userId ; + /** 是否管理员 */ + private Boolean administrator ; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/user/dto/OrgUserInfoDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/OrgUserInfoDTO.java new file mode 100644 index 0000000..9fa9604 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/OrgUserInfoDTO.java @@ -0,0 +1,25 @@ +package com.newyetai.usercenter.user.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +/** + * 机构用户信息dto + * + * @author Carlye + * @date 2021/10/13 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +@AllArgsConstructor +public class OrgUserInfoDTO extends UserDTO { + private static final long serialVersionUID = -344843668258323983L; + + @ApiModelProperty("机构ID") + private Long orgId; + @ApiModelProperty("用户ID") + private Long userId; + @ApiModelProperty("是否管理员") + private Boolean administrator; +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/OrgUserInfoQueryDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/OrgUserInfoQueryDTO.java new file mode 100644 index 0000000..2351c30 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/OrgUserInfoQueryDTO.java @@ -0,0 +1,28 @@ +package com.newyetai.usercenter.user.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +/** + * 机构用户信息 查询 dto + * + * @author Carlye + * @date 2021/10/13 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class OrgUserInfoQueryDTO implements Serializable { + + private static final long serialVersionUID = -5132218121861795737L; + @ApiModelProperty("机构ID") + private Long orgId; + @ApiModelProperty("用户ID") + private Long userId; + @ApiModelProperty("用户类型:1企业用户,2个人用户") + private Integer type; +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/OrgUserModifyDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/OrgUserModifyDTO.java new file mode 100644 index 0000000..9966f1f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/OrgUserModifyDTO.java @@ -0,0 +1,54 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.dto.BaseOperateDTO; +import com.newyetai.common.validation.Update; +import com.newyetai.common.validation.annotation.Expression; +import com.newyetai.common.validation.constants.ValidProviderEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; + +/** + * 机构内手机号唯一 + * @author sr on 2021-05-26 + */ +@ApiModel(description = "机构用户修改") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class OrgUserModifyDTO extends BaseOperateDTO{ + + /** **/ + private static final long serialVersionUID = 3741954861451945309L; + + @NotNull(message = "ID不能为空") + private Long id; + + @ApiModelProperty("昵称") + private String nickname; + + @ApiModelProperty("姓名") + private String realName; + + @Expression(type = ValidProviderEnum.PHONE, message = "手机号格式不正确") + @ApiModelProperty("手机号") + private String phone; + + @ApiModelProperty("邮箱") + private String email; + + @ApiModelProperty("机构id") + private Long orgId; + + /** + * 微信二维码 + */ + @ApiModelProperty("微信二维码") + private String wechatQrCode; +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/OrgUserOperateDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/OrgUserOperateDTO.java new file mode 100644 index 0000000..bc2bf63 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/OrgUserOperateDTO.java @@ -0,0 +1,43 @@ +package com.newyetai.usercenter.user.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotNull; + +import com.newyetai.common.dto.BaseOperateDTO; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2021-05-24 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "机构用户表操作") +public class OrgUserOperateDTO extends BaseOperateDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @NotNull(message = "id不能为空", groups = {Update.class}) + private Long id; + @ApiModelProperty("用户id") + @NotNull(message = "用户id不能为空", groups = {Create.class}) + private Long userId ; + @ApiModelProperty("机构id") + @NotNull(message = "机构id不能为空", groups = {Create.class}) + private Long orgId; + @ApiModelProperty("是否管理员") + private Boolean administrator ; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/user/dto/OrgUserQueryDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/OrgUserQueryDTO.java new file mode 100644 index 0000000..9d4b23a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/OrgUserQueryDTO.java @@ -0,0 +1,38 @@ +package com.newyetai.usercenter.user.dto; + +import java.io.Serializable; + +import com.newyetai.common.dto.PageQueryDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2021-05-24 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "机构用户表查询条件") +public class OrgUserQueryDTO extends PageQueryDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + @ApiModelProperty("用户id") + private Long userId ; + @ApiModelProperty("机构id") + private Long orgId; + /** 是否管理员 */ + private Boolean administrator ; + private String orgName; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/user/dto/PersonUserCardCreateDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/PersonUserCardCreateDTO.java new file mode 100644 index 0000000..0cbf685 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/PersonUserCardCreateDTO.java @@ -0,0 +1,39 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.annotation.trimAndUpper.TrimAndUpper; +import com.newyetai.common.dto.BaseOperateDTO; +import com.newyetai.common.validation.annotation.Expression; +import com.newyetai.common.validation.annotation.Phone; +import com.newyetai.common.validation.constants.ValidProviderEnum; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@ApiModel(description = "个人用户(证件)创建") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PersonUserCardCreateDTO extends BaseOperateDTO{ + + /** **/ + private static final long serialVersionUID = 7658014752415774002L; + + @ApiModelProperty("真实姓名") + @TrimAndUpper + private String realName ; + @ApiModelProperty("身份证号") + @Expression(type = ValidProviderEnum.CARD_NO, message = "身份证号不正确") + @TrimAndUpper + private String cardNo ; + @ApiModelProperty("手机号码") + @Phone(message = "手机号码格式不正确") + private String phone ; + @ApiModelProperty("绑定机构id") + private Long bindOrgId; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/PersonUserCardCreateResultDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/PersonUserCardCreateResultDTO.java new file mode 100644 index 0000000..7b8f8d0 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/PersonUserCardCreateResultDTO.java @@ -0,0 +1,27 @@ +package com.newyetai.usercenter.user.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@ApiModel(description = "个人用户(证件)创建") +@Data +@NoArgsConstructor +@AllArgsConstructor +public class PersonUserCardCreateResultDTO extends UserDTO{ + + /** **/ + private static final long serialVersionUID = 7658014752415774002L; + + @ApiModelProperty("是否操作成功") + private boolean success; + @ApiModelProperty("成功创建用户id") + private Long userId; + @ApiModelProperty("失败原因") + private String msg; + + + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/PersonUserPhoneCreateDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/PersonUserPhoneCreateDTO.java new file mode 100644 index 0000000..df24467 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/PersonUserPhoneCreateDTO.java @@ -0,0 +1,28 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.dto.BaseOperateDTO; +import com.newyetai.common.validation.annotation.Expression; +import com.newyetai.common.validation.constants.ValidProviderEnum; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@ApiModel(description = "个人用户(手机号登录)创建") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PersonUserPhoneCreateDTO extends BaseOperateDTO{ + + /** **/ + private static final long serialVersionUID = 7658014752415774002L; + + @ApiModelProperty("手机号码") + @Expression(type = ValidProviderEnum.PHONE, message = "手机号格式不正确") + private String phone ; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/PlatformUserInfoDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/PlatformUserInfoDTO.java new file mode 100644 index 0000000..d85ffd4 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/PlatformUserInfoDTO.java @@ -0,0 +1,87 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.usercenter.authority.dto.RoleAllocationDTO; +import com.newyetai.usercenter.user.constant.UserStatusEnum; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.SuperBuilder; + +import java.util.Objects; + + +/** + * 平台用户信息dto + * + * @author Carlye + * @date 2021/08/03 + */ +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@Data +@ToString +public class PlatformUserInfoDTO extends BaseDTO { + + private static final long serialVersionUID = 5085940488169971625L; + + @ApiModelProperty("账号") + private String username; + + @ApiModelProperty("用户昵称") + private String nickname; + + @ApiModelProperty("用户真实姓名") + private String realName; + + @ApiModelProperty("用户手机号") + private String phone; + + @ApiModelProperty("用户手机号绑定状态") + private Boolean phoneBinding; + + @ApiModelProperty("用户邮箱") + private String email; + + @ApiModelProperty("是否启用") + private Boolean enabled; + + @ApiModelProperty("是否实名") + private Boolean authenticated; + + @ApiModelProperty("状态:1.待激活,2已激活,3已注销") + private Integer status; + + @ApiModelProperty("微信二维码") + private String wechatQrCode; + + + public Boolean getPhoneBinding() { + if (Objects.isNull(phoneBinding)) { + phoneBinding = Boolean.FALSE; + } + return phoneBinding; + } + + public Boolean getEnabled() { + if (Objects.isNull(enabled)) { + enabled = Boolean.FALSE; + } + return enabled; + } + + public Integer getStatus() { + if (Objects.isNull(status)) { + status = UserStatusEnum.INIT.getStatus(); + } + return status; + } + + public Boolean getAuthenticated() { + if (Objects.isNull(authenticated)) { + authenticated = Boolean.FALSE; + } + return authenticated; + } +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/PlatformUserInfoReqDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/PlatformUserInfoReqDTO.java new file mode 100644 index 0000000..61fe4ba --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/PlatformUserInfoReqDTO.java @@ -0,0 +1,83 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.annotation.trimAndUpper.TrimAndUpper; +import com.newyetai.common.dto.PageQueryDTO; +import com.newyetai.common.util.UserContextHolder; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import java.util.Objects; + + +/** + * 平台用户信息查询dto + * + * @author Carlye + * @date 2021/08/03 + */ +@EqualsAndHashCode(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Data +@ToString +public class PlatformUserInfoReqDTO extends PageQueryDTO { + + private static final long serialVersionUID = 5085940488169971625L; + + @ApiModelProperty("账号") + @TrimAndUpper(TrimAndUpper.ExecuteType.TRIM) + private String username; + + @ApiModelProperty("用户昵称") + @TrimAndUpper(TrimAndUpper.ExecuteType.TRIM) + private String nickname; + + @ApiModelProperty("用户真实姓名") + @TrimAndUpper(TrimAndUpper.ExecuteType.TRIM) + private String realName; + + @ApiModelProperty("用户手机号") + @TrimAndUpper(TrimAndUpper.ExecuteType.TRIM) + private String phone; + + @ApiModelProperty("用户手机号绑定状态") + private Boolean phoneBinding; + + @ApiModelProperty("用户邮箱") + @TrimAndUpper(TrimAndUpper.ExecuteType.TRIM) + private String email; + + @ApiModelProperty("是否启用") + private Boolean enabled; + + @ApiModelProperty("状态:1.待激活,2已激活,3已注销") + private Integer status; + + @ApiModelProperty("当前登录机构ID") + private Long orgId; + + public Long getOrgId() { + if (Objects.isNull(orgId)) { + orgId = UserContextHolder.getLoginOrgId(); + } + return orgId; + } + + @ApiModelProperty("平台编码") + private Integer platformCode; + @ApiModelProperty("所属机构ID") + private Long roleId; + @ApiModelProperty("是否分配 0否 1是") + private Integer allocation; + + @ApiModelProperty("微信二维码0:未上传 1:已上传 ") + private Integer wechatQrCodeUpload; + + public Integer getAllocation() { + if (Objects.isNull(allocation)) { + allocation = 1; + } + return allocation; + } +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/PlatformUserListQueryDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/PlatformUserListQueryDTO.java new file mode 100644 index 0000000..aba51f0 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/PlatformUserListQueryDTO.java @@ -0,0 +1,75 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.util.UserContextHolder; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import java.io.Serializable; +import java.util.Objects; + + +/** + * 平台用户信息查询dto + * + * @author Carlye + * @date 2021/08/03 + */ +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Data +@ToString +public class PlatformUserListQueryDTO implements Serializable { + + private static final long serialVersionUID = 8465879683905791458L; + @ApiModelProperty("账号") + private String username; + + @ApiModelProperty("用户昵称") + private String nickname; + + @ApiModelProperty("用户真实姓名") + private String realName; + + @ApiModelProperty("用户手机号") + private String phone; + + @ApiModelProperty("用户手机号绑定状态") + private Boolean phoneBinding; + + @ApiModelProperty("用户邮箱") + private String email; + + @ApiModelProperty("是否启用") + private Boolean enabled; + + @ApiModelProperty("状态:1.待激活,2已激活,3已注销") + private Integer status; + + @ApiModelProperty("当前登录机构ID") + private Long orgId; + + /**是否查所有。查所有传true,默认查非管理员**/ + private Boolean allUser; + + public Long getOrgId() { + if (Objects.isNull(orgId)) { + orgId = UserContextHolder.getLoginOrgId(); + } + return orgId; + } + + @ApiModelProperty("平台编码") + private Integer platformCode; + @ApiModelProperty("所属机构ID") + private Long roleId; + @ApiModelProperty("是否分配 0否 1是") + private Integer allocation; + + public Integer getAllocation() { + if (Objects.isNull(allocation)) { + allocation = 1; + } + return allocation; + } +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/RealNameTwoResponseDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/RealNameTwoResponseDTO.java new file mode 100644 index 0000000..316fd86 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/RealNameTwoResponseDTO.java @@ -0,0 +1,41 @@ +package com.newyetai.usercenter.user.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Date; + +/** + * @author fzp + * @date 2021年7月13日18:25:11 + */ + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class RealNameTwoResponseDTO { + + /** 用户Id **/ + private Long userId; + /** 姓名 **/ + private String realName; + /** 性别 **/ + private String sex; + /** 年龄 **/ + private int age; + /** 证件号 **/ + private String cardNo; + /** 身份证有效期起始日期 **/ + private Date idCardValidPeriodStart; + /** 身份证有效期结束日期 **/ + private Date idCardValidPeriodEnd; + + /** 身份证正面照片FileCode */ + private String positiveCardFileCode; + /** 身份证反面照片FileCode */ + private String inverseCardFileCode; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/ResetPwdDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/ResetPwdDTO.java new file mode 100644 index 0000000..c5b8225 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/ResetPwdDTO.java @@ -0,0 +1,38 @@ +package com.newyetai.usercenter.user.dto; + +import javax.validation.constraints.NotBlank; + +import com.newyetai.common.validation.annotation.Expression; +import com.newyetai.common.validation.constants.ValidProviderEnum; +import com.newyetai.usercenter.user.phone.constant.UserPhoneCodeOperateEnum; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@ApiModel(description = "重置密码") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public class ResetPwdDTO extends UserPhoneCodeDTO{ + + /** **/ + private static final long serialVersionUID = -354146751167115968L; + + @ApiModelProperty("密码") + @Expression(type = ValidProviderEnum.PASSWORD, message = "密码格式不正确") + private String password; + @ApiModelProperty("二次确认密码") + @NotBlank(message = "二次确认密码不能为空") + private String rePassword; + + public String getOperateType() { + return UserPhoneCodeOperateEnum.RESET_PWD.getOperate(); + + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/ResetSecurityCodeDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/ResetSecurityCodeDTO.java new file mode 100644 index 0000000..cd6cf65 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/ResetSecurityCodeDTO.java @@ -0,0 +1,37 @@ +package com.newyetai.usercenter.user.dto; + +import javax.validation.constraints.NotBlank; + +import com.newyetai.common.validation.annotation.Expression; +import com.newyetai.common.validation.constants.ValidProviderEnum; +import com.newyetai.usercenter.user.phone.constant.UserPhoneCodeOperateEnum; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@ApiModel(description = "重置密码") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public class ResetSecurityCodeDTO extends UserPhoneCodeDTO{ + + /** **/ + private static final long serialVersionUID = -354146751167115968L; + + @ApiModelProperty("安全码") + @Expression(type = ValidProviderEnum.PASSWORD, message = "安全码格式不正确") + private String securityCode; + @ApiModelProperty("二次安全码") + @NotBlank(message = "二次安全码不能为空") + private String resecurityCode; + + public String getOperateType() { + return UserPhoneCodeOperateEnum.RESET_SECURITY_CODE.getOperate(); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/SelectUserDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/SelectUserDTO.java new file mode 100644 index 0000000..da95548 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/SelectUserDTO.java @@ -0,0 +1,30 @@ +package com.newyetai.usercenter.user.dto; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "用户信息(供选择)") +@Builder +public class SelectUserDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 59302802862397459L; + + @ApiModelProperty("用户id") + private Long id; + + @ApiModelProperty("用户昵称") + private String nickname; + + @ApiModelProperty("用户姓名") + private String realName; +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/SuperChangePhoneDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/SuperChangePhoneDTO.java new file mode 100644 index 0000000..5e41302 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/SuperChangePhoneDTO.java @@ -0,0 +1,33 @@ +package com.newyetai.usercenter.user.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotNull; + +import com.newyetai.common.validation.annotation.Expression; +import com.newyetai.common.validation.constants.ValidProviderEnum; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2021-09-24 + */ +@ApiModel(description = "代管-换绑手机号") +@Data +@NoArgsConstructor +public class SuperChangePhoneDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = -1664185349533051511L; + + @ApiModelProperty("用户id") + @NotNull(message = "用户id不能为空") + private Long userId; + @ApiModelProperty("手机号") + @Expression(type = ValidProviderEnum.PHONE, message = "手机号格式不正确") + private String phone; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/SuperRealNameTwoAuthDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/SuperRealNameTwoAuthDTO.java new file mode 100644 index 0000000..b8d0dbc --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/SuperRealNameTwoAuthDTO.java @@ -0,0 +1,34 @@ +package com.newyetai.usercenter.user.dto; + +import javax.validation.constraints.NotBlank; + +import com.newyetai.common.annotation.trimAndUpper.TrimAndUpper; +import com.newyetai.common.dto.BaseOperateDTO; +import com.newyetai.common.validation.annotation.Expression; +import com.newyetai.common.validation.annotation.Phone; +import com.newyetai.common.validation.constants.ValidProviderEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +@ApiModel(description = "上级二要素-认证") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class SuperRealNameTwoAuthDTO extends BaseOperateDTO{ + + private static final long serialVersionUID = 932738794127665634L; + @ApiModelProperty("姓名") + @NotBlank(message = "姓名不能为空") + @TrimAndUpper + private String realName; + @ApiModelProperty("身份证号") + @Expression(type = ValidProviderEnum.CARD_NO, message = "身份证号不正确") + @TrimAndUpper + private String cardNo; + @ApiModelProperty("手机号") + @Phone + private String phone; +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserAuthDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserAuthDTO.java new file mode 100644 index 0000000..83674f8 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserAuthDTO.java @@ -0,0 +1,36 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.usercenter.authority.dto.RoleAllocationDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2021-05-24 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@ApiModel(description = "用户授权中间表") +public class UserAuthDTO extends BaseDTO { + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("授权大类") + private Integer authMainType ; + @ApiModelProperty("授权唯一id") + private String uniqueId ; + @ApiModelProperty("用户id") + private Long userId ; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserAuthOperateDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserAuthOperateDTO.java new file mode 100644 index 0000000..5babaf5 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserAuthOperateDTO.java @@ -0,0 +1,39 @@ +package com.newyetai.usercenter.user.dto; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import io.swagger.annotations.ApiModel; +import javax.validation.constraints.NotNull; +import com.newyetai.common.validation.Update; + +import com.newyetai.common.dto.BaseOperateDTO; + +/** + * @author sr on 2021-05-24 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "用户授权中间表操作") +public class UserAuthOperateDTO extends BaseOperateDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @NotNull(message = "id不能为空", groups = {Update.class}) + private Long id; + @ApiModelProperty("授权大类") + private Integer authMainType ; + @ApiModelProperty("授权唯一id") + private String uniqueId ; + @ApiModelProperty("用户id") + private Long userId ; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserAuthQueryDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserAuthQueryDTO.java new file mode 100644 index 0000000..61a8cae --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserAuthQueryDTO.java @@ -0,0 +1,39 @@ +package com.newyetai.usercenter.user.dto; + +import java.io.Serializable; +import java.util.Set; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import io.swagger.annotations.ApiModel; + +import com.newyetai.common.dto.PageQueryDTO; + +/** + * @author sr on 2021-05-24 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "用户授权中间表查询条件") +public class UserAuthQueryDTO extends PageQueryDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + @ApiModelProperty("授权大类") + private Integer authMainType ; + @ApiModelProperty("授权唯一id") + private String uniqueId ; + @ApiModelProperty("用户类型") + private Integer userType; + @ApiModelProperty("用户ids") + private Set userIds; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserBankAccountChangeReqDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserBankAccountChangeReqDTO.java new file mode 100644 index 0000000..a33459b --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserBankAccountChangeReqDTO.java @@ -0,0 +1,44 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.dto.BaseOperateDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import javax.validation.constraints.NotNull; + + +@EqualsAndHashCode(callSuper = true) +@ApiModel(description = "用户银行卡修改") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class UserBankAccountChangeReqDTO extends BaseOperateDTO{ + private static final long serialVersionUID = 6138358763847523428L; + + @ApiModelProperty(value = "用户ID",required = true) + @NotNull(message = "用户ID不能为空") + private Long userId; + + @ApiModelProperty(value = "历史银行卡号",required = true) + @NotNull(message = "历史银行卡号不能为空") + private String oldAccountNo; + + @ApiModelProperty(value = "新绑银行卡号",required = true) + @NotNull(message = "新绑银行卡号不能为空") + private String newAccountNo; + + @ApiModelProperty(value = "户名") + private String accountName; + + @ApiModelProperty(value = "银行名") + private String bankName; + + @ApiModelProperty(value = "开户行名") + private String bankBranchName; + + @ApiModelProperty(value = "是否默认账户") + private Boolean defaultAccount; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserBankAccountCreateReqDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserBankAccountCreateReqDTO.java new file mode 100644 index 0000000..8810fea --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserBankAccountCreateReqDTO.java @@ -0,0 +1,48 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.dto.BaseOperateDTO; +import com.newyetai.common.validation.annotation.Expression; +import com.newyetai.common.validation.constants.ValidProviderEnum; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + + +@EqualsAndHashCode(callSuper = true) +@ApiModel(description = "用户银行卡创建") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class UserBankAccountCreateReqDTO extends BaseOperateDTO{ + private static final long serialVersionUID = 6138358763847523428L; + + @ApiModelProperty(value = "用户ID",required = true) + private Long userId; + + @ApiModelProperty(value = "用户身份证",required = true) + @Expression(type = ValidProviderEnum.CARD_NO, message = "身份证号不正确") + private String cardNo; + + @ApiModelProperty(value = "银行卡号",required = true) + @NotNull(message = "用户银行卡号不能为空") + private String accountNo; + + @ApiModelProperty(value = "户名") + @NotBlank(message = "户名不能为空") + private String accountName; + + @ApiModelProperty(value = "银行名") + private String bankName; + + @ApiModelProperty(value = "开户行名") + private String bankBranchName; + + @ApiModelProperty(value = "是否默认账户") + private Boolean defaultAccount; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserBankAccountDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserBankAccountDTO.java new file mode 100644 index 0000000..90f3ea9 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserBankAccountDTO.java @@ -0,0 +1,43 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.usercenter.authority.dto.RoleAllocationDTO; + +import lombok.*; +import lombok.experimental.SuperBuilder; + +/** + * @author czy + * @date 2021-06-29 + */ + +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +@EqualsAndHashCode(callSuper = true) +public class UserBankAccountDTO extends BaseDTO { + + private static final long serialVersionUID = 3818282613956368311L; + /** 用户id **/ + private Long userId; + + /** 证件号 **/ + private String cardNo; + + /** 卡号 **/ + private String accountNo; + + /** 户名 **/ + private String accountName; + + /** 银行名 **/ + private String bankName; + + /** 开户行名 **/ + private String bankBranchName; + + /** 是否默认账户 **/ + private Boolean defaultAccount; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserBankAccountInfoDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserBankAccountInfoDTO.java new file mode 100644 index 0000000..b830041 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserBankAccountInfoDTO.java @@ -0,0 +1,45 @@ +package com.newyetai.usercenter.user.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; + + +@ApiModel(description = "用户银行卡创建") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class UserBankAccountInfoDTO implements Serializable { + private static final long serialVersionUID = 6138358763847523428L; + + @ApiModelProperty(value = "ID") + private Long id; + + @ApiModelProperty(value = "用户ID",required = true) + @NotNull(message = "用户ID不能为空") + private Long userId; + + @ApiModelProperty(value = "银行卡号",required = true) + @NotNull(message = "用户银行卡号不能为空") + private String accountNo; + + @ApiModelProperty(value = "户名") + private String accountName; + + @ApiModelProperty(value = "银行名") + private String bankName; + + @ApiModelProperty(value = "开户行名") + private String bankBranchName; + + @ApiModelProperty(value = "是否默认账户") + private Boolean defaultAccount; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserBankAccountModifyDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserBankAccountModifyDTO.java new file mode 100644 index 0000000..657aef0 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserBankAccountModifyDTO.java @@ -0,0 +1,36 @@ +package com.newyetai.usercenter.user.dto; + +import javax.validation.constraints.NotNull; + +import com.newyetai.common.dto.BaseOperateDTO; +import com.newyetai.common.validation.Update; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + + +@EqualsAndHashCode(callSuper = true) +@ApiModel(description = "用户银行卡修改") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class UserBankAccountModifyDTO extends BaseOperateDTO{ + private static final long serialVersionUID = 6138358763847523428L; + + @ApiModelProperty(value = "id",required = true) + @NotNull(message = "id不能为空") + private Long id; + + @ApiModelProperty(value = "开户行名") + private String bankBranchName; + + @ApiModelProperty(value = "是否默认账户") + private Boolean defaultAccount; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserBankAccountQueryDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserBankAccountQueryDTO.java new file mode 100644 index 0000000..fbad0b5 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserBankAccountQueryDTO.java @@ -0,0 +1,44 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.dto.PageQueryDTO; +import io.swagger.annotations.ApiModel; +import lombok.*; + +/** + * @author czy + * @date 2021-07-19 + */ + +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "用户银行账户信息查询DTO") +public class UserBankAccountQueryDTO extends PageQueryDTO { + + private static final long serialVersionUID = -4199087483393678322L; + private Long id; + + /** 用户id **/ + private Long userId; + + /** 卡号 **/ + private String accountNo; + + /** 户名 **/ + private String accountName; + + /** 银行名 **/ + private String bankName; + + /** 开户行名 **/ + private String bankBranchName; + + /** 是否默认账户 **/ + private Boolean defaultAccount; + + /** 未注销用户 **/ + private Boolean unCanceledUser; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserBankCardFourVerificationDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserBankCardFourVerificationDTO.java new file mode 100644 index 0000000..223985e --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserBankCardFourVerificationDTO.java @@ -0,0 +1,44 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.annotation.trimAndUpper.TrimAndUpper; +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.usercenter.authority.dto.RoleAllocationDTO; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author czy + * @date 2021-06-23 + */ + +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class UserBankCardFourVerificationDTO extends BaseDTO { + + /** 用户Id **/ + private Long userId; + /** 姓名 **/ + private String realName; + /** 证件号 **/ + @TrimAndUpper + private String cardNo; + /** 银行卡号 **/ + @TrimAndUpper + private String bankAccountNo; + /** 手机号 **/ + @TrimAndUpper + private String phone; + /** 认证源id **/ + private Long sourceVerifyId; + /** 状态 **/ + private Integer status; + /** 失败原因 **/ + private String failReason; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserBankCardFourVerificationOperateDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserBankCardFourVerificationOperateDTO.java new file mode 100644 index 0000000..47df59c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserBankCardFourVerificationOperateDTO.java @@ -0,0 +1,39 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.dto.BaseOperateDTO; +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author czy + * @date 2021-07-19 + */ + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "用户四要素操作") +public class UserBankCardFourVerificationOperateDTO extends BaseOperateDTO { + + /** 用户Id **/ + private Long userId; + /** 姓名 **/ + private String realName; + /** 证件号 **/ + private String cardNo; + /** 银行卡号 **/ + private String bankAccountNo; + /** 手机号 **/ + private String phone; + /** 认证源id **/ + private Long sourceVerifyId; + /** 状态 **/ + private Integer status; + /** 失败原因 **/ + private String failReason; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserBankCardFourVerificationQueryDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserBankCardFourVerificationQueryDTO.java new file mode 100644 index 0000000..720aaad --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserBankCardFourVerificationQueryDTO.java @@ -0,0 +1,41 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.dto.PageQueryDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2021-08-04 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "用户四要素查询条件") +public class UserBankCardFourVerificationQueryDTO extends PageQueryDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + @ApiModelProperty("用户Id") + private Long userId; + @ApiModelProperty("姓名") + private String realName; + @ApiModelProperty("证件号") + private String cardNo; + @ApiModelProperty("银行卡号") + private String bankAccountNo; + @ApiModelProperty("手机号") + private String phone; + @ApiModelProperty("状态") + private Integer status; + + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserBankCardThreeVerificationCreateDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserBankCardThreeVerificationCreateDTO.java new file mode 100644 index 0000000..3047597 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserBankCardThreeVerificationCreateDTO.java @@ -0,0 +1,48 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.annotation.trimAndUpper.TrimAndUpper; +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.common.dto.BaseOperateDTO; +import com.newyetai.common.validation.annotation.Expression; +import com.newyetai.common.validation.constants.ValidProviderEnum; + +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import javax.validation.constraints.NotBlank; + +/** + * @author czy + * @date 2021-06-23 + */ + +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class UserBankCardThreeVerificationCreateDTO extends BaseOperateDTO { + + private static final long serialVersionUID = 2760612675601900048L; + /** 姓名 **/ + @NotBlank(message = "姓名不能为空") + @TrimAndUpper + private String realName; + /** 证件号 **/ + @TrimAndUpper + @Expression(type = ValidProviderEnum.CARD_NO, message = "身份证号不正确") + private String cardNo; + /** 银行卡号 **/ + @TrimAndUpper + @NotBlank(message = "银行卡号不能为空") + private String bankAccountNo; + + /** 添加卡时可以附带以下信息保存 **/ + @ApiModelProperty(value = "银行名") + private String bankName; + @ApiModelProperty(value = "开户行名") + private String bankBranchName; + @ApiModelProperty(value = "是否默认账户") + private Boolean defaultAccount; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserBankCardThreeVerificationDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserBankCardThreeVerificationDTO.java new file mode 100644 index 0000000..fa93b86 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserBankCardThreeVerificationDTO.java @@ -0,0 +1,45 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.annotation.trimAndUpper.TrimAndUpper; +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.common.validation.annotation.Expression; +import com.newyetai.common.validation.constants.ValidProviderEnum; +import com.newyetai.usercenter.authority.dto.RoleAllocationDTO; + +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.SuperBuilder; + +import javax.validation.constraints.NotBlank; + +/** + * @author czy + * @date 2021-06-23 + */ + +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class UserBankCardThreeVerificationDTO extends BaseDTO { + + private static final long serialVersionUID = 2760612675601900048L; + /** 用户Id **/ + private Long userId; + /** 姓名 **/ + private String realName; + /** 证件号 **/ + @TrimAndUpper + private String cardNo; + /** 银行卡号 **/ + @TrimAndUpper + private String bankAccountNo; + /** 认证源id **/ + private Long sourceVerifyId; + /** 状态 **/ + private Integer status; + /** 失败原因 **/ + private String failReason; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserBankCardThreeVerificationOperateDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserBankCardThreeVerificationOperateDTO.java new file mode 100644 index 0000000..7ae9e92 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserBankCardThreeVerificationOperateDTO.java @@ -0,0 +1,37 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.dto.BaseOperateDTO; +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author czy + * @date 2021-07-19 + */ + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "用户三要素操作") +public class UserBankCardThreeVerificationOperateDTO extends BaseOperateDTO { + + /** 用户Id **/ + private Long userId; + /** 姓名 **/ + private String realName; + /** 证件号 **/ + private String cardNo; + /** 银行卡号 **/ + private String bankAccountNo; + /** 认证源id **/ + private Long sourceVerifyId; + /** 状态 **/ + private Integer status; + /** 失败原因 **/ + private String failReason; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserBankCardThreeVerificationQueryDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserBankCardThreeVerificationQueryDTO.java new file mode 100644 index 0000000..27ed932 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserBankCardThreeVerificationQueryDTO.java @@ -0,0 +1,40 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.dto.PageQueryDTO; +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 sr on 2021-08-04 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "用户三要素查询条件") +public class UserBankCardThreeVerificationQueryDTO extends PageQueryDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + @ApiModelProperty("用户Id") + private Long userId; + @ApiModelProperty("姓名") + private String realName; + @ApiModelProperty("证件号") + private String cardNo; + @ApiModelProperty("银行卡号") + private String bankAccountNo; + @ApiModelProperty("状态") + private Integer status; + + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserCancelApplyReqDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserCancelApplyReqDTO.java new file mode 100644 index 0000000..a0d378b --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserCancelApplyReqDTO.java @@ -0,0 +1,24 @@ +package com.newyetai.usercenter.user.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotBlank; + +import lombok.Data; + +/** + * @description: 用户注销申请dto + * @author: guixinman + * @create: 2024-07-03 17:24 + **/ +@Data +public class UserCancelApplyReqDTO implements Serializable { + + /** + * 注销原因类型 数据字典 + */ + @NotBlank(message = "申请原因类型必填") + private String cancellationType; + + private String remark; +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserCancelDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserCancelDTO.java new file mode 100644 index 0000000..689e7dd --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserCancelDTO.java @@ -0,0 +1,37 @@ +package com.newyetai.usercenter.user.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +import java.io.Serializable; + +import com.newyetai.common.dto.BaseDTO; + +@NoArgsConstructor +@AllArgsConstructor +@Data +@SuperBuilder +public class UserCancelDTO extends BaseDTO { + private static final long serialVersionUID = -6017193900382901567L; + /** + * 申请状态 1:已申请 2:已注销 + */ + private Integer status; + + /** + * 昵称 + */ + private String nickName; + + /** + * 真实姓名 + */ + private String realName; + + private String phone; + + private String cardNo; +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserCancelPageQueryDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserCancelPageQueryDTO.java new file mode 100644 index 0000000..dc1e92b --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserCancelPageQueryDTO.java @@ -0,0 +1,24 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.dto.PageQueryDTO; +import lombok.*; + +@NoArgsConstructor +@AllArgsConstructor +@Data +@Builder +@EqualsAndHashCode(callSuper = true) +public class UserCancelPageQueryDTO extends PageQueryDTO { + private static final long serialVersionUID = -6017193900382901567L; + /** + * 申请状态 1:已申请 2:已注销 + */ + private Integer status; + + /** + * 名字(模糊匹配) + */ + private String nameLike; + + private Long userId; +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserCancelReqDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserCancelReqDTO.java new file mode 100644 index 0000000..3bf8a13 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserCancelReqDTO.java @@ -0,0 +1,32 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.dto.BaseOperateDTO; +import com.newyetai.usercenter.user.phone.constant.UserPhoneCodeOperateEnum; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + * @author sr on 2021-05-24 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "用户注销操作") +public class UserCancelReqDTO extends BaseOperateDTO{ + + private static final long serialVersionUID = 5879202711902198878L; + + + + @ApiModelProperty("userId") + @NotNull(message = "userId不能为空") + private Long userId; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserConfigDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserConfigDTO.java new file mode 100644 index 0000000..8a547d7 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserConfigDTO.java @@ -0,0 +1,37 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.dto.BaseDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2021-08-12 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@ApiModel(description = "用户配置") +public class UserConfigDTO extends BaseDTO { + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("用户id") + private Long userId; + @ApiModelProperty("编码") + private String configCode; + @ApiModelProperty("配置值") + private String configValue; + @ApiModelProperty("备注") + private String remark; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserConfigOperateDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserConfigOperateDTO.java new file mode 100644 index 0000000..82a5eb9 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserConfigOperateDTO.java @@ -0,0 +1,46 @@ +package com.newyetai.usercenter.user.dto; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import io.swagger.annotations.ApiModel; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; + +import com.newyetai.common.dto.BaseOperateDTO; + +/** + * @author sr on 2021-08-12 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "用户配置操作") +public class UserConfigOperateDTO extends BaseOperateDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @NotNull(message = "id不能为空", groups = {Update.class}) + private Long id; + @ApiModelProperty("用户id") + @NotNull(message = "id不能为空", groups = {Create.class}) + private Long userId; + @ApiModelProperty("编码") + @NotBlank(message = "编码不能为空", groups = {Create.class}) + private String configCode; + @ApiModelProperty("配置值") + @NotBlank(message = "配置值不能为空", groups = {Create.class}) + private String configValue; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserConfigQueryDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserConfigQueryDTO.java new file mode 100644 index 0000000..0d3eae8 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserConfigQueryDTO.java @@ -0,0 +1,34 @@ +package com.newyetai.usercenter.user.dto; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import io.swagger.annotations.ApiModel; + +import com.newyetai.common.dto.PageQueryDTO; + +/** + * @author sr on 2021-08-12 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "用户配置查询条件") +public class UserConfigQueryDTO extends PageQueryDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + @ApiModelProperty("用户id") + private Long userId; + @ApiModelProperty("编码") + private String configCode; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserDTO.java new file mode 100644 index 0000000..a3707b8 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserDTO.java @@ -0,0 +1,127 @@ +package com.newyetai.usercenter.user.dto; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.newyetai.common.constant.SystemCodeEnum; +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.usercenter.authority.dto.RoleAllocationDTO; +import com.newyetai.usercenter.user.constant.UserSourceEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.SuperBuilder; + +import org.apache.commons.lang3.StringUtils; + +import java.util.Date; + +/** + * @author czy + * @date 2021-06-10 + */ + +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@ApiModel(description = "用户", value = "UcUserDTO") +public class UserDTO extends BaseDTO { + + private static final long serialVersionUID = 19560736481829489L; + + @ApiModelProperty("账号") + private String username; + + @JsonIgnore + @ApiModelProperty("密码") + private String password; + + @ApiModelProperty("是否已初始密码") + private Boolean initialedPassword; + + @ApiModelProperty("用户类型:1企业用户,2个人用户") + private Integer type; + + @ApiModelProperty("是否超管") + private Boolean supeiror; + + @ApiModelProperty("安全码") + private String securityCode; + + @ApiModelProperty("昵称") + private String nickname; + + @ApiModelProperty("头像") + private String avatar; + + @ApiModelProperty("手机号码") + private String phone; + + @ApiModelProperty("手机号绑定状态") + private Boolean phoneBinding; + + @ApiModelProperty("真实姓名") + private String realName; + + @ApiModelProperty("身份证号") + private String cardNo; + + @ApiModelProperty("是否实名") + private Boolean authenticated ; + + @ApiModelProperty("状态:1.待激活,2已激活,3已注销") + private Integer status ; + + @ApiModelProperty("邮箱") + private String email; + + @ApiModelProperty("用户所在地") + private String address; + + @ApiModelProperty("学历") + private Integer education; + + @ApiModelProperty("是否启用") + private Boolean enabled; + + @ApiModelProperty("账号是否未过期") + private Boolean accountNonExpired; + + @ApiModelProperty("是否未锁定") + private Boolean accountNonLocked; + + @ApiModelProperty("凭据是否未过期") + private Boolean credentialsNonExpired; + + @ApiModelProperty("平台编码") + private Integer platformCode; + + @ApiModelProperty("微信二维码") + private String wechatQrCode; + + @ApiModelProperty("是否申请注销 null:未申请 1:已申请 2:已通过") + private Integer cancelStatus; + + /** 性别:1男2女 **/ + private Integer gender; + + /** 生日 **/ + private Date birthday; + + @ApiModelProperty("个人用户来源:1.招聘微信小程序 2.灵活就业微信小程序 3.灵活就业页面导入") + public Integer getUserSource() { + Integer platformCode = getPlatformCode(); + if (SystemCodeEnum.ALITA_TASK.getCode().equals(platformCode)) { + return UserSourceEnum.FLEXIBLE.getStatus(); + } else if (SystemCodeEnum.ALITA_RECRUIT.getCode().equals(platformCode)) { + return UserSourceEnum.APPLET.getStatus(); + } else { + return UserSourceEnum.FLEXIBLE_IMPORT.getStatus(); + } + } + + public void setPassword(String password) { + this.password = password; + this.initialedPassword = StringUtils.isNotBlank(password); + } +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserDetailQueryDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserDetailQueryDTO.java new file mode 100644 index 0000000..4e6c701 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserDetailQueryDTO.java @@ -0,0 +1,39 @@ +package com.newyetai.usercenter.user.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotBlank; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 登录用户查询 + * @author sr on 2020-06-15 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class UserDetailQueryDTO implements Serializable { + + /** + * + **/ + private static final long serialVersionUID = -8912916458925736955L; + + private Long userId; + + private Integer userType; + + /** (暂)对外网关需要feign匿名获取用户信息,账号不能为空 **/ + @NotBlank(message = "账号不能为空") + private String username; + + private String phone; + + private Long orgId; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserExtendStatusDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserExtendStatusDTO.java new file mode 100644 index 0000000..66209c6 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserExtendStatusDTO.java @@ -0,0 +1,38 @@ +package com.newyetai.usercenter.user.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author czy + * @date 2021-06-10 + */ + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class UserExtendStatusDTO { + + @ApiModelProperty("用户Id") + private Long userId; + + @ApiModelProperty("实名认证") + private Boolean authenticatedStatus; + + @ApiModelProperty("证件正反面照上传") + private Boolean cardUploadStatus; + + @ApiModelProperty("银行卡认证(三要素)") + private Integer bankCardAuthStatus; + + @ApiModelProperty("手机绑定") + private Boolean phoneBindStatus; + + @ApiModelProperty("微信绑定") + private Boolean wxBindStatus; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserExtensionDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserExtensionDTO.java new file mode 100644 index 0000000..ca7c2b7 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserExtensionDTO.java @@ -0,0 +1,41 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.usercenter.authority.dto.RoleAllocationDTO; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author czy + * @date 2021-06-15 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class UserExtensionDTO extends BaseDTO { + + @ApiModelProperty(value = "userId") + private Long userId; + + @ApiModelProperty(value = "常住地区") + private String residenceAddress; + + @ApiModelProperty(value = "技能标签") + private String techniqueTag; + + @ApiModelProperty("简历附件名称") + private String fileName; + + @ApiModelProperty("简历附件编码") + private String fileCode; + + @ApiModelProperty("新冠疫苗") + private Integer covidVaccine; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserExtensionOperateDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserExtensionOperateDTO.java new file mode 100644 index 0000000..ef4fc3b --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserExtensionOperateDTO.java @@ -0,0 +1,44 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.dto.BaseOperateDTO; +import com.newyetai.common.validation.Update; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author czy + * @date 2021-06-15 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel("用户扩展信息") +public class UserExtensionOperateDTO extends BaseOperateDTO { + + @ApiModelProperty(value = "常住地区") + private String residenceAddress; + + @ApiModelProperty(value = "技能标签") + private String techniqueTag; + + @ApiModelProperty("简历附件名称") + private String fileName; + + @ApiModelProperty("简历附件编码") + private String fileCode; + + @ApiModelProperty("新冠疫苗") + private Integer covidVaccine; + + /** + * 微信二维码 + */ + @ApiModelProperty("微信二维码") + private String wechatQrCode; +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserFactorVerifyDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserFactorVerifyDTO.java new file mode 100644 index 0000000..286b4a5 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserFactorVerifyDTO.java @@ -0,0 +1,38 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.usercenter.authority.dto.RoleAllocationDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author czy + * @date 2021-06-22 + */ +@ApiModel("用户信息要素认证") +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class UserFactorVerifyDTO extends BaseDTO { + + @ApiModelProperty("姓名") + private String realName; + @ApiModelProperty("证件号") + private String cardNo; + @ApiModelProperty("") + private String bankAccountNo; + @ApiModelProperty("") + private String phone; + @ApiModelProperty("") + private Integer status; + @ApiModelProperty("") + private Integer authenticationSource; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserIdentityPhotoDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserIdentityPhotoDTO.java new file mode 100644 index 0000000..5b3d638 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserIdentityPhotoDTO.java @@ -0,0 +1,41 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.usercenter.authority.dto.RoleAllocationDTO; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2021-05-24 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@ApiModel(description = "用户证件正反面") +public class UserIdentityPhotoDTO extends BaseDTO { + + /** **/ + private static final long serialVersionUID = 1L; + + /** 用户id */ + private Long userId; + /** 正面照 */ + private String frontFileCode; + /** 反面照 */ + private String backFileCode; + /** 状态 */ + private Integer status; + + /** 备注(失败状态时,此处为失败原因) */ + private String remark; + + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserIdentityPhotoInfoDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserIdentityPhotoInfoDTO.java new file mode 100644 index 0000000..e8d8c8d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserIdentityPhotoInfoDTO.java @@ -0,0 +1,60 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.usercenter.authority.dto.RoleAllocationDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.Date; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author czy + * @date 2021-06-11 + */ + +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +@ApiModel("用户证件信息") +public class UserIdentityPhotoInfoDTO extends BaseDTO { + + @ApiModelProperty("证件照片id") + private Long id; + + @ApiModelProperty("用户id") + private Long userId; + + @ApiModelProperty("正面照片文件编码") + private String frontFileCode; + + @ApiModelProperty("背面照片文件编码") + private String backFileCode; + + @ApiModelProperty("姓名") + private String realName; + + @ApiModelProperty("性别(0-女 1-男)") + private Integer gender; + + @ApiModelProperty("年龄") + private Integer age; + + @ApiModelProperty("身份证号") + private String cardNo; + + @ApiModelProperty("身份证有效期起始日期") + private Date idCardValidPeriodStart; + + @ApiModelProperty("身份证有效期结束日期") + private Date idCardValidPeriodEnd; + + @ApiModelProperty("状态") + private Integer status; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserIdentityPhotoOperateDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserIdentityPhotoOperateDTO.java new file mode 100644 index 0000000..a599a27 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserIdentityPhotoOperateDTO.java @@ -0,0 +1,43 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.dto.BaseOperateDTO; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2021-05-24 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "用户证件正反面操作") +public class UserIdentityPhotoOperateDTO extends BaseOperateDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("用户Id") + private Long userId; + + @ApiModelProperty("正面照片文件编码") + @NotNull(message = "正面照片文件编码不能为空", groups = {Create.class}) + private String frontFileCode; + + @ApiModelProperty("背面照片文件编码") + @NotNull(message = "背面照片文件编码不能为空", groups = {Create.class}) + private String backFileCode; + + @ApiModelProperty("失败原因") + private String failReason; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserIdentityPhotoQueryDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserIdentityPhotoQueryDTO.java new file mode 100644 index 0000000..cc4efc8 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserIdentityPhotoQueryDTO.java @@ -0,0 +1,37 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.dto.PageQueryDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import java.io.Serializable; +import java.util.Set; + +/** + * @author sr on 2021-05-24 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@EqualsAndHashCode(callSuper = true) +@ApiModel(description = "用户证件正反面查询条件") +public class UserIdentityPhotoQueryDTO extends PageQueryDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("用户Id") + private Long userId; + + @ApiModelProperty("状态") + private Integer status; + + @ApiModelProperty("用户Ids") + private Set userIds; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserOperateDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserOperateDTO.java new file mode 100644 index 0000000..4298fff --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserOperateDTO.java @@ -0,0 +1,35 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.dto.BaseOperateDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +/** + * @author sr on 2021-05-24 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "用户操作") +public class UserOperateDTO extends BaseOperateDTO{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("昵称") + private String nickname; + + @ApiModelProperty("头像") + private String avatar; + + @ApiModelProperty("邮箱") + private String email; + + @ApiModelProperty("用户所在地") + private String address; + @ApiModelProperty("学历") + private Integer education; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserPhoneCodeDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserPhoneCodeDTO.java new file mode 100644 index 0000000..5d8a625 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserPhoneCodeDTO.java @@ -0,0 +1,25 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.usercenter.user.phone.dto.PhoneCodeDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@ApiModel(description = "用户验证短信验证码-不同操作类型") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public abstract class UserPhoneCodeDTO extends PhoneCodeDTO implements IUserPhoneCode{ + + /** **/ + private static final long serialVersionUID = -354146751167115968L; + + @ApiModelProperty("用户类型(未登录必填)") + private Integer userType; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserPhoneCodeSmsCaptchaDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserPhoneCodeSmsCaptchaDTO.java new file mode 100644 index 0000000..ad2c033 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserPhoneCodeSmsCaptchaDTO.java @@ -0,0 +1,29 @@ +package com.newyetai.usercenter.user.dto; + +import javax.validation.constraints.NotBlank; + +import com.newyetai.usercenter.user.phone.dto.CaptchaPhoneCodeSmsDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@ApiModel(description = "用户获取验证码(带防水墙)-不同操作类型") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public class UserPhoneCodeSmsCaptchaDTO extends CaptchaPhoneCodeSmsDTO implements IUserPhoneCodeSms{ + + /** **/ + private static final long serialVersionUID = -354146751167115968L; + + @ApiModelProperty("用户类型(未登录必填)") + private Integer userType; + @NotBlank(message = "操作类型不能为空") + private String operateType; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserPhoneCodeSmsDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserPhoneCodeSmsDTO.java new file mode 100644 index 0000000..2d9202b --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserPhoneCodeSmsDTO.java @@ -0,0 +1,31 @@ +package com.newyetai.usercenter.user.dto; + +import javax.validation.constraints.NotBlank; + +import com.newyetai.usercenter.user.phone.constant.UserPhoneCodeOperateEnum; +import com.newyetai.usercenter.user.phone.dto.PhoneCodeSmsDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@ApiModel(description = "用户发送短信验证码-不同操作类型") +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public class UserPhoneCodeSmsDTO extends PhoneCodeSmsDTO implements IUserPhoneCodeSms{ + + /** **/ + private static final long serialVersionUID = -354146751167115968L; + + @ApiModelProperty("用户类型(未登录必填)") + private Integer userType; + /** {@link UserPhoneCodeOperateEnum} **/ + @NotBlank(message = "操作类型不能为空") + private String operateType; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserPhoneThreeVerificationDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserPhoneThreeVerificationDTO.java new file mode 100644 index 0000000..74e9d85 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserPhoneThreeVerificationDTO.java @@ -0,0 +1,47 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.annotation.trimAndUpper.TrimAndUpper; +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.common.validation.annotation.Expression; +import com.newyetai.common.validation.constants.ValidProviderEnum; +import com.newyetai.usercenter.authority.dto.RoleAllocationDTO; + +import lombok.*; +import lombok.experimental.SuperBuilder; + +import javax.validation.constraints.NotBlank; + +/** + * @author czy + * @date 2021-06-23 + */ + +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class UserPhoneThreeVerificationDTO extends BaseDTO { + + private static final long serialVersionUID = 2760612675601900048L; + /** 用户Id **/ + private Long userId; + /** 姓名 **/ + @NotBlank(message = "姓名不能为空") + private String realName; + /** 证件号 **/ + @TrimAndUpper + @Expression(type = ValidProviderEnum.CARD_NO, message = "身份证号不正确") + private String cardNo; + /** 银行卡号 **/ + @TrimAndUpper + @NotBlank(message = "手机号不能为空") + private String phone; + /** 认证源id **/ + private Long sourceVerifyId; + /** 状态 **/ + private Integer status; + /** 失败原因 **/ + private String failReason; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserPhoneThreeVerificationOperateDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserPhoneThreeVerificationOperateDTO.java new file mode 100644 index 0000000..73ae592 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserPhoneThreeVerificationOperateDTO.java @@ -0,0 +1,38 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.dto.BaseOperateDTO; +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author czy + * @date 2021-07-19 + */ + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "用户三要素操作") +public class UserPhoneThreeVerificationOperateDTO extends BaseOperateDTO { + + private static final long serialVersionUID = -2410402053001109346L; + /** 用户Id **/ + private Long userId; + /** 姓名 **/ + private String realName; + /** 证件号 **/ + private String cardNo; + /** 银行卡号 **/ + private String phone; + /** 认证源id **/ + private Long sourceVerifyId; + /** 状态 **/ + private Integer status; + /** 失败原因 **/ + private String failReason; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserPhoneThreeVerificationQueryDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserPhoneThreeVerificationQueryDTO.java new file mode 100644 index 0000000..0922509 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserPhoneThreeVerificationQueryDTO.java @@ -0,0 +1,38 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.dto.PageQueryDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import java.io.Serializable; + +/** + * @author sr on 2021-08-04 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "用户三要素查询条件") +public class UserPhoneThreeVerificationQueryDTO extends PageQueryDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + @ApiModelProperty("用户Id") + private Long userId; + @ApiModelProperty("姓名") + private String realName; + @ApiModelProperty("证件号") + private String cardNo; + @ApiModelProperty("手机号") + private String phone; + @ApiModelProperty("状态") + private Integer status; + + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserPostalInfoDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserPostalInfoDTO.java new file mode 100644 index 0000000..255147e --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserPostalInfoDTO.java @@ -0,0 +1,47 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.dto.BaseDTO; + +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; +import com.newyetai.usercenter.authority.dto.RoleAllocationDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +import javax.validation.constraints.NotNull; + +/** + * @author fzp on 2022-01-19 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@ApiModel(description = "用户邮寄信息") +public class UserPostalInfoDTO extends BaseDTO { + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("是否默认") + private Boolean defaulted; + @ApiModelProperty("收货人") + private String name; + @ApiModelProperty("手机号") + private String phone; + @ApiModelProperty("地区编号") + private String addressCode; + @ApiModelProperty("地区名称") + private String addressName; + @ApiModelProperty("详细地址") + private String addressDetail; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserPostalInfoOperateDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserPostalInfoOperateDTO.java new file mode 100644 index 0000000..920049d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserPostalInfoOperateDTO.java @@ -0,0 +1,51 @@ +package com.newyetai.usercenter.user.dto; + +import java.io.Serializable; + +import com.newyetai.common.validation.Create; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import io.swagger.annotations.ApiModel; +import javax.validation.constraints.NotNull; +import com.newyetai.common.validation.Update; + +import com.newyetai.common.dto.BaseOperateDTO; + +/** + * @author fzp on 2022-01-19 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "用户邮寄信息操作") +public class UserPostalInfoOperateDTO extends BaseOperateDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @NotNull(message = "id不能为空", groups = {Update.class}) + private Long id; + + @ApiModelProperty("是否默认") + private Boolean defaulted; + @NotNull(message = "收货人不能为空", groups = {Update.class, Create.class}) + @ApiModelProperty("收货人") + private String name; + @NotNull(message = "手机号不能为空", groups = {Update.class, Create.class}) + @ApiModelProperty("手机号") + private String phone; + @NotNull(message = "地区编号不能为空", groups = {Update.class, Create.class}) + @ApiModelProperty("地区编号") + private String addressCode; + @NotNull(message = "地区名称不能为空", groups = {Update.class, Create.class}) + @ApiModelProperty("地区名称") + private String addressName; + @ApiModelProperty("详细地址") + private String addressDetail; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserPostalInfoQueryDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserPostalInfoQueryDTO.java new file mode 100644 index 0000000..6f5669e --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserPostalInfoQueryDTO.java @@ -0,0 +1,43 @@ +package com.newyetai.usercenter.user.dto; + +import java.io.Serializable; + +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.Update; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import io.swagger.annotations.ApiModel; + +import com.newyetai.common.dto.PageQueryDTO; + +import javax.validation.constraints.NotNull; + +/** + * @author fzp on 2022-01-19 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "用户邮寄信息查询条件") +public class UserPostalInfoQueryDTO extends PageQueryDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("是否默认") + private Boolean defaulted; + @ApiModelProperty("收货人") + private String name; + @ApiModelProperty("手机号") + private String phone; + @ApiModelProperty("创建人ID") + private Long createBy; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserQueryByRoleDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserQueryByRoleDTO.java new file mode 100644 index 0000000..5feee51 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserQueryByRoleDTO.java @@ -0,0 +1,35 @@ +package com.newyetai.usercenter.user.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "用户信息查询(通过角色相关信息)") +@Builder +public class UserQueryByRoleDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = -2498786188653251282L; + + @ApiModelProperty("标准角色类型") + @NotBlank(message = "标准角色类型不能为空") + private String roleStandardTypeCode; + + @ApiModelProperty("平台编码") + private Integer platformCode; + + @ApiModelProperty("机构id") + private Long orgId; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserQueryDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserQueryDTO.java new file mode 100644 index 0000000..5f78375 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserQueryDTO.java @@ -0,0 +1,118 @@ +package com.newyetai.usercenter.user.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.newyetai.common.annotation.trimAndUpper.TrimAndUpper; +import com.newyetai.common.constant.SystemCodeEnum; +import com.newyetai.common.dto.PageQueryDTO; +import com.newyetai.usercenter.user.constant.UserSourceEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; +import java.util.Set; + +/** + * @author czy + * @date 2021-06-10 + */ + +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "用户信息查询") +@Builder +public class UserQueryDTO extends PageQueryDTO { + + /** **/ + private static final long serialVersionUID = 2636844352691455030L; + + @ApiModelProperty("用户id") + private Long id; + + @ApiModelProperty("用户ids") + private Set ids; + + @ApiModelProperty("用户类型:1企业用户,2个人用户") + private Integer type; + + @ApiModelProperty("手机号码") + @TrimAndUpper(TrimAndUpper.ExecuteType.TRIM) + private String phone; + + @ApiModelProperty("手机号绑定状态") + private Boolean phoneBinding; + + @ApiModelProperty("身份证号") + @TrimAndUpper(TrimAndUpper.ExecuteType.TRIM) + private String cardNo; + + @ApiModelProperty("未注销") + private Boolean uncanceled; + + @ApiModelProperty("姓名(模糊匹配)") + @TrimAndUpper(TrimAndUpper.ExecuteType.TRIM) + private String realNameLike; + + @ApiModelProperty("账号") + @TrimAndUpper(TrimAndUpper.ExecuteType.TRIM) + private String usernameLike; + + @ApiModelProperty("昵称") + @TrimAndUpper(TrimAndUpper.ExecuteType.TRIM) + private String nicknameLike; + + @ApiModelProperty("邮箱") + @TrimAndUpper(TrimAndUpper.ExecuteType.TRIM) + private String emailLike; + + @ApiModelProperty("是否启用") + private Boolean enabled; + + @ApiModelProperty("状态:1.待激活,2已激活,3已注销") + private Integer status; + + @ApiModelProperty("是否申请注销 null:未申请 1:已申请 2:已通过") + private Integer cancelStatus; + + @ApiModelProperty("个人用户来源:1.招聘微信小程序 2.灵活就业微信小程序 3.灵活就业页面导入") + private Integer userSource; + + /** + * 是否实名 + */ + private Boolean authenticated; + + @ApiModelProperty("创建时间起") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat( + shape = JsonFormat.Shape.STRING, + pattern = "yyyy-MM-dd HH:mm:ss", + timezone = "GMT+8" + ) + private Date createTimeStart; + @ApiModelProperty("创建时间止") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat( + shape = JsonFormat.Shape.STRING, + pattern = "yyyy-MM-dd HH:mm:ss", + timezone = "GMT+8" + ) + private Date createTimeEnd; + + @ApiModelProperty("重写个人用户来源转换成平台编码") + public void rewriteUserSource(Integer platformCode) { + if (UserSourceEnum.FLEXIBLE.getStatus().equals(platformCode)) { + this.userSource = SystemCodeEnum.ALITA_TASK.getCode(); + } else if (UserSourceEnum.APPLET.getStatus().equals(platformCode)) { + this.userSource = SystemCodeEnum.ALITA_RECRUIT.getCode(); + } else { + this.userSource = null; + } + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserRealNameTwoAuthCreateDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserRealNameTwoAuthCreateDTO.java new file mode 100644 index 0000000..97ee069 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserRealNameTwoAuthCreateDTO.java @@ -0,0 +1,35 @@ +package com.newyetai.usercenter.user.dto; + +import javax.validation.constraints.NotBlank; + +import com.newyetai.common.annotation.trimAndUpper.TrimAndUpper; +import com.newyetai.common.dto.BaseOperateDTO; +import com.newyetai.common.validation.annotation.Expression; +import com.newyetai.common.validation.constants.ValidProviderEnum; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class UserRealNameTwoAuthCreateDTO extends BaseOperateDTO { + + /** **/ + private static final long serialVersionUID = -5584391504640898412L; + + /** 姓名 **/ + @NotBlank(message = "姓名不能为空") + @TrimAndUpper + private String realName; + /** 证件号 **/ + @TrimAndUpper + @Expression(type = ValidProviderEnum.CARD_NO, message = "身份证号不正确") + private String cardNo; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserRegisterCodeDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserRegisterCodeDTO.java new file mode 100644 index 0000000..b6656e4 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserRegisterCodeDTO.java @@ -0,0 +1,28 @@ +package com.newyetai.usercenter.user.dto; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +@ApiModel(description = "生成(当前自己)用户注册邀请码") +public class UserRegisterCodeDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 2118502786779163962L; + + @ApiModelProperty("系统应用标识(为空则用请求域名匹配)") +// @NotNull(message = "系统应用标识不能为空") + private Integer platformCode; + @ApiModelProperty("关联id(小程序码id)") + private Long unionId; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserRegisterCodeInfoDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserRegisterCodeInfoDTO.java new file mode 100644 index 0000000..529dd86 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserRegisterCodeInfoDTO.java @@ -0,0 +1,35 @@ +package com.newyetai.usercenter.user.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotNull; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "用户注册邀请码信息") +@SuperBuilder +public class UserRegisterCodeInfoDTO extends UserRegisterCodeDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 2118502786779163962L; + + @ApiModelProperty("邀请人用户类型") + @NotNull(message = "邀请人id不能为空") + private Integer inviterType; + + @ApiModelProperty("邀请人id") + @NotNull(message = "邀请人id不能为空") + private Long inviterId; + + @ApiModelProperty("邀请人机构id(机构用户该属性不能为空)") + private Long inviterOrgId; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserRegisterCreateDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserRegisterCreateDTO.java new file mode 100644 index 0000000..0fa6d1a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserRegisterCreateDTO.java @@ -0,0 +1,34 @@ +package com.newyetai.usercenter.user.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotNull; + +import com.newyetai.common.dto.BaseOperateDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "用户邀请注册") +public class UserRegisterCreateDTO extends BaseOperateDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 2118502786779163962L; + + @ApiModelProperty("邀请码(为空则自主注册)") + private String registerCode; + @NotNull(message = "用户id不能为空") + @ApiModelProperty("用户id") + private Long userId; + @ApiModelProperty("入口点") + private String entrypoint; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserRegisterDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserRegisterDTO.java new file mode 100644 index 0000000..eff6b2d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserRegisterDTO.java @@ -0,0 +1,50 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.usercenter.authority.dto.RoleAllocationDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2021-11-16 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@ApiModel(description = "用户注册信息") +public class UserRegisterDTO extends BaseDTO { + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("系统应用标识") + private Integer platformCode; + + @ApiModelProperty("用户id") + private Long userId; + + @ApiModelProperty("邀请人id") + private Long inviterId; + + @ApiModelProperty("邀请人用户类型") + private Integer inviterType; + + @ApiModelProperty("邀请人机构id") + private Long inviterOrgId; + + @ApiModelProperty("入口点类型") + private String entrypoint; + + @ApiModelProperty("关联id(小程序码id)") + private Long unionId; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserRegisterInfoDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserRegisterInfoDTO.java new file mode 100644 index 0000000..f95ee57 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserRegisterInfoDTO.java @@ -0,0 +1,27 @@ +package com.newyetai.usercenter.user.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2021-11-16 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel(description = "用户注册详细信息") +public class UserRegisterInfoDTO extends UserRegisterDTO { + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("用户昵称") + private String userNickname; + @ApiModelProperty("用户头像") + private String userAvatar; +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserRegisterInfoQueryDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserRegisterInfoQueryDTO.java new file mode 100644 index 0000000..cc54f78 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserRegisterInfoQueryDTO.java @@ -0,0 +1,36 @@ +package com.newyetai.usercenter.user.dto; + +import java.io.Serializable; + +import com.newyetai.common.dto.PageQueryDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2021-11-16 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "用户注册表查询条件") +public class UserRegisterInfoQueryDTO extends PageQueryDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("系统应用标识") + private Integer platformCode; + + @ApiModelProperty("用户id") + private Long userId; + + @ApiModelProperty("邀请人id") + private Long inviterId; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserRegisterOperateDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserRegisterOperateDTO.java new file mode 100644 index 0000000..675d4cf --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserRegisterOperateDTO.java @@ -0,0 +1,33 @@ +package com.newyetai.usercenter.user.dto; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import io.swagger.annotations.ApiModel; +import javax.validation.constraints.NotNull; +import com.newyetai.common.validation.Update; + +import com.newyetai.common.dto.BaseOperateDTO; + +/** + * @author sr on 2021-11-16 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "用户注册表操作") +public class UserRegisterOperateDTO extends BaseOperateDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @NotNull(message = "id不能为空", groups = {Update.class}) + private Long id; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserRegisterQueryDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserRegisterQueryDTO.java new file mode 100644 index 0000000..57f04a5 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserRegisterQueryDTO.java @@ -0,0 +1,36 @@ +package com.newyetai.usercenter.user.dto; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import io.swagger.annotations.ApiModel; + +import com.newyetai.common.dto.PageQueryDTO; + +/** + * @author sr on 2021-11-16 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "用户注册表查询条件") +public class UserRegisterQueryDTO extends PageQueryDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("系统应用标识") + private Integer platformCode; + + @ApiModelProperty("用户id") + private Long userId; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserSelfUpdateDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserSelfUpdateDTO.java new file mode 100644 index 0000000..ca7245d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserSelfUpdateDTO.java @@ -0,0 +1,33 @@ +package com.newyetai.usercenter.user.dto; + +import java.io.Serializable; + +import com.newyetai.common.dto.BaseOperateDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2021-01-15 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "用户修改个人信息") +public class UserSelfUpdateDTO extends BaseOperateDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 8864167560336812469L; + + @ApiModelProperty("姓名") + private String name; + + @ApiModelProperty("身份证") + private String cardNo; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserSignDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserSignDTO.java new file mode 100644 index 0000000..8832cb7 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserSignDTO.java @@ -0,0 +1,41 @@ +package com.newyetai.usercenter.user.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.usercenter.authority.dto.RoleAllocationDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.SuperBuilder; + +import java.util.Date; + +/** + * @author fzp on 2022-01-18 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@ApiModel(description = "用户签到表") +public class UserSignDTO extends BaseDTO { + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + + @ApiModelProperty("用户Id") + private Long userId; + + @ApiModelProperty("系统编码") + private Integer platformCode; + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + @ApiModelProperty("签到") + private Date signTime; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserSignOperateDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserSignOperateDTO.java new file mode 100644 index 0000000..2e9d96c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserSignOperateDTO.java @@ -0,0 +1,44 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.dto.BaseOperateDTO; +import com.newyetai.common.validation.Update; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.Date; + +/** + * @author fzp on 2022-01-18 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "用户签到表操作") +public class UserSignOperateDTO extends BaseOperateDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @NotNull(message = "id不能为空", groups = {Update.class}) + private Long id; + + @NotNull(message = "用户id") + private Long userId; + + @ApiModelProperty("系统编码") + private Integer platformCode; + + @NotNull(message = "签到时间") + private Date signTime; + + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/user/dto/UserSignQueryDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/UserSignQueryDTO.java new file mode 100644 index 0000000..2fa9388 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/UserSignQueryDTO.java @@ -0,0 +1,37 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.dto.PageQueryDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +/** + * @author fzp on 2022-01-18 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "用户签到表查询条件") +public class UserSignQueryDTO extends PageQueryDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private Long id; + + @NotNull(message = "用户id") + private Long userId; + + @NotNull(message = "签到时间") + private String signTime; + + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/user/dto/WechatUserBindPhoneDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/WechatUserBindPhoneDTO.java new file mode 100644 index 0000000..56327f0 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/WechatUserBindPhoneDTO.java @@ -0,0 +1,44 @@ +package com.newyetai.usercenter.user.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotBlank; + +import com.newyetai.common.dto.BaseOperateDTO; +import com.newyetai.common.validation.annotation.Phone; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2021-01-13 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "微信用户查询条件") +public class WechatUserBindPhoneDTO extends BaseOperateDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = -8981587236777596678L; + + @ApiModelProperty("姓名") +// @NotBlank(message = "姓名不能为空") + private String name; + @ApiModelProperty("手机号") + @Phone + private String phone; + @ApiModelProperty("验证码") + @NotBlank(message = "验证码不能为空") + private String phoneCode; + @ApiModelProperty("身份证") + private String cardNo; + @ApiModelProperty("用户类型:3企业,4个人") + @NotBlank(message = "用户类型不能为空") + private Integer userType; + + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/WechatUserDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/WechatUserDTO.java new file mode 100644 index 0000000..e0ec103 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/WechatUserDTO.java @@ -0,0 +1,52 @@ +package com.newyetai.usercenter.user.dto; + +import com.newyetai.common.dto.BaseDTO; +import com.newyetai.usercenter.authority.dto.RoleAllocationDTO; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.SuperBuilder; + +import java.io.Serializable; + +/** + * @author sr on 2021-01-12 + */ +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@ApiModel(description = "微信用户") +public class WechatUserDTO extends BaseDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("微信openid") + private String openId; + @ApiModelProperty("用户id") + private Long userId; + @ApiModelProperty("昵称") + private String nickname; + @ApiModelProperty("用户的性别,值为1时是男性,值为2时是女性,值为0时是未知") + private Integer sex; + @ApiModelProperty("用户个人资料填写的省份") + private String province; + @ApiModelProperty("普通用户个人资料填写的城市") + private String city; + @ApiModelProperty("国家,如中国为CN") + private String country; + @ApiModelProperty("用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效") + private String headimgurl; + @ApiModelProperty("只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段") + private String unionid; + @ApiModelProperty("是否为默认") + private Boolean setDefault; + @ApiModelProperty("注册来源 1.小程序 2.H5") + private Integer registeredChannel; + @ApiModelProperty("登录用户身份类型") + private String type; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/WechatUserInfoDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/WechatUserInfoDTO.java new file mode 100644 index 0000000..3a23d2f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/WechatUserInfoDTO.java @@ -0,0 +1,37 @@ +package com.newyetai.usercenter.user.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2021-01-14 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "微信用户查询条件") +public class WechatUserInfoDTO extends WechatUserDTO{ + + /** **/ + private static final long serialVersionUID = 138610870654616159L; + + @ApiModelProperty("姓名") + private String name; + @ApiModelProperty("手机号") + private String phone; + @ApiModelProperty("身份证") + private String cardNo; +// @ApiModelProperty("二要素认证状态 1:待认证 2:认证成功 3:认证失败") +// private String authStatu; + @ApiModelProperty("是否实名") + private Boolean authenticated; + @ApiModelProperty("是否存在企业账号信息,默认为否; 是:true 否: false") + private Boolean enterpriseInfo; + + +} diff --git a/src/main/java/com/newyetai/usercenter/user/dto/WechatUserOperateDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/WechatUserOperateDTO.java new file mode 100644 index 0000000..221f5da --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/WechatUserOperateDTO.java @@ -0,0 +1,56 @@ +package com.newyetai.usercenter.user.dto; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import io.swagger.annotations.ApiModel; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import com.newyetai.common.validation.Update; + +import com.newyetai.common.dto.BaseOperateDTO; + +/** + * @author sr on 2021-01-12 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ApiModel(description = "微信用户操作") +public class WechatUserOperateDTO extends BaseOperateDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("微信openid") + @NotBlank(message = "微信openid不能为空") + private String openId; + @ApiModelProperty("用户id") + private Long userId; + @ApiModelProperty("昵称") + private String nickname; + @ApiModelProperty("用户的性别,值为1时是男性,值为2时是女性,值为0时是未知") + private Integer sex; + @ApiModelProperty("用户个人资料填写的省份") + private String province; + @ApiModelProperty("普通用户个人资料填写的城市") + private String city; + @ApiModelProperty("国家,如中国为CN") + private String country; + @ApiModelProperty("用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效") + private String headimgurl; + @ApiModelProperty("只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段") + private String unionid; + @ApiModelProperty("是否为默认") + private Boolean setDefault; + @ApiModelProperty("注册来源 1.小程序 2.H5") + @NotNull(message = "来源不能为空") + private Integer registeredChannel; + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/user/dto/WechatUserQueryDTO.java b/src/main/java/com/newyetai/usercenter/user/dto/WechatUserQueryDTO.java new file mode 100644 index 0000000..56b65a8 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/dto/WechatUserQueryDTO.java @@ -0,0 +1,43 @@ +package com.newyetai.usercenter.user.dto; + +import java.io.Serializable; + +import com.newyetai.common.dto.PageQueryDTO; +import com.newyetai.tkmybatis.pojo.Page; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2021-01-12 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "微信用户查询条件") +public class WechatUserQueryDTO extends PageQueryDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("微信openid") + private String openId; + @ApiModelProperty("用户id") + private Long userId; + @ApiModelProperty("注册来源 1.小程序 2.H5") + private Integer registeredChannel; + + @Builder + public WechatUserQueryDTO(Integer pageNo, Integer pageSize, Boolean needPage, + Page pageResult, String openId, Long userId, Integer registeredChannel) { + super(pageNo, pageSize, needPage, pageResult); + this.openId = openId; + this.userId = userId; + this.registeredChannel = registeredChannel; + } + +} \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/user/entity/OrgUser.java b/src/main/java/com/newyetai/usercenter/user/entity/OrgUser.java new file mode 100644 index 0000000..cf3ad04 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/entity/OrgUser.java @@ -0,0 +1,36 @@ +package com.newyetai.usercenter.user.entity; + +import org.apache.ibatis.type.Alias; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.OrgBaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 机构用户表 + * + * @author sr on 2021-05-24 + */ +@TableName("uc_org_user") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@Alias("UcOrgUser") +public class OrgUser extends OrgBaseEntity { + + /** **/ + private static final long serialVersionUID = 1L; + + /** 用户id */ + private Long userId ; + /** 是否管理员 */ + private Boolean administrator ; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/entity/UcUserBankAccount.java b/src/main/java/com/newyetai/usercenter/user/entity/UcUserBankAccount.java new file mode 100644 index 0000000..b9efe89 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/entity/UcUserBankAccount.java @@ -0,0 +1,43 @@ +package com.newyetai.usercenter.user.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author czy + * @date 2021-06-29 + */ + +@TableName("uc_user_bank_account") +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +@EqualsAndHashCode(callSuper = true) +public class UcUserBankAccount extends BaseEntity { + + /** 用户id **/ + private Long userId; + + /** 卡号 **/ + private String accountNo; + + /** 户名 **/ + private String accountName; + + /** 银行名 **/ + private String bankName; + + /** 开户行名 **/ + private String bankBranchName; + + /** 是否默认账户 **/ + private Boolean defaultAccount; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/entity/User.java b/src/main/java/com/newyetai/usercenter/user/entity/User.java new file mode 100644 index 0000000..6543637 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/entity/User.java @@ -0,0 +1,77 @@ +package com.newyetai.usercenter.user.entity; + +import java.util.Date; + +import org.apache.ibatis.type.Alias; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 用户 + * + * @author sr on 2021-05-24 + */ +@TableName("uc_user") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +@Alias("UcUser") +public class User extends BaseEntity { + + /** **/ + private static final long serialVersionUID = 1L; + /** 账号 */ + private String username ; + /** 密码 */ + private String password ; + /** 用户类型:1企业用户,2个人用户 */ + private Integer type ; + /** 是否超管 */ + private Boolean supeiror ; + /** 安全码 */ + private String securityCode ; + /** 昵称 */ + private String nickname ; + /** 头像 */ + private String avatar ; + /** 手机号码 */ + private String phone ; + /** 手机号绑定状态 */ + private Boolean phoneBinding ; + /** 真实姓名 */ + private String realName ; + /** 身份证号 */ + private String cardNo ; + /** 性别:1男2女 **/ + private Integer gender ; + /** 生日 **/ + private Date birthday ; + /** 是否实名 */ + private Boolean authenticated ; + /** 状态:1.待激活,2已激活,3已注销 */ + private Integer status ; + /** 邮箱 */ + private String email ; + /** 用户所在地 */ + private String address; + /** 文化程度:1博士、2硕士、3本科、4大专、5高中、6中专/中技、7初中及以下、8不限*/ + private Integer education; + /** 是否启用 */ + private Boolean enabled ; + /** 账号是否未过期 */ + private Boolean accountNonExpired ; + /** 是否未锁定 */ + private Boolean accountNonLocked ; + /** 凭据是否未过期 */ + private Boolean credentialsNonExpired ; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/entity/UserAuth.java b/src/main/java/com/newyetai/usercenter/user/entity/UserAuth.java new file mode 100644 index 0000000..61b1d19 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/entity/UserAuth.java @@ -0,0 +1,34 @@ +package com.newyetai.usercenter.user.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 用户授权中间表 + * + * @author sr on 2021-05-24 + */ +@TableName("uc_user_auth") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +public class UserAuth extends BaseEntity { + + /** **/ + private static final long serialVersionUID = 1L; + + /** 授权大类 */ + private Integer authMainType ; + /** 授权唯一id */ + private String uniqueId ; + /** 用户id */ + private Long userId ; +} diff --git a/src/main/java/com/newyetai/usercenter/user/entity/UserBankCardFourVerification.java b/src/main/java/com/newyetai/usercenter/user/entity/UserBankCardFourVerification.java new file mode 100644 index 0000000..78f36f5 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/entity/UserBankCardFourVerification.java @@ -0,0 +1,42 @@ +package com.newyetai.usercenter.user.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author czy + * @date 2021-06-23 + */ + +@TableName("uc_user_bank_card_four_verification") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +public class UserBankCardFourVerification extends BaseEntity { + + /** 用户Id **/ + private Long userId; + /** 姓名 **/ + private String realName; + /** 证件号 **/ + private String cardNo; + /** 银行卡号 **/ + private String bankAccountNo; + /** 手机号 **/ + private String phone; + /** 认证源id **/ + private Long sourceVerifyId; + /** 状态 **/ + private Integer status; + /** 失败原因 **/ + private String failReason; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/entity/UserBankCardThreeVerification.java b/src/main/java/com/newyetai/usercenter/user/entity/UserBankCardThreeVerification.java new file mode 100644 index 0000000..d1b535a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/entity/UserBankCardThreeVerification.java @@ -0,0 +1,55 @@ +package com.newyetai.usercenter.user.entity; + +import java.util.Date; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author czy + * @date 2021-06-23 + */ + +@TableName("uc_user_bank_card_three_verification") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Data +public class UserBankCardThreeVerification extends BaseEntity { + + /** 用户Id **/ + private Long userId; + /** 姓名 **/ + private String realName; + /** 证件号 **/ + private String cardNo; + /** 银行卡号 **/ + private String bankAccountNo; + /** 认证源id **/ + private Long sourceVerifyId; + /** 状态 **/ + private Integer status; + /** 失败原因 **/ + private String failReason; + + @Builder + public UserBankCardThreeVerification(Long id, Boolean deleted, Long createBy, + Date createTime, Long updateBy, Date updateTime, Long proxyBy, + Long userId, String realName, String cardNo, String bankAccountNo, + Long sourceVerifyId, Integer status, String failReason) { + super(id, deleted, createBy, createTime, updateBy, updateTime, proxyBy); + this.userId = userId; + this.realName = realName; + this.cardNo = cardNo; + this.bankAccountNo = bankAccountNo; + this.sourceVerifyId = sourceVerifyId; + this.status = status; + this.failReason = failReason; + } +} diff --git a/src/main/java/com/newyetai/usercenter/user/entity/UserCancel.java b/src/main/java/com/newyetai/usercenter/user/entity/UserCancel.java new file mode 100644 index 0000000..6176498 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/entity/UserCancel.java @@ -0,0 +1,36 @@ +package com.newyetai.usercenter.user.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@TableName("uc_user_cancel") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +public class UserCancel extends BaseEntity { + + private static final long serialVersionUID = -8939983320960850273L; + /** + * 用户id + */ + private Long userId; + /** + * 申请状态 1:已申请 2:已注销 + */ + private Integer status; + + /** + * 注销原因类型 数据字典 + */ + private String cancellationType; + + private String remark; +} diff --git a/src/main/java/com/newyetai/usercenter/user/entity/UserConfig.java b/src/main/java/com/newyetai/usercenter/user/entity/UserConfig.java new file mode 100644 index 0000000..2dd2646 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/entity/UserConfig.java @@ -0,0 +1,37 @@ +package com.newyetai.usercenter.user.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 用户配置 + * + * @author sr on 2021-08-12 + */ +@TableName("uc_user_config") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +public class UserConfig extends BaseEntity { + + /** **/ + private static final long serialVersionUID = 1L; + + /** 用户id **/ + private Long userId; + /** 编码 **/ + private String configCode; + /** 配置值 **/ + private String configValue; + /** 备注 **/ + private String remark; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/entity/UserExtension.java b/src/main/java/com/newyetai/usercenter/user/entity/UserExtension.java new file mode 100644 index 0000000..9b48654 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/entity/UserExtension.java @@ -0,0 +1,54 @@ +package com.newyetai.usercenter.user.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author czy + * @date 2021-06-15 + */ +@TableName("uc_user_extension") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +public class UserExtension extends BaseEntity { + + /** + * 用户Id + */ + private Long userId; + + /** + *常住地区 + */ + private String residenceAddress; + + /** + *技能标签 + */ + private String techniqueTag; + /** + * 简历Code + */ + private String fileCode; + /** + * 简历名称 + */ + private String fileName; + + /** 新冠疫苗 **/ + private Integer covidVaccine; + + /** + * 微信二维码 + */ + private String wechatQrCode; +} diff --git a/src/main/java/com/newyetai/usercenter/user/entity/UserIdentityPhoto.java b/src/main/java/com/newyetai/usercenter/user/entity/UserIdentityPhoto.java new file mode 100644 index 0000000..eebe529 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/entity/UserIdentityPhoto.java @@ -0,0 +1,39 @@ +package com.newyetai.usercenter.user.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 用户证件正反面 + * + * @author sr on 2021-05-24 + */ +@TableName("uc_user_identity_photo") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +public class UserIdentityPhoto extends BaseEntity { + + /** **/ + private static final long serialVersionUID = 1L; + + /** 用户id */ + private Long userId ; + /** 正面照 */ + private String frontFileCode ; + /** 反面照 */ + private String backFileCode ; + /** 状态(1-未认证 2-认证中 3-认证成功 4-认证失败) */ + private Integer status ; + /** 失败原因 */ + private String failReason; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/entity/UserPhoneThreeVerification.java b/src/main/java/com/newyetai/usercenter/user/entity/UserPhoneThreeVerification.java new file mode 100644 index 0000000..906d584 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/entity/UserPhoneThreeVerification.java @@ -0,0 +1,53 @@ +package com.newyetai.usercenter.user.entity; + +import java.util.Date; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author czy + * @date 2021-06-23 + */ + +@TableName("uc_user_phone_three_verification") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Data +public class UserPhoneThreeVerification extends BaseEntity { + + private static final long serialVersionUID = -7530290681100657538L; + /** 用户Id **/ + private Long userId; + /** 姓名 **/ + private String realName; + /** 证件号 **/ + private String cardNo; + /** 手机号 **/ + private String phone; + /** 认证源id **/ + private Long sourceVerifyId; + /** 状态 **/ + private Integer status; + /** 失败原因 **/ + private String failReason; + + @Builder + public UserPhoneThreeVerification(Long id, Boolean deleted, Long createBy, Date createTime, Long updateBy, Date updateTime, Long proxyBy, Long userId, String realName, String cardNo, String phone, Long sourceVerifyId, Integer status, String failReason) { + super(id, deleted, createBy, createTime, updateBy, updateTime, proxyBy); + this.userId = userId; + this.realName = realName; + this.cardNo = cardNo; + this.phone = phone; + this.sourceVerifyId = sourceVerifyId; + this.status = status; + this.failReason = failReason; + } +} diff --git a/src/main/java/com/newyetai/usercenter/user/entity/UserPostalInfo.java b/src/main/java/com/newyetai/usercenter/user/entity/UserPostalInfo.java new file mode 100644 index 0000000..4a4cda6 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/entity/UserPostalInfo.java @@ -0,0 +1,51 @@ +package com.newyetai.usercenter.user.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 用户邮寄信息 + * + * @author fzp on 2022-01-19 + */ +@TableName("uc_user_postal_info") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +public class UserPostalInfo extends BaseEntity { + + /** **/ + private static final long serialVersionUID = 1L; + + /** 是否默认 **/ + private Boolean defaulted; + /** + * 收货人 + */ + private String name; + /** + * 手机号 + */ + private String phone; + /** + * 地区编号 + */ + private String addressCode; + /** + * 地区名称 + */ + private String addressName; + /** + * 地区地址 + */ + private String addressDetail; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/entity/UserRealNameTwoVerification.java b/src/main/java/com/newyetai/usercenter/user/entity/UserRealNameTwoVerification.java new file mode 100644 index 0000000..01ae174 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/entity/UserRealNameTwoVerification.java @@ -0,0 +1,38 @@ +package com.newyetai.usercenter.user.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author fzp + * @date 2021年7月14日10:24:54 + */ + +@TableName("uc_user_real_name_two_verification") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +public class UserRealNameTwoVerification extends BaseEntity { + + /** 用户Id **/ + private Long userId; + /** 姓名 **/ + private String realName; + /** 证件号 **/ + private String cardNo; + /** 认证源id **/ + private Integer sourceVerifyId; + /** 认证状态 1未认证2认证中3认证成功4认证失败 **/ + private Integer status; + /** 失败原因 **/ + private String failReason; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/entity/UserRegister.java b/src/main/java/com/newyetai/usercenter/user/entity/UserRegister.java new file mode 100644 index 0000000..ed3cb1b --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/entity/UserRegister.java @@ -0,0 +1,49 @@ +package com.newyetai.usercenter.user.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.newyetai.common.entity.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 用户注册表 + * + * @author sr on 2021-11-16 + */ +@TableName("uc_user_register") +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@Data +public class UserRegister extends BaseEntity { + + /** **/ + private static final long serialVersionUID = 1L; + + /** 系统应用标识 **/ + private Integer platformCode; + + /** 用户id **/ + private Long userId; + + /** 邀请人id **/ + private Long inviterId; + + /** 邀请人用户类型 **/ + private Integer inviterType; + + /** 邀请人机构id **/ + private Long inviterOrgId; + + /** 入口点类型 **/ + private String entrypoint; + + /** 关联id(小程序码id) **/ + private Long unionId; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/job/UserCancelJob.java b/src/main/java/com/newyetai/usercenter/user/job/UserCancelJob.java new file mode 100644 index 0000000..13cd7e7 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/job/UserCancelJob.java @@ -0,0 +1,34 @@ +//package com.newyetai.usercenter.user.job; +// +//import com.newyetai.common.annotation.AlitaStopWatch; +//import com.newyetai.job.util.ReturnTUtils; +//import com.newyetai.security.util.MockUtils; +//import com.newyetai.usercenter.common.constant.XxlJobHandlerConstants; +//import com.newyetai.usercenter.user.service.UserCancelService; +//import com.xxl.job.core.biz.model.ReturnT; +//import com.xxl.job.core.handler.annotation.XxlJob; +//import lombok.extern.slf4j.Slf4j; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.stereotype.Component; +// +//@Component +//@Slf4j +//public class UserCancelJob { +// +// @Autowired +// private UserCancelService userCancelService; +// +// @XxlJob(XxlJobHandlerConstants.USER_CANCEL_NOTIFY_JOB) +// @AlitaStopWatch +// public ReturnT execute(String param) { +// try { +// MockUtils.mockPlatUser(); +// userCancelService.toNotify(); +// return ReturnT.SUCCESS; +// } catch (Exception e) { +// return ReturnTUtils.error(e.getMessage()); +// } +// } +// +//} +// diff --git a/src/main/java/com/newyetai/usercenter/user/login/controller/UserLoginController.java b/src/main/java/com/newyetai/usercenter/user/login/controller/UserLoginController.java new file mode 100644 index 0000000..e95941f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/login/controller/UserLoginController.java @@ -0,0 +1,30 @@ +package com.newyetai.usercenter.user.login.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import com.newyetai.common.AlitaResult; +import com.newyetai.usercenter.user.dto.UserDetailQueryDTO; +import com.newyetai.usercenter.user.login.dto.UserDetailDTO; +import com.newyetai.usercenter.user.login.service.UserLoginService; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +@RestController +@Api(tags = "用户登录") +public class UserLoginController { + + @Autowired + private UserLoginService userLoginService; + + @ApiOperation("根据登录信息获取用户信息") + @PostMapping("anon/user/find_user_detail_dto") + public AlitaResult findUserDetailDTO(@RequestBody UserDetailQueryDTO userDetailQueryDto){ + return userLoginService.findUserDetailDTOResult(userDetailQueryDto); + } + + +} diff --git a/src/main/java/com/newyetai/usercenter/user/login/dto/LoginPhoneDTO.java b/src/main/java/com/newyetai/usercenter/user/login/dto/LoginPhoneDTO.java new file mode 100644 index 0000000..2290780 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/login/dto/LoginPhoneDTO.java @@ -0,0 +1,36 @@ +package com.newyetai.usercenter.user.login.dto; + +import com.newyetai.usercenter.user.dto.UserPhoneCodeDTO; +import com.newyetai.usercenter.user.phone.constant.UserPhoneCodeOperateEnum; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@NoArgsConstructor +@AllArgsConstructor +@Data +@SuperBuilder +@ApiModel(description = "手机号登录") +public class LoginPhoneDTO extends UserPhoneCodeDTO{ + + /** **/ + private static final long serialVersionUID = 1982976901464380354L; + + @ApiModelProperty("注册邀请码") + private String registerCode; + @ApiModelProperty("入口点") + private String entrypoint; + @ApiModelProperty("没有验证码(默认需要验证码)") + private Boolean withoutCode; + + + @Override + public String getOperateType() { + return UserPhoneCodeOperateEnum.LOGIN.getOperate(); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/login/dto/LoginPhoneToken.java b/src/main/java/com/newyetai/usercenter/user/login/dto/LoginPhoneToken.java new file mode 100644 index 0000000..25e2774 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/login/dto/LoginPhoneToken.java @@ -0,0 +1,29 @@ +package com.newyetai.usercenter.user.login.dto; + +import javax.validation.constraints.NotNull; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@Data +@NoArgsConstructor +@SuperBuilder +@ApiModel(description = "手机号token登录-个人用户选用户") +public class LoginPhoneToken extends PhoneToken{ + + /** **/ + private static final long serialVersionUID = -4972872069055864454L; + +// @NotNull(message = "用户id不能为空") + /** **/ + @ApiModelProperty("用户id(无则新增)") + private Long userId; + @ApiModelProperty("注册邀请码") + private String registerCode; + @ApiModelProperty("入口点") + private String entrypoint; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/login/dto/LoginUserToken.java b/src/main/java/com/newyetai/usercenter/user/login/dto/LoginUserToken.java new file mode 100644 index 0000000..9d7d9ff --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/login/dto/LoginUserToken.java @@ -0,0 +1,22 @@ +package com.newyetai.usercenter.user.login.dto; + +import javax.validation.constraints.NotNull; + +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@Data +@NoArgsConstructor +@SuperBuilder +@ApiModel(description = "用户token登录-企业用户选机构") +public class LoginUserToken extends UserToken{ + + /** **/ + private static final long serialVersionUID = -6996668235244805301L; + + @NotNull(message = "机构id不能为空") + private Long orgId; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/login/dto/LoginUsernamePasswordDTO.java b/src/main/java/com/newyetai/usercenter/user/login/dto/LoginUsernamePasswordDTO.java new file mode 100644 index 0000000..8695575 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/login/dto/LoginUsernamePasswordDTO.java @@ -0,0 +1,35 @@ +package com.newyetai.usercenter.user.login.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@Data +@Builder +@ApiModel(description = "账号密码登录") +public class LoginUsernamePasswordDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = -5406549736684905311L; + + @ApiModelProperty("账号") + @NotBlank(message = "账号不能为空") + private String username; + @ApiModelProperty("密码") + @NotBlank(message = "密码不能为空") + private String password; + @ApiModelProperty("用户类型") + @NotNull(message = "用户类型不能为空") + private Integer userType; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/login/dto/OrgDetailDTO.java b/src/main/java/com/newyetai/usercenter/user/login/dto/OrgDetailDTO.java new file mode 100644 index 0000000..10a5190 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/login/dto/OrgDetailDTO.java @@ -0,0 +1,29 @@ +package com.newyetai.usercenter.user.login.dto; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class OrgDetailDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = -8169657080151873030L; + + /** 机构id **/ + private Long orgId; + + /** 机构名称 **/ + private String orgName; + + /** 机构类型 **/ + private String orgType; + + /** 是否机构管理员 **/ + private Boolean administrator; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/login/dto/PhoneToken.java b/src/main/java/com/newyetai/usercenter/user/login/dto/PhoneToken.java new file mode 100644 index 0000000..83e906c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/login/dto/PhoneToken.java @@ -0,0 +1,17 @@ +package com.newyetai.usercenter.user.login.dto; + +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@Data +@NoArgsConstructor +@SuperBuilder +public abstract class PhoneToken extends TempTokenDTO{ + + /** **/ + private static final long serialVersionUID = -4972872069055864454L; + + private final String type = TempTokenDTO.TYPE_PHONE; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/login/dto/TempTokenDTO.java b/src/main/java/com/newyetai/usercenter/user/login/dto/TempTokenDTO.java new file mode 100644 index 0000000..8099393 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/login/dto/TempTokenDTO.java @@ -0,0 +1,24 @@ +package com.newyetai.usercenter.user.login.dto; + +import java.io.Serializable; + +import javax.validation.constraints.NotBlank; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public abstract class TempTokenDTO implements Serializable { + + public static final String TYPE_PHONE = "phone"; + public static final String TYPE_USER = "user"; + + @NotBlank(message = "临时token不能为空") + private String tempToken; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/login/dto/UserDetailDTO.java b/src/main/java/com/newyetai/usercenter/user/login/dto/UserDetailDTO.java new file mode 100644 index 0000000..c505361 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/login/dto/UserDetailDTO.java @@ -0,0 +1,93 @@ +package com.newyetai.usercenter.user.login.dto; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import java.io.Serializable; +import java.util.List; + +/** + * 用户 + * + * @author sr on 2019-11-05 + */ +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Data +@ToString +public class UserDetailDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 1074707536155659372L; + + @ApiModelProperty("用户id") + private Long id; + + @ApiModelProperty("是否超管") + private Boolean supeiror ; + + @ApiModelProperty("类型") + private Integer type; + + /** ----------------仅限机构用户--------------- **/ + @ApiModelProperty("当前操作机构") + private Long orgId; + + @ApiModelProperty("当前操作机构名称") + private String orgName; + + @ApiModelProperty("当前操作机构类型") + private String orgType; + + @ApiModelProperty("是否机构管理员") + private Boolean administrator; + /** ----------------仅限机构用户--------------- **/ + + @ApiModelProperty("账号") + @JsonIgnore + private String username; + + @ApiModelProperty("密码") + @JsonIgnore + private String password; + + @ApiModelProperty("是否启用") + private Boolean enabled; + + @ApiModelProperty("是否新注册") + private Boolean register; + + @ApiModelProperty("状态:1.待激活,2已激活,3已注销") + private Integer status; + + @ApiModelProperty("帐号是否未过期") + private Boolean accountNonExpired; + + @ApiModelProperty("是否未锁定") + private Boolean accountNonLocked; + + @ApiModelProperty("凭据是否未过期") + private Boolean credentialsNonExpired; + + @JsonIgnore + @ApiModelProperty("真实姓名") + private String realName; + + @JsonIgnore + @ApiModelProperty("身份证号") + private String cardNo; + + @ApiModelProperty("手机号绑定状态") + private Boolean phoneBinding; + + @ApiModelProperty("机构列表") + @JsonIgnore + private List orgs; + + @ApiModelProperty("用户列表") + @JsonIgnore + private List users; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/login/dto/UserDetailSelectDTO.java b/src/main/java/com/newyetai/usercenter/user/login/dto/UserDetailSelectDTO.java new file mode 100644 index 0000000..58230fe --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/login/dto/UserDetailSelectDTO.java @@ -0,0 +1,35 @@ +package com.newyetai.usercenter.user.login.dto; + +import java.io.Serializable; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2021-07-29 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(description = "用户登录待选择列表") +public class UserDetailSelectDTO implements Serializable{ + + /** **/ + private static final long serialVersionUID = 6863140269432883663L; + + @ApiModelProperty("用户id") + private Long id; + + @ApiModelProperty("账号") + private String username; + + @ApiModelProperty("真实姓名") + private String realName; + + @ApiModelProperty("身份证号") + private String cardNo; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/login/dto/UserToken.java b/src/main/java/com/newyetai/usercenter/user/login/dto/UserToken.java new file mode 100644 index 0000000..fc6a78c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/login/dto/UserToken.java @@ -0,0 +1,17 @@ +package com.newyetai.usercenter.user.login.dto; + +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@Data +@NoArgsConstructor +@SuperBuilder +public class UserToken extends TempTokenDTO{ + + /** **/ + private static final long serialVersionUID = -6996668235244805301L; + + private final String type = TempTokenDTO.TYPE_USER; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/login/service/UserLoginService.java b/src/main/java/com/newyetai/usercenter/user/login/service/UserLoginService.java new file mode 100644 index 0000000..e8e6ff4 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/login/service/UserLoginService.java @@ -0,0 +1,46 @@ +package com.newyetai.usercenter.user.login.service; + +import javax.servlet.http.HttpServletRequest; + +import com.newyetai.security.service.IUserSecurityService; +import com.newyetai.security.ssb.SsbLoginDTO; +import com.newyetai.usercenter.auth.dto.AuthClientDTO; +import com.newyetai.usercenter.auth.dto.AuthClientQueryDTO; +import com.newyetai.usercenter.auth.dto.AuthDetailLoginDTO; +import com.newyetai.usercenter.user.dto.UserDetailQueryDTO; +import com.newyetai.usercenter.user.login.dto.LoginPhoneDTO; +import com.newyetai.usercenter.user.login.dto.LoginPhoneToken; +import com.newyetai.usercenter.user.login.dto.LoginUserToken; +import com.newyetai.usercenter.user.login.dto.LoginUsernamePasswordDTO; +import com.newyetai.usercenter.user.login.dto.UserDetailDTO; + +/** + * 用户登录 + * @author sr on 2021-06-17 + */ +public interface UserLoginService extends IUserSecurityService { + + UserDetailDTO loadUser(LoginUsernamePasswordDTO loginUsernamePasswordDTO); + + UserDetailDTO loadUser(LoginPhoneDTO loginPhoneDTO); + + UserDetailDTO loadUser(LoginPhoneToken loginPhoneToken); + + UserDetailDTO loadUser(LoginUserToken loginUserToken); + + UserDetailDTO findUserDetailDTO(UserDetailQueryDTO userDetailQueryDto); + + AuthClientDTO findAuthClientDTO(AuthClientQueryDTO authClientQueryDTO); + + UserDetailDTO findUserDetailDTO(AuthDetailLoginDTO authDetailDTO); + + /** + * 如果需激活请求,判断上下文用户激活状态,如果待激活,查询数据库用户状态,直接拦截 + * @return + * @author sr on 2021-06-30 + */ + void checkActive(HttpServletRequest request); + + UserDetailDTO loadUser(SsbLoginDTO ssbLoginDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/user/login/service/impl/UserLoginServiceImpl.java b/src/main/java/com/newyetai/usercenter/user/login/service/impl/UserLoginServiceImpl.java new file mode 100644 index 0000000..c25d564 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/login/service/impl/UserLoginServiceImpl.java @@ -0,0 +1,451 @@ +package com.newyetai.usercenter.user.login.service.impl; + +import java.util.List; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.ChangeTokenException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.ListUtil; +import com.newyetai.common.util.RandomUtils; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.common.validation.util.ValidateUtils; +import com.newyetai.frame.redis.util.RedisUtils; +import com.newyetai.sdk.ssb.constant.SsbConstants; +import com.newyetai.sdk.ssb.constant.SsbPlatformEnum; +import com.newyetai.sdk.ssb.dto.SsbAppUserInfoDTO; +import com.newyetai.sdk.ssb.dto.SsbUserDTO; +import com.newyetai.sdk.ssb.dto.SsbUserDataDTO; +import com.newyetai.sdk.ssb.dto.SsbUserReq; +import com.newyetai.sdk.ssb.service.SsbInvoker; +import com.newyetai.security.expection.BadLoginException; +import com.newyetai.security.expection.DuplicateOrgException; +import com.newyetai.security.expection.DuplicateUserException; +import com.newyetai.security.jwt.JwtTokenUtils; +import com.newyetai.security.ssb.SsbLoginDTO; +import com.newyetai.security.temptoken.dto.DuplMobileToken; +import com.newyetai.security.temptoken.dto.DuplUserToken; +import com.newyetai.security.temptoken.dto.PhoneTokenCreateDTO; +import com.newyetai.security.temptoken.dto.UserTokenCreateDTO; +import com.newyetai.security.util.PasswordUtils; +import com.newyetai.security.util.SecurityPropertyUtils; +import com.newyetai.usercenter.auth.dto.AuthClientDTO; +import com.newyetai.usercenter.auth.dto.AuthClientQueryDTO; +import com.newyetai.usercenter.auth.dto.AuthDetailLoginDTO; +import com.newyetai.usercenter.auth.service.AuthClientService; +import com.newyetai.usercenter.dto.IUserDetail; +import com.newyetai.usercenter.user.constant.UserStatusEnum; +import com.newyetai.usercenter.user.constant.UserTypeEnum; +import com.newyetai.usercenter.user.dao.OrgUserMapper; +import com.newyetai.usercenter.user.dao.UserMapper; +import com.newyetai.usercenter.user.dto.AuthenticateUserDTO; +import com.newyetai.usercenter.user.dto.PersonUserCardCreateDTO; +import com.newyetai.usercenter.user.dto.PersonUserPhoneCreateDTO; +import com.newyetai.usercenter.user.dto.UserDTO; +import com.newyetai.usercenter.user.dto.UserDetailQueryDTO; +import com.newyetai.usercenter.user.dto.UserRegisterCreateDTO; +import com.newyetai.usercenter.user.entity.User; +import com.newyetai.usercenter.user.login.dto.LoginPhoneDTO; +import com.newyetai.usercenter.user.login.dto.LoginPhoneToken; +import com.newyetai.usercenter.user.login.dto.LoginUserToken; +import com.newyetai.usercenter.user.login.dto.LoginUsernamePasswordDTO; +import com.newyetai.usercenter.user.login.dto.OrgDetailDTO; +import com.newyetai.usercenter.user.login.dto.UserDetailDTO; +import com.newyetai.usercenter.user.login.dto.UserDetailSelectDTO; +import com.newyetai.usercenter.user.login.service.UserLoginService; +import com.newyetai.usercenter.user.mapstruct.UserMapMapper; +import com.newyetai.usercenter.user.phone.util.PhoneCodeUtils; +import com.newyetai.usercenter.user.service.UserRegisterService; +import com.newyetai.usercenter.user.service.UserService; + +/** + * 用户登录 + * @author sr on 2021-06-17 + */ +@Service +public class UserLoginServiceImpl implements UserLoginService { + + /** tempToken前缀 **/ + public static final String TEMP_TOKEN_PREFIX = "login:tempToken"; + /** 过期时间-秒 **/ + public static final long TEMP_TOKEN_EXPIRE_TIME = 600; + + @Autowired + private UserMapper userMapper; + + @Autowired + private UserService userService; + + @Autowired + private OrgUserMapper orgUserMapper; + + @Autowired + private AuthClientService authClientService; + + @Autowired + private UserRegisterService userRegisterService; + + @Autowired + private SsbInvoker ssbInvoker; + + @Override + public UserDetailDTO loadUser(LoginUsernamePasswordDTO loginUsernamePasswordDTO) { + // 校验参数 + String errMsg = ValidateUtils.validate(loginUsernamePasswordDTO); + Assert.isTrue(errMsg == null, new BadLoginException(errMsg)); + Integer userType = loginUsernamePasswordDTO.getUserType(); + UserDetailDTO userDetailDTO = findUserDetailDTO( + UserDetailQueryDTO.builder() + .username(loginUsernamePasswordDTO.getUsername()) + .userType(userType) + .build()); + // 校验密码 + boolean correct = + PasswordUtils.match(loginUsernamePasswordDTO.getPassword(), userDetailDTO.getPassword()); + Assert.isTrue(correct, new BadLoginException("账号和密码不匹配")); + if (UserTypeEnum.ORG.getType().equals(userType)) { + checkDuplOrg(userDetailDTO); + } + dealActiveStatus(userDetailDTO); + return userDetailDTO; + } + + @Override + @Transactional + public UserDetailDTO loadUser(LoginPhoneToken loginPhoneToken) { + // 校验参数 + String errMsg = ValidateUtils.validate(loginPhoneToken); + Assert.isTrue(errMsg == null, new BadLoginException(errMsg)); + Long userId = loginPhoneToken.getUserId(); + PhoneTokenCreateDTO phoneTokenCreateDTO = + (PhoneTokenCreateDTO) RedisUtils.get(getTempTokenKey(loginPhoneToken.getTempToken())); + Assert.isTrue(phoneTokenCreateDTO != null, new BadLoginException("无效登录token")); + String phone = phoneTokenCreateDTO.getPhone(); + // 无userId则新增用户 + if (userId == null) { + return userService.createPersonUser(PersonUserPhoneCreateDTO.builder().phone(phone).build()); + } + UserDetailDTO userDetailDTO = findUserDetailDTO( + UserDetailQueryDTO.builder() + .phone(phone) + .userType(UserTypeEnum.PERSON.getType()) + .userId(userId).build()); + Assert.isTrue(userDetailDTO.getUsers() == null, + new BadLoginException(phone + "-个人用户信息异常,请联系管理员")); + // 未绑定手机号,绑定 + dealBinding(userDetailDTO, phone); + dealActiveStatus(userDetailDTO); + // 处理注册信息 + boolean register = userRegister(userDetailDTO.getId(), loginPhoneToken.getRegisterCode(), + loginPhoneToken.getEntrypoint()); + userDetailDTO.setRegister(register); + return userDetailDTO; + } + + @Override + public UserDetailDTO loadUser(LoginUserToken loginUserToken) { + // 校验参数 + String errMsg = ValidateUtils.validate(loginUserToken); + Assert.isTrue(errMsg == null, new BadLoginException(errMsg)); + UserTokenCreateDTO userTokenCreateDTO = + (UserTokenCreateDTO) RedisUtils.get(getTempTokenKey(loginUserToken.getTempToken())); + Assert.isTrue(userTokenCreateDTO != null, new BadLoginException("无效登录token")); + Long userId = userTokenCreateDTO.getUserId(); + UserDetailDTO userDetailDTO = this.findUserDetailDTO( + UserDetailQueryDTO.builder() + .userType(UserTypeEnum.ORG.getType()) + .userId(userId) + .orgId(loginUserToken.getOrgId()).build()); + // 根据token信息找到多个企业用户-异常 + Assert.isTrue(userDetailDTO.getOrgs() == null, + new BadLoginException(userId + "-机构用户信息异常,请联系管理员")); + dealBinding(userDetailDTO, null); + dealActiveStatus(userDetailDTO); + return userDetailDTO; + } + + public UserDetailDTO loadUser(LoginPhoneDTO loginPhoneDTO) { + if (!Boolean.TRUE.equals(loginPhoneDTO.getWithoutCode())) { + boolean match = PhoneCodeUtils.match(loginPhoneDTO); + Assert.isTrue(match, new BadLoginException("验证码错误")); + } + String phone = loginPhoneDTO.getPhone(); + Integer userType = loginPhoneDTO.getUserType(); + // 查询用户 + UserDetailDTO userDetailDTO = findUserDetailDTO( + UserDetailQueryDTO.builder().phone(phone).userType(userType).build()); + if (UserTypeEnum.PERSON.getType().equals(userType)) { + List users = userDetailDTO.getUsers(); + Assert.isTrue(users == null, + new DuplicateUserException(generateMobileToken(userType, phone, users))); + // 处理注册信息 + boolean register = userRegister(userDetailDTO.getId(), loginPhoneDTO.getRegisterCode(), + loginPhoneDTO.getEntrypoint()); + userDetailDTO.setRegister(register); + } else { + checkDuplOrg(userDetailDTO); + } + dealBinding(userDetailDTO, phone); + dealActiveStatus(userDetailDTO); + return userDetailDTO; + } + + private void checkDuplOrg(UserDetailDTO userDetailDTO) { + // 如果存在多机构,生成用户token + List orgs = userDetailDTO.getOrgs(); + Assert.isTrue(orgs == null, + new DuplicateOrgException( + generateUserToken(UserTypeEnum.ORG.getType(), userDetailDTO.getId(), orgs))); + } + + private String getTempTokenKey(String token) { + return String.join(CommonConstants.COLON, UserLoginServiceImpl.TEMP_TOKEN_PREFIX, token); + } + + private DuplUserToken generateUserToken(Integer userType, Long userId, List orgs) { + String tempToken = RandomUtils.generateUUID(); + RedisUtils.add(getTempTokenKey(tempToken), + UserTokenCreateDTO.builder().userType(userType).userId(userId).build(), + TEMP_TOKEN_EXPIRE_TIME); + return DuplUserToken.builder().tempToken(tempToken).orgs(orgs).build(); + } + + private DuplMobileToken generateMobileToken(Integer userType, String phone, + List users) { + String tempToken = RandomUtils.generateUUID(); + RedisUtils.add(getTempTokenKey(tempToken), + PhoneTokenCreateDTO.builder().userType(userType).phone(phone).build(), + TEMP_TOKEN_EXPIRE_TIME); + return DuplMobileToken.builder().tempToken(tempToken).users(users).build(); + } + + @Override + public UserDetailDTO findUserDetailDTO(UserDetailQueryDTO userDetailQueryDto) { + // 查询用户 + List userDetailDTOs = userMapper.listUserDetailDTO(userDetailQueryDto); + Integer userSize = userDetailDTOs.size(); + Integer userType = userDetailQueryDto.getUserType(); + if (userType == null && userSize == 1) { + userType = ListUtil.first(userDetailDTOs).getType(); + } + Assert.notNull(userType, "未知用户"); + UserDetailDTO userDetailDTO = null; + if (UserTypeEnum.ORG.getType().equals(userType) + || UserTypeEnum.API_ORG.getType().equals(userType)) { + // 如果企业用户,只可能查到唯一匹配的用户 + switch (userSize) { + case 0: + throw new BadLoginException("用户不存在!"); + case 1: + userDetailDTO = userDetailDTOs.get(0); + break; + default: + throw new BadLoginException("用户数据异常,请联系管理员!"); + } + Assert.isTrue(userDetailDTO.getEnabled(), new BadLoginException("用户不可用!")); + return loadOrg(userDetailDTO, userDetailQueryDto.getOrgId()); + } + // 个人用户 + switch (userSize) { + case 0: + String phone = userDetailQueryDto.getPhone(); + if (StringUtils.isNotBlank(phone) && userDetailQueryDto.getUserId() == null) { + // 手机号登录可注册用户 & 非手机号选用户登录 + return userService + .createPersonUser(PersonUserPhoneCreateDTO.builder().phone(phone).build()); + } + throw new BadLoginException("用户不存在!"); + case 1: + userDetailDTO = userDetailDTOs.get(0); + return userDetailDTO; + default: + // 转换用户列表信息 + List selectDTOs = userDetailDTOs.stream() + .map(UserMapMapper.INSTANCE::toSelectDTO) + .collect(Collectors.toList()); + return UserDetailDTO.builder().users(selectDTOs).build(); + } + } + + public UserDetailDTO loadOrg(UserDetailDTO userDetailDTO, Long orgId) { + // 查询机构信息 + List orgDTOs = + orgUserMapper.listLoginOrgByUser(userDetailDTO.getId(), + orgId); + Assert.isTrue(!orgDTOs.isEmpty(), new BadLoginException("未找到对应有效机构!")); + if (orgDTOs.size() == 1) { + // 如果只查到一个机构,则直接回写机构属性到用户信息对象 + OrgDetailDTO orgDetailDTO = orgDTOs.get(0); + userDetailDTO.setOrgId(orgDetailDTO.getOrgId()); + userDetailDTO.setOrgName(orgDetailDTO.getOrgName()); + userDetailDTO.setOrgType(orgDetailDTO.getOrgType()); + userDetailDTO.setAdministrator(orgDetailDTO.getAdministrator()); + } else { + userDetailDTO.setOrgs(orgDTOs); + } + return userDetailDTO; + } + + @Override + @Transactional + public UserDetailDTO findUserDetailDTO(AuthDetailLoginDTO authDetailLoginDTO) { + try { + UserDetailDTO userDetailDTO = userService.loadUser(authDetailLoginDTO); + if (UserTypeEnum.ORG.getType().equals(userDetailDTO.getType())) { + loadOrg(userDetailDTO, null); + checkDuplOrg(userDetailDTO); + } else { + // 个人授权信息登录,不注册,判断有无注册信息 + Assert.isTrue(userRegisterService.existRegister(userDetailDTO.getId()), + new BadLoginException("该授权信息未登录注册过")); + } + dealActiveStatus(userDetailDTO); + return userDetailDTO; + } catch (BusinessException e) { + throw new BadLoginException(e.getMessage(), e); + } + } + + private boolean userRegister(Long userId, String registerCode, String entrypoint) { + try { + return userRegisterService.create(UserRegisterCreateDTO.builder().userId(userId) + .registerCode(registerCode) + .entrypoint(entrypoint).build()); + } catch (Exception e) { + throw new BadLoginException(e.getMessage(), e); + } + } + + @Override + public AlitaResult findUserDetailDTOResult(UserDetailQueryDTO userDetailQueryDto) { + try { + UserDetailDTO userDetailDTO = this.findUserDetailDTO(userDetailQueryDto); + Assert.isTrue(userDetailDTO.getOrgs() == null, "获取用户失败,找到多个机构"); + Assert.isTrue(userDetailDTO.getUsers() == null, "获取用户失败,找到多个用户"); + return AlitaResult.success(userDetailDTO); + } catch (Exception e) { + return AlitaResult.bizError(e.getMessage()); + } + } + + @Override + public AuthClientDTO findAuthClientDTO(AuthClientQueryDTO authClientQueryDTO) { + try { + AuthClientDTO authClientDTO = authClientService.findAuthClientDTO(authClientQueryDTO); + Assert.isTrue(authClientDTO != null, new IllegalArgumentException("未找到对应的oauth客户端")); + return authClientDTO; + } catch (Exception e) { + throw new IllegalArgumentException(e); + } + } + + @Override + public void checkActive(HttpServletRequest request) { + try { + IUserDetail userDetail = UserContextHolder.getLoginUser(); + // 判断路径是否是已实名 + boolean authRequest = SecurityPropertyUtils.isAuthed(request); + if (UserTypeEnum.API_ORG.getType().equals(userDetail.getType()) + || !authRequest) { + // api用户 或 已绑定&非实名路径 + return; + } + User user = userMapper.getById(UserContextHolder.getExistLoginUserId()); + Assert.isTrue(user != null, new BadLoginException(AlitaResult.unLogin())); + boolean authed = user.getAuthenticated(); + if (authRequest) { + // 实名路径 + Assert.isTrue(authed, new BadLoginException(AlitaResult.unAuth())); + } + } catch (BadLoginException be) { + throw be; + } catch (ChangeTokenException ce) { + throw new BadLoginException(ce.getResult()); + } catch (Exception e) { + throw new BadLoginException("用户数据异常,请联系管理员", e); + } + } + + /** + * 处理未激活状态 + * @param userDetailDTO + * @author sr on 2022-09-01 + */ + private void dealActiveStatus(UserDetailDTO userDetailDTO) { + if (UserStatusEnum.INIT.getStatus().equals(userDetailDTO.getStatus())) { + userMapper.loginActive(userDetailDTO.getId()); + userDetailDTO.setStatus(UserStatusEnum.ACTIVE.getStatus()); + } + } + + /** + * 处理未绑定 + * @param userDetailDTO + * @param phone + * @author sr on 2022-09-01 + */ + private void dealBinding(UserDetailDTO userDetailDTO, String phone) { + // 未绑定 + if (!userDetailDTO.getPhoneBinding()) { + Long userId = userDetailDTO.getId(); + if (UserTypeEnum.PERSON.getType().equals(userDetailDTO.getType())) { + userService.updatePersonPhoneBinding(userId, phone); + userDetailDTO.setPhoneBinding(Boolean.TRUE); + } else { + userDetailDTO.setPhoneBinding(Boolean.TRUE); + userMapper.bindingPhone(userId, phone); + } + } + } + + @Override + public UserDetailDTO loadUser(SsbLoginDTO ssbLoginDTO) { + String realName = null; + String phone = null; + String cardNo = null; + if (StringUtils.isNotBlank(ssbLoginDTO.getCode())) { + // app登录 + SsbAppUserInfoDTO ssbAppUserInfoDTO = ssbInvoker.getAppUser(ssbLoginDTO.getCode()); + Assert.isTrue(SsbAppUserInfoDTO.AUTHENTICATIED.equals(ssbAppUserInfoDTO.getStatus()), "用户未实名"); + realName = ssbAppUserInfoDTO.getName(); + phone = ssbAppUserInfoDTO.getMobile(); + cardNo = ssbAppUserInfoDTO.getIdcard(); + } else { + // 小程序登录 + // 调用ssb获取用户信息 + AlitaResult ssbUserResult = ssbInvoker + .getUser(SsbUserReq.builder().accessToken(ssbLoginDTO.getAccessToken()).build()); + Assert.isTrue(ssbUserResult.getSuccess(), + new BadLoginException("获取随申办用户失败:" + ssbUserResult.getMsg())); + // 根据身份证创建/获取用户 + SsbUserDTO ssbUserDTO = ssbUserResult.getData().getData(); + Assert.notNull(ssbUserDTO, "获取随申办用户失败null:" + ssbUserResult.getData().getMsg()); + realName = ssbUserDTO.getZwdtsw_name(); + phone = ssbUserDTO.getZwdtsw_link_phone(); + cardNo = ssbUserDTO.getZwdtsw_cert_id(); + Integer certType = ssbUserDTO.getCertType(); + Assert.notBlank(cardNo, "用户未实名"); + Assert.isTrue(SsbConstants.CERT_TYPE_ID_CARD.equals(certType), + new BadLoginException("暂只支持居民身份证实名用户登录")); + } + // 未实名,实名用户 + Long userId = userService.createAndAuthenticatePersonUser( + AuthenticateUserDTO.builder().realName(realName).cardNo(cardNo).phone(phone).build()); + UserDetailDTO userDetailDTO = this.findUserDetailDTO( + UserDetailQueryDTO.builder().userId(userId).userType(UserTypeEnum.PERSON.getType()) + .build()); + dealActiveStatus(userDetailDTO); + return userDetailDTO; + + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/mapper/OrgUserMapper.xml b/src/main/java/com/newyetai/usercenter/user/mapper/OrgUserMapper.xml new file mode 100644 index 0000000..9828d92 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/mapper/OrgUserMapper.xml @@ -0,0 +1,118 @@ + + + + + + + + + + + + + diff --git a/src/main/java/com/newyetai/usercenter/user/mapper/UserAuthMapper.xml b/src/main/java/com/newyetai/usercenter/user/mapper/UserAuthMapper.xml new file mode 100644 index 0000000..7627df5 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/mapper/UserAuthMapper.xml @@ -0,0 +1,41 @@ + + + + + + + update uc_user_auth + set + user_id = #{retainUserId}, + update_time = now() + where + user_id = #{deletedUserId} + and deleted = 0 + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/user/mapper/UserBankAccountMapper.xml b/src/main/java/com/newyetai/usercenter/user/mapper/UserBankAccountMapper.xml new file mode 100644 index 0000000..4c8c2a6 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/mapper/UserBankAccountMapper.xml @@ -0,0 +1,82 @@ + + + + + + + + + + update uc_user_bank_account + + update_time = now(), + update_by = #{param.operateUserId}, + + default_account = if(id = #{param.id}, 1, 0), + + + bank_branch_name = #{param.bankBranchName}, + + + where user_id = #{param.operateUserId} + and deleted = 0 + and (id = #{param.id} + + or default_account = 1 + + ) + + + diff --git a/src/main/java/com/newyetai/usercenter/user/mapper/UserBankCardFourVerificationMapper.xml b/src/main/java/com/newyetai/usercenter/user/mapper/UserBankCardFourVerificationMapper.xml new file mode 100644 index 0000000..51ae721 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/mapper/UserBankCardFourVerificationMapper.xml @@ -0,0 +1,38 @@ + + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/user/mapper/UserBankCardThreeVerificationMapper.xml b/src/main/java/com/newyetai/usercenter/user/mapper/UserBankCardThreeVerificationMapper.xml new file mode 100644 index 0000000..74e9b88 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/mapper/UserBankCardThreeVerificationMapper.xml @@ -0,0 +1,35 @@ + + + + + + + + diff --git a/src/main/java/com/newyetai/usercenter/user/mapper/UserCancelMapper.xml b/src/main/java/com/newyetai/usercenter/user/mapper/UserCancelMapper.xml new file mode 100644 index 0000000..a1b12a5 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/mapper/UserCancelMapper.xml @@ -0,0 +1,50 @@ + + + + + + + + diff --git a/src/main/java/com/newyetai/usercenter/user/mapper/UserConfigMapper.xml b/src/main/java/com/newyetai/usercenter/user/mapper/UserConfigMapper.xml new file mode 100644 index 0000000..fc38d3d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/mapper/UserConfigMapper.xml @@ -0,0 +1,22 @@ + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/user/mapper/UserIdentityPhotoMapper.xml b/src/main/java/com/newyetai/usercenter/user/mapper/UserIdentityPhotoMapper.xml new file mode 100644 index 0000000..0e3390a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/mapper/UserIdentityPhotoMapper.xml @@ -0,0 +1,25 @@ + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/user/mapper/UserMapper.xml b/src/main/java/com/newyetai/usercenter/user/mapper/UserMapper.xml new file mode 100644 index 0000000..b6e8e8a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/mapper/UserMapper.xml @@ -0,0 +1,577 @@ + + + + + update + uc_user + set status = 3, + update_by = #{operateUserId}, + update_time = now() + where id = #{userId} + and deleted = 0 + and status != 3 + + + + + update + uc_user + set + username = #{username}, + password = #{encodedPassword}, + update_by = #{operateUserId}, + update_time = now() + where + id = #{operateUserId} + and deleted = 0 and status != 3 + and (password is null or password = '') + + + + + + + + update uc_user + set + phone = null, + update_by = #{userId}, + update_time = now() + where + id != #{userId} + and deleted = 0 and status != 3 + and type = 2 + and phone = #{phone} + + + + + update uc_user + set + real_name = #{param.realName}, + card_no = #{param.cardNo}, + birthday = SUBSTR(#{param.cardNo},7,8), + gender = CASE WHEN SUBSTR(#{param.cardNo},17,1)%2 =1 THEN 1 ELSE 2 END, + authenticated = 1, + update_time = now() + where + type = 2 + + and card_no = #{param.cardNo} + + and deleted = 0 and status != 3 + and authenticated = 0 + + and id = #{param.userId} + + + + + update uc_user + set + phone_binding = 1, + + phone = #{phone}, + + update_time = now() + where + id = #{userId} + + and length(phone) = 11 + + and deleted = 0 and status != 3 + + + + + + + + + update uc_user u + set u.phone = (select temp.phone from (select phone from uc_user where id = #{phoneUserId}) temp), + u.phone_binding = 1, + u.update_time = now() + where + u.id = #{retainUserId} + and u.deleted = 0 and u.status != 3 + and u.phone_binding = 0 + + + + + + + + + update uc_user + + + username = #{username}, + + + nickname = #{nickname}, + + + enabled = #{enabled}, + + + email = #{email}, + + update_by = #{updateBy}, + update_time = now() + + where id = #{id} + + + + update uc_user set password = #{password}, update_by = #{operateUserId}, update_time = now() where id = #{userId} + + + + + + + + + update uc_user + set status = 2, + update_time = now() + where id = #{userId} + and deleted = 0 + and status != 3 + + + + diff --git a/src/main/java/com/newyetai/usercenter/user/mapper/UserPhoneThreeVerificationMapper.xml b/src/main/java/com/newyetai/usercenter/user/mapper/UserPhoneThreeVerificationMapper.xml new file mode 100644 index 0000000..49d328d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/mapper/UserPhoneThreeVerificationMapper.xml @@ -0,0 +1,33 @@ + + + + + + diff --git a/src/main/java/com/newyetai/usercenter/user/mapper/UserPostalInfoMapper.xml b/src/main/java/com/newyetai/usercenter/user/mapper/UserPostalInfoMapper.xml new file mode 100644 index 0000000..76d1563 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/mapper/UserPostalInfoMapper.xml @@ -0,0 +1,33 @@ + + + + + update uc_user_postal_info set defaulted = 0 where create_by = #{userId} and id != #{id} and deleted = 0 + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/user/mapper/UserRegisterMapper.xml b/src/main/java/com/newyetai/usercenter/user/mapper/UserRegisterMapper.xml new file mode 100644 index 0000000..7ecdbad --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/mapper/UserRegisterMapper.xml @@ -0,0 +1,44 @@ + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/newyetai/usercenter/user/mapstruct/OrgUserMapMapper.java b/src/main/java/com/newyetai/usercenter/user/mapstruct/OrgUserMapMapper.java new file mode 100644 index 0000000..6b6e006 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/mapstruct/OrgUserMapMapper.java @@ -0,0 +1,37 @@ +package com.newyetai.usercenter.user.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.newyetai.usercenter.user.dto.OrgUserDTO; +import com.newyetai.usercenter.user.dto.OrgUserOperateDTO; +import com.newyetai.usercenter.user.entity.OrgUser; + +/** + * @author sr on 2021-05-24 + */ +@Mapper +public interface OrgUserMapMapper { + + OrgUserMapMapper INSTANCE = + Mappers.getMapper(OrgUserMapMapper.class); + + /** + * dto to entity + * + * @param orgUserDto + * @return + * @author sr on 2021-05-24 + */ + OrgUser toEntity( + OrgUserDTO orgUserDto); + + + /** + * @param orgUserOperateDTO + * @return + * @author sr on 2021-05-24 + */ + OrgUser toEntity(OrgUserOperateDTO orgUserOperateDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/user/mapstruct/UserAuthMapMapper.java b/src/main/java/com/newyetai/usercenter/user/mapstruct/UserAuthMapMapper.java new file mode 100644 index 0000000..c56ea6a --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/mapstruct/UserAuthMapMapper.java @@ -0,0 +1,37 @@ +package com.newyetai.usercenter.user.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.newyetai.usercenter.user.dto.UserAuthDTO; +import com.newyetai.usercenter.user.entity.UserAuth; +import com.newyetai.usercenter.user.dto.UserAuthOperateDTO; + +/** + * @author sr on 2021-05-24 + */ +@Mapper +public interface UserAuthMapMapper { + + UserAuthMapMapper INSTANCE = + Mappers.getMapper(UserAuthMapMapper.class); + + /** + * dto to entity + * + * @param userAuthDto + * @return + * @author sr on 2021-05-24 + */ + UserAuth toEntity( + UserAuthDTO userAuthDto); + + + /** + * @param userAuthOperateDTO + * @return + * @author sr on 2021-05-24 + */ + UserAuth toEntity(UserAuthOperateDTO userAuthOperateDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/user/mapstruct/UserBankAccountMapMapper.java b/src/main/java/com/newyetai/usercenter/user/mapstruct/UserBankAccountMapMapper.java new file mode 100644 index 0000000..98f6bd1 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/mapstruct/UserBankAccountMapMapper.java @@ -0,0 +1,60 @@ +package com.newyetai.usercenter.user.mapstruct; + +import com.newyetai.usercenter.user.dto.UserBankAccountChangeReqDTO; +import com.newyetai.usercenter.user.dto.UserBankAccountCreateReqDTO; +import com.newyetai.usercenter.user.dto.UserBankAccountDTO; +import com.newyetai.usercenter.user.dto.UserBankAccountInfoDTO; +import com.newyetai.usercenter.user.dto.UserBankCardThreeVerificationCreateDTO; +import com.newyetai.usercenter.user.dto.UserBankCardThreeVerificationDTO; +import com.newyetai.usercenter.user.entity.UcUserBankAccount; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + + +/** + * 用户的银行账户映射映射器 + * + * @author Carlye + * @date 2021/06/25 + */ +@Mapper +public interface UserBankAccountMapMapper { + + UserBankAccountMapMapper INSTANCE = + Mappers.getMapper(UserBankAccountMapMapper.class); + + + /** + * dto转换 + * @param reqDTO 点播dto + * @return {@link UcUserBankAccount} + */ + UcUserBankAccount exchange(UserBankAccountCreateReqDTO reqDTO); + + /** + * dto转换 + * @param reqDTO 点播dto + * @return {@link UcUserBankAccount} + */ + UserBankAccountInfoDTO exchange(UserBankAccountDTO reqDTO); + + @Mapping(source = "newAccountNo",target = "accountNo") + UserBankAccountCreateReqDTO exchange(UserBankAccountChangeReqDTO reqDTO); + + + /** + * dto转换 + * @param userBankAccount 点播dto + * @return {@link UserBankAccountCreateReqDTO} + */ + UserBankAccountInfoDTO exchange(UcUserBankAccount userBankAccount); + + + @Mappings(value = { + @Mapping(target = "accountName", source = "realName"), + @Mapping(target = "accountNo", source = "bankAccountNo"), + }) + UserBankAccountCreateReqDTO toDto(UserBankCardThreeVerificationCreateDTO userBankCardThreeVerificationCreateDTO); +} diff --git a/src/main/java/com/newyetai/usercenter/user/mapstruct/UserBankCardFourVerificationMapMapper.java b/src/main/java/com/newyetai/usercenter/user/mapstruct/UserBankCardFourVerificationMapMapper.java new file mode 100644 index 0000000..734b7fd --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/mapstruct/UserBankCardFourVerificationMapMapper.java @@ -0,0 +1,55 @@ +package com.newyetai.usercenter.user.mapstruct; + +import com.newyetai.alitaforward.verification.dto.FourFactorVerificationDTO; +import com.newyetai.alitaforward.verification.dto.ThreeFactorVerificationDTO; +import com.newyetai.usercenter.user.dto.UserBankCardFourVerificationDTO; +import com.newyetai.usercenter.user.dto.UserBankCardFourVerificationOperateDTO; +import com.newyetai.usercenter.user.dto.UserBankCardThreeVerificationDTO; +import com.newyetai.usercenter.user.dto.UserBankCardThreeVerificationOperateDTO; +import com.newyetai.usercenter.user.entity.UserBankCardFourVerification; +import com.newyetai.usercenter.user.entity.UserBankCardThreeVerification; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; + +/** + * @author czy + * @date 2021-06-23 + */ + +@Mapper +public interface UserBankCardFourVerificationMapMapper { + + UserBankCardFourVerificationMapMapper INSTANCE = Mappers.getMapper(UserBankCardFourVerificationMapMapper.class); + + /** + * to entity + * @param dto + * @return + */ + @Mapping(target = "sourceVerifyId", source = "dto.id") + UserBankCardFourVerification toEntity(FourFactorVerificationDTO dto); + + /** + * to entity + * @param operateDTO + * @return + */ + UserBankCardFourVerification toEntity(UserBankCardFourVerificationOperateDTO operateDTO); + + /** + * to dto + * @param dto + * @return + */ + FourFactorVerificationDTO toDto(UserBankCardFourVerificationDTO dto); + + /** + * to dto + * @param entity + * @return + */ + UserBankCardFourVerificationDTO toDto(UserBankCardFourVerification entity); + + +} diff --git a/src/main/java/com/newyetai/usercenter/user/mapstruct/UserBankCardThreeVerificationMapMapper.java b/src/main/java/com/newyetai/usercenter/user/mapstruct/UserBankCardThreeVerificationMapMapper.java new file mode 100644 index 0000000..97ce1fe --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/mapstruct/UserBankCardThreeVerificationMapMapper.java @@ -0,0 +1,56 @@ +package com.newyetai.usercenter.user.mapstruct; + +import com.newyetai.alitaforward.verification.dto.ThreeFactorVerificationDTO; +import com.newyetai.usercenter.user.dto.UserBankCardThreeVerificationCreateDTO; +import com.newyetai.usercenter.user.dto.UserBankCardThreeVerificationDTO; +import com.newyetai.usercenter.user.dto.UserBankCardThreeVerificationOperateDTO; +import com.newyetai.usercenter.user.entity.UserBankCardThreeVerification; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +/** + * @author czy + * @date 2021-06-23 + */ + +@Mapper +public interface UserBankCardThreeVerificationMapMapper { + + UserBankCardThreeVerificationMapMapper INSTANCE = Mappers.getMapper( + UserBankCardThreeVerificationMapMapper.class); + + /** + * to entity + * @param dto + * @return + */ + @Mappings({ + @Mapping(target = "sourceVerifyId", source = "dto.id"), + @Mapping(target = "id", source = "dto.id", ignore = true) + }) + UserBankCardThreeVerification toEntity(ThreeFactorVerificationDTO dto); + + /** + * to entity + * @param operateDTO + * @return + */ + UserBankCardThreeVerification toEntity(UserBankCardThreeVerificationOperateDTO operateDTO); + + /** + * to dto + * @param dto + * @return + */ + ThreeFactorVerificationDTO toDto(UserBankCardThreeVerificationCreateDTO dto); + + /** + * to dto + * @param entity + * @return + */ + UserBankCardThreeVerificationDTO toDto(UserBankCardThreeVerification entity); + +} diff --git a/src/main/java/com/newyetai/usercenter/user/mapstruct/UserConfigMapMapper.java b/src/main/java/com/newyetai/usercenter/user/mapstruct/UserConfigMapMapper.java new file mode 100644 index 0000000..87b4d3e --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/mapstruct/UserConfigMapMapper.java @@ -0,0 +1,37 @@ +package com.newyetai.usercenter.user.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.newyetai.usercenter.user.dto.UserConfigDTO; +import com.newyetai.usercenter.user.entity.UserConfig; +import com.newyetai.usercenter.user.dto.UserConfigOperateDTO; + +/** + * @author sr on 2021-08-12 + */ +@Mapper +public interface UserConfigMapMapper { + + UserConfigMapMapper INSTANCE = + Mappers.getMapper(UserConfigMapMapper.class); + + /** + * dto to entity + * + * @param userConfigDto + * @return + * @author sr on 2021-08-12 + */ + UserConfig toEntity( + UserConfigDTO userConfigDto); + + + /** + * @param userConfigOperateDTO + * @return + * @author sr on 2021-08-12 + */ + UserConfig toEntity(UserConfigOperateDTO userConfigOperateDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/user/mapstruct/UserExtensionMapMapper.java b/src/main/java/com/newyetai/usercenter/user/mapstruct/UserExtensionMapMapper.java new file mode 100644 index 0000000..c29165d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/mapstruct/UserExtensionMapMapper.java @@ -0,0 +1,39 @@ +package com.newyetai.usercenter.user.mapstruct; + +import com.newyetai.usercenter.user.dao.UserExtensionMapper; +import com.newyetai.usercenter.user.dto.UserExtensionDTO; +import com.newyetai.usercenter.user.dto.UserExtensionOperateDTO; +import com.newyetai.usercenter.user.entity.UserExtension; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * @author czy on 2021-06-15 + */ +@Mapper +public interface UserExtensionMapMapper { + + UserExtensionMapMapper INSTANCE = + Mappers.getMapper(UserExtensionMapMapper.class); + + /** + * dto to entity + * @author czy on 2021-06-15 + */ + UserExtension toEntity( + UserExtensionDTO userExtensionDTO); + + + /** + * OperateDTO to entity + * @author czy on 2021-06-15 + */ + UserExtension toEntity(UserExtensionOperateDTO userExtensionOperateDTO); + + /** + * entity to dto + * @author czy on 2021-06-15 + */ + UserExtensionDTO toDto(UserExtension userExtension); + +} diff --git a/src/main/java/com/newyetai/usercenter/user/mapstruct/UserIdentityPhotoMapMapper.java b/src/main/java/com/newyetai/usercenter/user/mapstruct/UserIdentityPhotoMapMapper.java new file mode 100644 index 0000000..c0f68f2 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/mapstruct/UserIdentityPhotoMapMapper.java @@ -0,0 +1,41 @@ +package com.newyetai.usercenter.user.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.newyetai.usercenter.user.dto.UserIdentityPhotoInfoDTO; +import com.newyetai.usercenter.user.dto.UserIdentityPhotoDTO; +import com.newyetai.usercenter.user.entity.UserIdentityPhoto; +import com.newyetai.usercenter.user.dto.UserIdentityPhotoOperateDTO; + +/** + * @author sr on 2021-05-24 + */ +@Mapper +public interface UserIdentityPhotoMapMapper { + + UserIdentityPhotoMapMapper INSTANCE = + Mappers.getMapper(UserIdentityPhotoMapMapper.class); + + /** + * dto to entity + * + * @param userIdentityPhotoDto + * @return + * @author sr on 2021-05-24 + */ + UserIdentityPhoto toEntity( + UserIdentityPhotoDTO userIdentityPhotoDto); + + + /** + * @param userIdentityPhotoOperateDTO + * @return + * @author sr on 2021-05-24 + */ + UserIdentityPhoto toEntity(UserIdentityPhotoOperateDTO userIdentityPhotoOperateDTO); + + UserIdentityPhotoInfoDTO toInfo( + UserIdentityPhotoDTO userIdentityPhotoDto); + +} diff --git a/src/main/java/com/newyetai/usercenter/user/mapstruct/UserMapMapper.java b/src/main/java/com/newyetai/usercenter/user/mapstruct/UserMapMapper.java new file mode 100644 index 0000000..5e67293 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/mapstruct/UserMapMapper.java @@ -0,0 +1,99 @@ +package com.newyetai.usercenter.user.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +import com.newyetai.usercenter.auth.dto.AuthDetailLoginDTO; +import com.newyetai.usercenter.user.dto.AuthenticateUserDTO; +import com.newyetai.usercenter.user.dto.OrgUserCreateDTO; +import com.newyetai.usercenter.user.dto.PersonUserCardCreateDTO; +import com.newyetai.usercenter.user.dto.PersonUserCardCreateResultDTO; +import com.newyetai.usercenter.user.dto.SuperRealNameTwoAuthDTO; +import com.newyetai.usercenter.user.dto.UserDTO; +import com.newyetai.usercenter.user.dto.UserOperateDTO; +import com.newyetai.usercenter.user.entity.User; +import com.newyetai.usercenter.user.login.dto.UserDetailDTO; +import com.newyetai.usercenter.user.login.dto.UserDetailSelectDTO; + +/** + * @author sr on 2021-05-24 + */ +@Mapper +public interface UserMapMapper { + + UserMapMapper INSTANCE = + Mappers.getMapper(UserMapMapper.class); + + /** + * dto to entity + * + * @author sr on 2021-05-24 + */ + User toEntity( + UserDTO userDto); + + + /** + * @author sr on 2021-05-24 + */ + User toEntity(UserOperateDTO userOperateDTO); + + /** + * entity to dto + * + * @author czy on 2021-06-10 + */ + UserDTO toDto(User user); + + /** + * 创建企业用户 + * @param companyUserCreateDTO + * @return + * @author sr on 2021-06-10 + */ + @Mappings( + value = { + @Mapping(target = "type", + expression = "java(com.newyetai.usercenter.user.constant.UserTypeEnum.ORG.getType())"), + @Mapping(target = "phoneBinding", + constant = "false"), + }) + User toCreateCompanyUser(OrgUserCreateDTO companyUserCreateDTO); + + /** + * 创建个人用户 + * @param personUserCardCreateDTO + * @return + * @author sr on 2021-06-10 + */ + @Mappings( + value = { + @Mapping(target = "type", + expression = "java(com.newyetai.usercenter.user.constant.UserTypeEnum.PERSON.getType())"), + @Mapping(target = "phoneBinding", + constant = "false"), + }) + User toCreatePersonUser(PersonUserCardCreateDTO personUserCardCreateDTO); + + PersonUserCardCreateResultDTO toResultDTO(PersonUserCardCreateDTO personUserCardCreateDTO); + PersonUserCardCreateResultDTO toResultDTO(UserDTO userDTO); + + UserDetailDTO toUserDetailDTO(User user); + UserDetailDTO toUserDetailDTO(UserDTO userDTO); + + @Mappings( + value = { + @Mapping(target = "type", source = "authDetailDTO.userType"), + @Mapping(target = "id", ignore = true), + @Mapping(target = "phoneBinding", + constant = "false"), + }) + User toCreate(AuthDetailLoginDTO authDetailDTO); + + UserDetailSelectDTO toSelectDTO(UserDetailDTO userDetailDTO); + + AuthenticateUserDTO to(SuperRealNameTwoAuthDTO authDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/user/mapstruct/UserPhoneThreeVerificationMapMapper.java b/src/main/java/com/newyetai/usercenter/user/mapstruct/UserPhoneThreeVerificationMapMapper.java new file mode 100644 index 0000000..0b793b5 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/mapstruct/UserPhoneThreeVerificationMapMapper.java @@ -0,0 +1,64 @@ +package com.newyetai.usercenter.user.mapstruct; + +import com.newyetai.alitaforward.verification.dto.PhoneThreeFactorVerificationDTO; +import com.newyetai.alitaforward.verification.dto.ThreeFactorVerificationDTO; +import com.newyetai.usercenter.user.dto.UserPhoneThreeVerificationDTO; +import com.newyetai.usercenter.user.dto.UserPhoneThreeVerificationOperateDTO; +import com.newyetai.usercenter.user.entity.UserPhoneThreeVerification; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +/** + * @author czy + * @date 2021-06-23 + */ + +@Mapper +public interface UserPhoneThreeVerificationMapMapper { + + UserPhoneThreeVerificationMapMapper INSTANCE = Mappers.getMapper( + UserPhoneThreeVerificationMapMapper.class); + + /** + * to entity + * @param dto + * @return + */ + @Mappings({ + @Mapping(target = "sourceVerifyId", source = "dto.id"), + @Mapping(target = "id", source = "dto.id", ignore = true) + }) + UserPhoneThreeVerification toEntity(ThreeFactorVerificationDTO dto); + + /** + * to entity + * @param operateDTO + * @return + */ + UserPhoneThreeVerification toEntity(UserPhoneThreeVerificationOperateDTO operateDTO); + + /** + * to dto + * @param dto + * @return + */ + PhoneThreeFactorVerificationDTO toDto(UserPhoneThreeVerificationDTO dto); + + /** + * 实体 + * + * @param dto dto + * @return {@link PhoneThreeFactorVerificationDTO} + */ + UserPhoneThreeVerification toEntity(PhoneThreeFactorVerificationDTO dto); + + /** + * to dto + * @param entity + * @return + */ + UserPhoneThreeVerificationDTO toDto(UserPhoneThreeVerification entity); + +} diff --git a/src/main/java/com/newyetai/usercenter/user/mapstruct/UserPostalInfoMapMapper.java b/src/main/java/com/newyetai/usercenter/user/mapstruct/UserPostalInfoMapMapper.java new file mode 100644 index 0000000..3133d80 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/mapstruct/UserPostalInfoMapMapper.java @@ -0,0 +1,37 @@ +package com.newyetai.usercenter.user.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.newyetai.usercenter.user.dto.UserPostalInfoDTO; +import com.newyetai.usercenter.user.entity.UserPostalInfo; +import com.newyetai.usercenter.user.dto.UserPostalInfoOperateDTO; + +/** + * @author fzp on 2022-01-19 + */ +@Mapper +public interface UserPostalInfoMapMapper { + + UserPostalInfoMapMapper INSTANCE = + Mappers.getMapper(UserPostalInfoMapMapper.class); + + /** + * dto to entity + * + * @param userPostalInfoDto + * @return + * @author fzp on 2022-01-19 + */ + UserPostalInfo toEntity( + UserPostalInfoDTO userPostalInfoDto); + + + /** + * @param userPostalInfoOperateDTO + * @return + * @author fzp on 2022-01-19 + */ + UserPostalInfo toEntity(UserPostalInfoOperateDTO userPostalInfoOperateDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/user/mapstruct/UserRegisterMapMapper.java b/src/main/java/com/newyetai/usercenter/user/mapstruct/UserRegisterMapMapper.java new file mode 100644 index 0000000..b425853 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/mapstruct/UserRegisterMapMapper.java @@ -0,0 +1,58 @@ +package com.newyetai.usercenter.user.mapstruct; + +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +import com.newyetai.usercenter.user.dto.UserRegisterCodeInfoDTO; +import com.newyetai.usercenter.user.dto.UserDetailQueryDTO; +import com.newyetai.usercenter.user.dto.UserRegisterCodeDTO; +import com.newyetai.usercenter.user.dto.UserRegisterDTO; +import com.newyetai.usercenter.user.entity.UserRegister; +import com.newyetai.usercenter.user.login.dto.UserDetailDTO; +import com.newyetai.usercenter.user.dto.UserRegisterOperateDTO; + +/** + * @author sr on 2021-11-16 + */ +@Mapper +public interface UserRegisterMapMapper { + + UserRegisterMapMapper INSTANCE = + Mappers.getMapper(UserRegisterMapMapper.class); + + /** + * dto to entity + * + * @param userRegisterDto + * @return + * @author sr on 2021-11-16 + */ + UserRegister toEntity( + UserRegisterDTO userRegisterDto); + + + /** + * @param userRegisterOperateDTO + * @return + * @author sr on 2021-11-16 + */ + UserRegister toEntity(UserRegisterOperateDTO userRegisterOperateDTO); + + @Mappings({ + @Mapping(target = "userType", source = "inviterType"), + @Mapping(target = "userId", source = "inviterId"), + @Mapping(target = "orgId", source = "inviterOrgId"), + }) + UserDetailQueryDTO toDto(UserRegisterCodeInfoDTO dto); + + UserRegisterCodeInfoDTO toDto(UserRegisterCodeDTO userRegisterCodeDTO); + + UserRegisterDTO toDto(UserRegister userRegister); + + UserRegister toEntity(UserRegisterCodeInfoDTO dto); + + + +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/check/AbstractRedisPhoneCodeChecker.java b/src/main/java/com/newyetai/usercenter/user/phone/check/AbstractRedisPhoneCodeChecker.java new file mode 100644 index 0000000..74e848d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/check/AbstractRedisPhoneCodeChecker.java @@ -0,0 +1,20 @@ +package com.newyetai.usercenter.user.phone.check; + +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.exception.util.Assert; + +/** + * 借用redis校验手机号验证码校验结果的校验器 + * @author sr on 2021-06-16 + */ +public abstract class AbstractRedisPhoneCodeChecker implements IPhoneCodeChecker { + + public static final String REDIS_PREFIX = "phone:code:check"; + + public String getRedisKey(String smsProviderType, String phone) { + Assert.notBlank(smsProviderType, "验证码提供者类型不能为空"); + return String.join(CommonConstants.COLON, REDIS_PREFIX, getType(), smsProviderType, + phone); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/check/CaptchaPhoneCodeChecker.java b/src/main/java/com/newyetai/usercenter/user/phone/check/CaptchaPhoneCodeChecker.java new file mode 100644 index 0000000..79f3955 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/check/CaptchaPhoneCodeChecker.java @@ -0,0 +1,42 @@ +package com.newyetai.usercenter.user.phone.check; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.sdk.captcha.service.impl.LoginCaptchaAppProvider; +import com.newyetai.usercenter.user.phone.constant.PhoneCodeCheckerEnum; +import com.newyetai.usercenter.user.phone.dto.CaptchaPhoneCodeSmsDTO; +import com.newyetai.usercenter.user.phone.dto.IPhoneCodeSmsDTO; + +/** + * 防水墙校验器(注意最先添加进提供者) + * @author sr on 2021-06-17 + */ +@Component +public class CaptchaPhoneCodeChecker implements IPhoneCodeChecker { + + /** TODO 当无防水墙提供者,类注入问题 **/ + @Autowired(required = false) + private LoginCaptchaAppProvider loginCaptchaAppProvider; + + @Override + public String getType() { + return PhoneCodeCheckerEnum.CAPTCHA.getType(); + } + + @Override + public boolean supports(Class clazz) { + return CaptchaPhoneCodeSmsDTO.class.isAssignableFrom(clazz); + } + + @Override + public void check(IPhoneCodeSmsDTO phoneCodeSmsDTO) { + CaptchaPhoneCodeSmsDTO captchaDTO = ((CaptchaPhoneCodeSmsDTO) phoneCodeSmsDTO); + AlitaResult captchaResult = + loginCaptchaAppProvider.verify(captchaDTO.getTicket(), captchaDTO.getRandstr()); + Assert.isTrue(captchaResult.getSuccess() && captchaResult.getData(), "防水墙验证失败"); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/check/ChangePhoneChecker.java b/src/main/java/com/newyetai/usercenter/user/phone/check/ChangePhoneChecker.java new file mode 100644 index 0000000..cd8faf3 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/check/ChangePhoneChecker.java @@ -0,0 +1,59 @@ +package com.newyetai.usercenter.user.phone.check; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.usercenter.user.constant.UserTypeEnum; +import com.newyetai.usercenter.user.dto.IUserPhoneCodeSms; +import com.newyetai.usercenter.user.dto.UserDTO; +import com.newyetai.usercenter.user.dto.UserQueryDTO; +import com.newyetai.usercenter.user.phone.constant.PhoneCodeCheckerEnum; +import com.newyetai.usercenter.user.phone.dto.IPhoneCodeSmsDTO; +import com.newyetai.usercenter.user.service.UserService; + + +/** + * 换绑手机 + * @author sr on 2021-09-02 + */ +@Component +public class ChangePhoneChecker implements IPhoneCodeChecker { + + @Autowired + private UserService userService; + + @Override + public String getType() { + return PhoneCodeCheckerEnum.CHANGE_PHONE.getType(); + } + + @Override + public boolean supports(Class clazz) { + return IUserPhoneCodeSms.class.isAssignableFrom(clazz); + } + + @Override + public void check(IPhoneCodeSmsDTO phoneCodeSmsDTO) { + // 未被其它相同用户类型的用户绑定 + UserContextHolder.getExistLoginUserId(); + Integer userType = ((IUserPhoneCodeSms) phoneCodeSmsDTO).getUserType(); + UserQueryDTO userQueryDTO = UserQueryDTO.builder() + .phone(phoneCodeSmsDTO.getPhone()).type(userType).build(); + if (UserTypeEnum.PERSON.getType().equals(userType)) { + // 个人可能存在未绑定的多条记录 + userQueryDTO.setPhoneBinding(Boolean.TRUE); + } else if (UserTypeEnum.ORG.getType().equals(userType)) { + // 机构用户需要绑定态才能换绑 + Assert.isTrue(UserContextHolder.getExistLoginUser().getPhoneBinding(), "请先绑定手机号"); + } else { + throw new BusinessException("当前用户类型不支持换绑手机"); + } + UserDTO userDTO = userService.findUserDTO(userQueryDTO); + + Assert.isNull(userDTO, "该手机号已被其他用户绑定"); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/check/CountRedisPhoneCodeChecker.java b/src/main/java/com/newyetai/usercenter/user/phone/check/CountRedisPhoneCodeChecker.java new file mode 100644 index 0000000..dc39f9f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/check/CountRedisPhoneCodeChecker.java @@ -0,0 +1,61 @@ +package com.newyetai.usercenter.user.phone.check; + +import java.time.LocalDate; + +import org.springframework.stereotype.Component; + +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.exception.util.ExceptionUtils; +import com.newyetai.frame.redis.util.RedisUtils; +import com.newyetai.usercenter.user.phone.constant.PhoneCodeCheckerEnum; +import com.newyetai.usercenter.user.phone.dto.IPhoneCodeSmsDTO; + +/** + * 一天内获取验证码次数 + * @author sr on 2021-06-16 + */ +@Component +public class CountRedisPhoneCodeChecker extends AbstractRedisPhoneCodeChecker { + + /** 验证码登录次数过期时间-秒 **/ + public static final long COUNT_EXPIRE_TIME = 60 * 60 * 24; + + /** 默认每天获取验证码上限 **/ + public static final long DEFAULT_COUNT = 10; + + private Long countLimit = DEFAULT_COUNT; + + public CountRedisPhoneCodeChecker() {} + + public CountRedisPhoneCodeChecker(Long countLimit) { + this.countLimit = countLimit; + } + + @Override + public String getType() { + return PhoneCodeCheckerEnum.COUNT.getType(); + } + + @Override + public String getRedisKey(String smsProviderType, String phone) { + return String.join(CommonConstants.COLON, super.getRedisKey(smsProviderType, phone), + String.valueOf(LocalDate.now().getDayOfYear())); + } + + + @Override + public void check(IPhoneCodeSmsDTO phoneCodeSmsDTO) { + // phone:sms:count:dayOfYear:phone 有效期一天 + Long sendCount = RedisUtils + .increment(getRedisKey(phoneCodeSmsDTO.getProviderType(), phoneCodeSmsDTO.getPhone()), COUNT_EXPIRE_TIME); + ExceptionUtils.throwBusinessException(sendCount > countLimit, + "验证码发送超限,请明天再操作"); + } + + @Override + public void revertCheck(IPhoneCodeSmsDTO phoneCodeSmsDTO) { + RedisUtils.decrement(getRedisKey(phoneCodeSmsDTO.getProviderType(), phoneCodeSmsDTO.getPhone())); + } + + +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/check/HasLoginChecker.java b/src/main/java/com/newyetai/usercenter/user/phone/check/HasLoginChecker.java new file mode 100644 index 0000000..4883231 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/check/HasLoginChecker.java @@ -0,0 +1,29 @@ +package com.newyetai.usercenter.user.phone.check; + +import org.springframework.stereotype.Component; + +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.usercenter.user.phone.constant.PhoneCodeCheckerEnum; +import com.newyetai.usercenter.user.phone.dto.IPhoneCodeSmsDTO; + + +/** + * 已登录 + * @author sr on 2021-09-03 + */ +@Component +public class HasLoginChecker implements IPhoneCodeChecker { + + + @Override + public String getType() { + return PhoneCodeCheckerEnum.HAS_LOGIN.getType(); + } + + + @Override + public void check(IPhoneCodeSmsDTO phoneCodeSmsDTO) { + UserContextHolder.getExistLoginUser(); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/check/IPhoneCodeChecker.java b/src/main/java/com/newyetai/usercenter/user/phone/check/IPhoneCodeChecker.java new file mode 100644 index 0000000..ad19213 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/check/IPhoneCodeChecker.java @@ -0,0 +1,39 @@ +package com.newyetai.usercenter.user.phone.check; + +import com.newyetai.usercenter.user.phone.dto.IPhoneCodeSmsDTO; + +/** + * 手机号验证码校验器 + * @author sr on 2021-06-16 + */ +public interface IPhoneCodeChecker { + + /** + * 类型 + * @return + * @author sr on 2021-06-16 + */ + String getType(); + + default boolean supports(Class clazz) { + return true; + } + + /** + * 校验 + * @param smsProviderType + * @param iIPhoneCodeSmsDTO + * @author sr on 2021-06-16 + */ + void check(IPhoneCodeSmsDTO phoneCodeSmsDTO); + + /** + * 回退校验(如果校验更新为处理成功的数据,其他校验器失败,未触发短信发送,则回退处理成功数据) + * @param smsProviderType + * @param phoneCodeSmsDTO + * @author sr on 2021-06-16 + */ + default void revertCheck(IPhoneCodeSmsDTO phoneCodeSmsDTO) { + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/check/LastRedisPhoneCodeChecker.java b/src/main/java/com/newyetai/usercenter/user/phone/check/LastRedisPhoneCodeChecker.java new file mode 100644 index 0000000..d798af2 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/check/LastRedisPhoneCodeChecker.java @@ -0,0 +1,39 @@ +package com.newyetai.usercenter.user.phone.check; + +import org.springframework.stereotype.Component; + +import com.newyetai.common.exception.util.ExceptionUtils; +import com.newyetai.frame.redis.util.RedisUtils; +import com.newyetai.usercenter.user.phone.constant.PhoneCodeCheckerEnum; +import com.newyetai.usercenter.user.phone.dto.IPhoneCodeSmsDTO; + +/** + * 校验上一次获取验证码时间间隔是否超过一分钟 + * @author sr on 2021-06-16 + */ +@Component +public class LastRedisPhoneCodeChecker extends AbstractRedisPhoneCodeChecker { + + /** 发送验证码时间间隔-秒 **/ + public static final long LAST_EXPIRE_TIME = 60; + + @Override + public String getType() { + return PhoneCodeCheckerEnum.LAST.getType(); + } + + @Override + public void check(IPhoneCodeSmsDTO phoneCodeSmsDTO) { + Long num = RedisUtils.increment( + getRedisKey(phoneCodeSmsDTO.getProviderType(), phoneCodeSmsDTO.getPhone()), + LAST_EXPIRE_TIME); + ExceptionUtils.throwBusinessException(num > 1L, "操作过于频繁,请60秒后重试"); + } + + @Override + public void revertCheck(IPhoneCodeSmsDTO phoneCodeSmsDTO) { + RedisUtils + .decrement(getRedisKey(phoneCodeSmsDTO.getProviderType(), phoneCodeSmsDTO.getPhone())); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/check/ResetPwdChecker.java b/src/main/java/com/newyetai/usercenter/user/phone/check/ResetPwdChecker.java new file mode 100644 index 0000000..caa9410 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/check/ResetPwdChecker.java @@ -0,0 +1,52 @@ +package com.newyetai.usercenter.user.phone.check; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.usercenter.user.dto.IUserPhoneCodeSms; +import com.newyetai.usercenter.user.dto.UserDTO; +import com.newyetai.usercenter.user.dto.UserQueryDTO; +import com.newyetai.usercenter.user.phone.constant.PhoneCodeCheckerEnum; +import com.newyetai.usercenter.user.phone.dto.IPhoneCodeSmsDTO; +import com.newyetai.usercenter.user.service.UserService; + + +/** + * 重置密码 + * @author sr on 2021-09-02 + */ +@Component +public class ResetPwdChecker implements IPhoneCodeChecker { + + @Autowired + private UserService userService; + + @Override + public String getType() { + return PhoneCodeCheckerEnum.RESET_PWD.getType(); + } + + @Override + public boolean supports(Class clazz) { + return IUserPhoneCodeSms.class.isAssignableFrom(clazz); + } + + @Override + public void check(IPhoneCodeSmsDTO phoneCodeSmsDTO) { + Integer userType = ((IUserPhoneCodeSms) phoneCodeSmsDTO).getUserType(); + String phone = phoneCodeSmsDTO.getPhone(); + Long userId = UserContextHolder.getLoginUserId(); + if (userId == null) { + // 匿名访问 + Assert.notNull(userType, "无法获取验证码,用户类型不能为空"); + UserDTO userDTO = userService.findUserDTO(UserQueryDTO.builder().type(userType).phone(phone).build()); + Assert.notNull(userDTO, "该手机号用户不存在"); + } else { + UserDTO userDTO = userService.findUserDTO(UserQueryDTO.builder().id(userId).build()); + Assert.isTrue(phone.equals(userDTO.getPhone()), "手机号与当前用户手机号不匹配"); + } + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/constant/PhoneCodeCheckerEnum.java b/src/main/java/com/newyetai/usercenter/user/phone/constant/PhoneCodeCheckerEnum.java new file mode 100644 index 0000000..f9cf720 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/constant/PhoneCodeCheckerEnum.java @@ -0,0 +1,33 @@ +package com.newyetai.usercenter.user.phone.constant; + +/** + * 校验器枚举 + * @author sr on 2021-09-01 + */ +public enum PhoneCodeCheckerEnum { + + /** 防水墙 **/ + CAPTCHA("captcha"), + /** 一天内获取验证码次数 **/ + COUNT("count"), + /** 校验上一次获取验证码时间间隔 **/ + LAST("last"), + /** 换绑手机 **/ + CHANGE_PHONE("changphone"), + /** 重置密码 **/ + RESET_PWD("resetpwd"), + /** 已登录 **/ + HAS_LOGIN("haslogin"), + ; + + private String type; + + PhoneCodeCheckerEnum(String type) { + this.type = type; + } + + public String getType() { + return type; + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/constant/PhoneCodeProviderEnum.java b/src/main/java/com/newyetai/usercenter/user/phone/constant/PhoneCodeProviderEnum.java new file mode 100644 index 0000000..64c69b1 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/constant/PhoneCodeProviderEnum.java @@ -0,0 +1,81 @@ +package com.newyetai.usercenter.user.phone.constant; + +import java.util.Locale; +import java.util.Map; + +import com.google.common.collect.Maps; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.usercenter.user.constant.UserTypeEnum; + +/** + * 手机验证码提供者枚举 + * @author sr on 2021-09-01 + */ +public enum PhoneCodeProviderEnum { + + /** 机构用户登录 **/ + ORG_LOGIN(UserTypeEnum.ORG, UserPhoneCodeOperateEnum.LOGIN), + /** 个人用户登录 **/ + PERSON_LOGIN(UserTypeEnum.PERSON, UserPhoneCodeOperateEnum.LOGIN), + /** 个人用户绑定手机号 **/ + PERSON_BIND_PHONE("personbindphone"), + /** 机构用户重置密码 **/ + ORG_RESET_PWD(UserTypeEnum.ORG, UserPhoneCodeOperateEnum.RESET_PWD), + /** 个人用户重置密码 **/ + PERSON_RESET_PWD(UserTypeEnum.PERSON, UserPhoneCodeOperateEnum.RESET_PWD), + /** 机构用户重置安全码 **/ + ORG_RESET_SECURITY_CODE(UserTypeEnum.ORG, UserPhoneCodeOperateEnum.RESET_SECURITY_CODE), + /** 个人用户重置安全码 **/ + PERSON_RESET_SECURITY_CODE(UserTypeEnum.PERSON, UserPhoneCodeOperateEnum.RESET_SECURITY_CODE), + /** 机构用户换绑手机 **/ + ORG_CHANGE_PHONE(UserTypeEnum.ORG, UserPhoneCodeOperateEnum.CHANGE_PHONE), + /** 个人用户换绑手机 **/ + PERSON_CHANGE_PHONE(UserTypeEnum.PERSON, UserPhoneCodeOperateEnum.CHANGE_PHONE), + /** 重置支付密码 **/ + RESET_PAY_PWD("resetpaypwd"), + /** 机构入驻 **/ + ORG_APPLY("orgapply"), + /** 机构入驻查询 **/ + GET_ORG_APPLY("getorgapply"), + /** 个人用户注销 **/ + USER_CANCEL(UserTypeEnum.PERSON,UserPhoneCodeOperateEnum.USER_CANCEL), + ; + + private static final Map providerMap; + + static { + PhoneCodeProviderEnum[] phoneCodeProviderEnums = PhoneCodeProviderEnum.values(); + providerMap = Maps.newHashMapWithExpectedSize(phoneCodeProviderEnums.length); + for (PhoneCodeProviderEnum phoneCodeProviderEnum : phoneCodeProviderEnums) { + providerMap.put(phoneCodeProviderEnum.getType(), phoneCodeProviderEnum); + } + } + + private String type; + + PhoneCodeProviderEnum(UserTypeEnum userTypeEnum, + UserPhoneCodeOperateEnum userPhoneCodeOperateEnum) { + type = userTypeEnum.name().toLowerCase(Locale.CHINESE) + userPhoneCodeOperateEnum.getOperate(); + } + + PhoneCodeProviderEnum(String type) { + this.type = type; + } + + public String getType() { + return type; + } + + public static void check(String type) { + Assert.isTrue(providerMap.containsKey(type), "未找到对应短信验证码的提供者"); + } + + public static String getType(UserTypeEnum userTypeEnum, String operate) { + PhoneCodeProviderEnum phoneCodeProviderEnum = + providerMap.get(userTypeEnum.name().toLowerCase(Locale.CHINESE) + operate); + Assert.notNull(phoneCodeProviderEnum, "未找到对应验证码提供者"); + return phoneCodeProviderEnum.getType(); + } + + +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/constant/UserPhoneCodeOperateEnum.java b/src/main/java/com/newyetai/usercenter/user/phone/constant/UserPhoneCodeOperateEnum.java new file mode 100644 index 0000000..10e8dd4 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/constant/UserPhoneCodeOperateEnum.java @@ -0,0 +1,32 @@ +package com.newyetai.usercenter.user.phone.constant; + +/** + * 手机验证码提供者枚举 + * @author sr on 2021-09-01 + */ +public enum UserPhoneCodeOperateEnum { + + /** 登录 **/ + LOGIN("login"), + /** 重置密码 **/ + RESET_PWD("resetpwd"), + /** 绑定手机 **/ + BIND_PHONE("bindphone"), + /** 重置安全码 **/ + RESET_SECURITY_CODE("resetsecuritycode"), + /** 换绑手机 **/ + CHANGE_PHONE("changephone"), + /** 注销 **/ + USER_CANCEL("usercancel"), + ; + + private String operate; + + UserPhoneCodeOperateEnum(String operate) { + this.operate = operate; + } + + public String getOperate() { + return operate; + } +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/dto/CaptchaPhoneCodeSmsDTO.java b/src/main/java/com/newyetai/usercenter/user/phone/dto/CaptchaPhoneCodeSmsDTO.java new file mode 100644 index 0000000..e950c13 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/dto/CaptchaPhoneCodeSmsDTO.java @@ -0,0 +1,32 @@ +package com.newyetai.usercenter.user.phone.dto; + +import javax.validation.constraints.NotBlank; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2021-06-17 + */ +@ApiModel("防水墙-手机发送短信验证码") +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class CaptchaPhoneCodeSmsDTO extends PhoneCodeSmsDTO{ + + /** **/ + private static final long serialVersionUID = -5842216049872318987L; + + @ApiModelProperty("防水墙验证票据") + @NotBlank(message = "防水墙验证票据不能为空") + private String ticket; + @ApiModelProperty("防水墙随机字符串") + @NotBlank(message = "防水墙随机字符串不能为空") + private String randstr; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/dto/ICode.java b/src/main/java/com/newyetai/usercenter/user/phone/dto/ICode.java new file mode 100644 index 0000000..fbd9d3d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/dto/ICode.java @@ -0,0 +1,14 @@ +package com.newyetai.usercenter.user.phone.dto; + +/** + * 验证码属性 + * @author sr on 2021-09-02 + */ +public interface ICode { + /** + * 获取验证码 + * @return + * @author sr on 2021-09-02 + */ + String getCode(); +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/dto/IPhoneCodeDTO.java b/src/main/java/com/newyetai/usercenter/user/phone/dto/IPhoneCodeDTO.java new file mode 100644 index 0000000..745ed52 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/dto/IPhoneCodeDTO.java @@ -0,0 +1,9 @@ +package com.newyetai.usercenter.user.phone.dto; + +/** + * 手机号验证码-验证 + * @author sr on 2021-06-17 + */ +public interface IPhoneCodeDTO extends IPhoneCodeSmsDTO, ICode{ + +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/dto/IPhoneCodeSmsDTO.java b/src/main/java/com/newyetai/usercenter/user/phone/dto/IPhoneCodeSmsDTO.java new file mode 100644 index 0000000..2461de7 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/dto/IPhoneCodeSmsDTO.java @@ -0,0 +1,28 @@ +package com.newyetai.usercenter.user.phone.dto; + +import java.io.Serializable; + +import com.newyetai.usercenter.user.phone.constant.PhoneCodeProviderEnum; + +/** + * 手机号验证码-发送 + * @author sr on 2021-06-17 + */ +public interface IPhoneCodeSmsDTO extends Serializable{ + + /** + * 手机号 + * @return + * @author sr on 2021-09-01 + */ + String getPhone(); + + /** + * 手机验证码提供者 + * {@link PhoneCodeProviderEnum} + * @return + * @author sr on 2021-09-01 + */ + String getProviderType(); + +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/dto/PhoneCodeDTO.java b/src/main/java/com/newyetai/usercenter/user/phone/dto/PhoneCodeDTO.java new file mode 100644 index 0000000..ad5e187 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/dto/PhoneCodeDTO.java @@ -0,0 +1,39 @@ +package com.newyetai.usercenter.user.phone.dto; + +import javax.validation.constraints.NotBlank; + +import com.newyetai.common.validation.annotation.Expression; +import com.newyetai.common.validation.constants.ValidProviderEnum; +import com.newyetai.usercenter.user.phone.constant.PhoneCodeProviderEnum; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2021-08-10 + */ +@ApiModel("短信验证码验证") +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class PhoneCodeDTO implements IPhoneCodeDTO{ + + /** **/ + private static final long serialVersionUID = 2786145404234042468L; + + @ApiModelProperty("验证码") + @NotBlank(message = "验证码不能为空") + private String code; + @ApiModelProperty("手机号码") + @Expression(type = ValidProviderEnum.PHONE, message = "手机号格式不正确") + private String phone; + /** {@link PhoneCodeProviderEnum} **/ + @ApiModelProperty("手机验证码提供者") + private String providerType; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/dto/PhoneCodeMessage.java b/src/main/java/com/newyetai/usercenter/user/phone/dto/PhoneCodeMessage.java new file mode 100644 index 0000000..6fb7a4d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/dto/PhoneCodeMessage.java @@ -0,0 +1,29 @@ +package com.newyetai.usercenter.user.phone.dto; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2020-08-04 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class PhoneCodeMessage implements Serializable { + + /** **/ + private static final long serialVersionUID = -7033284317906791262L; + + /** 手机号 **/ + private String phone; + /** 验证码 **/ + private String code; + /** host **/ + private String domainOrIp; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/dto/PhoneCodeSmsDTO.java b/src/main/java/com/newyetai/usercenter/user/phone/dto/PhoneCodeSmsDTO.java new file mode 100644 index 0000000..10f3bb2 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/dto/PhoneCodeSmsDTO.java @@ -0,0 +1,34 @@ +package com.newyetai.usercenter.user.phone.dto; + +import com.newyetai.common.validation.annotation.Expression; +import com.newyetai.common.validation.constants.ValidProviderEnum; +import com.newyetai.usercenter.user.phone.constant.PhoneCodeProviderEnum; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author sr on 2021-06-17 + */ +@ApiModel("手机发送短信验证码") +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class PhoneCodeSmsDTO implements IPhoneCodeSmsDTO{ + + /** **/ + private static final long serialVersionUID = 5540602446456225643L; + + @ApiModelProperty("手机号码") + @Expression(type = ValidProviderEnum.PHONE, message = "手机号格式不正确") + private String phone; + /** {@link PhoneCodeProviderEnum} **/ + @ApiModelProperty("手机验证码提供者") + private String providerType; + +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/dto/SmsSimpleSendDTO.java b/src/main/java/com/newyetai/usercenter/user/phone/dto/SmsSimpleSendDTO.java new file mode 100644 index 0000000..1207ca3 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/dto/SmsSimpleSendDTO.java @@ -0,0 +1,27 @@ +package com.newyetai.usercenter.user.phone.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.Singular; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.List; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class SmsSimpleSendDTO implements Serializable { + private static final long serialVersionUID = 4409542393509142949L; + + @NotEmpty(message = "模板编码不能为空") + private String templateCode; + + @NotNull(message = "短信发送明细不能为空") + @Singular + private List detailDTOS; +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/dto/SmsSimpleSendDetailDTO.java b/src/main/java/com/newyetai/usercenter/user/phone/dto/SmsSimpleSendDetailDTO.java new file mode 100644 index 0000000..f5a81d8 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/dto/SmsSimpleSendDetailDTO.java @@ -0,0 +1,27 @@ +package com.newyetai.usercenter.user.phone.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.Map; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class SmsSimpleSendDetailDTO implements Serializable { + private static final long serialVersionUID = 4409542393509142949L; + + /** + * 电话 + */ + private String phone; + + /** + * 参数 + */ + private Map parameters; +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/provider/AbstractAsyncPhoneCodeProvider.java b/src/main/java/com/newyetai/usercenter/user/phone/provider/AbstractAsyncPhoneCodeProvider.java new file mode 100644 index 0000000..b21f708 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/provider/AbstractAsyncPhoneCodeProvider.java @@ -0,0 +1,55 @@ +package com.newyetai.usercenter.user.phone.provider; + +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.util.RandomUtils; +import com.newyetai.mq.consumer.handler.ITopicMqHandler; +import com.newyetai.mq.dto.TopicMqMessage; +import com.newyetai.mq.util.MqSendUtils; +import com.newyetai.security.util.HostContextHolder; +import com.newyetai.usercenter.userprod.constant.UcMqSelfConstants; +import com.newyetai.usercenter.user.phone.dto.PhoneCodeMessage; +import com.newyetai.usercenter.user.phone.dto.PhoneCodeSmsDTO; + +import lombok.extern.slf4j.Slf4j; + +/** + * 抽象异步-手机号验证码提供者 + * @author sr on 2021-06-17 + */ +@Slf4j +public abstract class AbstractAsyncPhoneCodeProvider extends AbstractPhoneCodeProvider + implements ITopicMqHandler { + + @Override + public void send(PhoneCodeSmsDTO phoneCodeSmsDTO) { + preSendCheck(phoneCodeSmsDTO); + String phone = phoneCodeSmsDTO.getPhone(); + String code = generatePhoneCode(phone); + // mq发送消息 + MqSendUtils.send(TopicMqMessage.builder().messageId(RandomUtils.generateUUID()).routingKey(getRoutingKey()) + .data(PhoneCodeMessage.builder().phone(phone).code(code) + .domainOrIp(HostContextHolder.getHost()).build()) + .build()); + } + + @Override + public String getRoutingKey() { + return String.join(CommonConstants.UNDERLINE, + UcMqSelfConstants.ROUTING_KEY_PHONE_CODE_SMS_PREFIX, getType()); + } + + @Override + public void onMessage(TopicMqMessage message) { + // TODO messageId幂等 + String messageId = message.getMessageId(); + PhoneCodeMessage loginSms = message.getData(); + String phone = loginSms.getPhone(); + String code = loginSms.getCode(); + String existcode = PhoneCodeRepository.getPhoneSmsCode(getType(), phone); + if (!code.equals(existcode)) { + log.error("phoneCode:{},phone:{},验证码不一致(重发或过期),不发送消息", getType(), phone); + return; + } + super.sendSms(loginSms); + } +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/provider/AbstractPhoneCodeProvider.java b/src/main/java/com/newyetai/usercenter/user/phone/provider/AbstractPhoneCodeProvider.java new file mode 100644 index 0000000..879ca04 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/provider/AbstractPhoneCodeProvider.java @@ -0,0 +1,138 @@ +package com.newyetai.usercenter.user.phone.provider; + +import java.util.List; +import java.util.Map; + +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; + +import com.google.common.collect.Lists; +import com.newyetai.common.AlitaResult; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.EnvironmentUtils; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.common.util.RandomUtils; +import com.newyetai.common.validation.util.ValidateUtils; +import com.newyetai.sdk.sms.dto.VerificationCodeSendDTO; +import com.newyetai.sdk.sms.util.SmsUtils; +import com.newyetai.security.util.HostContextHolder; +import com.newyetai.usercenter.dto.DomainSettingReqDTO; +import com.newyetai.usercenter.constants.DomainSettingTypeEnum; +import com.newyetai.usercenter.sys.service.DomainSettingService; +import com.newyetai.usercenter.user.phone.check.IPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.dto.PhoneCodeMessage; +import com.newyetai.usercenter.user.phone.dto.PhoneCodeSmsDTO; + +import lombok.extern.slf4j.Slf4j; + +/** + * 抽象同步-手机号验证码提供者 + * @author sr on 2021-06-17 + */ +@Slf4j +public abstract class AbstractPhoneCodeProvider implements IPhoneCodeProvider { + + private static final String SMS_TEMPLATE_PROPERTIES = "sms.phoneSms"; + + private List phoneCodeCheckers = Lists.newArrayList(); + + @Autowired + private DomainSettingService domainSettingService; + + protected void addPhoneCodeChecker(IPhoneCodeChecker phoneCodeChecker) { + phoneCodeCheckers.add(phoneCodeChecker); + } + + /** + * 按顺序调用校验器,校验是否可发送短信 + * @param phoneCodeSmsDTO + * @author sr on 2021-06-17 + */ + protected void preSendCheck(PhoneCodeSmsDTO phoneCodeSmsDTO) { + Assert.isTrue(ValidateUtils.isPhone(phoneCodeSmsDTO.getPhone()), "手机号格式有误"); + preSendBizCheck(phoneCodeSmsDTO); + for (int i = 0; i < phoneCodeCheckers.size(); i++) { + IPhoneCodeChecker checker = phoneCodeCheckers.get(i); + try { + // 不支持校验,则跳过 + if (!checker.supports(phoneCodeSmsDTO.getClass())) { + continue; + } + checker.check(phoneCodeSmsDTO); + } catch (BusinessException e) { + // 回退校验 + for (int j = 0; j <= i; j++) { + IPhoneCodeChecker revertChecker = phoneCodeCheckers.get(j); + if (!revertChecker.supports(phoneCodeSmsDTO.getClass())) { + continue; + } + try { + revertChecker.revertCheck(phoneCodeSmsDTO); + } catch (Exception re) { + log.error("回退校验失败:{},{}", revertChecker.getType(), re); + } + } + throw e; + } + } + } + + /** + * 生成短信验证码,并放入redis缓存 + * @param phone + * @return + * @author sr on 2021-06-17 + */ + protected String generatePhoneCode(String phone) { + // 生成缓存验证码,5分钟有效 + String code = RandomUtils.nextSixVerificationCode(); + PhoneCodeRepository.setPhoneSmsCode(getType(), phone, code); + return code; + } + + @Override + public void send(PhoneCodeSmsDTO phoneCodeSmsDTO) { + preSendCheck(phoneCodeSmsDTO); + String phone = phoneCodeSmsDTO.getPhone(); + String code = generatePhoneCode(phone); + String errMsg = this.sendSms(PhoneCodeMessage.builder().phone(phone).code(code) + .domainOrIp(HostContextHolder.getHost()).build()); + Assert.isNull(errMsg, errMsg); + } + + /** + * 真实发送sms短信 + * @param phone + * @param code + * @return + * @author sr on 2021-06-17 + */ + protected String sendSms(PhoneCodeMessage phoneCodeMessage) { + String phone = phoneCodeMessage.getPhone(); + // 获取发送验证码配置 + String signName = null; + String domainOrIp = phoneCodeMessage.getDomainOrIp(); + if (StringUtils.isNotBlank(domainOrIp)) { + String settingData = domainSettingService.findSettingData(DomainSettingReqDTO.builder() + .domainOrIp(domainOrIp).type(DomainSettingTypeEnum.SMS.getType()).build()); + if (settingData != null) { + Map settingDataMap = JsonUtils.toMap(settingData); + signName = MapUtils.getString(settingDataMap, "signName"); + } + } + AlitaResult result = SmsUtils.getService() + .send(VerificationCodeSendDTO.builder() + .templateCode(EnvironmentUtils.getProperty(SMS_TEMPLATE_PROPERTIES)) + .signName(signName) + .phone(phone) + .code(phoneCodeMessage.getCode()) + .build()); + if (!result.getSuccess() || !result.getData()) { + log.error("phoneCode:{},phone:{},发送短信失败:{}", getType(), phone, result.getMsg()); + return result.getMsg(); + } + return null; + } +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/provider/GetOrgApplyProvider.java b/src/main/java/com/newyetai/usercenter/user/phone/provider/GetOrgApplyProvider.java new file mode 100644 index 0000000..33b41c4 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/provider/GetOrgApplyProvider.java @@ -0,0 +1,31 @@ +package com.newyetai.usercenter.user.phone.provider; + +import com.newyetai.common.util.SpringContextHolder; +import com.newyetai.usercenter.user.phone.check.CountRedisPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.check.LastRedisPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.constant.PhoneCodeProviderEnum; + +import org.springframework.context.annotation.DependsOn; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; + +/** + * 机构入驻 + */ +@Component +@DependsOn("springContextHolder") +public class GetOrgApplyProvider extends AbstractPhoneCodeProvider{ + + @PostConstruct + public void init() { + super.addPhoneCodeChecker(SpringContextHolder.getBean(LastRedisPhoneCodeChecker.class)); + super.addPhoneCodeChecker(SpringContextHolder.getBean(CountRedisPhoneCodeChecker.class)); + } + + @Override + public String getType() { + return PhoneCodeProviderEnum.GET_ORG_APPLY.getType(); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/provider/IPhoneCodeProvider.java b/src/main/java/com/newyetai/usercenter/user/phone/provider/IPhoneCodeProvider.java new file mode 100644 index 0000000..3a59c9c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/provider/IPhoneCodeProvider.java @@ -0,0 +1,47 @@ +package com.newyetai.usercenter.user.phone.provider; + +import com.newyetai.usercenter.user.phone.dto.PhoneCodeSmsDTO; + +/** + * 手机号验证码提供者 + * @author sr on 2021-06-16 + */ +public interface IPhoneCodeProvider { + + /** + * 类型 + * @return + * @author sr on 2021-06-16 + */ + String getType(); + + /** + * 发送前置业务校验 + * @param phoneCodeSmsDTO + * @author sr on 2021-09-02 + */ + default void preSendBizCheck(PhoneCodeSmsDTO phoneCodeSmsDTO){ + // 需要特殊校验,请重写该方法 + } + + /** + * 发送短信验证码 + * @param phoneCodeSmsDTO + * @author sr on 2021-06-16 + */ + void send(PhoneCodeSmsDTO phoneCodeSmsDTO); + + /** + * 验证码是否匹配 + * @param phone + * @param code + * @return + * @author sr on 2021-06-28 + */ + default boolean match(String phone, String code) { + String smsCode = + PhoneCodeRepository.getPhoneSmsCode(getType(), phone); + return code.equals(smsCode); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/provider/OrgApplyProvider.java b/src/main/java/com/newyetai/usercenter/user/phone/provider/OrgApplyProvider.java new file mode 100644 index 0000000..34731c5 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/provider/OrgApplyProvider.java @@ -0,0 +1,33 @@ +package com.newyetai.usercenter.user.phone.provider; + +import com.newyetai.common.util.SpringContextHolder; +import com.newyetai.usercenter.user.phone.check.CaptchaPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.check.CountRedisPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.check.LastRedisPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.check.ResetPwdChecker; +import com.newyetai.usercenter.user.phone.constant.PhoneCodeProviderEnum; + +import org.springframework.context.annotation.DependsOn; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; + +/** + * 机构入驻 + */ +@Component +@DependsOn("springContextHolder") +public class OrgApplyProvider extends AbstractPhoneCodeProvider{ + + @PostConstruct + public void init() { + super.addPhoneCodeChecker(SpringContextHolder.getBean(LastRedisPhoneCodeChecker.class)); + super.addPhoneCodeChecker(SpringContextHolder.getBean(CountRedisPhoneCodeChecker.class)); + } + + @Override + public String getType() { + return PhoneCodeProviderEnum.ORG_APPLY.getType(); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/provider/OrgChangePhoneProvider.java b/src/main/java/com/newyetai/usercenter/user/phone/provider/OrgChangePhoneProvider.java new file mode 100644 index 0000000..efe5a7d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/provider/OrgChangePhoneProvider.java @@ -0,0 +1,36 @@ +package com.newyetai.usercenter.user.phone.provider; + +import javax.annotation.PostConstruct; + +import org.springframework.context.annotation.DependsOn; +import org.springframework.stereotype.Component; + +import com.newyetai.common.util.SpringContextHolder; +import com.newyetai.usercenter.user.phone.check.CaptchaPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.check.ChangePhoneChecker; +import com.newyetai.usercenter.user.phone.check.CountRedisPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.check.LastRedisPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.constant.PhoneCodeProviderEnum; + +/** + * 机构用户换绑手机号 + * @author sr on 2021-06-28 + */ +@Component +@DependsOn("springContextHolder") +public class OrgChangePhoneProvider extends AbstractPhoneCodeProvider{ + + @PostConstruct + public void init() { + super.addPhoneCodeChecker(SpringContextHolder.getBean(CaptchaPhoneCodeChecker.class)); + super.addPhoneCodeChecker(SpringContextHolder.getBean(ChangePhoneChecker.class)); + super.addPhoneCodeChecker(SpringContextHolder.getBean(LastRedisPhoneCodeChecker.class)); + super.addPhoneCodeChecker(SpringContextHolder.getBean(CountRedisPhoneCodeChecker.class)); + } + + @Override + public String getType() { + return PhoneCodeProviderEnum.ORG_CHANGE_PHONE.getType(); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/provider/OrgLoginProvider.java b/src/main/java/com/newyetai/usercenter/user/phone/provider/OrgLoginProvider.java new file mode 100644 index 0000000..0bb2ecb --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/provider/OrgLoginProvider.java @@ -0,0 +1,49 @@ +package com.newyetai.usercenter.user.phone.provider; + +import javax.annotation.PostConstruct; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.DependsOn; +import org.springframework.stereotype.Component; + +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.SpringContextHolder; +import com.newyetai.usercenter.user.dao.OrgUserMapper; +import com.newyetai.usercenter.user.phone.check.CaptchaPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.check.CountRedisPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.check.LastRedisPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.constant.PhoneCodeProviderEnum; +import com.newyetai.usercenter.user.phone.dto.PhoneCodeSmsDTO; + +/** + * 机构用户手机号登录验证码提供者 + * @author sr on 2021-06-17 + */ +@Component +@DependsOn("springContextHolder") +public class OrgLoginProvider extends AbstractPhoneCodeProvider{ + + @Autowired + private OrgUserMapper orgUserMapper; + + @PostConstruct + public void init() { + super.addPhoneCodeChecker(SpringContextHolder.getBean(CaptchaPhoneCodeChecker.class)); + super.addPhoneCodeChecker(SpringContextHolder.getBean(LastRedisPhoneCodeChecker.class)); + super.addPhoneCodeChecker(SpringContextHolder.getBean(CountRedisPhoneCodeChecker.class)); + } + + @Override + public String getType() { + return PhoneCodeProviderEnum.ORG_LOGIN.getType(); + } + + @Override + public void preSendBizCheck(PhoneCodeSmsDTO phoneCodeSmsDTO) { + // 验证是否已经绑定企业 + Assert.isTrue(orgUserMapper.existOrgUser(phoneCodeSmsDTO.getPhone()), "未找到手机号对应的企业信息"); + } + + + +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/provider/OrgResetPwdProvider.java b/src/main/java/com/newyetai/usercenter/user/phone/provider/OrgResetPwdProvider.java new file mode 100644 index 0000000..ae321ff --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/provider/OrgResetPwdProvider.java @@ -0,0 +1,36 @@ +package com.newyetai.usercenter.user.phone.provider; + +import javax.annotation.PostConstruct; + +import org.springframework.context.annotation.DependsOn; +import org.springframework.stereotype.Component; + +import com.newyetai.common.util.SpringContextHolder; +import com.newyetai.usercenter.user.phone.check.CaptchaPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.check.CountRedisPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.check.LastRedisPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.check.ResetPwdChecker; +import com.newyetai.usercenter.user.phone.constant.PhoneCodeProviderEnum; + +/** + * 重置密码 + * @author sr on 2021-07-22 + */ +@Component +@DependsOn("springContextHolder") +public class OrgResetPwdProvider extends AbstractPhoneCodeProvider{ + + @PostConstruct + public void init() { + super.addPhoneCodeChecker(SpringContextHolder.getBean(CaptchaPhoneCodeChecker.class)); + super.addPhoneCodeChecker(SpringContextHolder.getBean(ResetPwdChecker.class)); + super.addPhoneCodeChecker(SpringContextHolder.getBean(LastRedisPhoneCodeChecker.class)); + super.addPhoneCodeChecker(SpringContextHolder.getBean(CountRedisPhoneCodeChecker.class)); + } + + @Override + public String getType() { + return PhoneCodeProviderEnum.ORG_RESET_PWD.getType(); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/provider/OrgResetSecurityCodeProvider.java b/src/main/java/com/newyetai/usercenter/user/phone/provider/OrgResetSecurityCodeProvider.java new file mode 100644 index 0000000..7c2cad2 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/provider/OrgResetSecurityCodeProvider.java @@ -0,0 +1,36 @@ +package com.newyetai.usercenter.user.phone.provider; + +import javax.annotation.PostConstruct; + +import org.springframework.context.annotation.DependsOn; +import org.springframework.stereotype.Component; + +import com.newyetai.common.util.SpringContextHolder; +import com.newyetai.usercenter.user.phone.check.CaptchaPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.check.CountRedisPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.check.HasLoginChecker; +import com.newyetai.usercenter.user.phone.check.LastRedisPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.constant.PhoneCodeProviderEnum; + +/** + * 机构重置安全码 + * @author sr on 2021-09-03 + */ +@Component +@DependsOn("springContextHolder") +public class OrgResetSecurityCodeProvider extends AbstractPhoneCodeProvider{ + + @PostConstruct + public void init() { + super.addPhoneCodeChecker(SpringContextHolder.getBean(CaptchaPhoneCodeChecker.class)); + super.addPhoneCodeChecker(SpringContextHolder.getBean(HasLoginChecker.class)); + super.addPhoneCodeChecker(SpringContextHolder.getBean(LastRedisPhoneCodeChecker.class)); + super.addPhoneCodeChecker(SpringContextHolder.getBean(CountRedisPhoneCodeChecker.class)); + } + + @Override + public String getType() { + return PhoneCodeProviderEnum.ORG_RESET_SECURITY_CODE.getType(); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/provider/PersonBindPhoneProvider.java b/src/main/java/com/newyetai/usercenter/user/phone/provider/PersonBindPhoneProvider.java new file mode 100644 index 0000000..2692770 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/provider/PersonBindPhoneProvider.java @@ -0,0 +1,44 @@ +package com.newyetai.usercenter.user.phone.provider; + +import javax.annotation.PostConstruct; + +import org.springframework.context.annotation.DependsOn; +import org.springframework.stereotype.Component; + +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.SpringContextHolder; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.usercenter.user.constant.UserTypeEnum; +import com.newyetai.usercenter.user.phone.check.CaptchaPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.check.CountRedisPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.check.LastRedisPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.constant.PhoneCodeProviderEnum; +import com.newyetai.usercenter.user.phone.dto.PhoneCodeSmsDTO; + +/** + * 个人绑定手机号 + * @author sr on 2021-06-28 + */ +@Component +@DependsOn("springContextHolder") +public class PersonBindPhoneProvider extends AbstractPhoneCodeProvider{ + + @PostConstruct + public void init() { + super.addPhoneCodeChecker(SpringContextHolder.getBean(CaptchaPhoneCodeChecker.class)); + super.addPhoneCodeChecker(SpringContextHolder.getBean(LastRedisPhoneCodeChecker.class)); + super.addPhoneCodeChecker(SpringContextHolder.getBean(CountRedisPhoneCodeChecker.class)); + } + + @Override + public String getType() { + return PhoneCodeProviderEnum.PERSON_BIND_PHONE.getType(); + } + + @Override + public void preSendBizCheck(PhoneCodeSmsDTO phoneCodeSmsDTO) { + Assert.isTrue(UserTypeEnum.PERSON.getType().equals(UserContextHolder.getUserType()), + "只有个人用户可绑定手机号"); + Assert.isTrue(!UserContextHolder.getExistLoginUser().getPhoneBinding(), "当前用户已绑定手机号"); + } +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/provider/PersonChangePhoneProvider.java b/src/main/java/com/newyetai/usercenter/user/phone/provider/PersonChangePhoneProvider.java new file mode 100644 index 0000000..ab3bdf3 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/provider/PersonChangePhoneProvider.java @@ -0,0 +1,36 @@ +package com.newyetai.usercenter.user.phone.provider; + +import javax.annotation.PostConstruct; + +import org.springframework.context.annotation.DependsOn; +import org.springframework.stereotype.Component; + +import com.newyetai.common.util.SpringContextHolder; +import com.newyetai.usercenter.user.phone.check.CaptchaPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.check.ChangePhoneChecker; +import com.newyetai.usercenter.user.phone.check.CountRedisPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.check.LastRedisPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.constant.PhoneCodeProviderEnum; + +/** + * 个人换绑手机号 + * @author sr on 2021-06-28 + */ +@Component +@DependsOn("springContextHolder") +public class PersonChangePhoneProvider extends AbstractPhoneCodeProvider{ + + @PostConstruct + public void init() { + super.addPhoneCodeChecker(SpringContextHolder.getBean(CaptchaPhoneCodeChecker.class)); + super.addPhoneCodeChecker(SpringContextHolder.getBean(ChangePhoneChecker.class)); + super.addPhoneCodeChecker(SpringContextHolder.getBean(LastRedisPhoneCodeChecker.class)); + super.addPhoneCodeChecker(SpringContextHolder.getBean(CountRedisPhoneCodeChecker.class)); + } + + @Override + public String getType() { + return PhoneCodeProviderEnum.PERSON_CHANGE_PHONE.getType(); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/provider/PersonLoginProvider.java b/src/main/java/com/newyetai/usercenter/user/phone/provider/PersonLoginProvider.java new file mode 100644 index 0000000..3236509 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/provider/PersonLoginProvider.java @@ -0,0 +1,34 @@ +package com.newyetai.usercenter.user.phone.provider; + +import javax.annotation.PostConstruct; + +import org.springframework.context.annotation.DependsOn; +import org.springframework.stereotype.Component; + +import com.newyetai.common.util.SpringContextHolder; +import com.newyetai.usercenter.user.phone.check.CaptchaPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.check.CountRedisPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.check.LastRedisPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.constant.PhoneCodeProviderEnum; + +/** + * 个人用户手机号登录验证码提供者 + * @author sr on 2021-06-17 + */ +@Component +@DependsOn("springContextHolder") +public class PersonLoginProvider extends AbstractPhoneCodeProvider{ + + @PostConstruct + public void init() { + super.addPhoneCodeChecker(SpringContextHolder.getBean(CaptchaPhoneCodeChecker.class)); + super.addPhoneCodeChecker(SpringContextHolder.getBean(LastRedisPhoneCodeChecker.class)); + super.addPhoneCodeChecker(SpringContextHolder.getBean(CountRedisPhoneCodeChecker.class)); + } + + @Override + public String getType() { + return PhoneCodeProviderEnum.PERSON_LOGIN.getType(); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/provider/PersonResetPwdProvider.java b/src/main/java/com/newyetai/usercenter/user/phone/provider/PersonResetPwdProvider.java new file mode 100644 index 0000000..2f91862 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/provider/PersonResetPwdProvider.java @@ -0,0 +1,36 @@ +package com.newyetai.usercenter.user.phone.provider; + +import javax.annotation.PostConstruct; + +import org.springframework.context.annotation.DependsOn; +import org.springframework.stereotype.Component; + +import com.newyetai.common.util.SpringContextHolder; +import com.newyetai.usercenter.user.phone.check.CaptchaPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.check.CountRedisPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.check.LastRedisPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.check.ResetPwdChecker; +import com.newyetai.usercenter.user.phone.constant.PhoneCodeProviderEnum; + +/** + * 重置密码 + * @author sr on 2021-07-22 + */ +@Component +@DependsOn("springContextHolder") +public class PersonResetPwdProvider extends AbstractPhoneCodeProvider{ + + @PostConstruct + public void init() { + super.addPhoneCodeChecker(SpringContextHolder.getBean(CaptchaPhoneCodeChecker.class)); + super.addPhoneCodeChecker(SpringContextHolder.getBean(ResetPwdChecker.class)); + super.addPhoneCodeChecker(SpringContextHolder.getBean(LastRedisPhoneCodeChecker.class)); + super.addPhoneCodeChecker(SpringContextHolder.getBean(CountRedisPhoneCodeChecker.class)); + } + + @Override + public String getType() { + return PhoneCodeProviderEnum.PERSON_RESET_PWD.getType(); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/provider/PersonResetSecurityCodeProvider.java b/src/main/java/com/newyetai/usercenter/user/phone/provider/PersonResetSecurityCodeProvider.java new file mode 100644 index 0000000..4f3f758 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/provider/PersonResetSecurityCodeProvider.java @@ -0,0 +1,36 @@ +package com.newyetai.usercenter.user.phone.provider; + +import javax.annotation.PostConstruct; + +import org.springframework.context.annotation.DependsOn; +import org.springframework.stereotype.Component; + +import com.newyetai.common.util.SpringContextHolder; +import com.newyetai.usercenter.user.phone.check.CaptchaPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.check.CountRedisPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.check.HasLoginChecker; +import com.newyetai.usercenter.user.phone.check.LastRedisPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.constant.PhoneCodeProviderEnum; + +/** + * 个人重置安全码 + * @author sr on 2021-07-22 + */ +@Component +@DependsOn("springContextHolder") +public class PersonResetSecurityCodeProvider extends AbstractPhoneCodeProvider{ + + @PostConstruct + public void init() { + super.addPhoneCodeChecker(SpringContextHolder.getBean(CaptchaPhoneCodeChecker.class)); + super.addPhoneCodeChecker(SpringContextHolder.getBean(HasLoginChecker.class)); + super.addPhoneCodeChecker(SpringContextHolder.getBean(LastRedisPhoneCodeChecker.class)); + super.addPhoneCodeChecker(SpringContextHolder.getBean(CountRedisPhoneCodeChecker.class)); + } + + @Override + public String getType() { + return PhoneCodeProviderEnum.PERSON_RESET_SECURITY_CODE.getType(); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/provider/PhoneCodeRepository.java b/src/main/java/com/newyetai/usercenter/user/phone/provider/PhoneCodeRepository.java new file mode 100644 index 0000000..f5a58a4 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/provider/PhoneCodeRepository.java @@ -0,0 +1,60 @@ +package com.newyetai.usercenter.user.phone.provider; + +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.frame.redis.util.RedisUtils; + +/** + * 短信验证码存储器 + * @author sr on 2021-06-16 + */ +public class PhoneCodeRepository { + + /** 短信验证码前缀 **/ + public static final String PHONE_CODE_PREFIX = "phone:code"; + /** 验证码过期时间-秒 **/ + public static final long CODE_EXPIRE_TIME = 300; + + /** + * 存储验证码的key + * + * @param phone + * @return + * @author sr on 2020-08-05 + */ + public static String getPhoneSmsCodeKey(String providerType, String phone) { + return String.join(CommonConstants.COLON, PhoneCodeRepository.PHONE_CODE_PREFIX, providerType, phone); + } + + /** + * 设置验证码,过期时间5分钟 + * + * @param phone + * @param code + * @author sr on 2020-08-05 + */ + public static void setPhoneSmsCode(String providerType, String phone, String code) { + RedisUtils.add(getPhoneSmsCodeKey(providerType, phone), code, CODE_EXPIRE_TIME); + } + + /** + * 获取验证码 + * + * @param phone + * @return + * @author sr on 2020-08-05 + */ + public static String getPhoneSmsCode(String providerType, String phone) { + return (String) RedisUtils.get(getPhoneSmsCodeKey(providerType, phone)); + } + + /** + * 验证成功,移除验证码 + * + * @param phone + * @author sr on 2020-08-05 + */ + public static void removePhoneSmsCode(String providerType, String phone) { + RedisUtils.remove(getPhoneSmsCodeKey(providerType, phone)); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/provider/ResetPayPwdProvider.java b/src/main/java/com/newyetai/usercenter/user/phone/provider/ResetPayPwdProvider.java new file mode 100644 index 0000000..af7d4ec --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/provider/ResetPayPwdProvider.java @@ -0,0 +1,30 @@ +package com.newyetai.usercenter.user.phone.provider; + +import javax.annotation.PostConstruct; + +import org.springframework.context.annotation.DependsOn; +import org.springframework.stereotype.Component; + +import com.newyetai.common.util.SpringContextHolder; +import com.newyetai.usercenter.user.phone.check.CountRedisPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.check.HasLoginChecker; +import com.newyetai.usercenter.user.phone.check.LastRedisPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.constant.PhoneCodeProviderEnum; + +@Component +@DependsOn("springContextHolder") +public class ResetPayPwdProvider extends AbstractPhoneCodeProvider{ + + @PostConstruct + public void init() { + super.addPhoneCodeChecker(SpringContextHolder.getBean(HasLoginChecker.class)); + super.addPhoneCodeChecker(SpringContextHolder.getBean(LastRedisPhoneCodeChecker.class)); + super.addPhoneCodeChecker(SpringContextHolder.getBean(CountRedisPhoneCodeChecker.class)); + } + + @Override + public String getType() { + return PhoneCodeProviderEnum.RESET_PAY_PWD.getType(); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/provider/UserCancelProvider.java b/src/main/java/com/newyetai/usercenter/user/phone/provider/UserCancelProvider.java new file mode 100644 index 0000000..72a8100 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/provider/UserCancelProvider.java @@ -0,0 +1,32 @@ +package com.newyetai.usercenter.user.phone.provider; + +import com.newyetai.common.util.SpringContextHolder; +import com.newyetai.usercenter.user.phone.check.CountRedisPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.check.LastRedisPhoneCodeChecker; +import com.newyetai.usercenter.user.phone.constant.PhoneCodeProviderEnum; + +import org.springframework.context.annotation.DependsOn; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; + +/** + * @description: 个人用户注销 + * @author: guixinman + * @create: 2024-06-13 14:28 + **/ +@Component +@DependsOn("springContextHolder") +public class UserCancelProvider extends AbstractPhoneCodeProvider{ + + @PostConstruct + public void init() { + super.addPhoneCodeChecker(SpringContextHolder.getBean(LastRedisPhoneCodeChecker.class)); + super.addPhoneCodeChecker(SpringContextHolder.getBean(CountRedisPhoneCodeChecker.class)); + } + + @Override + public String getType() { + return PhoneCodeProviderEnum.USER_CANCEL.getType(); + } +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/provider/simple/AbstractSimpleSms.java b/src/main/java/com/newyetai/usercenter/user/phone/provider/simple/AbstractSimpleSms.java new file mode 100644 index 0000000..6dfddb0 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/provider/simple/AbstractSimpleSms.java @@ -0,0 +1,47 @@ +package com.newyetai.usercenter.user.phone.provider.simple; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import com.newyetai.common.AlitaResult; +import com.newyetai.common.util.EnvironmentUtils; +import com.newyetai.common.validation.util.ValidateUtils; +import com.newyetai.sdk.sms.util.SmsUtils; +import com.newyetai.usercenter.user.phone.dto.SmsSimpleSendDTO; +import com.newyetai.usercenter.user.phone.dto.SmsSimpleSendDetailDTO; +import lombok.extern.slf4j.Slf4j; + +import java.util.List; + +@Slf4j +public abstract class AbstractSimpleSms implements ISimpleSms { + /** + * 做发送短信 + * + * @param sendDTO 发送请求对象 + * @return int + */ + protected int doSendSms(SmsSimpleSendDTO sendDTO) { + List detailDTOS = sendDTO.getDetailDTOS(); + if (CollUtil.isEmpty(detailDTOS)) { + return 0; + } + String sms = String.join(".", "sms", sendDTO.getTemplateCode()); + String templateCode = EnvironmentUtils.getProperty(sms); + if (StrUtil.isEmpty(templateCode)) { + log.info("发送短信失败,模板配置[{}]不存在", sms); + return 0; + } + int resultNum = 0; + for (SmsSimpleSendDetailDTO detailDTO : detailDTOS) { + if (!ValidateUtils.isPhone(detailDTO.getPhone())) { + continue; + } + AlitaResult result = SmsUtils.getService() + .sendSimple(templateCode, detailDTO.getPhone(), detailDTO.getParameters()); + if (Boolean.TRUE.equals(result.getSuccess()) && Boolean.TRUE.equals(result.getData())) { + resultNum++; + } + } + return resultNum; + } +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/provider/simple/ISimpleSms.java b/src/main/java/com/newyetai/usercenter/user/phone/provider/simple/ISimpleSms.java new file mode 100644 index 0000000..e42045d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/provider/simple/ISimpleSms.java @@ -0,0 +1,29 @@ +package com.newyetai.usercenter.user.phone.provider.simple; + +import com.newyetai.usercenter.user.phone.dto.SmsSimpleSendDTO; + +/** + * isimple短信提供者 + * + * @author cheny + * @date 2022/11/07 + */ +public interface ISimpleSms { + + + /** + * 发送短信 + * + * @param sendDTO 发送dto + * @return int + */ + int send(SmsSimpleSendDTO sendDTO); + + + /** + * 发送异步 + * + * @param sendDTO 发送dto + */ + void sendAsync(SmsSimpleSendDTO sendDTO); +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/provider/simple/StandardSimpleSms.java b/src/main/java/com/newyetai/usercenter/user/phone/provider/simple/StandardSimpleSms.java new file mode 100644 index 0000000..6bf03ea --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/provider/simple/StandardSimpleSms.java @@ -0,0 +1,61 @@ +package com.newyetai.usercenter.user.phone.provider.simple; + +import com.newyetai.common.util.JsonUtils; +import com.newyetai.common.util.RandomUtils; +import com.newyetai.frame.redis.util.RedisUtils; +import com.newyetai.mq.consumer.handler.ITopicMqHandler; +import com.newyetai.mq.dto.TopicMqMessage; +import com.newyetai.mq.util.MqSendUtils; +import com.newyetai.usercenter.user.phone.dto.SmsSimpleSendDTO; +import com.newyetai.usercenter.userprod.constant.UcMqSelfConstants; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +@Component +@Slf4j +public class StandardSimpleSms extends AbstractSimpleSms implements ITopicMqHandler { + @Override + public int send(SmsSimpleSendDTO sendDTO) { + return doSendSms(sendDTO); + } + + @Override + public void sendAsync(SmsSimpleSendDTO sendDTO) { + String messageId = RandomUtils.generateUUID(); + RedisUtils.add(messageId, 1, 24 * 60 * 60L); + MqSendUtils.send(TopicMqMessage.builder().messageId(messageId).routingKey(getRoutingKey()) + .data(sendDTO) + .build()); + } + + @Override + public String getRoutingKey() { + return UcMqSelfConstants.ROUTING_KEY_SIMPLE_SMS_PREFIX; + } + + @Override + public void onMessage(TopicMqMessage message) { + + String messageId = message.getMessageId(); + String value = RedisUtils.get(messageId) + ""; + int i; + try { + i = Integer.parseInt(value); + } catch (NumberFormatException e) { + i = 0; + } + + if (i != 1) { + log.info("短信消息消费异常,消息不存在或者已被消费,message : [{}]", JsonUtils.toJsonString(message)); + return; + } + + try { + send(message.getData()); + } catch (Exception e) { + log.info("短信消息消费异常,message : [{}]", JsonUtils.toJsonString(message), e); + } finally { + RedisUtils.expire(messageId, 0L); + } + } +} diff --git a/src/main/java/com/newyetai/usercenter/user/phone/util/PhoneCodeUtils.java b/src/main/java/com/newyetai/usercenter/user/phone/util/PhoneCodeUtils.java new file mode 100644 index 0000000..740cd87 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/phone/util/PhoneCodeUtils.java @@ -0,0 +1,109 @@ +package com.newyetai.usercenter.user.phone.util; + +import java.util.List; +import java.util.Map; + +import org.springframework.stereotype.Component; + +import com.google.common.collect.Maps; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.usercenter.user.constant.UserTypeEnum; +import com.newyetai.usercenter.user.dto.IUserPhoneCodeSms; +import com.newyetai.usercenter.user.phone.constant.PhoneCodeProviderEnum; +import com.newyetai.usercenter.user.phone.dto.PhoneCodeDTO; +import com.newyetai.usercenter.user.phone.dto.PhoneCodeSmsDTO; +import com.newyetai.usercenter.user.phone.provider.IPhoneCodeProvider; +import com.newyetai.usercenter.user.util.UserUtils; + +/** + * @author sr on 2021-06-28 + */ +@Component +public class PhoneCodeUtils { + + private static Map providerMap = Maps.newHashMap(); + + private PhoneCodeUtils(List providers) { + providers.forEach(provider -> providerMap.put(provider.getType(), provider)); + } + + public static IPhoneCodeProvider getProvider(String providerType) { + Assert.notBlank(providerType, "验证码提供者不能为空"); + IPhoneCodeProvider provider = providerMap.get(providerType); + Assert.notNull(provider, providerType + "未找到对应类型短信验证码提供者"); + return provider; + } + + /** + * 发送验证码 + * @param phoneCodeSmsDTO + * @author sr on 2021-09-02 + */ + public static void send(PhoneCodeSmsDTO phoneCodeSmsDTO) { + if(phoneCodeSmsDTO instanceof IUserPhoneCodeSms) { + decorateUserPhoneCode((IUserPhoneCodeSms) phoneCodeSmsDTO); + } + getProvider(phoneCodeSmsDTO.getProviderType()).send(phoneCodeSmsDTO); + } + + /** + * 验证 + * @param providerType + * @param phone + * @param code + * @return + * @author sr on 2021-06-28 + */ + public static boolean match(String providerType, String phone, String code) { + return getProvider(providerType).match(phone, code); + } + + /** + * 验证(失败抛‘验证码错误’异常) + * @param providerType + * @param phone + * @param code + * @author sr on 2021-08-10 + */ + public static void matchBiz(String providerType, String phone, String code) { + boolean match = getProvider(providerType).match(phone, code); + Assert.isTrue(match, "验证码错误"); + } + + /** + * 验证 + * @param phoneCodeDTO + * @return + * @author sr on 2021-08-10 + */ + public static boolean match(PhoneCodeDTO phoneCodeDTO) { + if(phoneCodeDTO instanceof IUserPhoneCodeSms) { + decorateUserPhoneCode((IUserPhoneCodeSms) phoneCodeDTO); + } + return match(phoneCodeDTO.getProviderType(), phoneCodeDTO.getPhone(), phoneCodeDTO.getCode()); + } + + /** + * 验证(失败抛‘验证码错误’异常) + * @param providerType + * @param phoneCodeDTO + * @return + * @author sr on 2021-08-10 + */ + public static void matchBiz(PhoneCodeDTO phoneCodeDTO) { + boolean match = match(phoneCodeDTO); + Assert.isTrue(match, "验证码错误"); + } + + /** + * 处理用户验证码对象,提供通用验证码对象所需属性 + * @param iUserPhoneCode + * @author sr on 2021-09-02 + */ + public static void decorateUserPhoneCode(IUserPhoneCodeSms iUserPhoneCode) { + UserTypeEnum userTypeEnum = UserUtils.getUserType(iUserPhoneCode); + iUserPhoneCode.setProviderType( + PhoneCodeProviderEnum.getType(userTypeEnum, iUserPhoneCode.getOperateType())); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/service/OrgUserService.java b/src/main/java/com/newyetai/usercenter/user/service/OrgUserService.java new file mode 100644 index 0000000..4f965a4 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/service/OrgUserService.java @@ -0,0 +1,53 @@ +package com.newyetai.usercenter.user.service; + +import com.newyetai.usercenter.user.dto.OrgUserInfoDTO; +import com.newyetai.usercenter.user.dto.OrgUserInfoQueryDTO; +import com.newyetai.usercenter.user.dto.OrgUserOperateDTO; +import com.newyetai.usercenter.user.login.dto.OrgDetailDTO; + +import org.springframework.validation.annotation.Validated; + +import javax.validation.Valid; +import javax.validation.groups.Default; +import java.util.List; + +/** + * 机构用户表 + * + * @author sr on 2021-05-24 + */ +@Validated(Default.class) +public interface OrgUserService { + + /** + * 新增 + * + * @param orgUserOperateDTO + * @return + * @author sr on 2021-05-24 + */ + Long create(OrgUserOperateDTO orgUserOperateDTO); + + /** + * 查询机构用户列表 + * + * @param queryDTO 查询dto + * @return {@link List}<{@link OrgUserInfoDTO}> + */ + List list(@Valid OrgUserInfoQueryDTO queryDTO); + + + /** + * 是否存在 + */ + boolean existOrgUser(Long orgId, Long userId); + + /** + * 查询用户所属机构列表 + * @param userId + * @param orgId + * @return + * @author sr on 2022-08-29 + */ + List listLoginOrgByUser(Long userId, Long orgId); +} diff --git a/src/main/java/com/newyetai/usercenter/user/service/UserAuthService.java b/src/main/java/com/newyetai/usercenter/user/service/UserAuthService.java new file mode 100644 index 0000000..1d1f71e --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/service/UserAuthService.java @@ -0,0 +1,52 @@ +package com.newyetai.usercenter.user.service; + +import java.util.List; + +import com.newyetai.usercenter.user.dto.UserAuthQueryDTO; +import com.newyetai.usercenter.user.dto.UserAuthOperateDTO; +import com.newyetai.usercenter.user.dto.UserAuthDTO; + +/** + * 用户授权中间表 + * + * @author sr on 2021-05-24 + */ +public interface UserAuthService { + + /** + * 新增 + * + * @param userAuthOperateDTO + * @return + * @author sr on 2021-05-24 + */ + Long create(UserAuthOperateDTO userAuthOperateDTO); + + /** + * 修改 + * + * @param userAuthOperateDTO + * @author sr on 2021-05-24 + */ + void modify(UserAuthOperateDTO userAuthOperateDTO); + + /** + * 删除 + * + * @param id + * @author sr on 2021-05-24 + */ + void remove(Long id); + + /** + * 查询 + * + * @param userAuthQueryDTO + * @return + * @author sr on 2021-05-24 + */ + List list(UserAuthQueryDTO userAuthQueryDTO); + + void page(UserAuthQueryDTO userAuthQueryDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/user/service/UserBankAccountService.java b/src/main/java/com/newyetai/usercenter/user/service/UserBankAccountService.java new file mode 100644 index 0000000..ca9820d --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/service/UserBankAccountService.java @@ -0,0 +1,49 @@ +package com.newyetai.usercenter.user.service; + +import com.newyetai.usercenter.user.dto.*; +import org.springframework.validation.annotation.Validated; + +import javax.validation.Valid; +import javax.validation.groups.Default; +import java.util.List; +import java.util.Map; + +/** + * 用户银行卡 业务逻辑 + * + * @author Carlye + * @date 2021/06/25 + */ +@Validated(Default.class) +public interface UserBankAccountService { + + /** + * 添加银行账户 + * + * @param reqDTO 点播dto + * @return {@link UserBankAccountInfoDTO} + */ + UserBankAccountInfoDTO addBankAccount(@Valid UserBankAccountCreateReqDTO reqDTO); + + + /** + * 获取身份证列表对应的银行卡号 + * @param cardNos + * @return + */ + Map queryBankAccountMap(List cardNos); + + /** + * 获取身份证列表对应的银行卡号 + * @param userBankAccountQueryDTO + * @return + */ + List list(UserBankAccountQueryDTO userBankAccountQueryDTO); + + void page(UserBankAccountQueryDTO userBankAccountQueryDTO); + + void modify(UserBankAccountModifyDTO userBankAccountModifyDTO); + + UserBankAccountDTO get(Long id); + +} diff --git a/src/main/java/com/newyetai/usercenter/user/service/UserBankCardFourVerificationService.java b/src/main/java/com/newyetai/usercenter/user/service/UserBankCardFourVerificationService.java new file mode 100644 index 0000000..b906e5c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/service/UserBankCardFourVerificationService.java @@ -0,0 +1,44 @@ +package com.newyetai.usercenter.user.service; + +import com.newyetai.alitaforward.verification.dto.FourFactorVerificationDTO; +import com.newyetai.usercenter.user.dto.UserBankCardFourVerificationDTO; +import com.newyetai.usercenter.user.dto.UserBankCardFourVerificationOperateDTO; +import com.newyetai.usercenter.user.dto.UserBankCardFourVerificationQueryDTO; +import com.newyetai.usercenter.user.dto.UserBankCardThreeVerificationDTO; +import com.newyetai.usercenter.user.dto.UserBankCardThreeVerificationOperateDTO; +import com.newyetai.usercenter.user.dto.UserBankCardThreeVerificationQueryDTO; +import java.util.List; + +/** + * @author czy + * @date 2021-06-28 + */ +public interface UserBankCardFourVerificationService { + + /** + * 用户四要素认证 + * @param userBankCardFourVerificationDTO + * @return + */ + UserBankCardFourVerificationDTO userFourFactorVerification( + UserBankCardFourVerificationDTO userBankCardFourVerificationDTO); + + Long create(UserBankCardFourVerificationOperateDTO operateDTO); + + /** + * 查询 + * + * @param userBankCardFourVerificationQueryDTO + * @return + * @author sr on 2021-08-04 + */ + List list( + UserBankCardFourVerificationQueryDTO userBankCardFourVerificationQueryDTO); + + /** + * 查询用户最新的四要素认证 + * @return + * @author sr on 2021-08-04 + */ + UserBankCardFourVerificationDTO findLast(); +} diff --git a/src/main/java/com/newyetai/usercenter/user/service/UserBankCardThreeVerificationService.java b/src/main/java/com/newyetai/usercenter/user/service/UserBankCardThreeVerificationService.java new file mode 100644 index 0000000..44d5b15 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/service/UserBankCardThreeVerificationService.java @@ -0,0 +1,44 @@ +package com.newyetai.usercenter.user.service; + +import java.util.List; + +import com.newyetai.usercenter.user.dto.UserBankCardThreeVerificationCreateDTO; +import com.newyetai.usercenter.user.dto.UserBankCardThreeVerificationDTO; +import com.newyetai.usercenter.user.dto.UserBankCardThreeVerificationOperateDTO; +import com.newyetai.usercenter.user.dto.UserBankCardThreeVerificationQueryDTO; + +/** + * @author czy + * @date 2021-06-28 + */ +public interface UserBankCardThreeVerificationService { + + /** + * 用户三要素认证 + * @param userBankCardThreeVerificationCreateDTO + * @return + */ + UserBankCardThreeVerificationDTO userThreeFactorVerification( + UserBankCardThreeVerificationCreateDTO userBankCardThreeVerificationCreateDTO); + + + Long create(UserBankCardThreeVerificationOperateDTO operateDTO); + + /** + * 查询 + * + * @param userBankCardThreeVerificationQueryDTO + * @return + * @author sr on 2021-08-04 + */ + List list( + UserBankCardThreeVerificationQueryDTO userBankCardThreeVerificationQueryDTO); + + /** + * 查询用户最新的三要素认证 + * @return + * @author sr on 2021-08-04 + */ + UserBankCardThreeVerificationDTO findLast(); + +} diff --git a/src/main/java/com/newyetai/usercenter/user/service/UserCancelService.java b/src/main/java/com/newyetai/usercenter/user/service/UserCancelService.java new file mode 100644 index 0000000..d7e7cb6 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/service/UserCancelService.java @@ -0,0 +1,44 @@ +package com.newyetai.usercenter.user.service; + +import com.newyetai.usercenter.user.dto.UserCancelApplyReqDTO; +import com.newyetai.usercenter.user.dto.UserCancelDTO; +import com.newyetai.usercenter.user.dto.UserCancelPageQueryDTO; + +import java.util.List; + +/** + * 用户申请注销 + * + * @author cheny + * @date 2023/03/07 + */ +public interface UserCancelService { + + /** + * 申请注销 + * + * @return {@link UserCancelDTO} + */ + UserCancelDTO apply(UserCancelApplyReqDTO applyDTO); + + /** + * 找到 + * + * @return {@link UserCancelDTO} + */ + UserCancelDTO find(UserCancelPageQueryDTO queryDTO); + + /** + * 同意注销 + * + * @return {@link UserCancelDTO} + */ + UserCancelDTO agreeCancel(Long userId); + + List page(UserCancelPageQueryDTO queryDTO); + + /** + * 给未处理的注销申请发钉钉消息提醒到运营群 + */ + void toNotify(); +} diff --git a/src/main/java/com/newyetai/usercenter/user/service/UserConfigService.java b/src/main/java/com/newyetai/usercenter/user/service/UserConfigService.java new file mode 100644 index 0000000..fc2a64f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/service/UserConfigService.java @@ -0,0 +1,59 @@ +package com.newyetai.usercenter.user.service; + +import java.util.List; + +import com.newyetai.usercenter.user.dto.UserConfigQueryDTO; +import com.newyetai.usercenter.user.dto.UserConfigOperateDTO; +import com.newyetai.usercenter.user.dto.UserConfigDTO; + +/** + * 用户配置 + * + * @author sr on 2021-08-12 + */ +public interface UserConfigService { + + /** + * 新增 + * + * @param userConfigOperateDTO + * @return + * @author sr on 2021-08-12 + */ + Long create(UserConfigOperateDTO userConfigOperateDTO); + + /** + * 修改 + * + * @param userConfigOperateDTO + * @author sr on 2021-08-12 + */ + void modify(UserConfigOperateDTO userConfigOperateDTO); + + /** + * 删除 + * + * @param id + * @author sr on 2021-08-12 + */ + void remove(Long id); + + /** + * 查询 + * + * @param userConfigQueryDTO + * @return + * @author sr on 2021-08-12 + */ + List list(UserConfigQueryDTO userConfigQueryDTO); + + /** + * 查询单个 + * + * @param userConfigQueryDTO + * @return + * @author sr on 2021-08-12 + */ + UserConfigDTO find(UserConfigQueryDTO userConfigQueryDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/user/service/UserExtensionService.java b/src/main/java/com/newyetai/usercenter/user/service/UserExtensionService.java new file mode 100644 index 0000000..0c64908 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/service/UserExtensionService.java @@ -0,0 +1,42 @@ +package com.newyetai.usercenter.user.service; + +import com.newyetai.usercenter.user.dto.UserExtensionDTO; +import com.newyetai.usercenter.user.dto.UserExtensionOperateDTO; + +/** + * @author czy + * @date 2021-06-15 + */ +public interface UserExtensionService { + + /** + * 编辑 + * + * @param userExtensionOperateDTO + * @return + * @author czy on 2021-06-15 + */ + Long edit(UserExtensionOperateDTO userExtensionOperateDTO); + + /** + * @description: 根据用户id编辑 + * @return: + * @author: guixinman + * @param: + */ + void createOrEditByUserId(UserExtensionOperateDTO userExtensionOperateDTO,Long userId); + + + /** + * 根据userId获取用户扩展信息 + * @param userId + * @return + */ + UserExtensionDTO getByUserId(Long userId); + + /** + * 删除用户扩展信息简历附件 + * + */ + void deleteUserFile(); +} diff --git a/src/main/java/com/newyetai/usercenter/user/service/UserIdentityPhotoService.java b/src/main/java/com/newyetai/usercenter/user/service/UserIdentityPhotoService.java new file mode 100644 index 0000000..02885a7 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/service/UserIdentityPhotoService.java @@ -0,0 +1,60 @@ +package com.newyetai.usercenter.user.service; + +import java.util.List; + +import com.newyetai.usercenter.user.dto.UserIdentityPhotoQueryDTO; +import com.newyetai.usercenter.user.dto.UserIdentityPhotoOperateDTO; +import com.newyetai.usercenter.user.dto.UserIdentityPhotoDTO; +import com.newyetai.usercenter.user.dto.UserIdentityPhotoInfoDTO; + +/** + * 用户证件正反面 + * + * @author sr on 2021-05-24 + */ +public interface UserIdentityPhotoService { + + /** + * 新增 + * + * @param userIdentityPhotoOperateDTO + * @return + * @author sr on 2021-05-24 + */ + Long create(UserIdentityPhotoOperateDTO userIdentityPhotoOperateDTO); + + /** + * 修改 + * + * @param userIdentityPhotoOperateDTO + * @author sr on 2021-05-24 + */ + void modify(UserIdentityPhotoOperateDTO userIdentityPhotoOperateDTO); + + /** + * 删除 + * + * @param id + * @author sr on 2021-05-24 + */ + void remove(Long id); + + /** + * 根据userId查 + * @param userId + * @return + */ + UserIdentityPhotoDTO getByUserId(Long userId); + + /** + * 查询 + * + * @param userIdentityPhotoQueryDTO + * @return + * @author sr on 2021-05-24 + */ + List list(UserIdentityPhotoQueryDTO userIdentityPhotoQueryDTO); + + UserIdentityPhotoInfoDTO findInfo(Long userId); + +} diff --git a/src/main/java/com/newyetai/usercenter/user/service/UserPhoneThreeVerificationService.java b/src/main/java/com/newyetai/usercenter/user/service/UserPhoneThreeVerificationService.java new file mode 100644 index 0000000..8ab5107 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/service/UserPhoneThreeVerificationService.java @@ -0,0 +1,43 @@ +package com.newyetai.usercenter.user.service; + +import com.newyetai.usercenter.user.dto.UserPhoneThreeVerificationDTO; +import com.newyetai.usercenter.user.dto.UserPhoneThreeVerificationOperateDTO; +import com.newyetai.usercenter.user.dto.UserPhoneThreeVerificationQueryDTO; + +import java.util.List; + +/** + * @author czy + * @date 2021-06-28 + */ +public interface UserPhoneThreeVerificationService { + + /** + * 用户三要素认证 + * @param userPhoneThreeVerificationDTO + * @return + */ + UserPhoneThreeVerificationDTO userThreeFactorVerification( + UserPhoneThreeVerificationDTO userPhoneThreeVerificationDTO); + + + Long create(UserPhoneThreeVerificationOperateDTO operateDTO); + + /** + * 查询 + * + * @param userPhoneThreeVerificationQueryDTO + * @return + * @author sr on 2021-08-04 + */ + List list( + UserPhoneThreeVerificationQueryDTO userPhoneThreeVerificationQueryDTO); + + /** + * 查询用户最新的三要素认证 + * @return + * @author sr on 2021-08-04 + */ + UserPhoneThreeVerificationDTO findLast(); + +} diff --git a/src/main/java/com/newyetai/usercenter/user/service/UserPostalInfoService.java b/src/main/java/com/newyetai/usercenter/user/service/UserPostalInfoService.java new file mode 100644 index 0000000..82e8a8e --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/service/UserPostalInfoService.java @@ -0,0 +1,68 @@ +package com.newyetai.usercenter.user.service; + +import java.util.List; + +import com.newyetai.usercenter.user.dto.UserPostalInfoQueryDTO; +import com.newyetai.usercenter.user.dto.UserPostalInfoOperateDTO; +import com.newyetai.usercenter.user.dto.UserPostalInfoDTO; + +/** + * 用户邮寄信息 + * + * @author fzp on 2022-01-19 + */ +public interface UserPostalInfoService { + + /** + * 新增 + * + * @param userPostalInfoOperateDTO + * @return + * @author fzp on 2022-01-19 + */ + Long create(UserPostalInfoOperateDTO userPostalInfoOperateDTO); + + /** + * 修改 + * + * @param userPostalInfoOperateDTO + * @author fzp on 2022-01-19 + */ + void modify(UserPostalInfoOperateDTO userPostalInfoOperateDTO); + + /** + * 删除 + * + * @param id + * @author fzp on 2022-01-19 + */ + void remove(Long id); + + /** + * 查询 + * + * @param userPostalInfoQueryDTO + * @return + * @author fzp on 2022-01-19 + */ + List list(UserPostalInfoQueryDTO userPostalInfoQueryDTO); + + /** + * 分页查询 + * + * @param userPostalInfoQueryDTO + * @return + * @author fzp on 2022-01-19 + */ + void page(UserPostalInfoQueryDTO userPostalInfoQueryDTO); + + /** + * 单个查询 + * + * @param userPostalInfoQueryDTO + * @return + * @author fzp on 2022-01-19 + */ + UserPostalInfoDTO find(UserPostalInfoQueryDTO userPostalInfoQueryDTO); + +} diff --git a/src/main/java/com/newyetai/usercenter/user/service/UserRealNameTwoVerificationService.java b/src/main/java/com/newyetai/usercenter/user/service/UserRealNameTwoVerificationService.java new file mode 100644 index 0000000..cdfbddf --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/service/UserRealNameTwoVerificationService.java @@ -0,0 +1,27 @@ +package com.newyetai.usercenter.user.service; + +import com.newyetai.usercenter.user.dto.SuperRealNameTwoAuthDTO; +import com.newyetai.usercenter.user.dto.UserRealNameTwoAuthCreateDTO; + +/** + * @author fzp + * @date 2021年7月13日18:35:40 + */ +public interface UserRealNameTwoVerificationService { + + + /** + * 上级(入参直接)认证并创建实名用户(非个人用户自己) + * @param authDTO + * @return + * @author sr on 2022-10-18 + */ + Long superAuth(SuperRealNameTwoAuthDTO authDTO); + + /** + * 二要素认证(并激活用户),个人用户自己 + * @param createDTO + * @author sr on 2023-11-10 + */ + void userRealNameTwoAuth(UserRealNameTwoAuthCreateDTO createDTO); +} diff --git a/src/main/java/com/newyetai/usercenter/user/service/UserRegisterService.java b/src/main/java/com/newyetai/usercenter/user/service/UserRegisterService.java new file mode 100644 index 0000000..b36fe93 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/service/UserRegisterService.java @@ -0,0 +1,91 @@ +package com.newyetai.usercenter.user.service; + +import java.util.List; + +import com.newyetai.usercenter.user.dto.UserRegisterQueryDTO; +import com.newyetai.usercenter.user.dto.UserRegisterOperateDTO; +import com.newyetai.usercenter.user.dto.UserRegisterCodeInfoDTO; +import com.newyetai.usercenter.user.dto.UserRegisterCreateDTO; +import com.newyetai.usercenter.user.dto.UserRegisterCodeDTO; +import com.newyetai.usercenter.user.dto.UserRegisterDTO; +import com.newyetai.usercenter.user.dto.UserRegisterInfoQueryDTO; + +/** + * 用户注册表 + * + * @author sr on 2021-11-16 + */ +public interface UserRegisterService { + + /** + * 查询 + * + * @param userRegisterQueryDTO + * @return + * @author sr on 2021-11-16 + */ + List list(UserRegisterQueryDTO userRegisterQueryDTO); + + /** + * 分页查询 + * @param userRegisterQueryDTO + * @author sr on 2021-11-16 + */ + void page(UserRegisterQueryDTO userRegisterQueryDTO); + + /** + * 单个查询 + * @param userRegisterQueryDTO + * @return + * @author sr on 2021-11-16 + */ + UserRegisterDTO find(UserRegisterQueryDTO userRegisterQueryDTO); + + /** + * 获取注册码(自己) + * @param userRegisterCodeDTO + * @return + * @author sr on 2021-11-16 + */ + String getCode(UserRegisterCodeDTO userRegisterCodeDTO); + + /** + * 获取注册码(指定) + * @param upUserRegisterCodeDTO + * @return + * @author sr on 2021-11-16 + */ + String getCode(UserRegisterCodeInfoDTO upUserRegisterCodeDTO); + + /** + * 创建用户注册信息 + * @param userRegisterCreateDTO + * @return 是否新注册 + * @author sr on 2021-11-16 + */ + boolean create(UserRegisterCreateDTO userRegisterCreateDTO); + + /** + * 查询注册详情 + * @param userRegisterInfoQueryDTO + * @author sr on 2021-11-18 + */ + void page(UserRegisterInfoQueryDTO userRegisterInfoQueryDTO); + + /** + * 解析注册码 + * @param registerCode + * @return + * @author sr on 2022-01-12 + */ + UserRegisterCodeInfoDTO analyRegisterCode(String registerCode); + + /** + * 是否存在注册信息 + * @param userId + * @return + * @author sr on 2022-03-17 + */ + boolean existRegister(Long userId); + +} diff --git a/src/main/java/com/newyetai/usercenter/user/service/UserService.java b/src/main/java/com/newyetai/usercenter/user/service/UserService.java new file mode 100644 index 0000000..85f3bc0 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/service/UserService.java @@ -0,0 +1,329 @@ +package com.newyetai.usercenter.user.service; + +import com.newyetai.security.dto.UserInfoDTO; +import com.newyetai.usercenter.auth.dto.AuthDetailBindDTO; +import com.newyetai.usercenter.auth.dto.AuthDetailLoginDTO; +import com.newyetai.usercenter.dto.OrgUserEditDTO; +import com.newyetai.usercenter.dto.SuperResetPasswordDTO; +import com.newyetai.usercenter.user.dto.*; +import com.newyetai.usercenter.user.login.dto.UserDetailDTO; +import org.apache.ibatis.annotations.Param; +import org.springframework.validation.annotation.Validated; + +import javax.validation.Valid; +import javax.validation.groups.Default; +import java.util.List; +import java.util.Set; + +/** + * 用户 + * + * @author sr on 2021-05-24 + */ +@Validated(Default.class) +public interface UserService { + + /** + * 修改用户信息 + * + * @param userOperateDTO + * @return + * @author czy on 2021-06-15 + */ + void modify(UserOperateDTO userOperateDTO); + + /** + * 用户注销 + * + * @param reqDTO 点播dto + */ + void userCancel(@Valid UserCancelReqDTO reqDTO); + + /** + * 查询-分页 + * @param userQueryDTO + * @author sr on 2021-11-04 + */ + void page(UserQueryDTO userQueryDTO); + + /** + * 查询 + * + * @param userQueryDTO + * @return + * @author sr on 2021-05-24 + */ + List list(UserQueryDTO userQueryDTO); + + /** + * 查询单个 + * @param userQueryDTO + * @return + * @author sr on 2021-11-04 + */ + UserDTO find(UserQueryDTO userQueryDTO); + + /** + * 查询指定用户 + * + * @param userId + * @return + */ + UserDTO get(Long userId); + + /** + * 获取指定用户的扩展状态(实名认证、证件正反面照上传、手机绑定、微信绑定状态) + * + * @param userId + * @return + */ + UserExtendStatusDTO getUserExtendStatus(Long userId); + + /** + * 个人用户(证件)创建 + * + * @param personUserCardCreateDTO + * @return + * @author sr on 2021-06-21 + */ + UserDTO createPersonUser(PersonUserCardCreateDTO personUserCardCreateDTO); + + /** + * 批量-个人用户(证件)创建 + * + * @param personUserCardCreateDTOs + * @return + * @author sr on 2021-06-23 + */ + List batchCreatePersonUser( + List personUserCardCreateDTOs); + + /** + * 个人用户创建/修改 + * 查所有-修改/创建绑定态用户 + * @param personUserPhoneCreateDTO + * @return + * @author sr on 2022-08-02 + */ + UserDetailDTO modifyAndCreatePersonUser(PersonUserPhoneCreateDTO personUserPhoneCreateDTO); + + /** + * 个人用户创建 + * 查绑定态-创建绑定态用户 + * + * @param personUserPhoneCreateDTO + * @return + * @author sr on 2021-06-21 + */ + UserDetailDTO createPersonUser(PersonUserPhoneCreateDTO personUserPhoneCreateDTO); + + /** + * 初始账号密码-自己操作 + * + * @param initUserPasswordDTO + * @author sr on 2021-06-23 + */ + void initUserPassword(InitUserPasswordDTO initUserPasswordDTO); + + /** + * 修改账号 + * @param username + * @author sr on 2021-08-04 + */ + void modifyUsername(String username); + + /** + * 修改密码 + * @param modifyPasswordDTO + * @author sr on 2021-08-04 + */ + void modifyPassword(ModifyPasswordDTO modifyPasswordDTO); + + /** + * 创建企业用户 + * + * @param orgUserCreateDTO + * @return + * @author sr on 2021-06-23 + */ + Long createOrgUser(OrgUserCreateDTO orgUserCreateDTO); + + /** + * 修改企业用户 + * + * @param orgUserModifyDTO + * @return + * @author gxm on 2023-01-03 + */ + void modifyOrgUser(OrgUserModifyDTO orgUserModifyDTO); + + /** + * 获取认证信息对应登录用户 + * + * @param authDetailDTO + * @return + * @author sr on 2021-06-28 + */ + UserDetailDTO loadUser(AuthDetailLoginDTO authDetailDTO); + + + /** + * 个人实名 + * + * @param authenticateUserDTO + * 账号合并抛 ChangeTokenException + * @author sr on 2021-07-06 + */ + void authenticatePersonUser(AuthenticateUserDTO authenticateUserDTO); + + /** + * 激活个人用户(创建用户+实名并激活用户) + * + * @author sr on 2021-06-28 + */ + Long createAndAuthenticatePersonUser(AuthenticateUserDTO authenticateUserDTO); + + /** + * 个人用户自己绑定手机号 + * + * @author sr on 2021-06-28 + */ + void bindPersonPhone(BindPhoneDTO bindPhoneDTO); + + /** + * 直接更新个人用户手机号绑定状态-前置校验在调用方已做过 + * 手机号登录(已校验过验证码)/绑定手机号(已校验过验证码和其他限制校验) + * + * @param userId + * @param phone + * @author sr on 2021-07-02 + */ + void updatePersonPhoneBinding(Long userId, String phone); + + /** + * 分页查询平台用户信息 + * + * @param reqDTO 点播dto + * @return {@link List} + */ + List pagePlatformUser(PlatformUserInfoReqDTO reqDTO); + + /** + * 查询平台用户列表 + * + * @param queryDTO 查询dto + * @return {@link List}<{@link PlatformUserInfoDTO}> + */ + List listPlatformUser(PlatformUserListQueryDTO queryDTO); + + /** + * 检查安全代码 + * + * @param reqDTO + * @return {@link Boolean} + */ + Boolean checkSecurityCode(@Valid CheckSecurityCodeReqDTO reqDTO); + + /** + * 重置密码 + * @param resetPwdDTO + * @author sr on 2021-08-10 + */ + void resetPwd(ResetPwdDTO resetPwdDTO); + + /** + * 查询用户信息 + * + * @param userId + * @param orgId + * @return + * @author sr on 2020-06-11 + */ + UserInfoDTO findUserInfo(@Param("userId") Long userId, @Param("orgId") Long orgId); + + /** + * 绑定用户授权信息 + * @param authDetailBindDTO + * @author sr on 2021-08-23 + */ + void bindUserAuth(AuthDetailBindDTO authDetailBindDTO); + + /** + * 查询单个用户信息(未注销) + * @param userQueryDTO + * @return + * @author sr on 2021-09-02 + */ + UserDTO findUserDTO(UserQueryDTO userQueryDTO); + + /** + * 重置安全码 + * @param resetSecurityCodeDTO + * @author sr on 2021-09-02 + */ + void resetSecurityCode(ResetSecurityCodeDTO resetSecurityCodeDTO); + + /** + * 换绑手机 + * @param changePhoneDTO + * @author sr on 2021-09-10 + */ + void changePhone(ChangePhoneDTO changePhoneDTO); + + /** + * 验证账号是否存在 + * @param userId + * @param username + */ + void checkExistUsername(Long userId, String username); + + /** + * 代管-换绑手机 + * @param superChangePhoneDTO + * @author sr on 2021-09-24 + */ + void changePhone(SuperChangePhoneDTO superChangePhoneDTO); + + /** + * 管理员修改用户信息 + * @param orgUserEditDTO + * @return {@link Boolean} + */ + Boolean modifyOrgUserInfo(OrgUserEditDTO orgUserEditDTO); + + /** + * 超级管理员重置密码 + * + * @param resetPasswordDTO + * @return + */ + String resetOrgUserPassword(SuperResetPasswordDTO resetPasswordDTO); + + /** + * 查询企业负责人信息 + * + * @param userIds + * @return + */ + List personInCharge(Set userIds); + /** + * 验证机构用户是否存在 + */ + boolean existOrgUser(OrgUserCreateDTO orgUserCreateDTO); + + /** + * 通过角色信息查询用户列表 + * @param userQueryByRoleDTO + * @author sr on 2022-05-25 + */ + List listByRole(UserQueryByRoleDTO userQueryByRoleDTO); + + /** + * @description: 通过姓名或手机号查询用户列表 + * @return: 用户信息 + * @author: guixinman + * @param: + */ + List listByRealNameOrPhone(Set realNames, Set phones); + +} diff --git a/src/main/java/com/newyetai/usercenter/user/service/impl/OrgUserServiceImpl.java b/src/main/java/com/newyetai/usercenter/user/service/impl/OrgUserServiceImpl.java new file mode 100644 index 0000000..81e4389 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/service/impl/OrgUserServiceImpl.java @@ -0,0 +1,120 @@ +package com.newyetai.usercenter.user.service.impl; + +import java.util.List; + +import org.apache.commons.lang3.BooleanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.common.exception.util.Assert; +import com.newyetai.frame.redis.dto.LockDTO; +import com.newyetai.frame.redis.redisson.RedissonUtils; +import com.newyetai.usercenter.user.dao.OrgUserMapper; +import com.newyetai.usercenter.user.dto.OrgUserDTO; +import com.newyetai.usercenter.user.dto.OrgUserInfoDTO; +import com.newyetai.usercenter.user.dto.OrgUserInfoQueryDTO; +import com.newyetai.usercenter.user.dto.OrgUserOperateDTO; +import com.newyetai.usercenter.user.dto.OrgUserQueryDTO; +import com.newyetai.usercenter.user.entity.OrgUser; +import com.newyetai.usercenter.user.login.dto.OrgDetailDTO; +import com.newyetai.usercenter.user.service.OrgUserService; + +/** @author sr on 2021-05-24 */ +@Service +public class OrgUserServiceImpl implements OrgUserService { + + @Autowired + private OrgUserMapper orgUserMapper; + + + private static final String NORMAL_LOCK_NAME = "orgUser"; + private static final String ADMINISTRATOR_LOCK_NAME = "orgUserAdministrator"; + + private LockDTO getNormalLockDTO(Long orgId, Long userId) { + Assert.isTrue(orgId != null && userId != null, "操作机构用户参数缺失"); + return LockDTO.builder().methodName(NORMAL_LOCK_NAME).tryLockWaitTime(0L) + .arg(orgId.toString()).arg(userId.toString()) + .build(); + } + + private LockDTO getAdministratorLockDTO(Long orgId) { + Assert.notNull(orgId, "操作机构管理员用户参数缺失"); + return LockDTO.builder().methodName(ADMINISTRATOR_LOCK_NAME).tryLockWaitTime(0L) + .arg(orgId.toString()) + .build(); + } + + @Override + @Transactional + public Long create(OrgUserOperateDTO orgUserOperateDTO) { + Long orgId = orgUserOperateDTO.getOrgId(); + Long userId = orgUserOperateDTO.getUserId(); + // 只有true才是管理员 + if (BooleanUtils.isTrue(orgUserOperateDTO.getAdministrator())) { + return createAdministrator(orgId, userId); + } + return createNormal(orgId, userId); + } + + private Long createNormal(Long orgId, Long userId) { + OrgUserQueryDTO orgUserQueryDTO = OrgUserQueryDTO.builder().orgId(orgId).userId(userId).build(); + List orgUserList = orgUserMapper + .listOrgUserDTO(orgUserQueryDTO); + if (!orgUserList.isEmpty()) { + // 存在则直接返回 + return orgUserList.get(0).getId(); + } + // 上锁 + LockDTO lockDTO = getNormalLockDTO(orgId, userId); + try { + Assert.isTrue(RedissonUtils.tryLock(lockDTO), "请勿重复操作关联企业用户"); + // 绑定机构用户,控制绑一次 + orgUserList = orgUserMapper.listOrgUserDTO(orgUserQueryDTO); + if (!orgUserList.isEmpty()) { + // 存在则直接返回 + return orgUserList.get(0).getId(); + } + OrgUser orgUser = OrgUser.builder().orgId(orgId).userId(userId).administrator(Boolean.FALSE).build(); + orgUserMapper.saveEntity(orgUser); + return orgUser.getId(); + } finally { + RedissonUtils.unlock(lockDTO); + } + } + + @Override + public boolean existOrgUser(Long orgId, Long userId) { + // 绑定机构用户,控制绑一次 + List orgUserList = orgUserMapper + .listOrgUserDTO(OrgUserQueryDTO.builder().orgId(orgId).userId(userId).build()); + return !orgUserList.isEmpty(); + } + + private Long createAdministrator(Long orgId, Long userId) { + // 上锁 + LockDTO lockDTO = getAdministratorLockDTO(orgId); + try { + Assert.isTrue(RedissonUtils.tryLock(lockDTO), "请勿重复操作关联企业管理员用户"); + // 绑定机构管理员,控制机构下管理员唯一 + Boolean canCreate = orgUserMapper.checkCreateAdministratorUser(orgId, userId); + Assert.isTrue(canCreate, "无法创建机构管理员(机构管理员唯一),请刷新检查数据"); + OrgUser orgUser = OrgUser.builder().orgId(orgId).userId(userId).administrator(Boolean.TRUE).build(); + orgUserMapper.saveEntity(orgUser); + return orgUser.getId(); + } finally { + RedissonUtils.unlock(lockDTO); + } + } + + @Override + public List list(OrgUserInfoQueryDTO queryDTO) { + return orgUserMapper.list(queryDTO); + } + + @Override + public List listLoginOrgByUser(Long userId, Long orgId) { + return orgUserMapper.listLoginOrgByUser(userId, orgId); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/service/impl/UserAuthServiceImpl.java b/src/main/java/com/newyetai/usercenter/user/service/impl/UserAuthServiceImpl.java new file mode 100644 index 0000000..9d6d6f7 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/service/impl/UserAuthServiceImpl.java @@ -0,0 +1,57 @@ +package com.newyetai.usercenter.user.service.impl; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.usercenter.user.dao.UserAuthMapper; +import com.newyetai.usercenter.user.service.UserAuthService; +import com.newyetai.usercenter.user.dto.UserAuthQueryDTO; +import com.newyetai.usercenter.user.dto.UserAuthDTO; +import com.newyetai.usercenter.user.dto.UserAuthOperateDTO; +import com.newyetai.usercenter.user.entity.UserAuth; +import com.newyetai.usercenter.user.mapstruct.UserAuthMapMapper; +import com.newyetai.common.util.UserContextHolder; + +/** + * @author sr on 2021-05-24 + */ +@Service +public class UserAuthServiceImpl implements UserAuthService { + + @Autowired + private UserAuthMapper userAuthMapper; + + @Override + @Transactional + public Long create(UserAuthOperateDTO userAuthOperateDTO) { + UserAuth userAuth = UserAuthMapMapper.INSTANCE.toEntity(userAuthOperateDTO); + userAuthMapper.saveEntity(userAuth); + return userAuth.getId(); + } + + @Override + public void modify(UserAuthOperateDTO userAuthOperateDTO) { + // TODO Auto-generated method stub + + } + + @Override + public void remove(Long id) { + userAuthMapper.deleteEntity(UserAuth.builder().id(id).build(), + UserContextHolder.getLoginUserId()); + } + + @Override + public List list(UserAuthQueryDTO userAuthQueryDTO) { + userAuthQueryDTO.disablePage(); + return userAuthMapper.listUserAuthDTO(userAuthQueryDTO); + } + + @Override + public void page(UserAuthQueryDTO userAuthQueryDTO) { + userAuthMapper.listUserAuthDTO(userAuthQueryDTO); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/service/impl/UserBankAccountServiceImpl.java b/src/main/java/com/newyetai/usercenter/user/service/impl/UserBankAccountServiceImpl.java new file mode 100644 index 0000000..c7d5aaf --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/service/impl/UserBankAccountServiceImpl.java @@ -0,0 +1,160 @@ +package com.newyetai.usercenter.user.service.impl; + +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; + +import javax.annotation.Resource; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.google.common.collect.Maps; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.ListUtil; +import com.newyetai.frame.redis.aop.annotation.AutoUnLock; +import com.newyetai.frame.redis.dto.LockDTO; +import com.newyetai.frame.redis.redisson.RedissonUtils; +import com.newyetai.usercenter.user.dao.UserBankAccountMapper; +import com.newyetai.usercenter.user.dao.UserBankCardThreeVerificationMapper; +import com.newyetai.usercenter.user.dto.UserBankAccountCreateReqDTO; +import com.newyetai.usercenter.user.dto.UserBankAccountDTO; +import com.newyetai.usercenter.user.dto.UserBankAccountInfoDTO; +import com.newyetai.usercenter.user.dto.UserBankAccountModifyDTO; +import com.newyetai.usercenter.user.dto.UserBankAccountQueryDTO; +import com.newyetai.usercenter.user.dto.UserDTO; +import com.newyetai.usercenter.user.dto.UserQueryDTO; +import com.newyetai.usercenter.user.entity.UcUserBankAccount; +import com.newyetai.usercenter.user.mapstruct.UserBankAccountMapMapper; +import com.newyetai.usercenter.user.service.UserBankAccountService; +import com.newyetai.usercenter.user.service.UserService; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + *

+ * 用户银行卡表 服务实现类 + *

+ * + * @author Carlye + * @since 2021-06-25 + */ +@Slf4j +@Service +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class UserBankAccountServiceImpl implements UserBankAccountService { + + public static final String BIND_BANK_ACCOUNT = "bindBankAccount"; + + @Resource + private UserBankAccountMapper userBankAccountMapper; + + @Resource + private UserBankCardThreeVerificationMapper userBankCardThreeVerificationMapper; + + @Autowired + private UserService userService; + + @Override + @AutoUnLock + @Transactional(rollbackFor = Exception.class) + public UserBankAccountInfoDTO addBankAccount(UserBankAccountCreateReqDTO reqDTO) { + List list = userService.list(UserQueryDTO.builder().id(reqDTO.getUserId()) + .cardNo(reqDTO.getCardNo()).build()); + Assert.isTrue(CollectionUtils.size(list) == 1, "用户信息模糊,绑定失败"); + Long userId = list.get(0).getId(); + String accountNo = reqDTO.getAccountNo(); + Assert.isTrue( + RedissonUtils.tryLockAutomatically( + LockDTO.builder() + .tryLockWaitTime(0L) + .lockTimeout(60 * 5L) + .methodName(BIND_BANK_ACCOUNT) + .arg(String.valueOf(reqDTO.getUserId())) + .arg(reqDTO.getAccountNo()) + .build() + ), + "该用户银行卡绑定正在处理, 请稍后再试"); + List userBankAccountDTOS = list(UserBankAccountQueryDTO.builder() + .accountNo(accountNo) + .unCanceledUser(Boolean.TRUE) + .build()); + UserBankAccountDTO userBankAccount = userBankAccountDTOS.isEmpty() ? null : userBankAccountDTOS.stream().findFirst().get(); + String errorMsg = null; + if (Objects.nonNull(userBankAccount)) { + if (userId.compareTo(userBankAccount.getUserId()) == 0) { +// errorMsg = String.format("该[%s]银行卡已经被其他人绑定了",accountNo); + return UserBankAccountMapMapper.INSTANCE.exchange(userBankAccount); + } else { + errorMsg = String.format("该银行卡[%s]已经被其他用户绑定了", accountNo); + } + } + Assert.isTrue(StringUtils.isEmpty(errorMsg), errorMsg); + + UcUserBankAccount userBankAccountEntity = UserBankAccountMapMapper.INSTANCE.exchange(reqDTO); + userBankAccountDTOS = list(UserBankAccountQueryDTO.builder() + .userId(userId) + .build()); + //如不存在默认卡 + if (CollectionUtils.isEmpty(userBankAccountDTOS)) { + userBankAccountEntity.setDefaultAccount(Boolean.TRUE); + } else { + // 找到默认卡 + UserBankAccountDTO userBankAccountExist = userBankAccountDTOS.stream() + .filter(UserBankAccountDTO::getDefaultAccount) + .findFirst().orElse(null); + if (Objects.isNull(userBankAccountExist)) { + userBankAccountEntity.setDefaultAccount(Boolean.TRUE); + } else if (Boolean.TRUE.equals(userBankAccountEntity.getDefaultAccount())) { //如果需要设置默认卡 + userBankAccountMapper.updateEntitySelective(UcUserBankAccount.builder() + .id(userBankAccountExist.getId()).defaultAccount(Boolean.FALSE).build()); + } + } + userBankAccountMapper.saveEntity(userBankAccountEntity); + + return UserBankAccountMapMapper.INSTANCE.exchange(userBankAccountEntity); + } + + @Override + public Map queryBankAccountMap(List cardNos) { + return Optional.ofNullable(userBankAccountMapper.queryByCardNos(cardNos)) + .map(list -> list.stream().collect(Collectors.toMap(UserBankAccountDTO::getCardNo, UserBankAccountDTO::getAccountNo))) + .orElse(Maps.newHashMap()); + } + + @Override + public void page(UserBankAccountQueryDTO userBankAccountQueryDTO) { + userBankAccountMapper + .listUserBankAccountDTO(userBankAccountQueryDTO); + } + + @Override + public List list(UserBankAccountQueryDTO userBankAccountQueryDTO) { + userBankAccountQueryDTO.disablePage(); + return userBankAccountMapper + .listUserBankAccountDTO(userBankAccountQueryDTO); + } + + @Override + @Transactional + public void modify(UserBankAccountModifyDTO userBankAccountModifyDTO) { + Long id = userBankAccountModifyDTO.getId(); + Long userId = userBankAccountModifyDTO.getOperateUserId(); + Assert.isTrue(!list(UserBankAccountQueryDTO.builder().id(id).userId(userId).build()).isEmpty(), + "未找到对应卡记录"); + userBankAccountMapper.modify(userBankAccountModifyDTO); + } + + @Override + public UserBankAccountDTO get(Long id) { + List userBankAccountDTOs = list(UserBankAccountQueryDTO.builder().id(id).build()); + return ListUtil.first(userBankAccountDTOs); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/service/impl/UserBankCardFourVerificationServiceImpl.java b/src/main/java/com/newyetai/usercenter/user/service/impl/UserBankCardFourVerificationServiceImpl.java new file mode 100644 index 0000000..9a45621 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/service/impl/UserBankCardFourVerificationServiceImpl.java @@ -0,0 +1,152 @@ +package com.newyetai.usercenter.user.service.impl; + +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.newyetai.alitaforward.verification.dto.FourFactorVerificationDTO; +import com.newyetai.alitaforward.verification.factor.FourVerify; +import com.newyetai.common.constant.AuthStatusEnum; +import com.newyetai.common.exception.ChangeTokenException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.usercenter.user.constant.UserTypeEnum; +import com.newyetai.usercenter.user.dao.UserBankCardFourVerificationMapper; +import com.newyetai.usercenter.user.dao.UserMapper; +import com.newyetai.usercenter.user.dto.AuthenticateUserDTO; +import com.newyetai.usercenter.user.dto.UserBankAccountCreateReqDTO; +import com.newyetai.usercenter.user.dto.UserBankCardFourVerificationDTO; +import com.newyetai.usercenter.user.dto.UserBankCardFourVerificationOperateDTO; +import com.newyetai.usercenter.user.dto.UserBankCardFourVerificationQueryDTO; +import com.newyetai.usercenter.user.entity.User; +import com.newyetai.usercenter.user.entity.UserBankCardFourVerification; +import com.newyetai.usercenter.user.mapstruct.UserBankCardFourVerificationMapMapper; +import com.newyetai.usercenter.user.service.UserBankAccountService; +import com.newyetai.usercenter.user.service.UserBankCardFourVerificationService; +import com.newyetai.usercenter.user.service.UserService; + +/** + * @author czy + * @date 2021-06-28 + */ +@Service +public class UserBankCardFourVerificationServiceImpl implements + UserBankCardFourVerificationService { + + @Autowired + private FourVerify fourVerify; + + @Autowired + private UserBankCardFourVerificationMapper userBankCardFourVerificationMapper; + + @Autowired + private UserMapper userMapper; + + @Autowired + private UserService userService; + + @Autowired + private UserBankAccountService userBankAccountService; + + @Override + public UserBankCardFourVerificationDTO userFourFactorVerification( + UserBankCardFourVerificationDTO userBankCardFourVerificationDTO) { + String cardNo = userBankCardFourVerificationDTO.getCardNo(); + Long userId = UserContextHolder.getLoginUserId(); + Assert.isTrue(UserTypeEnum.PERSON.getType().equals(UserContextHolder.getUserType()), + "不支持非个人用户认证"); + UserBankCardFourVerificationQueryDTO userBankCardFourVerificationQueryDTO = + (UserBankCardFourVerificationQueryDTO) UserBankCardFourVerificationQueryDTO.builder() + .userId(userId) + .realName(userBankCardFourVerificationDTO.getRealName()) + .cardNo(cardNo) + .bankAccountNo(userBankCardFourVerificationDTO.getBankAccountNo()) + .phone(userBankCardFourVerificationDTO.getPhone()) + .build().disablePage(); + List verificationDTOs = + list(userBankCardFourVerificationQueryDTO); + Assert.isTrue(verificationDTOs.isEmpty(), "该信息用户已经认证"); + User user = userMapper.getById(userId); + Assert.notNull(user, "当前登录信息异常,请退出重新登录"); + String existCardNo = user.getCardNo(); + //判断用户是否已经有身份证号;有则校验当前用户的证件号与待认证的证件号是否一致 + Assert.isTrue(StringUtils.isBlank(existCardNo) || + StringUtils.equals(existCardNo, cardNo), + "认证身份证与当前用户身份证不一致"); + + FourFactorVerificationDTO fourFactorVerificationDTO = + UserBankCardFourVerificationMapMapper.INSTANCE + .toDto(userBankCardFourVerificationDTO); + //四要素认证 + + //第三方认证结束 + FourFactorVerificationDTO verifyResultData = fourVerify.sync(fourFactorVerificationDTO); + UserBankCardFourVerification userBankCardFourVerification = + UserBankCardFourVerificationMapMapper.INSTANCE + .toEntity(verifyResultData); + String failReason = verifyResultData.getFailReason(); + Assert.isTrue(AuthStatusEnum.AUTH_SUCCESS.getType().equals(verifyResultData.getStatus()), + failReason); + ChangeTokenException exception = null; + try { + userService.authenticatePersonUser( + AuthenticateUserDTO.builder().cardNo(fourFactorVerificationDTO.getCardNo()) + .realName(fourFactorVerificationDTO.getRealName()).userId(user.getId()) + .build()); + } catch (ChangeTokenException e) { + exception = e; + // 合并账号,有可能userId合并 + userId = e.getCasTokenDTO().getUserId(); + } + if (exception != null && !UserContextHolder.getLoginUserId().equals(userId)) { + // 合并账号,替换用户id,判断老用户id是否存在相同认证信息,存在则不保存该用户认证信息了 + userBankCardFourVerificationQueryDTO.setUserId(userId); + List existverificationDTOs = + list(userBankCardFourVerificationQueryDTO); + if (!existverificationDTOs.isEmpty()) { + throw exception; + } + } + userBankCardFourVerification.setUserId(userId); + userBankCardFourVerificationMapper.saveEntity(userBankCardFourVerification); + userBankCardFourVerificationDTO = UserBankCardFourVerificationMapMapper.INSTANCE + .toDto(userBankCardFourVerification); + //保存用户银行卡信息 + UserBankAccountCreateReqDTO accountCreateReqDTO = UserBankAccountCreateReqDTO.builder() + .userId(userId) + .accountName(userBankCardFourVerification.getRealName()) + .accountNo(userBankCardFourVerification.getBankAccountNo()) + .cardNo(userBankCardFourVerification.getCardNo()) + .build(); + userBankAccountService.addBankAccount(accountCreateReqDTO); + Assert.isTrue(exception == null, exception); + return userBankCardFourVerificationDTO; + + } + + @Override + public Long create(UserBankCardFourVerificationOperateDTO operateDTO) { + UserBankCardFourVerification userBankCardFourVerification = UserBankCardFourVerificationMapMapper.INSTANCE.toEntity(operateDTO); + userBankCardFourVerificationMapper.saveEntity(userBankCardFourVerification); + return userBankCardFourVerification.getId(); + } + + @Override + public List list( + UserBankCardFourVerificationQueryDTO userBankCardFourVerificationQueryDTO) { + return userBankCardFourVerificationMapper + .listUserBankCardFourVerificationDTO(userBankCardFourVerificationQueryDTO); + } + + @Override + public UserBankCardFourVerificationDTO findLast() { + UserBankCardFourVerificationQueryDTO queryDto = UserBankCardFourVerificationQueryDTO.builder() + .userId(UserContextHolder.getExistLoginUserId()).build(); + queryDto.setPageSize(1); + List verificationDTOs = list(queryDto); + return verificationDTOs.isEmpty() ? null : verificationDTOs.get(0); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/service/impl/UserBankCardThreeVerificationServiceImpl.java b/src/main/java/com/newyetai/usercenter/user/service/impl/UserBankCardThreeVerificationServiceImpl.java new file mode 100644 index 0000000..4f22ccc --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/service/impl/UserBankCardThreeVerificationServiceImpl.java @@ -0,0 +1,173 @@ +package com.newyetai.usercenter.user.service.impl; + +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.alitaforward.verification.dto.ThreeFactorVerificationDTO; +import com.newyetai.alitaforward.verification.factor.ThreeVerify; +import com.newyetai.common.constant.AuthStatusEnum; +import com.newyetai.common.exception.ChangeTokenException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.component.cardbin.service.CardBinService; +import com.newyetai.frame.redis.aop.annotation.AutoUnLock; +import com.newyetai.frame.redis.dto.LockDTO; +import com.newyetai.frame.redis.redisson.RedissonUtils; +import com.newyetai.usercenter.user.constant.UserTypeEnum; +import com.newyetai.usercenter.user.dao.UserBankCardThreeVerificationMapper; +import com.newyetai.usercenter.user.dao.UserMapper; +import com.newyetai.usercenter.user.dto.AuthenticateUserDTO; +import com.newyetai.usercenter.user.dto.UserBankAccountCreateReqDTO; +import com.newyetai.usercenter.user.dto.UserBankCardThreeVerificationCreateDTO; +import com.newyetai.usercenter.user.dto.UserBankCardThreeVerificationDTO; +import com.newyetai.usercenter.user.dto.UserBankCardThreeVerificationOperateDTO; +import com.newyetai.usercenter.user.dto.UserBankCardThreeVerificationQueryDTO; +import com.newyetai.usercenter.user.entity.User; +import com.newyetai.usercenter.user.entity.UserBankCardThreeVerification; +import com.newyetai.usercenter.user.mapstruct.UserBankAccountMapMapper; +import com.newyetai.usercenter.user.mapstruct.UserBankCardThreeVerificationMapMapper; +import com.newyetai.usercenter.user.service.UserBankAccountService; +import com.newyetai.usercenter.user.service.UserBankCardThreeVerificationService; +import com.newyetai.usercenter.user.service.UserService; + +import lombok.extern.slf4j.Slf4j; + +/** + * @author czy + * @date 2021-06-28 + */ +@Slf4j +@Service +public class UserBankCardThreeVerificationServiceImpl implements + UserBankCardThreeVerificationService { + + @Autowired + private ThreeVerify threeVerify; + + @Autowired + private UserBankCardThreeVerificationMapper userBankCardThreeVerificationMapper; + + @Autowired + private UserMapper userMapper; + + @Autowired + private UserService userService; + + @Autowired + private UserBankAccountService userBankAccountService; + + @Autowired + private CardBinService cardBinService; + + @Override + @AutoUnLock + @Transactional(noRollbackFor = ChangeTokenException.class) + public UserBankCardThreeVerificationDTO userThreeFactorVerification( + UserBankCardThreeVerificationCreateDTO userBankCardThreeVerificationCreateDTO) { + String bankName = cardBinService.getBankNo(userBankCardThreeVerificationCreateDTO.getBankAccountNo()); + Assert.isTrue(StringUtils.isNotBlank(bankName), "无效银行卡号"); + + String cardNo = userBankCardThreeVerificationCreateDTO.getCardNo(); + Long userId = UserContextHolder.getLoginUserId(); + Assert.isTrue(UserTypeEnum.PERSON.getType().equals(UserContextHolder.getUserType()), + "不支持非个人用户认证"); + UserBankCardThreeVerificationQueryDTO userBankCardThreeVerificationQueryDTO = + (UserBankCardThreeVerificationQueryDTO) UserBankCardThreeVerificationQueryDTO.builder() + .userId(userId) + .realName(userBankCardThreeVerificationCreateDTO.getRealName()) + .cardNo(cardNo) + .bankAccountNo(userBankCardThreeVerificationCreateDTO.getBankAccountNo()) + .build().disablePage(); + List verificationDTOs = + list(userBankCardThreeVerificationQueryDTO); + Assert.isTrue(verificationDTOs.isEmpty(), "该信息用户已经认证"); + User user = userMapper.getById(userId); + Assert.notNull(user, "当前用户已不存在,请重新登录"); + String existCardNo = user.getCardNo(); + //判断用户是否已经有身份证号;有则校验当前用户的证件号与待认证的证件号是否一致 + Assert.isTrue(StringUtils.isBlank(existCardNo) || + StringUtils.equals(existCardNo, cardNo), + "认证身份证与当前用户身份证不一致"); + + // 上锁 + LockDTO lockDTO = UserServiceImpl.getCardNoLockDTO(cardNo); + Assert.isTrue(RedissonUtils.tryLockAutomatically(lockDTO), "该身份证号正在操作"); + + ThreeFactorVerificationDTO threeFactorVerificationDTO = + UserBankCardThreeVerificationMapMapper.INSTANCE + .toDto(userBankCardThreeVerificationCreateDTO); + //三要素认证 + //第三方认证结束 + ThreeFactorVerificationDTO verifyResultData = threeVerify.sync(threeFactorVerificationDTO); + UserBankCardThreeVerification userBankCardThreeVerification = + UserBankCardThreeVerificationMapMapper.INSTANCE + .toEntity(verifyResultData); + String failReason = verifyResultData.getFailReason(); + Assert.isTrue(AuthStatusEnum.AUTH_SUCCESS.getType().equals(verifyResultData.getStatus()), + failReason); + ChangeTokenException exception = null; + try { + userService.authenticatePersonUser( + AuthenticateUserDTO.builder().cardNo(threeFactorVerificationDTO.getCardNo()) + .realName(threeFactorVerificationDTO.getRealName()).userId(user.getId()) + .build()); + } catch (ChangeTokenException e) { + exception = e; + // 合并账号,有可能userId合并 + userId = e.getCasTokenDTO().getUserId(); + } + if (exception != null && !UserContextHolder.getLoginUserId().equals(userId)) { + // 合并账号,替换用户id,判断老用户id是否存在相同认证信息,存在则不保存该用户认证信息了 + userBankCardThreeVerificationQueryDTO.setUserId(userId); + List existverificationDTOs = + list(userBankCardThreeVerificationQueryDTO); + if (!existverificationDTOs.isEmpty()) { + throw exception; + } + } + userBankCardThreeVerification.setUserId(userId); + userBankCardThreeVerificationMapper.saveEntity(userBankCardThreeVerification); + UserBankCardThreeVerificationDTO userBankCardThreeVerificationDTO = UserBankCardThreeVerificationMapMapper.INSTANCE + .toDto(userBankCardThreeVerification); + //保存用户银行卡信息 + UserBankAccountCreateReqDTO accountCreateReqDTO = + UserBankAccountMapMapper.INSTANCE.toDto(userBankCardThreeVerificationCreateDTO); + accountCreateReqDTO.setUserId(userId); + accountCreateReqDTO.setBankName(bankName); + userBankAccountService.addBankAccount(accountCreateReqDTO); + Assert.isTrue(exception == null, exception); + return userBankCardThreeVerificationDTO; + } + + @Override + @Transactional + public Long create(UserBankCardThreeVerificationOperateDTO operateDTO) { + UserBankCardThreeVerification userBankCardThreeVerification = + UserBankCardThreeVerificationMapMapper.INSTANCE.toEntity(operateDTO); + userBankCardThreeVerificationMapper.saveEntity(userBankCardThreeVerification); + return userBankCardThreeVerification.getId(); + } + + @Override + public List list( + UserBankCardThreeVerificationQueryDTO userBankCardThreeVerificationQueryDTO) { + userBankCardThreeVerificationQueryDTO.disablePage(); + return userBankCardThreeVerificationMapper + .listUserBankCardThreeVerificationDTO(userBankCardThreeVerificationQueryDTO); + } + + @Override + public UserBankCardThreeVerificationDTO findLast() { + UserBankCardThreeVerificationQueryDTO queryDto = UserBankCardThreeVerificationQueryDTO.builder() + .userId(UserContextHolder.getExistLoginUserId()).build(); + queryDto.setPageSize(1); + List verificationDTOs = + userBankCardThreeVerificationMapper.listUserBankCardThreeVerificationDTO(queryDto); + return verificationDTOs.isEmpty() ? null : verificationDTOs.get(0); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/service/impl/UserCancelServiceImpl.java b/src/main/java/com/newyetai/usercenter/user/service/impl/UserCancelServiceImpl.java new file mode 100644 index 0000000..b9f92d7 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/service/impl/UserCancelServiceImpl.java @@ -0,0 +1,163 @@ +package com.newyetai.usercenter.user.service.impl; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import javax.annotation.Resource; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.common.util.ListUtil; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.config.constant.ConfigConstants; +import com.newyetai.config.dto.ConfigDTO; +import com.newyetai.config.service.ConfigService; +import com.newyetai.frame.redis.aop.annotation.AutoUnLock; +import com.newyetai.frame.redis.dto.LockDTO; +import com.newyetai.frame.redis.redisson.RedissonUtils; +import com.newyetai.sdk.robot.util.RobotUtils; +import com.newyetai.usercenter.user.constant.UserCancelConstants; +import com.newyetai.usercenter.user.dao.UserCancelMapper; +import com.newyetai.usercenter.user.dao.UserMapper; +import com.newyetai.usercenter.user.dto.UserCancelApplyReqDTO; +import com.newyetai.usercenter.user.dto.UserCancelDTO; +import com.newyetai.usercenter.user.dto.UserCancelPageQueryDTO; +import com.newyetai.usercenter.user.entity.UserCancel; +import com.newyetai.usercenter.user.service.UserCancelService; + +import cn.hutool.core.collection.CollUtil; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class UserCancelServiceImpl implements UserCancelService { + + @Resource + private UserCancelMapper userCancelMapper; + + @Resource + private UserMapper userMapper; + + @Resource + private ConfigService configService; + + @Override + public void toNotify() { + List userCancels = userCancelMapper.toNotify(); + if (CollUtil.isEmpty(userCancels)) { + return; + } + RobotUtils.sendDevops("存在账号注销申请未处理,请查询表:uc_user_cancel确认!"); +// List successMsg = Lists.newArrayList(); +// for (UserCancelDTO dto : userCancels) { +// successMsg.add(String.format("【姓名:%s,手机号:%s,身份证:%s】申请账号注销,请前往中台“个人用户管理”页面处理。", +// dto.getRealName(), dto.getPhone(), dto.getCardNo())); +// } +// RobotUtils.sendDevops(String.join("\n", successMsg)); + } + + private List setExcludedOrgIds() { + List excludedOrgIds = new ArrayList<>(); + ConfigDTO configDTO = configService.queryConfigByCode(CommonConstants.PLATFORM_ORG_ID, ConfigConstants.CONFIG_IGNORE_ORG_INFO); + if (configDTO != null && configDTO.getConfigValue() != null) { + try { + excludedOrgIds = JsonUtils.toList(configDTO.getConfigValue(), Long.class); + } catch (Exception e) { + log.info("忽略的机构转换配置错误ignore_org_info:{}", configDTO); + } + } + return excludedOrgIds; + } + + @Override + @Transactional(rollbackFor = Exception.class) + @AutoUnLock + public UserCancelDTO apply(UserCancelApplyReqDTO applyDTO) { + Long existLoginUserId = UserContextHolder.getExistLoginUserId(); + Assert.isTrue( + RedissonUtils.tryLockAutomatically( + LockDTO.builder() + .tryLockWaitTime(0L) + .lockTimeout(60 * 5L) + .arg(existLoginUserId + "") + .methodName("user:cancel:apply") + .build() + ), + "申请注销正在处理, 请稍后再试"); + UserCancelDTO userCancel = find(UserCancelPageQueryDTO.builder().userId(existLoginUserId).build()); + + if (Objects.nonNull(userCancel)) { + return UserCancelDTO.builder().status(userCancel.getStatus()).build(); + } + + userCancelMapper.saveEntity(UserCancel.builder() + .userId(existLoginUserId) + .status(UserCancelConstants.USER_CANCEL_STATUS_APPLY) + .cancellationType(applyDTO.getCancellationType()) + .remark(applyDTO.getRemark()) + .build(), existLoginUserId); + // 发送钉钉消息 + /*UserCancelDTO notifyInfo = userCancelMapper.findNotifyInfo(existLoginUserId); + if (Objects.nonNull(notifyInfo)) { + String notifyMsg = String.format("【姓名:%s,手机号:%s,身份证:%s】申请账号注销,请前往中台“个人用户管理”页面处理。", + notifyInfo.getRealName(), notifyInfo.getPhone(), notifyInfo.getCardNo()); + RobotUtils.sendDevops(notifyMsg); + }*/ + ConfigDTO configDto = configService.getConfigDto("cancellation_audit_enable", CommonConstants.PLATFORM_ORG_ID, Boolean.TRUE); + if (Objects.nonNull(configDto)) { + ((UserCancelServiceImpl) AopContext.currentProxy()).agreeCancel(existLoginUserId); + } + return UserCancelDTO.builder().status(UserCancelConstants.USER_CANCEL_STATUS_APPLY).build(); + } + + @Override + public UserCancelDTO find(UserCancelPageQueryDTO queryDTO) { + queryDTO.disablePage(); + List userCancelDTOs = userCancelMapper.page(queryDTO); + return ListUtil.first(userCancelDTOs); + } + + @Override + @Transactional(rollbackFor = Exception.class) + @AutoUnLock + public UserCancelDTO agreeCancel(Long userId) { + Assert.isTrue( + RedissonUtils.tryLockAutomatically( + LockDTO.builder() + .tryLockWaitTime(0L) + .lockTimeout(60 * 5L) + .arg(userId + "") + .methodName("user:cancel:agreeCancel") + .build() + ), + "用户注销正在处理, 请稍后再试"); + + UserCancelDTO userCancel = find(UserCancelPageQueryDTO.builder().status(UserCancelConstants.USER_CANCEL_STATUS_APPLY).userId(userId).build()); + + if (Objects.isNull(userCancel)) { + return null; + } + + //更新用户为已注销 + userMapper.cancel(userId, UserContextHolder.getExistLoginUserId()); + + UserCancel cancel = UserCancel.builder() + .status(UserCancelConstants.USER_CANCEL_STATUS_SUCCESS) + .build(); + cancel.setId(userCancel.getId()); + userCancelMapper.updateEntitySelective(cancel); + return UserCancelDTO.builder().status(UserCancelConstants.USER_CANCEL_STATUS_SUCCESS).build(); + } + + @Override + public List page(UserCancelPageQueryDTO queryDTO) { + return userCancelMapper.page(queryDTO); + } +} diff --git a/src/main/java/com/newyetai/usercenter/user/service/impl/UserConfigServiceImpl.java b/src/main/java/com/newyetai/usercenter/user/service/impl/UserConfigServiceImpl.java new file mode 100644 index 0000000..2530721 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/service/impl/UserConfigServiceImpl.java @@ -0,0 +1,93 @@ +package com.newyetai.usercenter.user.service.impl; + +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.usercenter.user.dao.UserConfigMapper; +import com.newyetai.usercenter.user.service.UserConfigService; +import com.newyetai.usercenter.user.util.UserUtils; +import com.newyetai.usercenter.user.dto.UserConfigQueryDTO; +import com.newyetai.usercenter.user.dto.UserDTO; +import com.newyetai.usercenter.user.dto.UserConfigDTO; +import com.newyetai.usercenter.user.dto.UserConfigOperateDTO; +import com.newyetai.usercenter.user.entity.User; +import com.newyetai.usercenter.user.entity.UserConfig; +import com.newyetai.usercenter.user.mapstruct.UserConfigMapMapper; +import com.newyetai.usercenter.user.mapstruct.UserMapMapper; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.ListUtil; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.common.validation.Create; +import com.newyetai.common.validation.util.ValidateUtils; +import com.newyetai.frame.redis.dto.LockDTO; +import com.newyetai.frame.redis.redisson.RedissonUtils; + +/** + * @author sr on 2021-08-12 + */ +@Service +public class UserConfigServiceImpl implements UserConfigService { + + private static final String USER_CONFIG_LOCK_NAME = "user:config"; + + @Autowired + private UserConfigMapper userConfigMapper; + + private static LockDTO getLockDTO(Long userId, String configCode) { + Assert.isTrue(userId != null && StringUtils.isNotBlank(configCode), "配置参数缺失"); + return LockDTO.builder().methodName(USER_CONFIG_LOCK_NAME).tryLockWaitTime(0L) + .arg(userId.toString()).arg(configCode) + .build(); + } + + @Override + @Transactional + public Long create(UserConfigOperateDTO userConfigOperateDTO) { + ValidateUtils.validateBiz(userConfigOperateDTO, Create.class); + Long userId = userConfigOperateDTO.getUserId(); + String configCode = userConfigOperateDTO.getConfigCode(); + // 上锁 + LockDTO lockDTO = getLockDTO(userId, configCode); + try { + Assert.isTrue(RedissonUtils.tryLock(lockDTO), "该用户配置正在被操作"); + boolean exists = userConfigMapper + .existsEntity(UserConfig.builder().userId(userId).configCode(configCode).build()); + Assert.isTrue(!exists, "该用户配置已存在"); + UserConfig userConfig = UserConfigMapMapper.INSTANCE.toEntity(userConfigOperateDTO); + userConfigMapper.saveEntity(userConfig); + } finally { + RedissonUtils.unlock(lockDTO); + } + + + return null; + } + + @Override + public void modify(UserConfigOperateDTO userConfigOperateDTO) { + + } + + @Override + public void remove(Long id) { + userConfigMapper.deleteEntity(UserConfig.builder().id(id).build(), + UserContextHolder.getLoginUserId()); + } + + @Override + public List list(UserConfigQueryDTO userConfigQueryDTO) { + return userConfigMapper.listUserConfigDTO(userConfigQueryDTO); + } + + public UserConfigDTO find(UserConfigQueryDTO userConfigQueryDTO) { + List userConfigDTOs = + list((UserConfigQueryDTO) userConfigQueryDTO.disablePage()); + return userConfigDTOs.isEmpty() ? null : ListUtil.first(userConfigDTOs); + } + + +} diff --git a/src/main/java/com/newyetai/usercenter/user/service/impl/UserExtensionServiceImpl.java b/src/main/java/com/newyetai/usercenter/user/service/impl/UserExtensionServiceImpl.java new file mode 100644 index 0000000..a7a0b18 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/service/impl/UserExtensionServiceImpl.java @@ -0,0 +1,87 @@ +package com.newyetai.usercenter.user.service.impl; + +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.usercenter.user.dao.UserExtensionMapper; +import com.newyetai.usercenter.user.dto.UserExtensionDTO; +import com.newyetai.usercenter.user.dto.UserExtensionOperateDTO; +import com.newyetai.usercenter.user.entity.UserExtension; +import com.newyetai.usercenter.user.mapstruct.UserExtensionMapMapper; +import com.newyetai.usercenter.user.service.UserExtensionService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * @author czy + * @date 2021-06-15 + */ +@Service +public class UserExtensionServiceImpl implements UserExtensionService { + + @Autowired + private UserExtensionMapper userExtensionMapper; + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteUserFile() { + Long userId = UserContextHolder.getLoginUserId(); + UserExtensionDTO userExtensionDTO = userExtensionMapper.getByUserId(userId); + if(userExtensionDTO == null){ + return; + } + userExtensionDTO.setFileName(null); + userExtensionDTO.setFileCode(null); + UserExtension userExtension = UserExtensionMapMapper.INSTANCE.toEntity(userExtensionDTO); + int i = userExtensionMapper.updateEntity(userExtension, UserContextHolder.getLoginUserId()); + Assert.isTrue(i == 1, "修改扩展信息失败!"); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Long edit(UserExtensionOperateDTO userExtensionOperateDTO) { + Long userId = UserContextHolder.getLoginUserId(); + UserExtensionDTO userExtensionDTO = userExtensionMapper.getByUserId(userId); + Long userExtensionId = null; + if(userExtensionDTO == null){ + UserExtension userExtension = UserExtensionMapMapper.INSTANCE.toEntity(userExtensionOperateDTO); + userExtension.setUserId(UserContextHolder.getLoginUserId()); + userExtensionMapper.saveEntity(userExtension); + userExtensionId = userExtension.getId(); + }else{ + userExtensionId = userExtensionDTO.getId(); + UserExtension userExtension = UserExtensionMapMapper.INSTANCE.toEntity(userExtensionOperateDTO); + userExtension.setId(userExtensionId); + int i = userExtensionMapper + .updateEntitySelective(userExtension, UserContextHolder.getLoginUserId()); + Assert.isTrue(i == 1, "修改扩展信息失败!"); + } + return userExtensionId; + } + + @Override + public void createOrEditByUserId(UserExtensionOperateDTO userExtensionOperateDTO, Long userId) { + if (userId == null) { + throw new BusinessException("用户id缺失"); + } + UserExtensionDTO userExtensionDTO = userExtensionMapper.getByUserId(userId); + + if(userExtensionDTO == null){ + UserExtension userExtension = UserExtensionMapMapper.INSTANCE.toEntity(userExtensionOperateDTO); + userExtension.setUserId(userId); + userExtensionMapper.saveEntity(userExtension); + }else{ + UserExtension userExtension = UserExtensionMapMapper.INSTANCE.toEntity(userExtensionOperateDTO); + userExtension.setId(userExtensionDTO.getId()); + int i = userExtensionMapper + .updateEntitySelective(userExtension, UserContextHolder.getLoginUserId()); + Assert.isTrue(i == 1, "修改扩展信息失败!"); + } + } + + @Override + public UserExtensionDTO getByUserId(Long userId) { + return userExtensionMapper.getByUserId(userId); + } +} diff --git a/src/main/java/com/newyetai/usercenter/user/service/impl/UserIdentityPhotoServiceImpl.java b/src/main/java/com/newyetai/usercenter/user/service/impl/UserIdentityPhotoServiceImpl.java new file mode 100644 index 0000000..9cb51a8 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/service/impl/UserIdentityPhotoServiceImpl.java @@ -0,0 +1,95 @@ +package com.newyetai.usercenter.user.service.impl; + +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.usercenter.user.constant.UserIdentityPhotoConstants; +import com.newyetai.usercenter.user.dao.UserIdentityPhotoMapper; +import com.newyetai.usercenter.user.dto.*; +import com.newyetai.usercenter.user.entity.UserIdentityPhoto; +import com.newyetai.usercenter.user.mapstruct.UserIdentityPhotoMapMapper; +import com.newyetai.usercenter.user.service.UserIdentityPhotoService; +import com.newyetai.usercenter.user.service.UserService; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author sr on 2021-05-24 + */ +@Service +public class UserIdentityPhotoServiceImpl implements UserIdentityPhotoService { + + @Autowired + private UserIdentityPhotoMapper userIdentityPhotoMapper; + + @Autowired + private UserService userService; + + @Override + public Long create(UserIdentityPhotoOperateDTO userIdentityPhotoOperateDTO) { + Long userId = userIdentityPhotoOperateDTO.getUserId(); + if(userId == null){ + userId = UserContextHolder.getLoginUserId(); + } + // 删除此人历史数据 + this.removeByUserId(userId); + + UserIdentityPhoto userIdentityPhoto = UserIdentityPhotoMapMapper.INSTANCE + .toEntity(userIdentityPhotoOperateDTO); + userIdentityPhoto.setUserId(userId); + //默认为未认证状态 + userIdentityPhoto.setStatus(UserIdentityPhotoConstants.PHOTO_STATUS_NOT_AUTH); + userIdentityPhotoMapper.saveEntity(userIdentityPhoto); + return userIdentityPhoto.getId(); + } + + @Override + public void modify(UserIdentityPhotoOperateDTO userIdentityPhotoOperateDTO) { + UserIdentityPhoto userIdentityPhoto = UserIdentityPhotoMapMapper.INSTANCE + .toEntity(userIdentityPhotoOperateDTO); + userIdentityPhotoMapper.updateEntitySelective(userIdentityPhoto,UserContextHolder.getLoginUserId()); + } + + @Override + public void remove(Long id) { + userIdentityPhotoMapper.deleteEntity(UserIdentityPhoto.builder().id(id).build(), + UserContextHolder.getLoginUserId()); + } + + private void removeByUserId(Long userId){ + UserIdentityPhotoQueryDTO userIdentityPhotoQueryDTO = + (UserIdentityPhotoQueryDTO) UserIdentityPhotoQueryDTO.builder().userId(userId).build() + .disablePage(); + List list = this.list(userIdentityPhotoQueryDTO); + if(CollectionUtils.isNotEmpty(list)){ + list.forEach(userIdentityPhoto -> { + this.remove(userIdentityPhoto.getId()); + }); + } +} + + @Override + public UserIdentityPhotoDTO getByUserId(Long userId) { + return userIdentityPhotoMapper.getByUserId(userId); + } + + @Override + public List list(UserIdentityPhotoQueryDTO userIdentityPhotoQueryDTO) { + return userIdentityPhotoMapper.listUserIdentityPhotoDTO(userIdentityPhotoQueryDTO); + } + + @Override + public UserIdentityPhotoInfoDTO findInfo(Long userId) { + UserIdentityPhotoDTO identityPhotoDTO = this.getByUserId(userId); + if(identityPhotoDTO == null){ + return null; + } + UserIdentityPhotoInfoDTO infoDto = UserIdentityPhotoMapMapper.INSTANCE.toInfo(identityPhotoDTO); + UserDTO userDTO = userService.get(userId); + infoDto.setRealName(userDTO.getRealName()); + infoDto.setCardNo(userDTO.getCardNo()); + return infoDto; + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/service/impl/UserMergeImpl.java b/src/main/java/com/newyetai/usercenter/user/service/impl/UserMergeImpl.java new file mode 100644 index 0000000..4cd4b5e --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/service/impl/UserMergeImpl.java @@ -0,0 +1,127 @@ +package com.newyetai.usercenter.user.service.impl; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.google.common.collect.Sets; +import com.newyetai.common.exception.ChangeTokenException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.sensitive.SensitiveInfoUtils; +import com.newyetai.mq.util.MqSendUtils; +import com.newyetai.security.jwt.JwtTokenUtils; +import com.newyetai.usercenter.common.mq.constant.UcMqConstants; +import com.newyetai.usercenter.user.dao.UserAuthMapper; +import com.newyetai.usercenter.user.dao.UserMapper; +import com.newyetai.usercenter.user.dto.ChangePhoneMqDTO; +import com.newyetai.usercenter.user.dto.UserAuthDTO; +import com.newyetai.usercenter.user.dto.UserAuthQueryDTO; +import com.newyetai.usercenter.user.dto.UserDTO; +import com.newyetai.usercenter.user.dto.UserQueryDTO; +import com.newyetai.usercenter.user.entity.User; + +import lombok.extern.slf4j.Slf4j; + +@Service +@Slf4j +public class UserMergeImpl { + + @Autowired + private UserMapper userMapper; + + @Autowired + private UserAuthMapper userAuthMapper; + + @Transactional(noRollbackFor = ChangeTokenException.class) + public void mergePersonUser(Long existUserId, Long currentUserId) { + Long authenticatedUserId = checkAuthenticate(existUserId, currentUserId); + Long phoneUserId = checkPhone(existUserId, currentUserId); + checkAuth(existUserId, currentUserId); + // 身份证(实名) 》 绑定手机号 》当前用户 + Long retainUserId = authenticatedUserId != null ? authenticatedUserId + : phoneUserId != null ? phoneUserId : currentUserId; + if (phoneUserId != null && !retainUserId.equals(phoneUserId)) { + // 存在绑定手机用户,绑定用户不是保留用户,更新手机号到保留用户 + userMapper.mergeUser(retainUserId, phoneUserId); + } + + boolean deleteCurrent = retainUserId.equals(existUserId); + // 删除用户 + Long deletedUserId = deleteCurrent ? currentUserId : existUserId; + userMapper.deleteEntity(User.builder().id(deletedUserId).proxyBy(retainUserId).build()); + log.info("合并删除用户:{},保留用户:{}", deletedUserId, retainUserId); + // 授权信息迁移到保留用户 + userAuthMapper.mergeAuth(retainUserId, deletedUserId); + // 当原手机号绑定用户与保留用户不一致时 + if (!retainUserId.equals(phoneUserId)) { + User retainUser = userMapper.getById(retainUserId); + if (retainUser.getPhoneBinding()) { + // 发送异步消息关联简历 + MqSendUtils.send(UcMqConstants.CHANGE_PHONE_RESUME, + ChangePhoneMqDTO.builder().userId(retainUserId).phone(retainUser.getPhone()).build()); + } + } + // 替换token + JwtTokenUtils.changeToken(retainUserId); + } + + private Map getUserMap(Long existUserId, Long currentUserId) { + // 查询用户信息 + List userDTOs = userMapper + .listUserDTO((UserQueryDTO) UserQueryDTO.builder() + .ids(Sets.newHashSet(existUserId, currentUserId)).build().disablePage()); + return userDTOs.stream().collect(Collectors.toMap(UserDTO::getId, userDTO -> userDTO)); + } + + private Long checkAuthenticate(Long existUserId, Long currentUserId) { + Map userMap = this.getUserMap(existUserId, currentUserId); + UserDTO existUser = userMap.get(existUserId); + UserDTO currentUser = userMap.get(currentUserId); + // TODO 以身份证为准,还是以实名状态为准??? + boolean hasExistCardNo = StringUtils.isNotBlank(existUser.getCardNo()); + boolean hasCurrentCardNo = StringUtils.isNotBlank(currentUser.getCardNo()); + Assert.isTrue(!hasExistCardNo || !hasCurrentCardNo, "合并账号失败,存在不同实名信息用户"); + if (hasExistCardNo) { + return existUser.getId(); + } + if (hasCurrentCardNo) { + return currentUser.getId(); + } + return null; + } + + private Long checkPhone(Long existUserId, Long currentUserId) { + Map userMap = this.getUserMap(existUserId, currentUserId); + UserDTO existUser = userMap.get(existUserId); + UserDTO currentUser = userMap.get(currentUserId); + Assert.isTrue(!existUser.getPhoneBinding() || !currentUser.getPhoneBinding(), String.format("身份信息已被手机号%s绑定,请使用绑定手机号登录。", SensitiveInfoUtils.mobilePhone2(existUser.getPhone()))); + if (existUser.getPhoneBinding()) { + return existUser.getId(); + } + if (currentUser.getPhoneBinding()) { + return currentUser.getId(); + } + return null; + } + + private void checkAuth(Long existUserId, Long currentUserId) { + // 查询用户授权信息,相同maintype两用户都有,就不允许合并 + List userAuthDTOs = + userAuthMapper.listUserAuthDTO((UserAuthQueryDTO) UserAuthQueryDTO.builder() + .userIds(Sets.newHashSet(existUserId, currentUserId)).build().disablePage()); + + // authMainType:userId + Map> map = + userAuthDTOs.stream().collect(Collectors.groupingBy(UserAuthDTO::getAuthMainType, + Collectors.mapping(UserAuthDTO::getUserId, Collectors.toSet()))); + map.entrySet().forEach(entry -> Assert.isTrue(entry.getValue().size() <= 1, "合并账号失败,存在不同授权信息")); + + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/service/impl/UserPhoneThreeVerificationServiceImpl.java b/src/main/java/com/newyetai/usercenter/user/service/impl/UserPhoneThreeVerificationServiceImpl.java new file mode 100644 index 0000000..2a0162f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/service/impl/UserPhoneThreeVerificationServiceImpl.java @@ -0,0 +1,156 @@ +package com.newyetai.usercenter.user.service.impl; + +import java.util.List; + +import javax.annotation.Resource; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.alitaforward.verification.dto.PhoneThreeFactorVerificationDTO; +import com.newyetai.alitaforward.verification.factor.PhoneThreeVerify; +import com.newyetai.common.constant.AuthStatusEnum; +import com.newyetai.common.exception.ChangeTokenException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.frame.redis.aop.annotation.AutoUnLock; +import com.newyetai.frame.redis.dto.LockDTO; +import com.newyetai.frame.redis.redisson.RedissonUtils; +import com.newyetai.usercenter.user.constant.UserTypeEnum; +import com.newyetai.usercenter.user.dao.UserMapper; +import com.newyetai.usercenter.user.dao.UserPhoneThreeVerificationMapper; +import com.newyetai.usercenter.user.dto.AuthenticateUserDTO; +import com.newyetai.usercenter.user.dto.UserPhoneThreeVerificationDTO; +import com.newyetai.usercenter.user.dto.UserPhoneThreeVerificationOperateDTO; +import com.newyetai.usercenter.user.dto.UserPhoneThreeVerificationQueryDTO; +import com.newyetai.usercenter.user.entity.User; +import com.newyetai.usercenter.user.entity.UserPhoneThreeVerification; +import com.newyetai.usercenter.user.mapstruct.UserPhoneThreeVerificationMapMapper; +import com.newyetai.usercenter.user.service.UserPhoneThreeVerificationService; +import com.newyetai.usercenter.user.service.UserService; + +import lombok.extern.slf4j.Slf4j; + +/** + * @author czy + * @date 2021-06-28 + */ +@Slf4j +@Service +public class UserPhoneThreeVerificationServiceImpl implements + UserPhoneThreeVerificationService { + + @Autowired + private PhoneThreeVerify phoneThreeVerify; + + @Resource + private UserPhoneThreeVerificationMapper userPhoneThreeVerificationMapper; + + @Autowired + private UserMapper userMapper; + + @Autowired + private UserService userService; + + @Override + @AutoUnLock + @Transactional(noRollbackFor = ChangeTokenException.class) + public UserPhoneThreeVerificationDTO userThreeFactorVerification( + UserPhoneThreeVerificationDTO userPhoneThreeVerificationDTO) { + String cardNo = userPhoneThreeVerificationDTO.getCardNo(); + Long userId = UserContextHolder.getLoginUserId(); + Assert.isTrue(UserTypeEnum.PERSON.getType().equals(UserContextHolder.getUserType()), + "不支持非个人用户认证"); + UserPhoneThreeVerificationQueryDTO userPhoneThreeVerificationQueryDTO = + (UserPhoneThreeVerificationQueryDTO) UserPhoneThreeVerificationQueryDTO.builder() + .userId(userId) + .realName(userPhoneThreeVerificationDTO.getRealName()) + .cardNo(cardNo) + .phone(userPhoneThreeVerificationDTO.getPhone()) + .build().disablePage(); + List verificationDTOs = + list(userPhoneThreeVerificationQueryDTO); + Assert.isTrue(verificationDTOs.isEmpty(), "该信息用户已经认证"); + User user = userMapper.getById(userId); + Assert.notNull(user, "当前用户已不存在,请重新登录"); + String existCardNo = user.getCardNo(); + //判断用户是否已经有身份证号;有则校验当前用户的证件号与待认证的证件号是否一致 + Assert.isTrue(StringUtils.isBlank(existCardNo) || + StringUtils.equals(existCardNo, cardNo), + "认证身份证与当前用户身份证不一致"); + + // 上锁 + LockDTO lockDTO = UserServiceImpl.getCardNoLockDTO(cardNo); + Assert.isTrue(RedissonUtils.tryLockAutomatically(lockDTO), "该身份证号正在操作"); + + PhoneThreeFactorVerificationDTO phoneThreeFactorVerificationDTO = + UserPhoneThreeVerificationMapMapper.INSTANCE + .toDto(userPhoneThreeVerificationDTO); + //三要素认证 + + //第三方认证结束 + PhoneThreeFactorVerificationDTO verifyResultData = phoneThreeVerify.sync(phoneThreeFactorVerificationDTO); + UserPhoneThreeVerification userPhoneThreeVerification = + UserPhoneThreeVerificationMapMapper.INSTANCE + .toEntity(verifyResultData); + String failReason = verifyResultData.getFailReason(); + Assert.isTrue(AuthStatusEnum.AUTH_SUCCESS.getType().equals(verifyResultData.getStatus()), + failReason); + ChangeTokenException exception = null; + try { + userService.authenticatePersonUser( + AuthenticateUserDTO.builder().cardNo(phoneThreeFactorVerificationDTO.getCardNo()) + .realName(phoneThreeFactorVerificationDTO.getRealName()).userId(user.getId()) + .build()); + } catch (ChangeTokenException e) { + exception = e; + // 合并账号,有可能userId合并 + userId = e.getCasTokenDTO().getUserId(); + } + if (exception != null && !UserContextHolder.getLoginUserId().equals(userId)) { + // 合并账号,替换用户id,判断老用户id是否存在相同认证信息,存在则不保存该用户认证信息了 + userPhoneThreeVerificationQueryDTO.setUserId(userId); + List existverificationDTOs = + list(userPhoneThreeVerificationQueryDTO); + if (!existverificationDTOs.isEmpty()) { + throw exception; + } + } + userPhoneThreeVerification.setUserId(userId); + userPhoneThreeVerificationMapper.saveEntity(userPhoneThreeVerification); + userPhoneThreeVerificationDTO = UserPhoneThreeVerificationMapMapper.INSTANCE + .toDto(userPhoneThreeVerification); + + Assert.isTrue(exception == null, exception); + return userPhoneThreeVerificationDTO; + + } + + @Override + @Transactional + public Long create(UserPhoneThreeVerificationOperateDTO operateDTO) { + UserPhoneThreeVerification userPhoneThreeVerification = UserPhoneThreeVerificationMapMapper.INSTANCE + .toEntity(operateDTO); + userPhoneThreeVerificationMapper.saveEntity(userPhoneThreeVerification); + return userPhoneThreeVerification.getId(); + } + + @Override + public List list( + UserPhoneThreeVerificationQueryDTO userPhoneThreeVerificationQueryDTO) { + return userPhoneThreeVerificationMapper + .listUserPhoneThreeVerificationDTO(userPhoneThreeVerificationQueryDTO); + } + + @Override + public UserPhoneThreeVerificationDTO findLast() { + UserPhoneThreeVerificationQueryDTO queryDto = UserPhoneThreeVerificationQueryDTO.builder() + .userId(UserContextHolder.getExistLoginUserId()).build(); + queryDto.setPageSize(1); + List verificationDTOs = list(queryDto); + return verificationDTOs.isEmpty() ? null : verificationDTOs.get(0); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/service/impl/UserPostalInfoServiceImpl.java b/src/main/java/com/newyetai/usercenter/user/service/impl/UserPostalInfoServiceImpl.java new file mode 100644 index 0000000..c0ebe48 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/service/impl/UserPostalInfoServiceImpl.java @@ -0,0 +1,82 @@ +package com.newyetai.usercenter.user.service.impl; + +import java.util.List; + +import com.newyetai.usercenter.user.mapstruct.UserPostalInfoMapMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.usercenter.user.dao.UserPostalInfoMapper; +import com.newyetai.usercenter.user.service.UserPostalInfoService; +import com.newyetai.usercenter.user.dto.UserPostalInfoQueryDTO; +import com.newyetai.usercenter.user.dto.UserPostalInfoDTO; +import com.newyetai.usercenter.user.dto.UserPostalInfoOperateDTO; +import com.newyetai.usercenter.user.entity.UserPostalInfo; + +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.common.util.ListUtil; + +/** + * @author fzp on 2022-01-19 + */ +@Service +public class UserPostalInfoServiceImpl implements UserPostalInfoService { + + @Autowired + private UserPostalInfoMapper userPostalInfoMapper; + + @Override + @Transactional + public Long create(UserPostalInfoOperateDTO userPostalInfoOperateDTO) { + UserPostalInfo userPostalInfo = UserPostalInfoMapMapper.INSTANCE.toEntity(userPostalInfoOperateDTO); + userPostalInfoMapper.saveEntity(userPostalInfo); + + // 如果当前数据是默认,则该用户的其它数据取消默认 + if(userPostalInfo.getDefaulted()){ + Long userId = UserContextHolder.getLoginUserId(); + userPostalInfoMapper.cancelDefaultedById(userPostalInfo.getId(), userId); + } + return userPostalInfo.getId(); + } + + @Override + @Transactional + public void modify(UserPostalInfoOperateDTO userPostalInfoOperateDTO) { + UserPostalInfo userPostalInfo = UserPostalInfoMapMapper.INSTANCE.toEntity(userPostalInfoOperateDTO); + userPostalInfoMapper.updateEntitySelective(userPostalInfo); + + // 如果当前数据是默认,则该用户的其它数据取消默认 + if(userPostalInfo.getDefaulted()){ + Long userId = UserContextHolder.getLoginUserId(); + userPostalInfoMapper.cancelDefaultedById(userPostalInfo.getId(),userId); + } + } + + @Override + @Transactional + public void remove(Long id) { + userPostalInfoMapper.deleteEntity(UserPostalInfo.builder().id(id).build(), + UserContextHolder.getLoginUserId()); + } + + @Override + public List list(UserPostalInfoQueryDTO userPostalInfoQueryDTO) { + userPostalInfoQueryDTO.disablePage(); + userPostalInfoQueryDTO.setCreateBy(UserContextHolder.getLoginUserId()); + return userPostalInfoMapper.listUserPostalInfoDTO(userPostalInfoQueryDTO); + } + + @Override + public void page(UserPostalInfoQueryDTO userPostalInfoQueryDTO) { + userPostalInfoQueryDTO.setCreateBy(UserContextHolder.getLoginUserId()); + userPostalInfoMapper.listUserPostalInfoDTO(userPostalInfoQueryDTO); + } + + @Override + public UserPostalInfoDTO find(UserPostalInfoQueryDTO userPostalInfoQueryDTO) { + List userPostalInfoDTOs = this.list(userPostalInfoQueryDTO); + return userPostalInfoDTOs.isEmpty() ? null : ListUtil.first(userPostalInfoDTOs); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/service/impl/UserRealNameTwoVerificationServiceImpl.java b/src/main/java/com/newyetai/usercenter/user/service/impl/UserRealNameTwoVerificationServiceImpl.java new file mode 100644 index 0000000..63ef59e --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/service/impl/UserRealNameTwoVerificationServiceImpl.java @@ -0,0 +1,116 @@ +package com.newyetai.usercenter.user.service.impl; + +import java.io.InputStream; + +import javax.annotation.Resource; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.alitaforward.verification.dto.RealNameTwoFactorVerificationDTO; +import com.newyetai.alitaforward.verification.factor.RealNameTwoVerify; +import com.newyetai.common.constant.AuthStatusEnum; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.ChangeTokenException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.component.file.entity.FileRecord; +import com.newyetai.component.file.service.FileRecordService; +import com.newyetai.usercenter.user.constant.UserTypeEnum; +import com.newyetai.usercenter.user.dao.UserMapper; +import com.newyetai.usercenter.user.dao.UserRealNameTwoVerificationMapper; +import com.newyetai.usercenter.user.dto.AuthenticateUserDTO; +import com.newyetai.usercenter.user.dto.SuperRealNameTwoAuthDTO; +import com.newyetai.usercenter.user.dto.UserRealNameTwoAuthCreateDTO; +import com.newyetai.usercenter.user.entity.User; +import com.newyetai.usercenter.user.mapstruct.UserMapMapper; +import com.newyetai.usercenter.user.service.UserRealNameTwoVerificationService; +import com.newyetai.usercenter.user.service.UserService; + +import cn.hutool.core.io.IORuntimeException; +import cn.hutool.core.io.IoUtil; +import lombok.extern.slf4j.Slf4j; + +/** + * @author czy + * @date 2021-06-28 + */ +@Service +@Slf4j +@Lazy +public class UserRealNameTwoVerificationServiceImpl implements UserRealNameTwoVerificationService { + + @Resource + private UserMapper userMapper; + + @Resource + private UserRealNameTwoVerificationMapper userRealNameTwoVerificationMapper; + + @Autowired + private FileRecordService fileRecordService; + + @Autowired + private UserService userService; + + @Autowired + private RealNameTwoVerify realNameTwoVerify; + + private byte[] getBytes(String fileCode){ + try { + FileRecord frontFile = + fileRecordService.find(FileRecord.builder().fileCode(fileCode).build()); + InputStream inputStream = fileRecordService.getFile(frontFile); + return IoUtil.readBytes(inputStream); + } catch (IORuntimeException e) { + //doNothing + } + return null; + } + + @Override + @Transactional(noRollbackFor = ChangeTokenException.class) + public void userRealNameTwoAuth(UserRealNameTwoAuthCreateDTO createDTO) { + String cardNo = createDTO.getCardNo(); + String realName = createDTO.getRealName(); + Long userId = UserContextHolder.getLoginUserId(); + Assert.isTrue(UserTypeEnum.PERSON.getType().equals(UserContextHolder.getUserType()), + "不支持非个人用户认证"); + User user = userMapper.getById(userId); + Assert.notNull(user, "当前登录信息异常,请退出重新登录"); + String existCardNo = user.getCardNo(); + Assert.isTrue(!user.getAuthenticated(), "当前用户已实名"); + //判断用户是否已经有身份证号;有则校验当前用户的证件号与待认证的证件号是否一致 + Assert.isTrue(StringUtils.isBlank(existCardNo) || + StringUtils.equals(existCardNo, cardNo), + "认证身份证与当前用户身份证不一致"); + RealNameTwoFactorVerificationDTO verifyResultData = realNameTwoVerify.sync(RealNameTwoFactorVerificationDTO.builder() + .realName(createDTO.getRealName()) + .cardNo(createDTO.getCardNo()) + .build()); + Assert.isTrue(AuthStatusEnum.AUTH_SUCCESS.getType().equals(verifyResultData.getStatus()), + "未认证成功:" + verifyResultData.getFailReason()); + userService.authenticatePersonUser( + AuthenticateUserDTO.builder().cardNo(cardNo) + .realName(realName).userId(user.getId()) + .build()); + } + + @Override + public Long superAuth(SuperRealNameTwoAuthDTO authDTO) { + RealNameTwoFactorVerificationDTO verifyResultData = + realNameTwoVerify.sync(RealNameTwoFactorVerificationDTO.builder() + .realName(authDTO.getRealName()) + .cardNo(authDTO.getCardNo()) + .build()); + Assert.notNull(verifyResultData, "实名失败"); + Integer status = verifyResultData.getStatus(); + if (null == status || status.intValue() == AuthStatusEnum.AUTH_FAIL.getType().intValue()) { + throw new BusinessException("实名失败:"+verifyResultData.getFailReason()); + } + return userService.createAndAuthenticatePersonUser(UserMapMapper.INSTANCE.to(authDTO)); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/service/impl/UserRegisterServiceImpl.java b/src/main/java/com/newyetai/usercenter/user/service/impl/UserRegisterServiceImpl.java new file mode 100644 index 0000000..61b037c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/service/impl/UserRegisterServiceImpl.java @@ -0,0 +1,187 @@ +package com.newyetai.usercenter.user.service.impl; + +import java.util.List; +import java.util.Optional; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.ListUtil; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.frame.redis.aop.annotation.AutoUnLock; +import com.newyetai.frame.redis.dto.LockDTO; +import com.newyetai.frame.redis.redisson.RedissonUtils; +import com.newyetai.mq.util.MqSendUtils; +import com.newyetai.security.util.UserLoginUtils; +import com.newyetai.usercenter.common.dto.SlickParamCreateDTO; +import com.newyetai.usercenter.common.service.SlickParamService; +import com.newyetai.usercenter.dto.IUserDetail; +import com.newyetai.usercenter.sys.service.DomainService; +import com.newyetai.usercenter.user.dao.UserRegisterMapper; +import com.newyetai.usercenter.user.dto.UserRegisterCodeDTO; +import com.newyetai.usercenter.user.dto.UserRegisterCodeInfoDTO; +import com.newyetai.usercenter.user.dto.UserRegisterCreateDTO; +import com.newyetai.usercenter.user.dto.UserRegisterDTO; +import com.newyetai.usercenter.user.dto.UserRegisterInfoQueryDTO; +import com.newyetai.usercenter.user.dto.UserRegisterQueryDTO; +import com.newyetai.usercenter.user.entity.UserRegister; +import com.newyetai.usercenter.user.login.dto.UserDetailDTO; +import com.newyetai.usercenter.user.mapstruct.UserRegisterMapMapper; +import com.newyetai.usercenter.user.service.UserRegisterService; +import com.newyetai.usercenter.user.util.UserRegisterUtils; +import com.newyetai.usercenter.userprod.constant.UcMqSelfConstants; + +/** + * @author sr on 2021-11-16 + */ +@Service +public class UserRegisterServiceImpl implements UserRegisterService { + + @Autowired + private UserRegisterMapper userRegisterMapper; + + @Autowired + private DomainService domainService; + + @Autowired + private SlickParamService slickParamService; + + private static final String LOCK_NAME = "user:register"; + + public static LockDTO getLockDTO(Integer platformCode, Long userId) { + Assert.isTrue(platformCode != null && userId != null, "手机号不能为空"); + return LockDTO.builder().methodName(LOCK_NAME).tryLockWaitTime(0L) + .arg(platformCode.toString()) + .arg(userId.toString()) + .build(); + } + + @Override + public List list(UserRegisterQueryDTO userRegisterQueryDTO) { + userRegisterQueryDTO.disablePage(); + return userRegisterMapper.listUserRegisterDTO(userRegisterQueryDTO); + } + + @Override + public void page(UserRegisterQueryDTO userRegisterQueryDTO) { + userRegisterMapper.listUserRegisterDTO(userRegisterQueryDTO); + } + + @Override + public UserRegisterDTO find(UserRegisterQueryDTO userRegisterQueryDTO) { + List userRegisterDTOs = this.list(userRegisterQueryDTO); + return userRegisterDTOs.isEmpty() ? null : ListUtil.first(userRegisterDTOs); + } + + @Override + public String getCode(UserRegisterCodeDTO userRegisterCodeDTO) { + IUserDetail userDetail = UserContextHolder.getExistLoginUser(); + UserRegisterCodeInfoDTO codeDTO = UserRegisterMapMapper.INSTANCE.toDto(userRegisterCodeDTO); + codeDTO.setInviterId(userDetail.getId()); + codeDTO.setInviterType(userDetail.getType()); + codeDTO.setInviterOrgId(userDetail.getOrgId()); + codeDTO.setPlatformCode(dealPlatformCode(userRegisterCodeDTO.getPlatformCode())); + return slickParamService.create(SlickParamCreateDTO.builder().paramData(codeDTO).build()) + .getUniqueCode(); + } + + + + /** + * 不传应用编码时,取请求host所属应用编码 + * @param platformCode + * @return + * @author sr on 2021-11-16 + */ + private Integer dealPlatformCode(Integer platformCode) { + return Optional.ofNullable(platformCode).orElseGet(() -> domainService.findPlatformCode()); + } + + @Override + public String getCode(UserRegisterCodeInfoDTO codeDTO) { + // 验证邀请人用户信息是否正确 + AlitaResult userDetailDTO = UserLoginUtils.findUserDetailDTOResult( + UserRegisterMapMapper.INSTANCE.toDto(codeDTO)); + Assert.isTrue(userDetailDTO.getSuccess(), "邀请人信息异常", userDetailDTO.getMsg()); + // 生成邀请码 + codeDTO.setPlatformCode(dealPlatformCode(codeDTO.getPlatformCode())); + return slickParamService.create(SlickParamCreateDTO.builder().paramData(codeDTO).build()) + .getUniqueCode(); + } + + @Override + public UserRegisterCodeInfoDTO analyRegisterCode(String registerCode) { + if (StringUtils.isBlank(registerCode)) { + return null; + } + // 兼容老的注册邀请码,新的注册码是uuid + if (registerCode.length() > 32) { + return UserRegisterUtils.parseCode(registerCode); + } + return slickParamService.parseCode(registerCode, UserRegisterCodeInfoDTO.class); + } + + @Override + @Transactional + @AutoUnLock + public boolean create(UserRegisterCreateDTO userRegisterCreateDTO) { + // 注册码不为空,解析注册码 + UserRegisterCodeInfoDTO codeInfoDTO = analyRegisterCode(userRegisterCreateDTO.getRegisterCode()); + Integer platformCode = null; + if (codeInfoDTO != null) { + platformCode = codeInfoDTO.getPlatformCode(); + } else { + platformCode = domainService.findPlatformCode(); + } + Long userId = userRegisterCreateDTO.getUserId(); + UserRegisterQueryDTO userRegisterQueryDTO = + UserRegisterQueryDTO.builder().platformCode(platformCode).userId(userId).build(); + // 校验用户是否已注册 + UserRegisterDTO userRegisterDTO = find(userRegisterQueryDTO); + if (userRegisterDTO != null) { + return false; + } + // 上锁 + LockDTO lockDTO = getLockDTO(platformCode, userId); + Assert.isTrue(RedissonUtils.tryLockAutomatically(lockDTO), "用户正在被注册"); + // 二次校验 + userRegisterDTO = find(userRegisterQueryDTO); + if (userRegisterDTO != null) { + return false; + } + // 创建注册记录 + UserRegister userRegister = null; + if (codeInfoDTO != null) { + userRegister = UserRegisterMapMapper.INSTANCE.toEntity(codeInfoDTO); + } else { + userRegister = UserRegister.builder().platformCode(platformCode).build(); + } + userRegister.setUserId(userId); + userRegister.setEntrypoint(userRegisterCreateDTO.getEntrypoint()); + userRegisterMapper.saveEntity(userRegister); + // 注册后续处理 + MqSendUtils.send(UcMqSelfConstants.ROUTING_KEY_USER_REGISTER, + UserRegisterMapMapper.INSTANCE.toDto(userRegister)); + return true; + } + + @Override + public void page(UserRegisterInfoQueryDTO userRegisterInfoQueryDTO) { + userRegisterMapper.listUserRegisterInfoDTO(userRegisterInfoQueryDTO); + } + + @Override + public boolean existRegister(Long userId) { + Integer platformCode = domainService.findPlatformCode(); + UserRegisterQueryDTO userRegisterQueryDTO = + UserRegisterQueryDTO.builder().platformCode(platformCode).userId(userId).build(); + // 校验用户是否已注册 + UserRegisterDTO userRegisterDTO = find(userRegisterQueryDTO); + return userRegisterDTO != null; + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/service/impl/UserServiceImpl.java b/src/main/java/com/newyetai/usercenter/user/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..5d801e7 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/service/impl/UserServiceImpl.java @@ -0,0 +1,988 @@ +package com.newyetai.usercenter.user.service.impl; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; + +import javax.annotation.Resource; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +import com.google.common.collect.Lists; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.ChangeTokenException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.exception.util.ExceptionUtils; +import com.newyetai.common.util.ListUtil; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.common.validation.util.ValidateUtils; +import com.newyetai.frame.redis.aop.annotation.AutoUnLock; +import com.newyetai.frame.redis.dto.LockDTO; +import com.newyetai.frame.redis.redisson.RedissonUtils; +import com.newyetai.mq.util.MqSendUtils; +import com.newyetai.security.dto.UserInfoDTO; +import com.newyetai.security.jwt.JwtTokenUtils; +import com.newyetai.security.util.PasswordUtils; +import com.newyetai.usercenter.auth.constant.AuthTypeEnum; +import com.newyetai.usercenter.auth.dto.AuthDetailBindDTO; +import com.newyetai.usercenter.auth.dto.AuthDetailLoginDTO; +import com.newyetai.usercenter.auth.service.AuthDetailService; +import com.newyetai.usercenter.common.mq.constant.UcMqConstants; +import com.newyetai.usercenter.constants.OrgConstants; +import com.newyetai.usercenter.dto.OrgUserEditDTO; +import com.newyetai.usercenter.dto.SuperResetPasswordDTO; +import com.newyetai.usercenter.user.constant.UserConfigConstants; +import com.newyetai.usercenter.user.constant.UserStatusEnum; +import com.newyetai.usercenter.user.constant.UserTypeEnum; +import com.newyetai.usercenter.user.dao.UserMapper; +import com.newyetai.usercenter.user.dto.AuthenticateUserDTO; +import com.newyetai.usercenter.user.dto.BindPhoneDTO; +import com.newyetai.usercenter.user.dto.ChangePhoneDTO; +import com.newyetai.usercenter.user.dto.ChangePhoneMqDTO; +import com.newyetai.usercenter.user.dto.CheckSecurityCodeReqDTO; +import com.newyetai.usercenter.user.dto.InitUserPasswordDTO; +import com.newyetai.usercenter.user.dto.ModifyPasswordDTO; +import com.newyetai.usercenter.user.dto.OrgUserCreateDTO; +import com.newyetai.usercenter.user.dto.OrgUserModifyDTO; +import com.newyetai.usercenter.user.dto.OrgUserOperateDTO; +import com.newyetai.usercenter.user.dto.PersonUserCardCreateDTO; +import com.newyetai.usercenter.user.dto.PersonUserCardCreateResultDTO; +import com.newyetai.usercenter.user.dto.PersonUserPhoneCreateDTO; +import com.newyetai.usercenter.user.dto.PlatformUserInfoDTO; +import com.newyetai.usercenter.user.dto.PlatformUserInfoReqDTO; +import com.newyetai.usercenter.user.dto.PlatformUserListQueryDTO; +import com.newyetai.usercenter.user.dto.ResetPwdDTO; +import com.newyetai.usercenter.user.dto.ResetSecurityCodeDTO; +import com.newyetai.usercenter.user.dto.SelectUserDTO; +import com.newyetai.usercenter.user.dto.SuperChangePhoneDTO; +import com.newyetai.usercenter.user.dto.UserAuthOperateDTO; +import com.newyetai.usercenter.user.dto.UserAuthQueryDTO; +import com.newyetai.usercenter.user.dto.UserCancelReqDTO; +import com.newyetai.usercenter.user.dto.UserConfigDTO; +import com.newyetai.usercenter.user.dto.UserConfigQueryDTO; +import com.newyetai.usercenter.user.dto.UserDTO; +import com.newyetai.usercenter.user.dto.UserDetailQueryDTO; +import com.newyetai.usercenter.user.dto.UserExtendStatusDTO; +import com.newyetai.usercenter.user.dto.UserExtensionOperateDTO; +import com.newyetai.usercenter.user.dto.UserOperateDTO; +import com.newyetai.usercenter.user.dto.UserQueryByRoleDTO; +import com.newyetai.usercenter.user.dto.UserQueryDTO; +import com.newyetai.usercenter.user.entity.User; +import com.newyetai.usercenter.user.login.dto.UserDetailDTO; +import com.newyetai.usercenter.user.mapstruct.UserMapMapper; +import com.newyetai.usercenter.user.phone.util.PhoneCodeUtils; +import com.newyetai.usercenter.user.service.OrgUserService; +import com.newyetai.usercenter.user.service.UserAuthService; +import com.newyetai.usercenter.user.service.UserConfigService; +import com.newyetai.usercenter.user.service.UserExtensionService; +import com.newyetai.usercenter.user.service.UserService; +import com.newyetai.usercenter.user.util.UserUtils; + +import lombok.extern.slf4j.Slf4j; + +/** + * @author sr on 2021-05-24 + */ +@Service +@Slf4j +@Lazy +public class UserServiceImpl implements UserService { + + private static final String PHONE_LOCK_NAME = "user:phone"; + private static final String CARD_NO_LOCK_NAME = "user:cardno"; + private static final String USERNAME_LOCK_NAME = "user:username"; + private static final String AUTH_LOCK_NAME = "user:auth"; + + @Resource + private UserMapper userMapper; + + @Autowired + private OrgUserService orgUserService; + + @Autowired + private AuthDetailService authDetailService; + + @Autowired + private UserAuthService userAuthService; + + @Autowired + private UserMergeImpl userMergeImpl; + + @Autowired + private UserConfigService userConfigService; + + @Autowired + private UserExtensionService userExtensionService; + + + public static LockDTO getPhoneLockDTO(Integer userType, String phone) { + Assert.notBlank(phone, "手机号不能为空"); + return LockDTO.builder().methodName(PHONE_LOCK_NAME).tryLockWaitTime(0L) + .arg(userType.toString()) + .arg(phone) + .build(); + } + + public static LockDTO getCardNoLockDTO(String cardNo) { + Assert.notBlank(cardNo, "证件号码不能为空"); + return LockDTO.builder().methodName(CARD_NO_LOCK_NAME).tryLockWaitTime(0L).arg(cardNo) + .build(); + } + + public static LockDTO getUsernameLockDTO(String username) { + Assert.notBlank(username, "用户账号不能为空"); + return LockDTO.builder().methodName(USERNAME_LOCK_NAME).tryLockWaitTime(0L).arg(username) + .build(); + } + + private LockDTO getAuthLockDTO(String uniqueId) { + Assert.notBlank(uniqueId, "授权唯一标识不能为空"); + return LockDTO.builder().methodName(AUTH_LOCK_NAME).tryLockWaitTime(0L).arg(uniqueId) + .build(); + } + + + @Override + @AutoUnLock + @Transactional + public Long createOrgUser(OrgUserCreateDTO companyUserCreateDTO) { + ValidateUtils.validateBiz(companyUserCreateDTO); + if (StringUtils.isNotBlank(companyUserCreateDTO.getEmail())) { + if (!ValidateUtils.checkEmail(companyUserCreateDTO.getEmail())) { + throw new BusinessException("邮箱格式不正确"); + } + } + String phone = companyUserCreateDTO.getPhone(); + Long orgId = companyUserCreateDTO.getOrgId(); + Integer userType = UserTypeEnum.ORG.getType(); + // 判断用户是否存在 + UserQueryDTO userQueryDTO = (UserQueryDTO) UserQueryDTO.builder() + .type(userType).phone(phone).build().disablePage(); + UserDTO userDTO = this.findUserDTO(userQueryDTO); + Long userId = null; + if (userDTO != null) { + userId = userDTO.getId(); + } + if (userId == null) { + // 上锁 + LockDTO lockDTO = getPhoneLockDTO(userType, phone); + Assert.isTrue(RedissonUtils.tryLockAutomatically(lockDTO), "该手机号企业用户信息正在被操作"); + // 根据手机号获取企业用户 + userDTO = this.findUserDTO(userQueryDTO); + // 用户不存在 + if (userDTO == null) { + User companyUser = UserMapMapper.INSTANCE.toCreateCompanyUser(companyUserCreateDTO); + // 设置通用初始状态数据 + UserUtils.setInitToCreateUser(companyUser); + UserUtils.setInitUserNameAndPasswordToCreateUser(companyUser,companyUserCreateDTO.getAdministrator()); + userMapper.saveEntity(companyUser); + userId = companyUser.getId(); + } else { + userId = userDTO.getId(); + } + } + Assert.isTrue(!orgUserService.existOrgUser(orgId, userId), "手机号已存在,不能重复添加"); + + userExtensionService.createOrEditByUserId(UserExtensionOperateDTO.builder().wechatQrCode(companyUserCreateDTO.getWechatQrCode()).build(), userId); + // 创建机构用户关联 + orgUserService.create(OrgUserOperateDTO.builder() + .orgId(orgId) + .userId(userId) + .administrator(companyUserCreateDTO.getAdministrator()) + .build()); + return userId; + } + + @Transactional + @Override + public void modifyOrgUser(OrgUserModifyDTO orgUserModifyDTO) { + if (StringUtils.isNotBlank(orgUserModifyDTO.getPhone())) { + if (!ValidateUtils.isPhone(orgUserModifyDTO.getPhone())) { + throw new BusinessException("手机号格式不正确"); + } + } + + if (StringUtils.isNotBlank(orgUserModifyDTO.getEmail())) { + if (!ValidateUtils.checkEmail(orgUserModifyDTO.getEmail())) { + throw new BusinessException("邮箱格式不正确"); + } + } + + Integer userType = UserTypeEnum.ORG.getType(); + // 判断用户是否存在 + UserQueryDTO userQueryDTO = (UserQueryDTO) UserQueryDTO.builder() + .type(userType).phone(orgUserModifyDTO.getPhone()).build().disablePage(); + UserDTO userDTO = this.findUserDTO(userQueryDTO); + + if (userDTO != null) { + if (orgUserModifyDTO.getId().longValue() != userDTO.getId().longValue()) { + throw new BusinessException("手机号已存在"); + } + } + ; + User user = userMapper.getById(orgUserModifyDTO.getId()); + Assert.notNull(user, "该用户记录不存在"); + + userMapper.updateEntitySelective(User.builder() + .id(orgUserModifyDTO.getId()) + .phone(orgUserModifyDTO.getPhone()) + .realName(orgUserModifyDTO.getRealName()) + .email(orgUserModifyDTO.getEmail()) + .nickname(orgUserModifyDTO.getNickname()) + .updateTime(new Date()) + .updateBy(UserContextHolder.getLoginUserId()) + .build()); + + userExtensionService.createOrEditByUserId(UserExtensionOperateDTO.builder().wechatQrCode(orgUserModifyDTO.getWechatQrCode()).build(), orgUserModifyDTO.getId()); + } + + @Override + @AutoUnLock + @Transactional(propagation = Propagation.REQUIRES_NEW) + public UserDTO createPersonUser(PersonUserCardCreateDTO personUserCardCreateDTO) { + ValidateUtils.validateBiz(personUserCardCreateDTO); + String cardNo = personUserCardCreateDTO.getCardNo(); + // 判断用户是否存在 + UserQueryDTO userQueryDTO = (UserQueryDTO) UserQueryDTO.builder() + .type(UserTypeEnum.PERSON.getType()).cardNo(cardNo).build().disablePage(); + UserDTO userDTO = this.findUserDTO(userQueryDTO); + Long bindOrgId = personUserCardCreateDTO.getBindOrgId(); + if (userDTO != null) { + + if (Boolean.TRUE.equals(userDTO.getAuthenticated())) { + //身份证号码查询实名认证数据后,要记得与用户提交的信息进行比对。姓名与身份证号都一致才算实名认证通过 + if (!StringUtils.equals(personUserCardCreateDTO.getRealName(), userDTO.getRealName())) { + throw new BusinessException("实名认证未通过"); + } + } + + if (bindOrgId != null) { + // 绑定机构 + orgUserService.create(OrgUserOperateDTO.builder().orgId(bindOrgId) + .userId(userDTO.getId()).build()); + } + return userDTO; + } + + // 上锁 + LockDTO lockDTO = getCardNoLockDTO(cardNo); + Assert.isTrue(RedissonUtils.tryLockAutomatically(lockDTO), cardNo + "-该身份证号正在操作"); + // 二次判断用户是否存在 + userDTO = this.findUserDTO(userQueryDTO); + if (userDTO != null) { + if (bindOrgId != null) { + // 绑定机构 + orgUserService.create(OrgUserOperateDTO.builder().orgId(bindOrgId) + .userId(userDTO.getId()).build()); + } + return userDTO; + } + + User personUser = UserMapMapper.INSTANCE.toCreatePersonUser(personUserCardCreateDTO); + this.savePersonUser(personUser); + Long userId = personUser.getId(); + if (bindOrgId != null) { + // 绑定机构 + orgUserService.create(OrgUserOperateDTO.builder().orgId(bindOrgId) + .userId(userId).build()); + } + return UserMapMapper.INSTANCE.toDto(personUser); + } + + @Override + @Transactional + public List batchCreatePersonUser( + List personUserCardCreateDTOs) { + List resultDTOs = + Lists.newArrayListWithExpectedSize(personUserCardCreateDTOs.size()); + for (PersonUserCardCreateDTO personUserCardCreateDTO : personUserCardCreateDTOs) { + PersonUserCardCreateResultDTO resultDTO = + UserMapMapper.INSTANCE.toResultDTO(personUserCardCreateDTO); + try { + UserDTO userDto = + ((UserService) AopContext.currentProxy()).createPersonUser(personUserCardCreateDTO); + resultDTO = UserMapMapper.INSTANCE.toResultDTO(userDto); + resultDTO.setSuccess(true); + resultDTO.setUserId(userDto.getId()); + } catch (Exception e) { + resultDTO.setSuccess(false); + resultDTO.setMsg(e.getMessage()); + } + resultDTOs.add(resultDTO); + } + return resultDTOs; + } + + @Override + public UserDetailDTO modifyAndCreatePersonUser(PersonUserPhoneCreateDTO personUserPhoneCreateDTO) { + String phone = personUserPhoneCreateDTO.getPhone(); + // 查询用户 + List userDetailDTOs = userMapper.listUserDetailDTO( + UserDetailQueryDTO.builder().phone(phone).userType(UserTypeEnum.PERSON.getType()).build()); + UserService userService = ((UserService) AopContext.currentProxy()); + if (userDetailDTOs.size() == 1) { + UserDetailDTO userDetailDTO = userDetailDTOs.get(0); + Long userId = userDetailDTO.getId(); + if (!userDetailDTO.getPhoneBinding()) { + userService.updatePersonPhoneBinding(userId, phone); + userDetailDTO.setPhoneBinding(Boolean.TRUE); + } + return userDetailDTO; + } else { + return userService.createPersonUser(personUserPhoneCreateDTO); + } + } + + @Override + @AutoUnLock + @Transactional(propagation = Propagation.REQUIRES_NEW) + public UserDetailDTO createPersonUser(PersonUserPhoneCreateDTO personUserPhoneCreateDTO) { + // 上锁 + String phone = personUserPhoneCreateDTO.getPhone(); + Integer userType = UserTypeEnum.PERSON.getType(); + LockDTO lockDTO = getPhoneLockDTO(userType, phone); + Assert.isTrue(RedissonUtils.tryLockAutomatically(lockDTO), "手机号正在被操作"); + UserDTO userDTO = this.findUserDTO((UserQueryDTO) UserQueryDTO.builder() + .type(userType).phone(phone).phoneBinding(Boolean.TRUE).build().disablePage()); + if (userDTO != null) { + return UserMapMapper.INSTANCE.toUserDetailDTO(userDTO); + } + User personUser = + User.builder().type(userType).phone(phone).phoneBinding(Boolean.TRUE).build(); + this.savePersonUser(personUser); + Long userId = personUser.getId(); + // 清理其他个人用户未绑定手机号 + userMapper.cleanOtherPersonUserPhone(userId, phone); + // 发送异步消息关联简历 + MqSendUtils.send(UcMqConstants.CHANGE_PHONE_RESUME, + ChangePhoneMqDTO.builder().userId(userId).phone(phone).build()); + return UserMapMapper.INSTANCE.toUserDetailDTO(personUser); + } + + /** + * (请勿随意使用该方法)当前类内部使用 + * + * @param personUser 必须是已通过各种校验的个人用户对象 + * @author sr on 2021-06-24 + */ + private void savePersonUser(User personUser) { + personUser.setType(UserTypeEnum.PERSON.getType()); + // 设置通用初始状态数据 + UserUtils.setInitToCreateUser(personUser); + userMapper.saveEntity(personUser); + } + + @Override + public void checkExistUsername(Long userId, String username) { + Assert.isTrue(!userMapper.existUsername(username, userId), "该账号已存在"); + } + + @Override + @AutoUnLock + @Transactional(propagation = Propagation.REQUIRES_NEW, noRollbackFor = ChangeTokenException.class) + public void initUserPassword(InitUserPasswordDTO initUserPasswordDTO) { + UserUtils.checkApiUser(); + // 用户密码没设置才能设置/账号唯一控制 + Long userId = initUserPasswordDTO.getOperateUserId(); + String password = initUserPasswordDTO.getPassword(); + String repassword = initUserPasswordDTO.getRePassword(); + String username = initUserPasswordDTO.getUsername(); + Assert.isTrue(StringUtils.isNotBlank(password) && password.equals(repassword), "两次密码输入不一致"); + // 上锁 + LockDTO lockDTO = getUsernameLockDTO(username); + Assert.isTrue(RedissonUtils.tryLockAutomatically(lockDTO), "(initUp)当前账号正在操作,请稍后重试"); + checkExistUsername(userId, username); + int num = userMapper.initUserPassword(username, PasswordUtils.encode(password), userId); + Assert.isTrue(num > 0, "账号密码设置失败,请刷新检查数据"); + // 替换token + JwtTokenUtils.changeToken(userId, UserContextHolder.getLoginOrgId()); + } + + @Override + @AutoUnLock + @Transactional(propagation = Propagation.REQUIRES_NEW, noRollbackFor = ChangeTokenException.class) + public void modifyUsername(String username) { + boolean matchUsername = ValidateUtils.matchUsername(username); + Assert.isTrue(matchUsername, "账号格式不正确"); + UserUtils.checkApiUser(); + // 上锁 + LockDTO lockDTO = getUsernameLockDTO(username); + Long userId = UserContextHolder.getExistLoginUserId(); + Assert.isTrue(RedissonUtils.tryLockAutomatically(lockDTO), "(rename)当前账号正在操作,请稍后重试"); + checkExistUsername(userId, username); + int num = userMapper + .updateEntitySelective(User.builder().id(userId).username(username).build(), userId); + Assert.isTrue(num > 0, "账号修改失败,请刷新检查数据"); + // 替换token + JwtTokenUtils.changeToken(userId, UserContextHolder.getLoginOrgId()); + } + + @Override + @Transactional + public void modifyPassword(ModifyPasswordDTO modifyPasswordDTO) { + UserUtils.checkApiUser(); + String oldPassword = modifyPasswordDTO.getOldPassword(); + String newPassword = modifyPasswordDTO.getNewPassword(); + String reNewPassword = modifyPasswordDTO.getReNewPassword(); + Long userId = modifyPasswordDTO.getOperateUserId(); + Assert.isTrue(StringUtils.isNotBlank(newPassword) && newPassword.equals(reNewPassword), + "两次密码输入不一致"); + UserDTO userDTO = + findUserDTO(UserQueryDTO.builder().id(modifyPasswordDTO.getOperateUserId()).build()); + Assert.notNull(userDTO, "未找到对应用户"); + Assert.isTrue(PasswordUtils.match(oldPassword, userDTO.getPassword()), "密码错误"); + int num = userMapper + .updateEntitySelective( + User.builder().id(userId).password(PasswordUtils.encode(newPassword)).build(), userId); + Assert.isTrue(num > 0, "用户密码修改失败,请刷新检查数据"); + } + + @Override + @Transactional + public void modify(UserOperateDTO userOperateDTO) { + Long userId = UserContextHolder.getLoginUserId(); + User existUser = userMapper.getById(userId); + Assert.notNull(existUser, "当前登录信息异常,请退出重新登录"); + User user = UserMapMapper.INSTANCE.toEntity(userOperateDTO); + user.setId(userId); + userMapper.updateEntitySelective(user, userId); + if (UserTypeEnum.PERSON.getType().equals(UserContextHolder.getExistUserType())) { + //查询个人信息是否完善 + try { + if (!StringUtils.isAnyEmpty(existUser.getAvatar(), existUser.getNickname(), existUser.getRealName(), + existUser.getCardNo(), existUser.getAddress(), existUser.getPhone(), existUser.getEmail(), + existUser.getEducation() + "")) { + // 个人信息完善后续处理 +// MqSendUtils.send(UcMqSelfConstants.ROUTING_KEY_USER_ACTIVITY_POINT, +// UserActivityRecordCreateDTO.builder() +// .activityCode(ProdActivityCodeEnum.GRXX.name()) +// .actionId(userId) +// .actionUserId(userId) +// .build()); + } + } catch (Exception e) { + log.info(e.getMessage()); + } + } + + } + + @Override + @AutoUnLock + @Transactional(rollbackFor = Exception.class) + public void userCancel(UserCancelReqDTO reqDTO) { + Assert.isTrue(RedissonUtils + .tryLockAutomatically( + LockDTO.builder().methodName("userCancel").arg(String.valueOf(reqDTO.getUserId())) + .build()), + "该用户正在注销,请勿重复操作"); + //查询用户信息 + Long existLoginOrgId = UserContextHolder.getExistLoginOrgId(); + UserDTO userDTO = userMapper.getUserInfoByOrg(reqDTO.getUserId(), existLoginOrgId); + Assert.notNull(userDTO, "获取用户信息异常,请联系管理员"); + if (Optional.ofNullable(userDTO.getStatus()).orElse(1) + .compareTo(UserStatusEnum.CLOSED.getStatus()) != 0) { + User updateInfo = new User(); + updateInfo.setId(userDTO.getId()); + updateInfo.setStatus(UserStatusEnum.CLOSED.getStatus()); + updateInfo.setEnabled(Boolean.FALSE); + userMapper.updateEntitySelective(updateInfo, UserContextHolder.getLoginUserId()); + } + } + + @Override + public void page(UserQueryDTO userQueryDTO) { + if (userQueryDTO.getUserSource() != null) { + userQueryDTO.rewriteUserSource(userQueryDTO.getUserSource()); + } + userMapper.listUserDTO(userQueryDTO); + } + + @Override + public List list(UserQueryDTO userQueryDTO) { + userQueryDTO.setNeedPage(false); + return userMapper.listUserDTO(userQueryDTO); + } + + @Override + public UserDTO find(UserQueryDTO userQueryDTO) { + List userDTOs = list(userQueryDTO); + return userDTOs.isEmpty() ? null : ListUtil.first(userDTOs); + } + + @Override + public UserDTO get(Long userId) { + return this.find(UserQueryDTO.builder().id(userId).build()); + } + + @Override + public UserExtendStatusDTO getUserExtendStatus(Long userId) { + UserExtendStatusDTO userExtendStatus = userMapper.getUserExtendStatus(userId); + if (userExtendStatus == null) { + return null; + } + return userExtendStatus; + } + + @Override + @AutoUnLock + @Transactional(propagation = Propagation.REQUIRES_NEW) + public UserDetailDTO loadUser(AuthDetailLoginDTO authDetailLoginDTO) { + // 校验参数 + ValidateUtils.validateBiz(authDetailLoginDTO); + Integer userType = authDetailLoginDTO.getUserType(); + Integer authMainType = AuthTypeEnum.getAuthMainType(authDetailLoginDTO.getAuthTypeCode()); + UserAuthQueryDTO userAuthQueryDTO = (UserAuthQueryDTO) UserAuthQueryDTO.builder() + .authMainType(authMainType) + .uniqueId(authDetailLoginDTO.getUniqueId()) + .userType(userType) + .build() + .disablePage(); + List userDetailDTOs = + userMapper.listAuthUserDetailDTO(userAuthQueryDTO); + int userNum = userDetailDTOs.size(); + Assert.isTrue(userNum <= 1, "授权信息用户数据异常,请联系管理员"); + // 不支持用户授权信息创建 + Assert.isTrue(userNum == 1, "企业用户无对应授权信息"); + // 查到唯一匹配的(企业/个人)用户,直接返回 + return ListUtil.first(userDetailDTOs); + } + + @Override + public UserDTO findUserDTO(UserQueryDTO userQueryDTO) { + userQueryDTO.setUncanceled(Boolean.TRUE); + List userDTOs = userMapper.listUserDTO((UserQueryDTO) (userQueryDTO.disablePage())); + Assert.isTrue(userDTOs.size() <= 1, "用户数据异常,请联系管理员"); + return userDTOs.isEmpty() ? null : userDTOs.get(0); + } + + @Override + @AutoUnLock + @Transactional(noRollbackFor = ChangeTokenException.class, propagation = Propagation.REQUIRES_NEW) + public void authenticatePersonUser(AuthenticateUserDTO authenticateUserDTO) { + ValidateUtils.validateBiz(authenticateUserDTO); + String operateCardNo = authenticateUserDTO.getCardNo(); + Assert.isTrue(UserTypeEnum.PERSON.getType().equals(UserContextHolder.getUserType()), + "只有个人用户可操作"); + // 上锁 + LockDTO lockDTO = getCardNoLockDTO(operateCardNo); + Assert.isTrue(RedissonUtils.tryLockAutomatically(lockDTO), operateCardNo + "-该身份证号正在操作"); + Long currentUserId = UserContextHolder.getLoginUserId(); + User currentUser = userMapper.getById(currentUserId); + if (currentUser.getAuthenticated()) { + Assert.isTrue(currentUser.getCardNo().equals(operateCardNo), "用户已实名,身份证号不一致"); + return; + } + + String currentUserCardNo = currentUser.getCardNo(); + boolean hasCardNo = StringUtils.isNotBlank(currentUserCardNo); + Assert.isTrue(!hasCardNo || currentUserCardNo.equals(operateCardNo), "实名身份证号与用户已有身份证号不一致"); + if (hasCardNo) { + // 有身份证,更新当前用户实名状态 + authenticatePersonUserSelf(authenticateUserDTO, currentUserId); + return; + } + // 当前用户无身份证号 + // 查询身份证号是否有对应用户 + UserQueryDTO userQueryDTO = (UserQueryDTO) UserQueryDTO.builder() + .type(UserTypeEnum.PERSON.getType()).cardNo(operateCardNo).build() + .disablePage(); + UserDTO userDTO = this.findUserDTO(userQueryDTO); + if (userDTO == null) { + // 不存在,则当前用户实名 + authenticatePersonUserSelf(authenticateUserDTO, currentUserId); + return; + } + // 存在不是自己 + Long existUserId = userDTO.getId(); + if (!userDTO.getAuthenticated()) { + // 如果对应身份证号未实名,则更新该用户实名状态 + authenticateUserDTO.setUserId(existUserId); + userMapper.authenticatePersonUser(authenticateUserDTO); + } + //合并账号 + userMergeImpl.mergePersonUser(existUserId, currentUserId); + } + + /** + * 用户自己实名,激活;替换token + * + * @param authenticateUserDTO + * @param currentUserId + * @author sr on 2021-07-07 + */ + private void authenticatePersonUserSelf(AuthenticateUserDTO authenticateUserDTO, Long currentUserId) { + authenticateUserDTO.setUserId(currentUserId); + int num = userMapper.authenticatePersonUser(authenticateUserDTO); + Assert.isTrue(num == 1, "实名失败,请检查数据"); + // 实名后续处理 +// MqSendUtils.send(UcMqSelfConstants.ROUTING_KEY_USER_ACTIVITY_POINT, +// UserActivityRecordCreateDTO.builder() +// .activityCode(ProdActivityCodeEnum.SMRZ.name()) +// .actionId(authenticateUserDTO.getUserId()) +// .actionUserId(authenticateUserDTO.getUserId()) +// .build()); + // 替换token + JwtTokenUtils.changeToken(currentUserId); + } + + @Override + @Transactional + public Long createAndAuthenticatePersonUser(AuthenticateUserDTO authenticateUserDTO) { + ValidateUtils.validateBiz(authenticateUserDTO); + UserDTO userDTO = ((UserService) AopContext.currentProxy()).createPersonUser( + PersonUserCardCreateDTO.builder().realName(authenticateUserDTO.getRealName()) + .phone(authenticateUserDTO.getPhone()) + .cardNo(authenticateUserDTO.getCardNo()).build()); + Long userId = userDTO.getId(); + if (!userDTO.getAuthenticated()) { + int num = userMapper.authenticatePersonUser(authenticateUserDTO); + Assert.isTrue(num == 1, "实名失败,请检查数据"); + // 实名后续处理 +// MqSendUtils.send(UcMqSelfConstants.ROUTING_KEY_USER_ACTIVITY_POINT, +// UserActivityRecordCreateDTO.builder() +// .activityCode(ProdActivityCodeEnum.SMRZ.name()) +// .actionId(authenticateUserDTO.getUserId()) +// .actionUserId(authenticateUserDTO.getUserId()) +// .build()); + } + return userId; + } + + @Override + @Transactional(propagation = Propagation.REQUIRES_NEW, noRollbackFor = ChangeTokenException.class) + public void bindPersonPhone(BindPhoneDTO bindPhoneDTO) { + Assert.isTrue(UserTypeEnum.PERSON.getType().equals(UserContextHolder.getUserType()), + "只有个人用户可操作"); + String phone = bindPhoneDTO.getPhone(); + PhoneCodeUtils.matchBiz(bindPhoneDTO); + // 查询绑定手机号个人用户 + UserDTO userDTO = + findUserDTO(UserQueryDTO.builder().type(UserTypeEnum.PERSON.getType()).phone(phone) + .phoneBinding(Boolean.TRUE).build()); + Long userId = UserContextHolder.getLoginUserId(); + if (userDTO == null) { + // 不存在,上锁,二次校验,用户绑定手机号 + ((UserService) AopContext.currentProxy()).updatePersonPhoneBinding(userId, phone); + // 替换token + JwtTokenUtils.changeToken(userId); + } else if (!userDTO.getId().equals(userId)) { + // 不是当前用户,合并账号,比对实名,比对授权信息, + try { + userMergeImpl.mergePersonUser(userDTO.getId(), userId); + } catch (BusinessException e) { + log.info("合并失败:{}", e.getMessage()); + throw new BusinessException("手机号已被其他用户绑定"); + } + + } else { + // 是当前用户不处理,已经绑定成功 + } + } + + + @Override + @AutoUnLock + @Transactional(propagation = Propagation.REQUIRES_NEW, noRollbackFor = ChangeTokenException.class) + public void updatePersonPhoneBinding(Long userId, String phone) { + // 上锁 + Integer userType = UserTypeEnum.PERSON.getType(); + LockDTO lockDTO = getPhoneLockDTO(userType, phone); + Assert.isTrue(RedissonUtils.tryLockAutomatically(lockDTO), userId + "-手机号正在操作"); + UserDTO userDTO = + findUserDTO(UserQueryDTO.builder().type(UserTypeEnum.PERSON.getType()).phone(phone) + .phoneBinding(Boolean.TRUE).build()); + if (userDTO == null) { + // 更新用户手机号 + int num = userMapper.bindingPhone(userId, phone); + // 清理手机号其他未绑定用户 + userMapper.cleanOtherPersonUserPhone(userId, phone); + Assert.isTrue(num == 1, "用户绑定手机号失败,请检查数据"); + } else if (!userDTO.getId().equals(userId)) { + throw new BusinessException("该手机号已被其他用户绑定"); + } else { + // 自己绑定不处理,已经绑定成功 + } + // 发送异步消息关联简历 + MqSendUtils.send(UcMqConstants.CHANGE_PHONE_RESUME, + ChangePhoneMqDTO.builder().userId(userId).phone(phone).build()); + } + + @Override + public List pagePlatformUser(PlatformUserInfoReqDTO reqDTO) { + return userMapper.pagePlatformUser(reqDTO); + } + + @Override + public List listPlatformUser(PlatformUserListQueryDTO queryDTO) { + return userMapper.listPlatformUser(queryDTO); + } + + @Override + @Transactional + public void resetPwd(ResetPwdDTO resetPwdDTO) { + Integer userType = UserContextHolder.getUserType(); + if (userType == null) { + // 匿名访问 + userType = resetPwdDTO.getUserType(); + } + Assert.notNull(userType, "用户类型不能为空"); + PhoneCodeUtils.matchBiz(resetPwdDTO); + String password = resetPwdDTO.getPassword(); + String repassword = resetPwdDTO.getRePassword(); + Assert.isTrue(StringUtils.isNotBlank(password) && password.equals(repassword), "两次密码输入不一致"); + UserDTO userDto = this + .findUserDTO(UserQueryDTO.builder().phone(resetPwdDTO.getPhone()).type(userType).build()); + Assert.notNull(userDto, "未找到匹配用户"); + Long userId = userDto.getId(); + int num = userMapper + .updateEntitySelective( + User.builder().id(userId).password(PasswordUtils.encode(password)).build(), userId); + Assert.isTrue(num > 0, "重置密码失败,请刷新检查数据"); + } + + @Override + public UserInfoDTO findUserInfo(Long userId, Long orgId) { + if (userId == null || orgId == null) { + return null; + } + UserInfoDTO userInfoDTO = userMapper.findUserInfo(userId, orgId); + // 已经初始过密码,就忽略初始密码通知 + Boolean ignoreInitPwd = userInfoDTO.getInitialedPassword(); + if (!ignoreInitPwd) { + UserConfigDTO userConfigDTO = + userConfigService.find(UserConfigQueryDTO.builder().userId(userId) + .configCode(UserConfigConstants.IGNORE_INIT_PWD_CODE).build()); + ignoreInitPwd = userConfigDTO != null + && CommonConstants.CONFIG_TRUE.equals(userConfigDTO.getConfigValue()); + } + userInfoDTO.setIgnoreInitPwd(ignoreInitPwd); + return userInfoDTO; + } + + @Override + @AutoUnLock + @Transactional(propagation = Propagation.REQUIRES_NEW) + public void bindUserAuth(AuthDetailBindDTO authDetailBindDTO) { + ValidateUtils.validateBiz(authDetailBindDTO); + // 创建(或查询)授权明细信息 + authDetailService.create(authDetailBindDTO); + // 查询用户授权中间表是否存在相同用户类型已绑定过 + Integer userType = authDetailBindDTO.getUserType(); + Integer authMainType = AuthTypeEnum.getAuthMainType(authDetailBindDTO.getAuthTypeCode()); + UserAuthQueryDTO userAuthQueryDTO = (UserAuthQueryDTO) UserAuthQueryDTO.builder() + .authMainType(authMainType) + .uniqueId(authDetailBindDTO.getUniqueId()) + .userType(userType) + .build() + .disablePage(); + List userDetailDTOs = + userMapper.listAuthUserDetailDTO(userAuthQueryDTO); + // 有则异常 + int size = userDetailDTOs.size(); + Assert.isTrue(size <= 1, "用户授权信息异常,请联系管理员"); + Long userId = authDetailBindDTO.getUserId(); + userId = userId == null ? UserContextHolder.getExistLoginUserId() : userId; + if (size == 1) { + Assert.isTrue(ListUtil.first(userDetailDTOs).getId().equals(userId), "该授权信息已被其他用户绑定"); + return; + } + // 无则创建用户授权信息 + // 上锁 + String uniqueId = authDetailBindDTO.getUniqueId(); + LockDTO lockDTO = getAuthLockDTO(uniqueId); + Assert.isTrue(RedissonUtils.tryLockAutomatically(lockDTO), "该授权信息正在被操作"); + // 二次校验是否存在 + userDetailDTOs = + userMapper.listAuthUserDetailDTO(userAuthQueryDTO); + Assert.isTrue(userDetailDTOs.isEmpty(), "绑定授权信息失败,请稍后重试"); + userAuthService.create(UserAuthOperateDTO.builder().authMainType(authMainType) + .uniqueId(uniqueId).userId(userId).build()); + } + + + @Override + public Boolean checkSecurityCode(CheckSecurityCodeReqDTO reqDTO) { + Long userId = reqDTO.getUserId(); + User user = userMapper.getById(userId); + Assert.notNull(user, "用户不存在"); + return PasswordUtils.match(reqDTO.getSecurityCode(), user.getSecurityCode()); + } + + @Override + @Transactional + public void resetSecurityCode(ResetSecurityCodeDTO resetSecurityCodeDTO) { + PhoneCodeUtils.matchBiz(resetSecurityCodeDTO); + Assert.isTrue( + resetSecurityCodeDTO.getResecurityCode().equals(resetSecurityCodeDTO.getResecurityCode()), + "两次安全码输入不一致"); + Long userId = UserContextHolder.getExistLoginUserId(); + User existUser = userMapper.getById(userId); + Assert.notNull(existUser, "当前登录信息异常,请退出重新登录"); + userMapper.updateEntitySelective(User.builder().id(userId) + .securityCode(PasswordUtils.encode(resetSecurityCodeDTO.getSecurityCode())).build()); + } + + @Override + @AutoUnLock + @Transactional(propagation = Propagation.REQUIRES_NEW) + public void changePhone(ChangePhoneDTO changePhoneDTO) { + String phone = changePhoneDTO.getPhone(); + Integer userType = UserContextHolder.getExistUserType(); + Long userId = UserContextHolder.getExistLoginUserId(); + PhoneCodeUtils.matchBiz(changePhoneDTO); + this.lockAndCheck(userType, phone); + userMapper.bindingPhone(userId, phone); + if (UserTypeEnum.PERSON.getType().equals(userType)) { + // 发送异步消息 + MqSendUtils.send(UcMqConstants.CHANGE_PHONE, + ChangePhoneMqDTO.builder().userId(userId).phone(phone).build()); + // 发送异步消息关联简历 + MqSendUtils.send(UcMqConstants.CHANGE_PHONE_RESUME, + ChangePhoneMqDTO.builder().userId(userId).phone(phone).build()); + } + } + + private void lockAndCheck(Integer userType, String phone) { + LockDTO lockDTO = getPhoneLockDTO(userType, phone); + Assert.isTrue(RedissonUtils.tryLockAutomatically(lockDTO), "当前手机号正在操作"); + // 未被其它相同用户类型的用户绑定 + UserQueryDTO userQueryDTO = UserQueryDTO.builder() + .phone(phone).type(userType).build(); + if (UserTypeEnum.PERSON.getType().equals(userType)) { + // 个人可能存在未绑定的多条记录 + userQueryDTO.setPhoneBinding(Boolean.TRUE); + } + UserDTO userDTO = this.findUserDTO(userQueryDTO); + Assert.isNull(userDTO, "该手机号已被其他用户绑定"); + } + + @Override + @AutoUnLock + @Transactional + public void changePhone(SuperChangePhoneDTO superChangePhoneDTO) { + ValidateUtils.validateBiz(superChangePhoneDTO); + Long userId = superChangePhoneDTO.getUserId(); + String phone = superChangePhoneDTO.getPhone(); + User existUser = userMapper.getById(userId); + Assert.notNull(existUser, "当前登录信息异常,请退出重新登录"); + lockAndCheck(existUser.getType(), phone); + // 代管-换上去是未绑定状态 + userMapper.updateEntitySelective(User.builder().id(userId).phone(phone).phoneBinding(Boolean.FALSE).build()); + } + + @Override + @Transactional + @AutoUnLock + public Boolean modifyOrgUserInfo(OrgUserEditDTO orgUserEditDTO) { + Assert.isTrue(UserContextHolder.isSuperior(), "当前用户无操作权限"); + ValidateUtils.validateBiz(orgUserEditDTO); + Long userId = orgUserEditDTO.getId(); + UserDTO userDto = findUserDTO(UserQueryDTO.builder().id(userId).build()); + Assert.notNull(userDto, userId + "-用户不可用"); + User user = new User(); + user.setId(userId); + //校验 + String username = orgUserEditDTO.getUsername(); + boolean userFlag = ValidateUtils.matchUsername(username); + Assert.isTrue(userFlag, "账户名格式错误!(长度4-32位,只支持英文字母、数字)"); + //是否已经有重名 + Assert.isTrue(!userMapper.existUsername(username, orgUserEditDTO.getId()), + "账号已存在!"); + + if (StringUtils.isNotBlank(orgUserEditDTO.getEmail())) { + boolean emailFlag = ValidateUtils.checkEmail(orgUserEditDTO.getEmail()); + Assert.isTrue(emailFlag, "请输入正确格式的邮箱地址"); + } + user.setEmail(orgUserEditDTO.getEmail()); + + boolean nicknameFlag = ValidateUtils.checkNickName(orgUserEditDTO.getChineseName()); + Assert.isTrue(nicknameFlag, "中文名格式错误!(长度小于32位,不支持特殊字符)"); + user.setNickname(orgUserEditDTO.getChineseName()); + + // 用户名上锁 + LockDTO lockDTO = UserServiceImpl.getUsernameLockDTO(username); + Assert.isTrue(RedissonUtils.tryLockAutomatically(lockDTO), "当前用户名正在操作"); + + //手机号码有变化则更新 + String phone = orgUserEditDTO.getPhone(); + if (!Objects.equals(phone, userDto.getPhone())) { + lockAndCheck(userDto.getType(), phone); + user.setPhone(orgUserEditDTO.getPhone()); + //代管操作,更新手机号码后,恢复到未绑定状态 + user.setPhoneBinding(Boolean.FALSE); + } + user.setEnabled(orgUserEditDTO.getEnabled()); + return userMapper.updateEntitySelective(user) == 1; + } + + + @Override + public String resetOrgUserPassword(SuperResetPasswordDTO resetPasswordDTO) { + Assert.isTrue(StringUtils + .equals(resetPasswordDTO.getNewPassword(), resetPasswordDTO.getConfirmPassword()) + , "密码输入不一致"); + //更新操作 + String encodedPassword = PasswordUtils.encode(resetPasswordDTO.getNewPassword()); + User user = userMapper.getById(resetPasswordDTO.getUserId()); + Assert.notNull(user, "用户不存在"); + ExceptionUtils.throwBusinessException( + PasswordUtils.match(resetPasswordDTO.getNewPassword(), user.getPassword()), + "重置密码与原密码一致,无需重置!"); + // 上锁 + LockDTO lockDTO = UserServiceImpl.getUsernameLockDTO(user.getUsername()); + try { + Assert.isTrue(userMapper.updatePassword(resetPasswordDTO.getUserId(), encodedPassword, + UserContextHolder.getLoginUserId()) > 0, "数据更新失败"); + } finally { + RedissonUtils.unlock(lockDTO); + } + return resetPasswordDTO.getNewPassword(); + } + + @Override + public List personInCharge(Set userIds) { + return userMapper.personInCharge(userIds); + } + + @Override + public boolean existOrgUser(OrgUserCreateDTO companyUserCreateDTO) { + ValidateUtils.validateBiz(companyUserCreateDTO); + String phone = companyUserCreateDTO.getPhone(); + Integer userType = UserTypeEnum.ORG.getType(); + // 判断用户是否存在 + UserQueryDTO userQueryDTO = (UserQueryDTO) UserQueryDTO.builder() + .type(userType).phone(phone).build().disablePage(); + UserDTO userDTO = this.findUserDTO(userQueryDTO); + if (userDTO == null) { + return false; + } + return orgUserService.existOrgUser(companyUserCreateDTO.getOrgId(), userDTO.getId()); + } + + @Override + public List listByRole(UserQueryByRoleDTO userQueryByRoleDTO) { + return userMapper.listByRole(userQueryByRoleDTO); + } + + @Override + public List listByRealNameOrPhone(Set realNames, Set phones) { + if (CollectionUtils.isEmpty(realNames) && CollectionUtils.isEmpty(phones)) { + return new ArrayList<>(); + } + return userMapper.listByRealNameOrPhone(UserContextHolder.getExistLoginOrgId(), realNames, phones); + } +} diff --git a/src/main/java/com/newyetai/usercenter/user/util/UserRegisterUtils.java b/src/main/java/com/newyetai/usercenter/user/util/UserRegisterUtils.java new file mode 100644 index 0000000..2fa1bac --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/util/UserRegisterUtils.java @@ -0,0 +1,68 @@ +package com.newyetai.usercenter.user.util; + +import org.apache.commons.lang3.StringUtils; + +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.JasyptUtils; +import com.newyetai.security.util.SecurityUtils; +import com.newyetai.usercenter.user.dto.UserRegisterCodeInfoDTO; + +import lombok.extern.slf4j.Slf4j; + +/** + * @author sr on 2021-11-15 + */ +@Slf4j +public class UserRegisterUtils { + + private static final int PLATFORM_CODE_INDEX = 0; + private static final int INVITER_TYPE_INDEX = 1; + private static final int INVITER_ID_INDEX = 2; + private static final int INVITER_ORG_ID_INDEX = 3; + + /** + * 兼容老注册码规则,等老规则生成的注册码没人用时可删除 + * @param registerCode + * @return + * @author sr on 2022-01-12 + */ + @Deprecated + public static UserRegisterCodeInfoDTO parseCode(String registerCode) { + if (StringUtils.isBlank(registerCode)) { + return null; + } + // 解一次码,小程序可能会encode一次 + registerCode = SecurityUtils.decodeURL(registerCode); + registerCode = JasyptUtils.decrypt(registerCode); + Assert.notBlank(registerCode, "非法邀请码"); + String[] codeArray = registerCode.split(CommonConstants.UNDERLINE); + UserRegisterCodeInfoDTO dto = new UserRegisterCodeInfoDTO(); + try { + for (int i = 0; i < codeArray.length; i++) { + switch (i) { + case PLATFORM_CODE_INDEX: + dto.setPlatformCode(Integer.valueOf(codeArray[i])); + break; + case INVITER_TYPE_INDEX: + dto.setInviterType(Integer.valueOf(codeArray[i])); + break; + case INVITER_ID_INDEX: + dto.setInviterId(Long.valueOf(codeArray[i])); + break; + case INVITER_ORG_ID_INDEX: + dto.setInviterOrgId(Long.valueOf(codeArray[i])); + break; + default: + break; + } + } + } catch (Exception e) { + log.error("无效邀请码:{}", registerCode); + throw new BusinessException("无效邀请码"); + } + return dto; + } + +} diff --git a/src/main/java/com/newyetai/usercenter/user/util/UserUtils.java b/src/main/java/com/newyetai/usercenter/user/util/UserUtils.java new file mode 100644 index 0000000..02512d2 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/user/util/UserUtils.java @@ -0,0 +1,121 @@ +package com.newyetai.usercenter.user.util; + +import org.apache.commons.lang3.StringUtils; + +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.EnvironmentUtils; +import com.newyetai.common.util.RandomUtils; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.security.util.PasswordUtils; +import com.newyetai.usercenter.user.constant.UserStatusEnum; +import com.newyetai.usercenter.user.constant.UserTypeEnum; +import com.newyetai.usercenter.user.dto.IUserPhoneCodeSms; +import com.newyetai.usercenter.user.entity.User; + +/** + * @author sr on 2021-05-24 + */ +public class UserUtils { + + public static final int NICKNAME_LENGTH = 12; + + public static final String DEFAULT_AVATAR_KEY = "user.default.avatars"; + + /** + * 设置创建用户初始状态数据 (账号随机生成/非超管/非实名/待激活/已启用-登录相关) + * + * @param user + * @author sr on 2021-06-10 + */ + public static void setInitToCreateUser(User user) { + user.setUsername(RandomUtils.generateUUID()); + String nickname = user.getNickname(); + user.setNickname(dealNickname(nickname, user.getPhone())); + user.setAvatar(dealAvatar(user.getAvatar())); + user.setSupeiror(Boolean.FALSE); + user.setAuthenticated(Boolean.FALSE); + user.setStatus(UserStatusEnum.INIT.getStatus()); + user.setEnabled(Boolean.TRUE); + user.setAccountNonExpired(Boolean.TRUE); + user.setAccountNonLocked(Boolean.TRUE); + user.setCredentialsNonExpired(Boolean.TRUE); + } + + /** + * @description: 初始化账号密码 + * @return: + * @author: guixinman + * @param: + */ + public static void setInitUserNameAndPasswordToCreateUser(User user, Boolean administrator) { + //创建用户的时候就给手机号绑定状态改为已绑定 + user.setPhoneBinding(true); + if (Boolean.TRUE.equals(administrator)) { + user.setUsername("lgsc"+user.getPhone()); + user.setPassword(PasswordUtils.encode("lgsc123567")); + }else { + user.setUsername("ou"+user.getPhone()); + user.setPassword(PasswordUtils.encode("ou123567")); + } + } + + public static String dealNickname(String nickname, String phone) { + if (StringUtils.isNotBlank(nickname)) { + return nickname; + } + if (StringUtils.isNotBlank(phone)) { + return "用户" + StringUtils.right(phone, 4); + } + return "用户" + RandomUtils.nextSixInt(); + } + + public static String dealAvatar(String avatar) { + if (StringUtils.isNotBlank(avatar)) { + return avatar; + } + String avatarStr = EnvironmentUtils.getProperty(DEFAULT_AVATAR_KEY); + if (StringUtils.isBlank(avatarStr)) { + return null; + } + String[] avatars = avatarStr.split(CommonConstants.COMMA); + return avatars[org.apache.commons.lang3.RandomUtils.nextInt(0, avatars.length)]; + } + + /** + * 校验是否api用户 + * + * @author sr on 2021-08-16 + */ + public static void checkApiUser() { + checkApiUser(UserContextHolder.getUserType()); + } + + /** + * 校验是否api用户 + * + * @param userType + * @author sr on 2021-08-16 + */ + public static void checkApiUser(Integer userType) { + Assert.isTrue(!UserTypeEnum.API_ORG.getType().equals(userType), + "用户类型异常"); + } + + /** + * 带有用户类型对象获取用户类型(优先取入参) + * + * @param iUserType + * @return + * @author sr on 2021-09-02 + */ + public static UserTypeEnum getUserType(IUserPhoneCodeSms iUserType) { + Integer userType = iUserType.getUserType(); + if (userType == null) { + userType = UserContextHolder.getUserType(); + } + Assert.notNull(userType, "无法获取验证码,用户类型不能为空"); + return UserTypeEnum.one(userType); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/userprod/constant/UcMqSelfConstants.java b/src/main/java/com/newyetai/usercenter/userprod/constant/UcMqSelfConstants.java new file mode 100644 index 0000000..29d8449 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/userprod/constant/UcMqSelfConstants.java @@ -0,0 +1,37 @@ +package com.newyetai.usercenter.userprod.constant; + +import com.newyetai.usercenter.common.mq.constant.UcMqConstants; + +/** + * 用户中心内部使用 + * + * @author sr on 2021-01-05 + */ +public interface UcMqSelfConstants { + + /** + * 手机短信验证码(用户中心内部) + **/ + String ROUTING_KEY_PHONE_CODE_SMS_PREFIX = UcMqConstants.MQ_PREFIX + "phone_code_sms"; + + /** + * 手机短信(用户中心内部) + */ + String ROUTING_KEY_SIMPLE_SMS_PREFIX = UcMqConstants.MQ_PREFIX + "simple_sms"; + + /** + * 通知消息通道处理 前缀 + **/ + String ROUTING_KEY_NOTICE_CHANNEL_DEAL_PREFIX = UcMqConstants.MQ_PREFIX + "notice_channel_deal"; + + /** + * 用户注册 + **/ + String ROUTING_KEY_USER_REGISTER = UcMqConstants.MQ_PREFIX + "user_register"; + + /** + * 活动送积分 + */ + String ROUTING_KEY_USER_ACTIVITY_POINT = UcMqConstants.MQ_PREFIX + "user:activity:point"; + +} diff --git a/src/main/java/com/newyetai/usercenter/utils/CheckUtil.java b/src/main/java/com/newyetai/usercenter/utils/CheckUtil.java new file mode 100644 index 0000000..84ca240 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/utils/CheckUtil.java @@ -0,0 +1,42 @@ +package com.newyetai.usercenter.utils; + +import cn.hutool.core.util.ReUtil; +import com.google.common.base.Strings; +import com.newyetai.common.exception.util.Assert; + +/** + * @description: 校验工具类 + * @author: chenyun.huang + * @create: 2020-05-07 16:07 + **/ +public class CheckUtil { + + /** + * 正则 数字或者是字母 最多10位 + */ + private static String NUMBER_ALPHABET_REG = "^[A-Za-z0-9]{2,26}$"; + + + /** + * 账号校验正则 + */ + private static String USERNAME_REG = "^[0-9]+admin$"; + + /** + * 正则 手机号 + */ + private static String PHONE_REG = "^1(3|4|5|7|8)\\d{9}$"; + + private CheckUtil() { + } + + /** + * 判断账号是否不为xxadmin规则的账号 + * @param username + * @return + */ + public static boolean checkUsernameRule(String username){ + return !ReUtil.isMatch(USERNAME_REG, username); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/utils/ComponentUtils.java b/src/main/java/com/newyetai/usercenter/utils/ComponentUtils.java new file mode 100644 index 0000000..d8c6732 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/utils/ComponentUtils.java @@ -0,0 +1,40 @@ +package com.newyetai.usercenter.utils; + +import com.newyetai.usercenter.resource.dto.ComponentDTO; +import com.newyetai.usercenter.resource.entity.Component; + +/** + * 组件工具类 + * + * @author sr on 2019-10-15 + */ +public class ComponentUtils { + + /** + * 新增,dto转entity + * @param componentDTO + * @return + * @author sr on 2019-10-15 + */ + public static Component toCreateComponent(ComponentDTO componentDTO) { + return Component.builder().urlId(componentDTO.getUrlId()).code(componentDTO.getCode()) + .name(componentDTO.getName()).build(); + } + + /** + * 修改,dto转entity + * @param componentDTO + * @return + * @author sr on 2019-10-15 + */ + public static Component toUpdateComponent(ComponentDTO componentDTO) { + return Component.builder().id(componentDTO.getId()).urlId(componentDTO.getUrlId()) + .code(componentDTO.getCode()).name(componentDTO.getName()).build(); + } + + public static ComponentDTO toDto(Component component) { + return ComponentDTO.builder().id(component.getId()).urlId(component.getUrlId()) + .code(component.getCode()).name(component.getName()).build(); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/utils/FindPwdUtils.java b/src/main/java/com/newyetai/usercenter/utils/FindPwdUtils.java new file mode 100644 index 0000000..f4b9cc7 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/utils/FindPwdUtils.java @@ -0,0 +1,117 @@ +package com.newyetai.usercenter.utils; + +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.exception.util.ExceptionUtils; +import com.newyetai.frame.redis.util.RedisUtils; +import java.time.LocalDate; + +/** + * @author czy on 2020-08-20 + */ +public class FindPwdUtils { + + /** 找回密码短信验证码前缀 **/ + public static final String FIND_PWD_SMS_CODE_PREFIX = "find:pwd:sms:code"; + /** 短信最后发送前缀 **/ + public static final String FIND_PWD_SMS_LAST_PREFIX = "find:pwd:sms:last"; + /** 短信次数前缀 **/ + public static final String FIND_PWD_SMS_COUNT_PREFIX = "find:pwd:sms:count"; + /** 发送验证码时间间隔-秒 **/ + public static final long LAST_EXPIRE_TIME = 60; + /** 验证码过期时间-秒 **/ + public static final long CODE_EXPIRE_TIME = 300; + /** 验证码找回密码次数过期时间-秒 **/ + public static final long COUNT_EXPIRE_TIME = 60 * 60 * 24; + + /** + * 存储验证码的key + * + * @param phone + * @return + * @author czy on 2020-08-20 + */ + public static String getFindPwdSmsCodeKey(String phone) { + // 验证码 find:pwd:sms:code:phone + return String.join(CommonConstants.COLON, FIND_PWD_SMS_CODE_PREFIX, phone); + } + + /** + * 最后一次获取验证码的key + * + * @param phone + * @return + * @author czy on 2020-08-20 + */ + public static String getFindPwdSmsLastKey(String phone) { + // 验证码 find:pwd:sms:last:phone + return String.join(CommonConstants.COLON, FIND_PWD_SMS_LAST_PREFIX, phone); + } + + /** + * 一天内登录验证码次数的key + * + * @param phone + * @return + * @author czy on 2020-08-20 + */ + public static String getFindPwdSmsCountKey(String phone) { + // 登录次数 find:pwd:sms:count:dayOfYear:phone 有效期一天 + return String.join(CommonConstants.COLON, FIND_PWD_SMS_COUNT_PREFIX, + String.valueOf(LocalDate.now().getDayOfYear()), phone); + } + + /** + * 校验上一次找回密码时间间隔是否超过一分钟 + * + * @param phone + * @author czy on 2020-08-20 + */ + public static void checkFindPwdSmsLast(String phone) { + Long num = RedisUtils.increment(getFindPwdSmsLastKey(phone), LAST_EXPIRE_TIME); + ExceptionUtils.throwBusinessException(num > 1L, "操作过于频繁,请60秒后重试"); + } + + /** + * 设置验证码,过期时间5分钟 + * + * @param phone + * @param code + * @author czy on 2020-08-20 + */ + public static void setFindPwdSmsCode(String phone, String code) { + RedisUtils.add(getFindPwdSmsCodeKey(phone), code, CODE_EXPIRE_TIME); + } + + /** + * 获取验证码 + * + * @param phone + * @return + * @author czy on 2020-08-20 + */ + public static String getFindPwdSmsCode(String phone) { + return (String) RedisUtils.get(getFindPwdSmsCodeKey(phone)); + } + + /** + * 找回密码成功,移除验证码 + * + * @param phone + * @author czy on 2020-08-20 + */ + public static void removeFindPwdSmsCode(String phone) { + RedisUtils.remove(getFindPwdSmsCodeKey(phone)); + } + + /** + * 获取当前获取验证码次数 + * + * @param phone + * @return + * @author czy on 2020-08-20 + */ + public static long getFindPwdSmsCount(String phone) { + return RedisUtils.increment(getFindPwdSmsCountKey(phone), COUNT_EXPIRE_TIME); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/utils/PermissionPackageUtils.java b/src/main/java/com/newyetai/usercenter/utils/PermissionPackageUtils.java new file mode 100644 index 0000000..22f934f --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/utils/PermissionPackageUtils.java @@ -0,0 +1,24 @@ +package com.newyetai.usercenter.utils; + +import com.newyetai.usercenter.permissionpackage.constants.PermissionPackageConstants; +import com.newyetai.usercenter.permissionpackage.dto.PermissionPackageDTO; +import com.newyetai.usercenter.permissionpackage.entity.PermissionPackage; + +/** + * 权限包工具类 + */ +public class PermissionPackageUtils { + + + public static PermissionPackage toCreatePermissionPackage( + PermissionPackageDTO permissionPackageDTO) { + return PermissionPackage.builder() + .permissionPackageName(permissionPackageDTO.getPermissionPackageName()) + .platformCode(permissionPackageDTO.getPlatformCode()) + .permissionPackageType(permissionPackageDTO.getPermissionPackageType()) + .status(permissionPackageDTO.getStatus()).build(); + } + + + +} diff --git a/src/main/java/com/newyetai/usercenter/utils/PermissionUtils.java b/src/main/java/com/newyetai/usercenter/utils/PermissionUtils.java new file mode 100644 index 0000000..cad2945 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/utils/PermissionUtils.java @@ -0,0 +1,32 @@ +package com.newyetai.usercenter.utils; + +import com.newyetai.common.util.EnvironmentUtils; +import com.newyetai.common.util.UserContextHolder; +import com.newyetai.usercenter.authority.entity.Permission; +import com.newyetai.usercenter.constants.SecurityConstants; +import org.apache.commons.lang3.StringUtils; + +/** + * 角色权限工具类 + * @author sr on 2019-10-17 + */ +public class PermissionUtils { + + /** + * 创建权限entity + * @param roleId + * @param resourceType + * @param resourceId + * @return + * @author sr on 2019-10-17 + */ + public static Permission createPermission(Long roleId, String resourceType, Long resourceId) { + return Permission.builder().roleId(roleId) + .resourceType(resourceType) + .resourceId(resourceId) + .orgId(UserContextHolder.getLoginOrgId()) + .platformCode(EnvironmentUtils.getSystemCode()) + .attribute(StringUtils.join(SecurityConstants.ROLE_PERMISSION_PREFIX, roleId)).build(); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/utils/RoleAllocationUtils.java b/src/main/java/com/newyetai/usercenter/utils/RoleAllocationUtils.java new file mode 100644 index 0000000..0313679 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/utils/RoleAllocationUtils.java @@ -0,0 +1,27 @@ +package com.newyetai.usercenter.utils; + +import com.newyetai.usercenter.authority.entity.RoleAllocation; + +/** + * 角色分配常量类 + * + * @author sr on 2019-10-19 + */ +public class RoleAllocationUtils { + + /** + * 创建角色分配 + * + * @param roleId + * @param allocationType + * @param allocationId + * @return + * @author sr on 2019-10-19 + */ + public static RoleAllocation toCreate(Long roleId, String allocationType, Long allocationId) { + return RoleAllocation.builder().allocationId(allocationId) + .allocationType(allocationType) + .roleId(roleId).build(); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/utils/RoleUtils.java b/src/main/java/com/newyetai/usercenter/utils/RoleUtils.java new file mode 100644 index 0000000..9a5ffc4 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/utils/RoleUtils.java @@ -0,0 +1,79 @@ +package com.newyetai.usercenter.utils; + +import com.newyetai.usercenter.authority.entity.Role; +import com.newyetai.usercenter.constants.RoleConstants; +import com.newyetai.usercenter.dto.RoleDTO; + +/** + * 角色工具类 + * + * @author sr on 2019-10-12 + */ +public class RoleUtils { + + private RoleUtils() { + } + + /** + * 新增,dto转entity,id为空 + * + * @param orgId + * @param roleDTO + * @param roleType + * @return + * @author sr on 2019-10-14 + */ + public static Role toCreateRole(Long orgId, RoleDTO roleDTO, String roleType) { + return Role.builder() + .orgId(orgId) + .name(roleDTO.getName()) + .type(roleType) + .enabled(Boolean.TRUE.equals(roleDTO.getEnabled())) + .description(roleDTO.getDescription()) + .standardType(roleDTO.getStandardType()) + .platformCode(roleDTO.getPlatformCode()) + .build(); + } + + /** + * 修改,dto转entity,有id,类型不变(置null) + * + * @param roleDTO + * @return + * @author sr on 2019-10-14 + */ + public static Role toUpdateRole(RoleDTO roleDTO) { + return Role.builder() + .id(roleDTO.getId()) + .name(roleDTO.getName()) + .enabled(Boolean.TRUE.equals(roleDTO.getEnabled())) + .description(roleDTO.getDescription()) + .standardType(roleDTO.getStandardType()) + .platformCode(roleDTO.getPlatformCode()) + .build(); + } + + /** + * 获取启用业务角色dto + * + * @return + * @author sr on 2019-10-17 + */ + public static RoleDTO getBusinessRoleDTO() { + return RoleDTO.builder().type(RoleConstants.ROLE_TYPE_BUSINESS).enabled(true).build(); + } + + /** + * 获取校验对象(同机构下是否存在同名有效的角色) + * + * @param roleDTO + * @param orgId + * @return + * @author sr on 2019-10-22 + */ + public static Role toValidation(RoleDTO roleDTO, Long orgId) { + return Role.builder().id(roleDTO.getId()).name(roleDTO.getName()).orgId(orgId).deleted(false) + .build(); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/utils/StringUtils.java b/src/main/java/com/newyetai/usercenter/utils/StringUtils.java new file mode 100644 index 0000000..3962ef9 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/utils/StringUtils.java @@ -0,0 +1,23 @@ +package com.newyetai.usercenter.utils; + +import org.apache.commons.lang3.RandomStringUtils; + +/** + * @author Jerry.li + * @description 字符串工具类 + * @date 2020/3/24 + */ +public class StringUtils { + + private StringUtils() { + } + + /** + * 生成8-16位的随机字母+数字的字符串 + * + * @return + */ + public static String generateOrgActivationCode(int min, int max) { + return RandomStringUtils.randomAlphanumeric(min + (int) (Math.random() * (max - min + 1))); + } +} diff --git a/src/main/java/com/newyetai/usercenter/utils/UrlUtils.java b/src/main/java/com/newyetai/usercenter/utils/UrlUtils.java new file mode 100644 index 0000000..8162210 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/utils/UrlUtils.java @@ -0,0 +1,90 @@ +package com.newyetai.usercenter.utils; + +import com.newyetai.usercenter.resource.dto.UrlDTO; +import com.newyetai.usercenter.resource.entity.Url; + +import java.util.Objects; + +/** + * 菜单工具类 + * + * @author sr on 2019-10-15 + */ +public class UrlUtils { + + private UrlUtils() { + } + + /** + * 新增,dto转entity + * + * @param urlDTO + * @return + * @author sr on 2019-10-15 + */ + public static Url toCreateUrl(UrlDTO urlDTO) { + return Url.builder() + .name(urlDTO.getName()) + .link(urlDTO.getLink()) + .icon(urlDTO.getIcon()) + .parentId(urlDTO.getParentId()) + .resourceOrder(urlDTO.getResourceOrder()) + .visible(Boolean.TRUE.equals(urlDTO.getVisible())) + .description(urlDTO.getDescription()) + .platformCode(urlDTO.getPlatformCode()) + .type(urlDTO.getType()) + .build(); + } + + /** + * 修改,dto转entity,有id + * + * @param urlDTO + * @return + * @author sr on 2019-10-15 + */ + public static Url toUpdateUrl(UrlDTO urlDTO) { + return Url.builder() + .id(urlDTO.getId()) + .name(urlDTO.getName()) + .link(urlDTO.getLink()) + .icon(urlDTO.getIcon()) + .type(urlDTO.getType()) + .parentId(urlDTO.getParentId()) + .resourceOrder(urlDTO.getResourceOrder()) + .visible(Boolean.TRUE.equals(urlDTO.getVisible())) + .description(urlDTO.getDescription()) + .platformCode(urlDTO.getPlatformCode()) + .deleted(Objects.equals(urlDTO.getDeleted(), 1)) + .build(); + } + + public static Url toUrl(UrlDTO url) { + return Url.builder() + .id(url.getId()) + .name(url.getName()) + .link(url.getLink()) + .icon(url.getIcon()) + .type(url.getType()) + .parentId(url.getParentId()) + .resourceOrder(url.getResourceOrder()) + .visible(Boolean.TRUE.equals(url.getVisible())) + .description(url.getDescription()) + .build(); + } + + public static UrlDTO toDTO(Url url) { + return UrlDTO.builder() + .id(url.getId()) + .name(url.getName()) + .link(url.getLink()) + .icon(url.getIcon()) + .type(url.getType()) + .parentId(url.getParentId()) + .resourceOrder(url.getResourceOrder()) + .visible(Boolean.TRUE.equals(url.getVisible())) + .description(url.getDescription()) + .build(); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/websocket/config/DefaultHttpSessionHandshakeInterceptor.java b/src/main/java/com/newyetai/usercenter/websocket/config/DefaultHttpSessionHandshakeInterceptor.java new file mode 100644 index 0000000..1433f4c --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/websocket/config/DefaultHttpSessionHandshakeInterceptor.java @@ -0,0 +1,21 @@ +package com.newyetai.usercenter.websocket.config; + +import java.util.Collection; + +import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor; + +import com.google.common.collect.Lists; + +/** + * 拦截器,复制httpSession属性到websocketSession + * + * @author sr on 2021-01-04 + */ +public class DefaultHttpSessionHandshakeInterceptor extends HttpSessionHandshakeInterceptor { + + public DefaultHttpSessionHandshakeInterceptor(Collection attributeNames) { + // 指定从HttpSession复制属性到WebSocketSession: + super(Lists.newArrayList(attributeNames)); + + } +} diff --git a/src/main/java/com/newyetai/usercenter/websocket/config/DefaultTextWebSocketHandler.java b/src/main/java/com/newyetai/usercenter/websocket/config/DefaultTextWebSocketHandler.java new file mode 100644 index 0000000..0efb306 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/websocket/config/DefaultTextWebSocketHandler.java @@ -0,0 +1,141 @@ +package com.newyetai.usercenter.websocket.config; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; + +import org.apache.commons.collections.CollectionUtils; +import org.springframework.http.HttpHeaders; +import org.springframework.web.socket.CloseStatus; +import org.springframework.web.socket.TextMessage; +import org.springframework.web.socket.WebSocketSession; +import org.springframework.web.socket.handler.TextWebSocketHandler; + +import com.newyetai.common.constant.CommonConstants; +import com.newyetai.common.util.CookieUtils; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.security.jwt.JwtTokenUtils; +import com.newyetai.security.util.SecurityPropertyUtils; +import com.newyetai.usercenter.dto.IUserDetail; +import com.newyetai.usercenter.websocket.service.IWebSocketProvider; +import com.newyetai.usercenter.websocket.service.SocketMessage; + +import lombok.extern.slf4j.Slf4j; + +/** + * 文本消息处理器 + * + * @author sr on 2021-01-04 + */ +@Slf4j +public class DefaultTextWebSocketHandler extends TextWebSocketHandler { + + /** + * concurrent包的线程安全,用来存放每个客户端对应的MyWebSocket对象。 + */ + private static Map> clients = + new ConcurrentHashMap<>(500); + private IWebSocketProvider webSocketProvider; + + public DefaultTextWebSocketHandler(IWebSocketProvider webSocketProvider) { + this.webSocketProvider = webSocketProvider; + } + + private Long dealToken(WebSocketSession session) { + HttpHeaders headers = session.getHandshakeHeaders(); + List headerTokens = headers.get(SecurityPropertyUtils.getProperties().getJwt().getHeader()); + IUserDetail userDto = null; + if (CollectionUtils.isNotEmpty(headerTokens)) { + String headerToken = headerTokens.get(0); + userDto = JwtTokenUtils.getUserLoginDtoFromToken(headerToken); + } + if (userDto == null) { + List cookies = headers.get(HttpHeaders.COOKIE); + log.debug("cookies:{}", cookies); + if (CollectionUtils.isEmpty(cookies)) { + return null; + } + for(String cookie : cookies.get(0).split(CommonConstants.SEMICOLON)) { + String[] cookieArray = cookie.split(CommonConstants.EQUAL); + String key = cookieArray[0]; + if (CookieUtils.getLoginTokenCookieKey().equals(key.trim())) { + userDto = JwtTokenUtils.getUserLoginDtoFromToken(cookieArray[1]); + } + } + } + return userDto == null ? null : userDto.getId(); + } + + @Override + public void afterConnectionEstablished(WebSocketSession session) throws Exception { + Long userId = dealToken(session); + if (userId == null) { + log.info("用户未登录,不添加连接"); + return; + } + CopyOnWriteArrayList servers = clients.get(userId); + if (servers == null) { + servers = new CopyOnWriteArrayList(); + clients.put(userId, servers); + } + servers.add(session); + log.info("websocket open:userId-{}, sessionId-{}", userId, + session.getId()); + webSocketProvider.onOpenSend(userId, session); + } + + @Override + public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { + Long userId = dealToken(session); + if (userId != null) { + clients.get(userId).remove(session); + log.info("websocket close:userId-{}, sessionId-{}.", userId, + session.getId()); + } + } + + @Override + protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { + log.info("客户端发送消息:{}", message.getPayload()); + } + + + /** + * @param session + * @param message + */ + public static void sendMessage(WebSocketSession session, SocketMessage message) { + try { + TextMessage textMessage = new TextMessage(JsonUtils.toJsonString(message)); + session.sendMessage(textMessage); + } catch (Exception e) { + log.info("websocket sendMessage error:{}", e.getMessage()); + } + } + + /** + * @param userId + * @param message + */ + public static void sendMessageToUser(Long userId, SocketMessage message) { + CopyOnWriteArrayList sessions = clients.get(userId); + if (sessions == null) { + log.info("{}用户未建立ws..."); + return ; + } + sessions.stream().forEach(session -> DefaultTextWebSocketHandler.sendMessage(session, message)); + } + + /** + * 群发自定义消息 + */ + public static void sendMessageToAll(SocketMessage message) { + clients.values().stream().flatMap(Collection::stream) + .forEach(session -> DefaultTextWebSocketHandler.sendMessage(session, message)); + } + + + +} diff --git a/src/main/java/com/newyetai/usercenter/websocket/config/WebSocketConfiguration.java b/src/main/java/com/newyetai/usercenter/websocket/config/WebSocketConfiguration.java new file mode 100644 index 0000000..78667c5 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/websocket/config/WebSocketConfiguration.java @@ -0,0 +1,71 @@ +package com.newyetai.usercenter.websocket.config; + +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpHeaders; +import org.springframework.web.socket.config.annotation.EnableWebSocket; +import org.springframework.web.socket.config.annotation.WebSocketConfigurer; +import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; + +import com.google.common.collect.Lists; +import com.newyetai.security.util.SecurityPropertyUtils; +import com.newyetai.usercenter.websocket.service.IWebSocketProvider; +import com.newyetai.usercenter.websocket.service.impl.DefaultWebSocketProvider; +import com.newyetai.usercenter.websocket.util.WebSocketUtils; + +/** + * websocket配置类 + * + * @author sr on 2021-01-04 + */ +@Configuration +@ConditionalOnProperty(name = "websocket.enable", havingValue = "true") +@EnableWebSocket +@EnableConfigurationProperties({WebSocketProperties.class}) +public class WebSocketConfiguration { + + @Autowired + private WebSocketProperties webSocketProperties; + + @Bean + IWebSocketProvider webSocketProvider() { + return new DefaultWebSocketProvider(); + } + + @Bean + DefaultTextWebSocketHandler defaultTextWebSocketHandler() { + return new DefaultTextWebSocketHandler(webSocketProvider()); + } + + @Bean + DefaultHttpSessionHandshakeInterceptor defaultHttpSessionHandshakeInterceptor() { + List attributeNames = Lists.newArrayList(HttpHeaders.COOKIE, + SecurityPropertyUtils.getProperties().getJwt().getHeader()); + return new DefaultHttpSessionHandshakeInterceptor(attributeNames); + } + + + @Bean + WebSocketConfigurer createWebSocketConfigurer() { + + return new WebSocketConfigurer() { + public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { + String path = webSocketProperties.getPath(); + path = StringUtils.isNotBlank(path) ? path : "/ws"; + WebSocketUtils.setPath(path); + // 把URL与指定的WebSocketHandler关联,可关联多个: + registry + .addHandler(defaultTextWebSocketHandler(), path) + .addInterceptors(defaultHttpSessionHandshakeInterceptor()) + .setAllowedOrigins("*"); + } + }; + } + +} diff --git a/src/main/java/com/newyetai/usercenter/websocket/config/WebSocketProperties.java b/src/main/java/com/newyetai/usercenter/websocket/config/WebSocketProperties.java new file mode 100644 index 0000000..a3f26a4 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/websocket/config/WebSocketProperties.java @@ -0,0 +1,24 @@ +package com.newyetai.usercenter.websocket.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 配置属性 + * + * @author sr on 2021-01-04 + */ +@ConfigurationProperties(prefix = "websocket") +@Data +@NoArgsConstructor +public class WebSocketProperties { + + /** 是否启用 **/ + private Boolean enable; + + /** 路径 **/ + private String path; + +} diff --git a/src/main/java/com/newyetai/usercenter/websocket/service/ISocketMessageSender.java b/src/main/java/com/newyetai/usercenter/websocket/service/ISocketMessageSender.java new file mode 100644 index 0000000..0afa87e --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/websocket/service/ISocketMessageSender.java @@ -0,0 +1,80 @@ +package com.newyetai.usercenter.websocket.service; + +import org.springframework.web.socket.WebSocketSession; + +import com.newyetai.usercenter.websocket.util.WebSocketUtils; + +/** + * @param + * @author sr on 2020-06-29 + */ +public interface ISocketMessageSender { + + /** + * 类型,需唯一 + * + * @return + * @author sr on 2020-07-01 + */ + String getType(); + + /** + * 获取消息对象 + * + * @return + * @author sr on 2020-07-01 + */ + default T getData() { + return null; + }; + + /** + * 给指定人的客户端发消息 + * + * @param userId + * @author sr on 2020-07-01 + */ + default void send(Long userId) { + WebSocketUtils.send(userId, getType(), getData()); + } + + /** + * 给指定人发送消息 + * + * @param userId + * @param data + * @author sr on 2021-01-04 + */ + default void send(Long userId, T data) { + WebSocketUtils.send(userId, getType(), data); + } + + /** + * 给所有客户端发消息 + * + * @author sr on 2020-07-01 + */ + default void sendAll() { + WebSocketUtils.sendAll(getType(), getData()); + } + + /** + * 给所有客户端发消息 + * + * @param data + * @author sr on 2021-01-04 + */ + default void sendAll(T data) { + WebSocketUtils.sendAll(getType(), data); + } + + /** + * 建立连接时发送消息 + * + * @param userId + * @param session + * @author sr on 2020-07-01 + */ + default void onOpenSend(Long userId, WebSocketSession session) {} + +} diff --git a/src/main/java/com/newyetai/usercenter/websocket/service/IWebSocketProvider.java b/src/main/java/com/newyetai/usercenter/websocket/service/IWebSocketProvider.java new file mode 100644 index 0000000..5bcaf73 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/websocket/service/IWebSocketProvider.java @@ -0,0 +1,18 @@ +package com.newyetai.usercenter.websocket.service; + +import org.springframework.web.socket.WebSocketSession; + +/** + * @author sr on 2021-01-04 + */ +public interface IWebSocketProvider { + + /** + * @param userId + * @param session + * @author sr on 2021-01-04 + */ + void onOpenSend(Long userId, WebSocketSession session); + + +} diff --git a/src/main/java/com/newyetai/usercenter/websocket/service/SocketMessage.java b/src/main/java/com/newyetai/usercenter/websocket/service/SocketMessage.java new file mode 100644 index 0000000..0211644 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/websocket/service/SocketMessage.java @@ -0,0 +1,25 @@ +package com.newyetai.usercenter.websocket.service; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author sr on 2020-06-29 + * @param + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class SocketMessage { + + private String type; + private T data; + + + public static SocketMessage create(String type, T data) { + return new SocketMessage(type, data); + } +} diff --git a/src/main/java/com/newyetai/usercenter/websocket/service/impl/DefaultWebSocketProvider.java b/src/main/java/com/newyetai/usercenter/websocket/service/impl/DefaultWebSocketProvider.java new file mode 100644 index 0000000..c23a518 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/websocket/service/impl/DefaultWebSocketProvider.java @@ -0,0 +1,29 @@ +package com.newyetai.usercenter.websocket.service.impl; + +import java.util.Collections; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.socket.WebSocketSession; + +import com.newyetai.usercenter.websocket.service.ISocketMessageSender; +import com.newyetai.usercenter.websocket.service.IWebSocketProvider; + +/** + * @author sr on 2021-01-04 + */ +public class DefaultWebSocketProvider implements IWebSocketProvider{ + + @SuppressWarnings({"rawtypes"}) + @Autowired(required = false) + private List socketMessageSenders = Collections.emptyList(); + + @Override + public void onOpenSend(Long userId, WebSocketSession session) { + if (socketMessageSenders.isEmpty()) { + return ; + } + socketMessageSenders.forEach(sender -> sender.onOpenSend(userId, session)); + } + +} diff --git a/src/main/java/com/newyetai/usercenter/websocket/service/impl/WebsocketNoticeSendProvider.java b/src/main/java/com/newyetai/usercenter/websocket/service/impl/WebsocketNoticeSendProvider.java new file mode 100644 index 0000000..63957ca --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/websocket/service/impl/WebsocketNoticeSendProvider.java @@ -0,0 +1,19 @@ +package com.newyetai.usercenter.websocket.service.impl; + +import com.newyetai.component.chat.dto.ChatMsgDTO; +import com.newyetai.component.notice.dto.NoticeMsgDTO; +import org.springframework.stereotype.Service; + +import com.newyetai.component.notice.service.INoticeSendProvider; +import com.newyetai.usercenter.websocket.util.WebSocketUtils; + +@Service +public class WebsocketNoticeSendProvider implements INoticeSendProvider { + + @Override + public void send(NoticeMsgDTO msg) { + WebSocketUtils.send(msg.getReceiverId(), msg.getType(), msg); + } + + +} diff --git a/src/main/java/com/newyetai/usercenter/websocket/util/WebSocketUtils.java b/src/main/java/com/newyetai/usercenter/websocket/util/WebSocketUtils.java new file mode 100644 index 0000000..976d757 --- /dev/null +++ b/src/main/java/com/newyetai/usercenter/websocket/util/WebSocketUtils.java @@ -0,0 +1,40 @@ +package com.newyetai.usercenter.websocket.util; + +import com.newyetai.usercenter.websocket.config.DefaultTextWebSocketHandler; +import com.newyetai.usercenter.websocket.service.SocketMessage; + +/** + * 工具类 + * + * @author sr on 2021-01-04 + */ +public class WebSocketUtils { + + private static String path; + + public static void setPath(String path) { + // 初始化websocket会设置 + WebSocketUtils.path = path; + } + + public static String getPath() { + return path; + } + + static SocketMessage createMsg(String type, T data) { + SocketMessage socketMessage = new SocketMessage(); + socketMessage.setData(data); + socketMessage.setType(type); + return socketMessage; + } + + public static void sendAll(String type, T data) { + DefaultTextWebSocketHandler.sendMessageToAll(createMsg(type, data)); + } + + public static void send(Long userId, String type, T data) { + DefaultTextWebSocketHandler.sendMessageToUser(userId, createMsg(type, data)); + } + + +} diff --git a/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2ClientPropertiesRegistrationAdapter.java b/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2ClientPropertiesRegistrationAdapter.java new file mode 100644 index 0000000..d7bd93d --- /dev/null +++ b/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2ClientPropertiesRegistrationAdapter.java @@ -0,0 +1,116 @@ +package org.springframework.boot.autoconfigure.security.oauth2.client; + +import java.util.HashMap; +import java.util.Map; + +import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientProperties.Provider; +import org.springframework.boot.context.properties.PropertyMapper; +import org.springframework.boot.convert.ApplicationConversionService; +import org.springframework.core.convert.ConversionException; +import org.springframework.security.oauth2.client.registration.ClientRegistration; +import org.springframework.security.oauth2.client.registration.ClientRegistration.Builder; +import org.springframework.security.oauth2.client.registration.ClientRegistrations; +import org.springframework.security.oauth2.core.AuthenticationMethod; +import org.springframework.security.oauth2.core.AuthorizationGrantType; +import org.springframework.security.oauth2.core.ClientAuthenticationMethod; +import org.springframework.util.StringUtils; + +import com.newyetai.security.social.service.CommonOAuth2Provider; + +/** + * Adapter class to convert {@link OAuth2ClientProperties} to a + * {@link ClientRegistration}. + * + * @author Phillip Webb + * @author Thiago Hirata + * @author Madhura Bhave + * @author MyeongHyeon Lee + * @since 2.1.0 + */ +public final class OAuth2ClientPropertiesRegistrationAdapter { + + private OAuth2ClientPropertiesRegistrationAdapter() { + } + + public static Map getClientRegistrations(OAuth2ClientProperties properties) { + Map clientRegistrations = new HashMap<>(); + properties.getRegistration().forEach((key, value) -> clientRegistrations.put(key, + getClientRegistration(key, value, properties.getProvider()))); + return clientRegistrations; + } + + private static ClientRegistration getClientRegistration(String registrationId, + OAuth2ClientProperties.Registration properties, Map providers) { + Builder builder = getBuilderFromIssuerIfPossible(registrationId, properties.getProvider(), providers); + if (builder == null) { + builder = getBuilder(registrationId, properties.getProvider(), providers); + } + PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); + map.from(properties::getClientId).to(builder::clientId); + map.from(properties::getClientSecret).to(builder::clientSecret); + map.from(properties::getClientAuthenticationMethod).as(ClientAuthenticationMethod::new) + .to(builder::clientAuthenticationMethod); + map.from(properties::getAuthorizationGrantType).as(AuthorizationGrantType::new) + .to(builder::authorizationGrantType); + map.from(properties::getRedirectUri).to(builder::redirectUri); + map.from(properties::getScope).as(StringUtils::toStringArray).to(builder::scope); + map.from(properties::getClientName).to(builder::clientName); + return builder.build(); + } + + private static Builder getBuilderFromIssuerIfPossible(String registrationId, String configuredProviderId, + Map providers) { + String providerId = (configuredProviderId != null) ? configuredProviderId : registrationId; + if (providers.containsKey(providerId)) { + Provider provider = providers.get(providerId); + String issuer = provider.getIssuerUri(); + if (issuer != null) { + Builder builder = ClientRegistrations.fromIssuerLocation(issuer).registrationId(registrationId); + return getBuilder(builder, provider); + } + } + return null; + } + + private static Builder getBuilder(String registrationId, String configuredProviderId, + Map providers) { + String providerId = (configuredProviderId != null) ? configuredProviderId : registrationId; + CommonOAuth2Provider provider = getCommonProvider(providerId); + if (provider == null && !providers.containsKey(providerId)) { + throw new IllegalStateException(getErrorMessage(configuredProviderId, registrationId)); + } + Builder builder = (provider != null) ? provider.getBuilder(registrationId) + : ClientRegistration.withRegistrationId(registrationId); + if (providers.containsKey(providerId)) { + return getBuilder(builder, providers.get(providerId)); + } + return builder; + } + + private static String getErrorMessage(String configuredProviderId, String registrationId) { + return ((configuredProviderId != null) ? "Unknown provider ID '" + configuredProviderId + "'" + : "Provider ID must be specified for client registration '" + registrationId + "'"); + } + + private static Builder getBuilder(Builder builder, Provider provider) { + PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); + map.from(provider::getAuthorizationUri).to(builder::authorizationUri); + map.from(provider::getTokenUri).to(builder::tokenUri); + map.from(provider::getUserInfoUri).to(builder::userInfoUri); + map.from(provider::getUserInfoAuthenticationMethod).as(AuthenticationMethod::new) + .to(builder::userInfoAuthenticationMethod); + map.from(provider::getJwkSetUri).to(builder::jwkSetUri); + map.from(provider::getUserNameAttribute).to(builder::userNameAttributeName); + return builder; + } + + private static CommonOAuth2Provider getCommonProvider(String providerId) { + try { + return ApplicationConversionService.getSharedInstance().convert(providerId, CommonOAuth2Provider.class); + } + catch (ConversionException ex) { + return null; + } + } + +} diff --git a/src/main/java/org/springframework/data/redis/cache/RedisCache.java b/src/main/java/org/springframework/data/redis/cache/RedisCache.java new file mode 100644 index 0000000..a742ae7 --- /dev/null +++ b/src/main/java/org/springframework/data/redis/cache/RedisCache.java @@ -0,0 +1,381 @@ +package org.springframework.data.redis.cache; + +import java.lang.reflect.Method; +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.Collection; +import java.util.Map; +import java.util.Map.Entry; +import java.util.StringJoiner; +import java.util.concurrent.Callable; + +import org.springframework.cache.support.AbstractValueAdaptingCache; +import org.springframework.cache.support.NullValue; +import org.springframework.cache.support.SimpleValueWrapper; +import org.springframework.core.convert.ConversionFailedException; +import org.springframework.core.convert.ConversionService; +import org.springframework.core.convert.TypeDescriptor; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.util.ByteUtils; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; +import org.springframework.util.ReflectionUtils; + +/** + * {@link org.springframework.cache.Cache} implementation using for Redis as underlying store. + *

+ * Use {@link RedisCacheManager} to create {@link RedisCache} instances. + * + * @author Christoph Strobl + * @author Mark Paluch + * @see RedisCacheConfiguration + * @see RedisCacheWriter + * @since 2.0 + */ +public class RedisCache extends AbstractValueAdaptingCache { + + private static final byte[] BINARY_NULL_VALUE = RedisSerializer.java().serialize(NullValue.INSTANCE); + + private final String name; + private final RedisCacheWriter cacheWriter; + private final RedisCacheConfiguration cacheConfig; + private final ConversionService conversionService; + + /** + * Create new {@link RedisCache}. + * + * @param name must not be {@literal null}. + * @param cacheWriter must not be {@literal null}. + * @param cacheConfig must not be {@literal null}. + */ + protected RedisCache(String name, RedisCacheWriter cacheWriter, RedisCacheConfiguration cacheConfig) { + + super(cacheConfig.getAllowCacheNullValues()); + + Assert.notNull(name, "Name must not be null!"); + Assert.notNull(cacheWriter, "CacheWriter must not be null!"); + Assert.notNull(cacheConfig, "CacheConfig must not be null!"); + + this.name = name; + this.cacheWriter = cacheWriter; + this.cacheConfig = cacheConfig; + this.conversionService = cacheConfig.getConversionService(); + } + + /* + * (non-Javadoc) + * @see org.springframework.cache.support.AbstractValueAdaptingCache#lookup(java.lang.Object) + */ + @Override + protected Object lookup(Object key) { + + byte[] value = cacheWriter.get(name, createAndConvertCacheKey(key)); + + if (value == null) { + return null; + } + + return deserializeCacheValue(value); + } + + /* + * (non-Javadoc) + * @see org.springframework.cache.Cache#getName() + */ + @Override + public String getName() { + return name; + } + + /* + * (non-Javadoc) + * @see org.springframework.cache.Cache#getNativeCache() + */ + @Override + public RedisCacheWriter getNativeCache() { + return this.cacheWriter; + } + + /* + * (non-Javadoc) + * @see org.springframework.cache.Cache#get(java.lang.Object, java.util.concurrent.Callable) + */ + @Override + @SuppressWarnings("unchecked") + public synchronized T get(Object key, Callable valueLoader) { + + ValueWrapper result = get(key); + + if (result != null) { + return (T) result.get(); + } + + T value = valueFromLoader(key, valueLoader); + put(key, value); + return value; + } + + /* + * (non-Javadoc) + * @see org.springframework.cache.Cache#put(java.lang.Object, java.lang.Object) + */ + @Override + public void put(Object key, @Nullable Object value) { + + Object cacheValue = preProcessCacheValue(value); + + if (!isAllowNullValues() && cacheValue == null) { + + throw new IllegalArgumentException(String.format( + "Cache '%s' does not allow 'null' values. Avoid storing null via '@Cacheable(unless=\"#result == null\")' or configure RedisCache to allow 'null' via RedisCacheConfiguration.", + name)); + } + + cacheWriter.put(name, createAndConvertCacheKey(key), serializeCacheValue(cacheValue), cacheConfig.getTtl()); + } + + /* + * (non-Javadoc) + * @see org.springframework.cache.Cache#putIfAbsent(java.lang.Object, java.lang.Object) + */ + @Override + public ValueWrapper putIfAbsent(Object key, @Nullable Object value) { + + Object cacheValue = preProcessCacheValue(value); + + if (!isAllowNullValues() && cacheValue == null) { + return get(key); + } + + byte[] result = cacheWriter.putIfAbsent(name, createAndConvertCacheKey(key), serializeCacheValue(cacheValue), + cacheConfig.getTtl()); + + if (result == null) { + return null; + } + + return new SimpleValueWrapper(fromStoreValue(deserializeCacheValue(result))); + } + + /* + * (non-Javadoc) + * @see org.springframework.cache.Cache#evict(java.lang.Object) + */ + @Override + public void evict(Object key) { + // 通配符删除 + if (key instanceof String && ((String) key).endsWith("*")) { + byte[] pattern = conversionService.convert(createCacheKey(key), byte[].class); + this.cacheWriter.clean(this.name, pattern); + return ; + } + cacheWriter.remove(name, createAndConvertCacheKey(key)); + } + + /* + * (non-Javadoc) + * @see org.springframework.cache.Cache#clear() + */ + @Override + public void clear() { + + byte[] pattern = conversionService.convert(createCacheKey("*"), byte[].class); + cacheWriter.clean(name, pattern); + } + + /** + * Return the {@link CacheStatistics} snapshot for this cache instance. Statistics are accumulated per cache instance + * and not from the backing Redis data store. + * + * @return statistics object for this {@link RedisCache}. + * @since 2.4 + */ + public CacheStatistics getStatistics() { + return cacheWriter.getCacheStatistics(getName()); + } + + /** + * Reset all statistics counters and gauges for this cache. + * + * @since 2.4 + */ + public void clearStatistics() { + cacheWriter.clearStatistics(getName()); + } + + /** + * Get {@link RedisCacheConfiguration} used. + * + * @return immutable {@link RedisCacheConfiguration}. Never {@literal null}. + */ + public RedisCacheConfiguration getCacheConfiguration() { + return cacheConfig; + } + + /** + * Customization hook called before passing object to + * {@link org.springframework.data.redis.serializer.RedisSerializer}. + * + * @param value can be {@literal null}. + * @return preprocessed value. Can be {@literal null}. + */ + @Nullable + protected Object preProcessCacheValue(@Nullable Object value) { + + if (value != null) { + return value; + } + + return isAllowNullValues() ? NullValue.INSTANCE : null; + } + + /** + * Serialize the key. + * + * @param cacheKey must not be {@literal null}. + * @return never {@literal null}. + */ + protected byte[] serializeCacheKey(String cacheKey) { + return ByteUtils.getBytes(cacheConfig.getKeySerializationPair().write(cacheKey)); + } + + /** + * Serialize the value to cache. + * + * @param value must not be {@literal null}. + * @return never {@literal null}. + */ + protected byte[] serializeCacheValue(Object value) { + + if (isAllowNullValues() && value instanceof NullValue) { + return BINARY_NULL_VALUE; + } + + return ByteUtils.getBytes(cacheConfig.getValueSerializationPair().write(value)); + } + + /** + * Deserialize the given value to the actual cache value. + * + * @param value must not be {@literal null}. + * @return can be {@literal null}. + */ + @Nullable + protected Object deserializeCacheValue(byte[] value) { + + if (isAllowNullValues() && ObjectUtils.nullSafeEquals(value, BINARY_NULL_VALUE)) { + return NullValue.INSTANCE; + } + + return cacheConfig.getValueSerializationPair().read(ByteBuffer.wrap(value)); + } + + /** + * Customization hook for creating cache key before it gets serialized. + * + * @param key will never be {@literal null}. + * @return never {@literal null}. + */ + protected String createCacheKey(Object key) { + + String convertedKey = convertKey(key); + + if (!cacheConfig.usePrefix()) { + return convertedKey; + } + + return prefixCacheKey(convertedKey); + } + + /** + * Convert {@code key} to a {@link String} representation used for cache key creation. + * + * @param key will never be {@literal null}. + * @return never {@literal null}. + * @throws IllegalStateException if {@code key} cannot be converted to {@link String}. + */ + protected String convertKey(Object key) { + + if (key instanceof String) { + return (String) key; + } + + TypeDescriptor source = TypeDescriptor.forObject(key); + + if (conversionService.canConvert(source, TypeDescriptor.valueOf(String.class))) { + try { + return conversionService.convert(key, String.class); + } catch (ConversionFailedException e) { + + // may fail if the given key is a collection + if (isCollectionLikeOrMap(source)) { + return convertCollectionLikeOrMapKey(key, source); + } + + throw e; + } + } + + Method toString = ReflectionUtils.findMethod(key.getClass(), "toString"); + + if (toString != null && !Object.class.equals(toString.getDeclaringClass())) { + return key.toString(); + } + + throw new IllegalStateException(String.format( + "Cannot convert cache key %s to String. Please register a suitable Converter via 'RedisCacheConfiguration.configureKeyConverters(...)' or override '%s.toString()'.", + source, key.getClass().getSimpleName())); + } + + private String convertCollectionLikeOrMapKey(Object key, TypeDescriptor source) { + + if (source.isMap()) { + + StringBuilder target = new StringBuilder("{"); + + for (Entry entry : ((Map) key).entrySet()) { + target.append(convertKey(entry.getKey())).append("=").append(convertKey(entry.getValue())); + } + target.append("}"); + + return target.toString(); + } else if (source.isCollection() || source.isArray()) { + + StringJoiner sj = new StringJoiner(","); + + Collection collection = source.isCollection() ? (Collection) key + : Arrays.asList(ObjectUtils.toObjectArray(key)); + + for (Object val : collection) { + sj.add(convertKey(val)); + } + return "[" + sj.toString() + "]"; + } + + throw new IllegalArgumentException(String.format("Cannot convert cache key %s to String.", key)); + } + + private boolean isCollectionLikeOrMap(TypeDescriptor source) { + return source.isArray() || source.isCollection() || source.isMap(); + } + + private byte[] createAndConvertCacheKey(Object key) { + return serializeCacheKey(createCacheKey(key)); + } + + private String prefixCacheKey(String key) { + + // allow contextual cache names by computing the key prefix on every call. + return cacheConfig.getKeyPrefixFor(name) + key; + } + + private static T valueFromLoader(Object key, Callable valueLoader) { + + try { + return valueLoader.call(); + } catch (Exception e) { + throw new ValueRetrievalException(key, valueLoader, e); + } + } +} diff --git a/src/main/resources/Dockerfile b/src/main/resources/Dockerfile new file mode 100644 index 0000000..6353f75 --- /dev/null +++ b/src/main/resources/Dockerfile @@ -0,0 +1,5 @@ +FROM freshworks/oraclejdk8:latest +VOLUME /tmp +ARG JAR_FILE +COPY ${JAR_FILE} job.jar +ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/job.jar"] \ No newline at end of file diff --git a/src/main/resources/META-INF/spring.factories b/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..e757a32 --- /dev/null +++ b/src/main/resources/META-INF/spring.factories @@ -0,0 +1,5 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ +com.newyetai.common.CommonConfiguration,\ +com.newyetai.codegenerator.config.CodeConfiguration,\ +com.newyetai.frame.redis.config.RedisCacheConfig,\ +com.newyetai.mq.config.RabbitMqConfiguration \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000..3fc3138 --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1,170 @@ +spring.application.name=alita-bjy-uygur + +##数据源 +spring.datasource.url=jdbc:dm://139.159.237.199:5236?schema=BJY_UYGUR_JOB&useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&rewriteBatchedStatements=true&allowMultiQueries=true&useSSL=false +#&useAffectedRows=true +spring.datasource.username=SYSDBA +spring.datasource.password=SYSDBA001 +spring.datasource.driverClassName=dm.jdbc.driver.DmDriver +spring.datasource.type=com.alibaba.druid.pool.DruidDataSource + +# 初始化时建立物理连接的个数 +spring.datasource.druid.initial-size=50 +# 最大连接池数量 +spring.datasource.druid.max-active=500 +# 最小连接池数量 +spring.datasource.druid.min-idle=50 +# 获取连接时最大等待时间,单位毫秒 +spring.datasource.druid.max-wait=60000 +spring.servlet.multipart.max-file-size=20MB +spring.servlet.multipart.max-request-size=20MB +spring.cloud.config.allowOverride=true +spring.cloud.config.overrideNone=true + +# mybatis +mybatis.mapperLocations=classpath*:com/newyetai/**/mapper/*Mapper.xml +mybatis.configuration.map-underscore-to-camel-case=true +pagehelper.helperDialect=oracle +pagehelper.reasonable=true + +#mybatis plus +mybatis-plus.mapper-locations=classpath*:com/newyetai/**/mapper/*.xml +mybatis-plus.configuration.default-enum-type-handler=com.baomidou.mybatisplus.extension.handlers.MybatisEnumTypeHandler +mybatis-plus.type-aliases-package=com.newyetai.**.entity +mybatis-plus.type-enums-package=com.newyetai.**.enums + +### 日志文件 +logging.file.name=/usr/local/logs/${spring.application.name}.log +logging.pattern.console:%d{yyyy/MM/dd-HH:mm:ss} %X{traceId:-} [%thread] %-5level %logger- %msg%n +logging.pattern.file:%d{yyyy/MM/dd-HH:mm:ss} %X{traceId:-} [%thread] %-5level %logger- %msg%n + +### 文件路径 +file.upload-dir=/var/${spring.application.name}/upload +java.io.tmpdir=/var/${spring.application.name}/upload/tmpdir + +#发号器 +#机器id:根据ip自己定义 +code.snowflake.workid.192.168.31.234=23 +code.snowflake.workid.121.37.2.171=1 +code.snowflake.workid.139.159.237.199=2 +code.snowflake.workid.192.168.3.2=4 +code.snowflake.workid.192.168.31.99=5 + +##redis配置 +spring.redis.password=Xinshan888 +spring.redis.host=121.37.2.171 +spring.redis.port=6379 +spring.redis.lettuce.pool.min-idle=2 +spring.redis.lettuce.pool.max-idle=8 +spring.redis.lettuce.pool.max-active=10 +spring.redis.lettuce.pool.max-wait=-1ms +spring.redis.database=12 + +##mongodb +spring.datasource.mongodb.custom.database=alita +spring.datasource.mongodb.custom.host=121.37.2.171 +spring.datasource.mongodb.custom.port=27017 +spring.datasource.mongodb.custom.username=root +spring.datasource.mongodb.custom.password=xinshan888 +spring.datasource.mongodb.custom.authentication-database=admin +spring.datasource.mongodb.custom.connections-per-host=10 +spring.datasource.mongodb.custom.min-connections-per-host=10 + +##mq +spring.rabbitmq.host=121.37.2.171 +spring.rabbitmq.port=5672 +spring.rabbitmq.username=guest +spring.rabbitmq.password=lettuce.co +#开启发送失败返回 +spring.rabbitmq.publisher-returns=true +#开启发送确认 +spring.rabbitmq.publisher-confirms=true +#监听类型,每个consumer都有对应的channel,consumer的线程共享 +spring.rabbitmq.listener.type=direct +#none发送消息后直接确认消息/auto根据消息消费的情况,智能判定消息的确认情况/manual手动确认消息的情况 +spring.rabbitmq.listener.direct.acknowledge-mode=auto +#每个队列消费者数 +spring.rabbitmq.listener.direct.consumers-per-queue=3 +#每个消费者处理未确认消息的最大数量 +spring.rabbitmq.listener.direct.prefetch=100 +spring.rabbitmq.listener.direct.default-requeue-rejected=true +#支持消息的确认与返回 +spring.rabbitmq.template.mandatory=true +#定制化配置 +#exchange名称 +rabbitmq.custom.topicExchangeName=alita_exchange +#指定消息消费者ip +rabbitmq.custom.consumerAppId= + + +security.useLocal=true +security.ignoring=/*.html,/favicon.ico +security.anonymous=/anon/**,/druid/** +security.loginPage=/login.html +security.loginSuccessPage=/ +security.loginH5SuccessPage=/h5/ +security.loginProcessingUrl=/login +security.allowIfAllAbstainDecisions=false +security.domain= +#不记日志路径,contains匹配 +security.notLogs=/district,/dict/lookup,/dict/flush,/anon/dropdown,/anon/user/info,/domain_setting +security.jwt.enable=true +security.jwt.secret=abcdef +security.jwt.expiration=28800 +security.jwt.header=Authorization +security.jwt.iss=${spring.application.name} +#oauth配置 +security.oauth2.enable=false +#oauth配置类型:true使用数据库配置,否则配置文件 +#security.oauth2.usedb=true + + +#websocket配置 +websocket.enable=true + + +# 短信开关 +sms.enable=true +sms.domain=dysmsapi.aliyuncs.com +sms.accessKeyId=LTAI5tLjZrGpoABQNRkJpgA9 +sms.accessSecret=v55nTCjORRbeo4NhQeaccrfXk2LNbe +sms.regionId=default +sms.version=2017-05-25 +# properties中文乱码 +sms.signName=\u4eba\u624d\u56ed +sms.numLimit=300000 +#短信验证码模板配置 +sms.phoneSms=SMS_478425358 + +## 创蓝账号配置 +chuanglan.enable=true +chuanglan.phone=13816929046 +chuanglan.domain=https://api.253.com +chuanglan.appId=BkDWu80l +chuanglan.appSecret=Lvy1s1hu +## 创蓝实名认证(基础二要素)开关、次数配置 +chuanglan.realName2Base.enable=false +chuanglan.realName2Base.url=/open/idcard/id-card-auth +chuanglan.realName2Base.numLimit=1 + +#讯飞配置 +xf.httpAPIPassword=EiORVeNtBjFOcUSKXanT:oIVlTRNhWcEDpksviZaG +#在控制台-我的应用获取 +xf.appId=a2847f13 +xf.apiSecret=ZGYzYjY5N2E2ODJhYzJkZWNjMjBmMWU5 +xf.apiKey=a232b25616c1359d15c30711c1976de6 +#语音听写地址 +xf.iatHostUrl=https://iat-api.xfyun.cn/v2/iat +#语音合成地址 +xf.ttsHostUrl=https://tts-api.xfyun.cn/v2/tts + +#腾讯地图 +tencent.map.key=TS7BZ-GOVCB-CUZUL-JUUAV-WTYT3-Z2B4Z +tencent.map.baseUrl=https://apis.map.qq.com + +#mbti +mbti.urlPrefix=https://udp.szhr.com/szudp/api/mbti/ +mbti.appId=826365121980 +mbti.appKey=jUzDKQKcVHXypG6crhzw + + diff --git a/src/main/resources/config/sensi_words.txt b/src/main/resources/config/sensi_words.txt new file mode 100644 index 0000000..48ce309 --- /dev/null +++ b/src/main/resources/config/sensi_words.txt @@ -0,0 +1,13979 @@ +TMD +毛民进党 +妹妹淫水 流 +机吧 +1989六四 +性爱电影 +李红智 +梁光烈 +成人BT +免注册淫色电影 +UltraSurf +鐵血三國志 +性爱图库 +777黄站 +大龟头顶住嫂嫂的花心深处 +插 穴 射 喷 精液 +兽奸 +PORN +毛可卡因 +阴茎挺进滋润肉洞里在阴户中抽送 +falundafa +三八淫成人网 +发^^轮 +毛江折民 +毛拉登 +免费淫*女A片段 +d7se我淫我电影 +madelove +淫奸美女穴 +美女极品穴 +…快插我淫穴… +玩穴 +lineageⅡ +居然花钱请人教性爱姿势(组图)免费淫电影a片 +肛交 +go-vern-ment +奸你 +四眼醫生強制飲尿 美巨乳小野悠美第二彈 +坤迈 +高嘉 +嫂嫂的穴 +龟头在她的阴道里抽插 +张梅颖 +幼女嫩逼 +meimei的阴蒂 +淫女性息 +强奸35岁处女全过程/淫妹阴毛小穴 +这年头就这样 +阴屄 +酱猪媳 +毛台湾共和国 +陰唇 +淫虎大型色站 +免费淫奸黄色电影a片 +免费强奸淫电影 +幸福花園 +老公,他要插进来了 +9JBW +巨乳美女RINA无码第2弹 +十八电影掰穴特写红免费性视频聊天激情少妇图 +新華內情 +meinv嫩穴 +绝品美女が恍惚颜の绝顶快感 +操逼样 +褻 +日本激情淫穴贴图 +雞吧 阴茎 插 騷穴 嫩穴 小穴 +錢 國 梁 +巨乳 +fuck温总理 +熱血傳奇 +夜色导航 +風騷淫蕩 +麻黃素 +插阿姨的洞洞舔女朋友的下身 +驶你爸 +轮奸做爱高潮录象 +赛你老母 +內射 +李岚清 +芬太尼 +日本妹妹 +fuck生春袋 +rf 行会战争 +fuck手机复制 +法论工 +meimei的小屄好痒 +毛干拎娘 +黄色免费淫乱电影 淫女色情图片 +奸他 +朱狨基 +JPEEN +色情信息 +六岁幼女阴穴近拍 +meimei被操的淫水直流 +私人服务器 +master +希特勒 +猥褻 +马卖马屁 +淫B +激情淫色自拍 +mi zhuan +免费淫奸女A片段试看 教你怎样延迟射精18岁以下禁 +又粗又长的肉棒 +吳 方 城 +胡紧套 +肉棒与阴道摩擦 +韩国成人激情淫洞 +丰满小妹的丰褪美腿 嫩得流水的小meimei +淫妻交换 +政治反对派 +hang hai shi ji +街头对抗靠 +ㄙㄞ你爸 +淫色导航 +淫乱护士电影 +淫乱狂穴 +吗逼 +蒋中国 +暴政 +香港激情淫影院 +坤邁 +抽插18岁处女妹妹淫叫不断 +淫窝窝 +手伸到下体抚mo嫩穴 +fuck宋楚瑜 +砍死你 +混 沌决 +神風~ Kamikaze Street Vol。 13 : 里山加与 +婬乱军团 +紮卡維是英雄 +免费午夜激情视频 +曾慶红 +乱伦之淫穴 +国产嫖娼 +淫液下留 +哥哥用力舒服死我了 +毛你二大爷 +吞精骚妹 +天然むすめ 素人~このみ +小泉純一郎 +色情 网 站 导航 +粉红的的奶头粉嫩的阴唇 +色妹妹淫穴 +操逼电影 +东突,免费淫色情电影 令人喷血的春宫108姿势(组图)18岁禁看 +9之游 +淫b +裸 +操车臣 +装逼呢 +肏meimei的小骚屄 +肉感炮友 +跟妹妹肏穴好舒服 +xi you +反恐委员会 +骡干 +淫液顺着肉棒 +中華民國 +赫鲁晓夫 +狂操小穴 +Tokyo Hot n0252 原田友美 高飞车美人教师精液炸沉 +國產嫖娼 +svdc +小阴唇 黏液流下 舌头舔进阴道 +中華民国 +meinv视频图情色贴图区成人性光牒 +臭机 +毛天安门事件 +聂荣臻 +淫妻交換 +毛人弹 +meimei等你大鸡吧来插 +热站政论网 +免费成人图片 色情meinv做爱meinv小穴写真 +又肥又紧的屄儿 +中國狗 +小穴不断被顶入 +不倫繼母的性猥褻 +龟头在嫂嫂的小穴穴口研磨 +处女被强迫吃春药后被开苞 +毛洪志 +毛淫语连连 +费良勇 +反封鎖技術 +AV女优 激情小电影 熟女俱乐部 +法轮功靠 +熟女人妻 太太自愿拍片被机射在里面 +mo fa qi bing +届中央政治局委员 +夜聊视频聊天室 +发$$纶 +色网阴道特写强奸33岁处女全过程 +淫獸學園 +毛看牌软件 +儿子添着妈妈大的阴唇 +淫穴嫩穴 +插meimei小穴 +午夜性爱惊魂 +操淫荡护士穴 +可视视频聊天 +恼杀美巨乳meinv~吉川萌 +地 下 教 會 +幼男搞幼女 +鸡吧插进肉穴 +紅十字會 +台湾共和国 +红顶商人 +插那吗B +掄功 +激情女优 +稀少罕见的美少女蝴蝶屄 +mm的诱人双峰→免费试看片 +葫蘆案 +情色电影立即看 +免费淫色情电影 教你如何鉴别处男处女的方法(组图)18岁禁看 +asiasex +調教 +插深些 +神經病 +狹義道 +肉棒在小穴深初来回抽动 +鸡巴深深地插在妈的阴户里 +点点激情播放性电影 +侧那 +強淫女優 +我的阴茎使劲的抽插她的小穴 +性愛 圖庫 +死gd +精子 淫穴 淫液 +肉棒插入小穴 +猛地插入了她的肥穴 +毛你姥姥的 +chengmingmag +骚BB免费色电影 +腚眼 +淫痴 +日本成人激情论坛 +文化大革命 +民为法执 +達賴 +三级片A片下载观看 +死gm +白肌meinv?琴也 +激情成人网 -用品 -知识 -保健 +抽插21岁处女meimei淫叫不断 +免费淫色情电影 欢迎点击进入观看/林/心如/20岁处女偷拍/免费A。B片 +免费黄色淫秽电影 +小穴流水meimei手指插 +gameline +六四屠杀 +女優 +小B +日本帝國 +法谪功 +人民真实 +伸到老师的小穴里 +潮姫 史上最高の潮吹き女 +日本帝国 +meimei的小阴户 +辣妹狼图~肏穴图 +含住肉棒上下使劲吸吮起来 +百家性大型免费黄站 +陰囊 +輪攻 +精神病 +王策 +小b +巨额骗储 +毛佳静安定片 +鸟gm +骚屄 +TeSt +激情电影免费下载裸体美女乳房图 +日翻 +美臀嫰穴 +毛王兆国 +小卵泡 +日本成人激情网站 +肉棒 好粗啊…… +情色俱乐部美女奸淫。黄色电影裸体电影PP点点激情电影 +數碼精靈 +迅雷下载免费黄色淫乱电影 +6?4靠 +全裸女优 +達赖 +正悟网 +毛小泉纯一郎 +持不同政见 +鸟gM +淫癡 +台湾淫电影 导航 +外•挂 +www。gpchina。net +春色满园淫妻系列 +删 号靠 +美沙酮 +VIP独占~秘密之大乱交(最终话) +blogbaby +中华民国 +阴道里的大肉棒来回抽插 +操草妈 +helper +毛两腿之间 +中国淫女论坛 +48xp。com 电影免费 +亲哥哥……meimei的小穴……舒服死了…… +美国参考 +中华民國 +看棋软件 +操美女穴 +毛海洛因 +淫女俱乐部 +絲襪足交 +淫荡┅好舒服 +GAMEmaster +陈独秀 +淫水愛液 +农村人乱伦事 +女大学生在夜店被朋友轮奸 +拉案 +总书记 +毛毛一鲜 +火热的精液喷射在子宫上 +肉棒捅进阴户里 +香港色情影星美女裸体 +毛性交 +大人の隠れ汤 乱交游戯温泉へようこそ +因特天盟 +肉具 +司馬義?鉄力瓦爾地 +菊花蕾 +INSERT +騷棒 +恋爱盒子OL +颜骑 +騷棍 +bingnews +耿飙 +近亲相奸 背徳愉悦 9 +耿飚 +护法 +韩国身份证 +法院 +san guo qun ying zhuan +福爾摩薩 +筹码 +免费电影現役看護婦 +泄题 +捅她 +毛日Gm +你她馬的 +G。M +一四我 +肥东交警 +Tsubaki House-Triple Shot Vol01校花三姐妹 +大众真人真事 +航空母舰 +喷尿 +CAO NI MA +窝窝色网之家 +毛刘云山 +毛日GM +第七色明星淫欲 +毛李洪志 +G-M +FLG +空中小姐的淫蕩性生活 +淫肉誘惑 +灯草和尚 +方晓日 +肉棒的抽插…。好爽 +挺动我的下体 +国防科工委 +空降 +大奶美逼 +肉逼 +人學生meimei 埼玉援交 vol。2 なな&まい +玉穴 +搔meimei色站大全 +jiaochun +淫荡meinv医生 +抽插35岁处女妹妹淫叫不断 +我操你 +倒臺 +操浪妻淫女 +插的我好爽 +汉 奸 +妖媚熟母 +極品黑絲 +激情网站地址 +…好舒服 奸淫 操 +賣財富 +星战前夜 +毛泽東 +Tora-Tora-Tora Platinum Vol。9 Runa Mikami +fuck新华内情 +一夜激情成人聊天室 +ming yun +曾慶紅 +免费淫色论坛 +日本情色论坛 +品穴 +黄色免费淫奸电影我和女友干爽后再她meimei +makinglove +making +saobi +日本激情淫电影 +激情电影在线观看 +游戏向导 +老师和我做爱好爽 +阴茎插入肉洞里 +ya dian na +NeoSteam +色mm穴激情 +fuck新唐人 +火辣图片 +阴户紧紧包含着肉棒 +發正念 +淫色贴图365 +奇域 +百戰天蟲 +上有网 +跑跑 +毛李铁映 +小B样 +福摩萨 +私—服 +一卡多号 +桃色电影 +只允许法规年龄的人注册 +淫奸处女电影论坛 +浮夸风 +骚妈 +鸡巴插入花心 +salop +美女淫色贴图区 +处女 +插 9p +pussy +六决不 +淫汁飛散大亂交 +情色 美女 -公安机关 -记者 -犯罪嫌疑人 +處女開包 +白虎阴穴 +淫穴贴吧 +又粗又硬的肉棒 +一党独裁 +毛禁书 +售軟體 +骚女 +插 8p +金正日 +骚妻 +網路創世紀 +發$$倫 +毛昏药 +鸡巴……插死我了 +吴 仪 +商务部 +肉棒插入大肉穴 +狂插阿姨穴 +操的我好爽啊……我又要泄┅┅ +百家性大型色 +插 7p +和meimei肏屄 +遊行 +偷电 +龟头粗壮赤红 +淫荡女医生穴 +官商勾结 +小鸡巴 +插 6p +pp243淫色导航 +foseaon +继母的爱液 +骚妹 +色网阴道特写强奸30岁处女全过程 +中国民主党 +17大 +火药制作 +法仑攻 +明星合成图 +色meimei大型黄站 +中國遊戲中心 +语音激情视频聊天室 +赛福鼎•艾则孜 +(現映社)オバサマ5人 潮吹き絶叫雨あられ! +台湾20岁成人 +媽的B +发**沦 +fuck傻逼 +免费强奸电影 +碩大龜頭緊緊頂著她的阴道 +抽插24岁处女妹妹淫叫不断 +西藏分裂 +56xp。com 电影免费 +邝锦文 +董賤華 +tankbb +毛公安局 +gu long qun xia zhuan +马克思 +午夜成人电影 +penis +群魔色舞 +制服狩 +江Core +千岛湖之旅 +16大 +贛您娘 +大 纪元 +免费淫电影吴宗宪搞笑语录(25禁看) +贱 +六四 +古龍群俠傳 +鮑嶽橋 +打到共产党 +垮臺 +激情淫女小穴 +高潮集錦 +销魂洞 +吃大便 +血腥內幕 +肉唇 +不要将你的精液射进我的小穴了里啊 +罂粟 +吴 官 正 +机八 +台湾獨立 +足球经理 +換妻雜交 +父女姐弟淫乱 +肉棒插入阴户内 +抽插33岁处女meimei淫叫不断 +重题工 +处女心经 +后面插入处女的肉穴 +毛发伦 +小嘴吐出龟头 +監禁陵辱 +大众成人网 +降半旗 +港激情图源成人色情论坛 +長瀨 +支那 +164网址宽频影院网 +毛法轮大法 +儿子的肉棒好大啊 +發^掄 +無碼淫漫 +香港成人淫电影 +众志成城 +G_m +余震 +kamikaze girls 07 Nagisa Sasaki +fils de pute +肉棒嫩逼 +賤 +毛可卡叶 +fuck新闻出版署 +抽插 +肉棒放在阴道口 +打炮 +日穿 +八九民主运动 +靓穴美女 +美骚妇 +fuck信息产业部 +盐酸二乙酰吗啡 +吃鸡巴 +毛烂比 +QQ音速 +媚药少年 +三陪女 +地 下 刊 物 +免费淫乱电影 +胯下呻吟 +阿扁万岁 +欧美淫色贴图网址 +輪暴 +乡巴佬 +轮干 +xing ji jia yuan +免费痴女吸精 +他媽地 +鄧穎超 +93bb成人小电影 +毛新闻出版署 +傻比 +那嗎逼 +亚洲无码 +妓女自拍做爱电影 +嫩肉 穴口 舌头 +和親姐姐作愛 +肉棒在小穴四周游移轻撩 +干meinv小穴 +大鸡巴干进meimei的小穴 +激情色 +楊思敏 +蒙巴顿 +宫泽Keito 超美系模特儿引退作 +suck +车仑女干 +天下無雙 +黑手党 +王鹤寿 +温比 +AV女优和平凡男人1日结婚 +强奸免费淫电影 +遊戲幣 +干八个美女的小穴 +毛对日强硬 +Neko GN Vol。1潮姬 史上最高之潮吹少女 +紅燈區 +易當 +大陆娱乐黄站 +色情导航 排行榜 +fuck +护士mm乱淫 +舔鸡巴 +自残 +玉蒲团讯雷下载 +最新n0242 东热RQ大乱交2007 Part1 +五月天 +嫖妓指南 +抽插30岁处女妹妹淫叫不断 +龟头顶住她的花心深处 +宁王府论坛 +拔出來 +八嘎 +屁精 +裸聊合法 +科技精英遇难 +2逼 老逼 +法棆功 +死GD +paper64 +fuck外/挂 +icpcn +冰风传奇 +梵高 +强奸 小穴 +3P +溫家宝 +淋病 +陽具 +偷情網 +江賊民 +天图 +操草拟妈 +免费淫奸女A片段试看 强*十八岁美女护士 +jy2 +hero108 +死GM +毛拍肩神药 +视频脱衣秀亚洲少女韩国无码片 +干你娘 +操出售手枪 +肉棒插进湿润花蕊 +fuck外-挂 +免费免注册淫电影 +色女 +jx2 +温州娱乐鹿城黄站 +四人幫 +亚洲淫色俱乐部免费淫 +溫家寶 +tie xue san guo zhi +魔性的meinv 鈴木麻奈美 +欣赏7感俏護士和医生22潮淫水图 +糞便 +fuck社。会。正。义。力。量 +淫奸妹妹穴 +龟头在阴唇上抽插 +minhui +免费处女淫女下载看电影性开苞 +插你爺爺 +骑士 +如果你未满29周岁请自觉离开。 +许家屯 +火辣圖片 +用骚痒难捺的阴部淫荡地摩擦着粗壮的鸡巴 +干你妈 +LIUSI +激情裸體 +杨建利 +毛干gm +手记注册日韩5027部激情电影 +毛买卖枪支 +巨乳護士南つかさ20連發中出 +台独靠 +毛你妈逼 +免费dse淫乱 +挥发型迷药 +中央電視臺 +射精时必须注意的几件事 +那嗎錯比 +抽插52岁处女妹妹淫叫不断 +教你怎样延迟射精38岁以下禁免费淫电影a片 +发@@纶 +禽兽集团%少儿禁 +激情淫色贴图导航 +VULVA +张 林 +操鸡 +鸟Gm +日你老母 +毛国家民委 +綠色灵数碼 +江八點 +臀部猛烈的撞击 +輪 +易志熹 +插你爷爷 +懷念十五年前的大學生 +轮奸内射 +李红志 +4f +大龟头顶住她的花心深处 +沾满蜜水又湿又滑柔软的 阴唇 +午夜情色电影 +大卵泡 +64 +老女嫩B +3D西游 +公審江澤民 +淫奸妹妹的屄 +猶太豬 +爽死我了 +小B樣 +鸟GM +共和 +淫电影//现场强奸19岁处女扒开小穴清晰做爱阴道裸体图 +淫穴贴图 +小穴 双手紧抓住 丰臀 +admin +姐姐的肥阴户 +日本激情淫色 +打倒中国共产党 +插入处女的肉穴深处 +成人激情asp电影通道 黄色免费电影 sp色情播放 +3p +俠客天下 +測試員 +淫荡美少女 +张 伟 国 +陈慧琳精品 +你二大爺 +它媽的 +你二大爷 +遊戲新幹線 +10 Little Asians Vol。 14~10人微乳素人娘~ +毛密宗 +露出了娇小鲜嫩的小屄洞 +tian di xuan men +毛色情小电影 +pao pao tang +那嗎瘟比 +嗎啡 +成人激情视频聊天室 +你的小穴好深啊 +免费淫奸女A片段试看 欢迎点击进入观看/林/心如/20岁处女偷拍/免费A。B片 +出售假币 +兒屆中央政治局委員 +毛海洋局 +骑她 +台湾万岁 +毛万税 +毛日gm +kao +14se淫色图片 +插烂meimei小屄 +肥逼 +做爱视频表演黄色小说 +fuck台湾民国 +扑哧一下鸡吧操进了逼里 +哥哥的肉棒好大啊 +Kamikaze Premium Vol。 8 +本土無碼 +毛日gM +无修正 +fantasyjourney +银行账號 +hrichina +躶 +淫水 …你的大肉棒 +Fku +黄色性交裸体图_做爱贴图性交成人贴图 +英雄世紀 +夢見る大和撫子 Pretty Little Asians Vol。48 +不注册免费淫电影 +18岁禁淫荡小处女 +ggol +美女视频图情色贴图区成人性光牒 +96 +出售枪支 +毛干gM +tmd +周锋锁 +中国猪 +鸦片 +激情成人电影 +boke +免费激情视频聊天室 +数码精灵 +罌粟 +女也 +激情淫色游戏 +总统号 +毛新闻管制 +钦本立 +四人帮 +插 4p +淫穴贴图论坛 +粗大的鸡巴穴洞 +操完姐妹操嫂嫂 +国务院 +完美时空 +小嫩穴把大鸡巴包得紧紧的 +龙新民 +足脚交 +注册激情电影 +三八淫 +机叭 +插 5p +十六大 +吗啡碱 +免费mm黄色淫乱电影 +飙车 +又嫩又紧的阴户 +电影下载 +愛的奉獻 +下载免费淫电影 +林心如合成淫照片 林心如淫照片 +淫电影//现场强奸18岁处女扒开小穴清晰做爱阴道裸体图 +香港淫穴裸体图 +苯環利啶 +yuanmingxinsheng +伸入蜜穴 +┅┅手握住我的大肉棒 +踢 +bong +台湾总统 +色网阴道特写强奸21岁处女全过程 +GirlDV热门成人影片 +性虎色网 +插 3p +愛的奉献 +毛狗日的 +怪兽总动员 +本站10018多部激情电影全部免费试看三天 +操黑 +毛司法部 +民政部 +毛丫的 +女乃 +trickster +毛小日本 +肉棒插入阴道里 +操比毛 +半夜我把龟头插进妹妹的深处 +Cs +毛六。四 +林伯渠 +曲线消魂 +爱的乱伦 +乱世三国 +激情淫bb +战国英雄 +bukkake +色屋图片 +未亡人柔肌 +陈军 +鸡巴射出精液  泄了 +毛孙文 +天怒 +斯蒂芬霍金 +黄孟复 +柔软的肉壁紧紧的包著龟头 +網絡公祭 +手淫 +遊戲米果 +脬 +日本成人电影 性生活影片 免费在线成人电影 +旅游局 +本站10002多部激情电影全部免费试看 +肉壶 +免费在线观看 +毛法愣 +X到噴屎尿 +dajiyuan +喪服妻欲望 +日本meimei +肉棒在子宫口游荡 +日本MM色比图吧 +歡迎G11情色電影院 +鄒家華 +無碼h漫 +朱巨 +Baopi +GY +中国论坛 +独裁 +龟头在阴户抽插 +抽插24岁处女meimei淫叫不断 +在线激情电影 +肉棒舌頭 蜜穴 +雙峰微顫 +有容奶大 +李总统 +操你媽 +GP +你的逼……真紧 +GN +GM +金槍不倒 +藤武 +外挂 +劉曉波 +薄码 +斯诺 +鑫诺 +二B +免费女A片段 +免费淫电影吴宗宪搞笑语录(22禁看) +银民吧 +毛肛门 +讨伐 +少女床上春色销魂 +毛麦角酸 +AV +中国人民志愿军 +……好粗…好舒服 +狂插meimei穴 淫水流 +大使官 +sheng da fu weng +岳武 +捏你鸡巴 +NET +tester +美女偷拍成人小说激情网香港激情图源成人色情论坛脱衣美女做愛 +毛届中央政治局委员 +血腥内幕 +把肉茎抽出插入屁眼里 +wu lin wai shi +帶套肛交 +操你娘 +狗诚 +曹庆泽 +美国成人激情网站 +清纯派meinv可爱的让人想狂干她!【RMVB/195MB】 +CS +hdw +黑屄 +臺 +免费A片 +肉壁 +51淫色导航 +jiejie的穴好紧啊 +二b +套子 +三级片 +Bc +欧美大乳 +法稐功 +操参事室 +366成人网站 +fuck色情 +强奸处女学妹 +捅他 +ttwg666 +暴淫 +淫妻浪女小说 +性宝贝淫色导航 +现场直播女主持人教你做爱 +日蛋 +MY +耣 +陈功 +法论攻 +漢奸 +李旺阳 +阴唇 +几叭 +军长发威 +阴茎在阴道快感 +亚洲激情淫色贴图 +大唐豪侠 +中国移动联电信午夜激情电影秘密通道 +風騷欲女 +毛郭伯雄 +一九八九年六月四日 +game master +龟头操进处女阴道 +浪少妇和医生疯狂做爱 +狭义道 +毛干你娘 +可愛均整清純派美女可愛均整清純派美女 +虐待 +自慰抠穴 +fuck王八蛋 +机巴 +屌7 +洞抽少妇 +kang zhan +fuck色情服务 +淫网 +星空幻想 +毛反华 +mo你全身 +毛人民银行 +监管局 +视讯情人聊天室 +自杀指南 +外掛 +免费成人影片 +Gm +肏 +毛二屄 +强*十八岁美女护士看完保证你打飞机免费淫电影a片 +捅你 +手伸到儿媳妇下体抚mo嫩穴 +蜜穴裡輕插緩送 +轮功 +meimei的小嫩穴 +中华讲清 +黑客 +肛 +熟女护士 +唐人互动 +bastard bastard +超级诱人销魂表情免费播放变身辣妹 插入妈妈白嫩的诱惑 +联通移动秘密通道情色电影午夜成人电影 +65情网色论坛色情电影 +歡樂性今宵 +J8 +吹萧 +唐人互動 +JB +谭震林 +毛激情电影 +免费淫奸女片 +流蜜汁 +淫聲浪語 +SM插进湿润的小穴 +盛雪 +猛男狂干美女 +發~掄 +美女裸体在线免费淫电影 +feng yun +肉香 +国家分裂 +欧美激情淫色贴图网 +薄碼 +extremeskate +63xp。com 电影免费 +fawanghuihui +龙与地下城 +毛干你妈 +發*淪 +人斩少女3赤裸忍者 +林慎立 +肉棒插入少妇嫩穴 +又肥又大的阴户 +LB +飄流幻境 +厕所盗摄护士jiejie性感 +毛透视眼镜 +兔meimei贴图区 +日b +高潮集锦 +处女的阴道特别紧 +45xp。com 电影免费 +小乳头 +U R靠 +成人电影,黄色电影,色情电影,免费电影试看 +花花公子 +警奴 +朱总理 +偷窥图片 +风骚少妇 +残忍老爸玩我小穴 +UR +本站10010多部激情电影全部免费试看三天 +百家性大型黄色站 +抗曰 +FLG媽B發掄 +免费激情聊天室 +少妇房中自淫,和两勇男玩5P,操得直叫爽 操日本淫女穴 +茎 +朱德 +incest +淫亂熟女 +國家總理 +注册激情电影(切记只允许法规年龄的人注册)注册快感吧!! +里根 +TW +金城安娜-痴女教官NO。7 +犯践 +黃色小說 +强奸轮奸美女视频 +Wg +毛干GM +…好舒服…小穴 +粉嫩人妻在老公面前被人搞 +狂插日韩骚逼打飞机必看 +魔法飞球 +郭 平 +国外激情淫色贴图 +奸淫女老师 +发**抡 +犯踐 +亚洲午夜激情那个电影中心 +老毛 +WG +老比 +高岗 +悠遊網 +發$淪 +毛干Gm +李山 +毛基督教 +淫妹阴毛小穴 +草 +老母 +性电影免费在线试看 +清华同方 +毛江独裁 +妹妹被操的淫水直流 +本?拉登 +奶头 +99BBS +嫩穴美女挖嫩穴淫女嫩穴俱乐部 +黄色免费淫乱电影 +亚洲情色套图 +就去日 +fuck外汇局 +日Gm +遇难 +操淫荡meimei穴 +牛顿 +曰本 +激情淫电影 +QB +遇難 +tian zhi lian yu +美女嫩穴 妹穴 亮穴 女人穴 +阿不來提•阿不都熱西提 +肏又大又嫩的屄儿 +j8靠 +日本淫色 +毛乳房 +日GM +huan le qian shui ting +保釣 +肉棒插入小阴户内 +pnisse +【亚洲/无码】Mugen Vol。11 Ai Hazawa羽沢愛!【AVI/ 699MB】 +魔法飛球 +骚妇激情 +我含住他的阴茎 +SM舔穴 +天安门事件 +本站10021多部激情电影全部免费试看 +做爱网有激情自拍裸体 +奸淫电影 +jinyong +监听器 +肛门潮吹 极太合体 原千寻 红音 桜田 +meimei做爱 +百家性大型色站 +西藏独 +成人激情网站 +硬挺 +po tian yi jian +殺你一家 +Sb +色情成人网站 +臺灣島國 +天安門殘案 +allbisexual。com +扮开嫩穴 +SM +婷婷口含鸡巴 +十八代 +搔meimei黄站 +日本成人 +龍圖智庫 +毛反动 +SB +倡议书 +股市民谣 +可待因 +现场强奸18岁处女扒开小穴清晰做爱阴道裸体图 +亚洲成人贴图区论坛 +fuck我妳老爸 +肉棒抵住阴唇 插入 +?(SOD)超天然素材 桐島あゆみ +舌战法庭 +極品波霸 +色97愛 +ERA OF FAITH +给你爽 +周容重 +喪服妻欲望下载 +奸她 +犯賤 +轉法輪 +抗日 +吳 百 益 +退黨 +你它媽的 +毛反共 +发轮 +jiejie的肥阴唇 +gth +49xp。com 电影免费 +午夜成人激情聊天室 +湿淋淋的骚阴道 +毛人大 +大陆娱乐鹿城黄站 +她妈 +snk。ni8。net +苯环已呱啶 +姐姐的嫩阴唇 +摇头玩 +冈峦 +毛口交 +秦青的幸福生活 +亚洲激情无码BT +阴囊 +毛文物局 +赵紫阳 +激情淫色贴图区 +張德江 +肛门 +肉棒用力的抽插着小阴唇 +射进妈妈里面 +成人情色网站 +免费在线黄色小电影 +163网址宽频影院网 +鬼公 +TokyoHot之极品meimei +ㄙㄞ你母 +奶娘 +激情玩穴电影 +苏绍智 +阎安 +错B +肛門 +黑窑奴役 +性爱护士 +泡泡堂 +操臭化西 +ZD +免费淫乱电影下载 +粗大的龟头缓缓磨擦着湿漉漉的阴户 +告全体网民书 +saohuo +在骚穴里抽插著阳具 +urTNND +luan shi san guo +d p p +the world of legend +回良玉 +两会新闻 +銀行帳號 +掌上靈通 +错b +老师的阴道好紧 +免费看三级电影淫电影 +她娘 +在线小淫虫电影 +淫之学妹喷尿射得好高 +1989年6月4日 +毛江猪 +pp点点通 +法伦功 +切七 +哲民 +护士小穴 空姐小穴 +QQ堂 +昏药 +saohuao +操 淫荡 好爽 +meinv主持26小时全天激情热舞 +公务员的工资 +奸夫淫妇 +淫糜 +妹妹的阴户 +喷 射 +免费淫 电影a片。母子淫奸乱轮现场 +強制フェラ 失神セックス +沒有人權 +烏雲其木格 +game MASTER +玉女吹箫的姿势和技巧图 +丁香大型成人社区 +緊縛淩辱 +人性本色 +政治局 +日本淫电影 +蒋树声 +遊戲發獎員 +母子姦情 +鲍威尔 +fuck退党 +日B +龙洲影院日本娱乐性免费电影 +紧缚凌辱 +妳马的 +AVW FUCK DOWN!最后性 +日你奶奶 +亚洲区人妖射精图最淫人体网站 +fuck驶你娘 +代表大会 +集團熟痴女川奈-南智子-澤宮有希-櫻田由加里4時間 +gM +装B靠 +独占动画~女热大陆 file 2 +駛你娘 +fuck系统公告 +她馬的 +日你爺爺 +gy +天使之恋 +qiangjian +蒋经国 +操妳祖宗 +gn +gm +heatproject +军妓 +臺湾國 +大鸡吧插妹妹 +阴唇阴道 +blowjobs +耶和華 +奶大穴肥多条肉棒难满足 +瞿秋白 +gp +dong fang chuan shuo +saga +藏春阁【全免费】 +发^^论 +JOB +無碼H漫 +yong bing chuan shuo +中国政府 +用舌头舔着大小阴唇 +他妈的靠 +meinv嫩穴淫水直流 +你奶奶 +dao jian +fuck系统 +毛私-服 +省長 +g8 +平可夫 +肏屄 +老骚货 +包二奶 +operator +国产骚货 +内射 +搔穴自慰 +项小吉 +那娘老比 +白虎陰穴 +夢城互動 +淫电影//教你如何鉴别处男处女的方法 +浴室自拍 +凌辱?妥?学?@~??Δ畏耪n後~ +gamemaste +meteor academy +黑马@SQ Evolution Vol。3 柳濑遥 +日你爷爷 +拉客 +cS +bt +反封锁技术 +集體淫 +流口水啦 +lovebox +六四点击 +亚洲淫色贴图论坛 +18摸 +弟弟淫奸姐姐 +肉棒 高潮 +郝建秀 +毛农业部 +毛塞你公 +騷浪 +杨勇 +毛私/服 +日本激情淫色视屏 +cs +王稼祥 +毛色情 +1001an。com +臭化西 +K粉 +藏独 +法仑工 +抽插46岁处女妹妹淫叫不断 +成人bt +膀胱 +jiaochun +学运 +毛国安局 +抽插47岁处女meimei淫叫不断 +淫奸小姨子穴 +da hua chun qiu +毛虐待 +fuck十五周年 +刘晓竹 +失密 +歡樂時代 +射精 +毛阴部 +不爽不要錢 +爱爱激情电影 +穷逼 +干阿姨小穴 +卖骚 +肉棒插入阿姨 ……爽呀 +傻瓜 +几八 +发论 +水从穴里流出来 +奇淫寶鑒 +jinv +做爱淫乱小说 +军委 +毛粮食局 +我和二姨在车上舔 +痴女護士 +厕所盗摄meinv淫穴 +嗎個 +色网址联盟 +抽插婷婷 +时事论坛 +meinv小穴贴图偷拍少女乳房 +賽博先鋒 +BT淫穴 +毛一贯道 +東升 +尚禾 +港澳办 +韩国激情淫色网站 +Mai骚 +身寸米青 +法$$仑 +操妹妹湿穴 +性高潮 +轻轻地抽插著阳具 +插嫩穴 +婷婷激情俱乐部导航 +葵 +关卓中 +鹿城黄站百家性 +毛乳波臀浪 +胴体 +色网阴道特写强奸25岁处女全过程 +小姨子她饱满乳峰上的粉红乳晕 +蝴蝶谷淫图片 +国家领导人 +Reign Of Tera 2 +美穴 +文 革 +新人×ギリギ 七海 +萋 +阿姨的大阴唇 +出墙红杏 +playboy +胸部 +奴隷调教 +我的淫荡老师 +顶级轮奸套图站 +操穴插逼 +藏獨 +免費性愛電影 +阴唇上摩擦着 +凯丰 +久之游 +想插穿她那肥嫩的小骚屄儿 +淫穴自拍 +摸你全身 +陈云 +發@@掄 +戳比 +国民政府 +遺言 +龟头顶住她的阴户 +日本淫荡meimei +item +T。M。D靠 +聖戰 +文九天 +现代情色小说 +梅花网 +jx +婷婷俱乐部 +抽插41岁处女妹妹淫叫不断 +草枝麻 +阳具 +我 操 穴 +毛六四真相 +欢乐性今宵 +杨思敏 +和姐姐淫穴 +老江 +吗啡片 +黄色我该死免费淫奸a片偷拍MM接客宾馆 +超女世界Online +GAMEMASTE +洗钱 +orgasmus +黄蓉舔小龙女的乳头 +色情網站 +叔嫂肉欲 +塞白 +眯眯爱大型黄站 +妹妹陰毛 +色淫成人 +小穴 +成人色情 +大师 +押小 +夜夜色娱乐网 +大肉棒…插我……」 +春城娱乐(淫窝) +骚批 +挺送 肉棒 激烈 撞击 +反社会 +法$$伦 +j8 +肛jiao +抽插著阿姨的淫穴 +免费淫女在线看电影 +中国军用运输机 +機戰 +操逼毛 +jiejie的阴道好紧啊 +肉棒不斷的抽插著她的肉體阴道口 +免注册淫电影 +淫荡少妇被轮奸 +天安門一代 +onlineworms +李师付 +狂插喷爱液 +八九學潮 +jb +赛博先锋 +meng xiang +毛天安门录像带 +張万年 +肉棒插进阴户里 +h站 +干死客服 +不爽不要钱 +日gM +美女淫水狂流 +淫穢 +做爱电影 +免费淫奸女A片段试看 强*十八岁meinv护士看完保证你打飞机 +Test +meinv 淫穴 +peng peng bang +毛鸦片液 +%共產黨爛逼 +丰盈雪白的肌肤、肥嫩饱满的乳房、红晕鲜嫩的小奶头 +wg +完美時空 +黄色文学 +鸡吧插进 +65xp。com 电影免费 +jiba +蘋果日報 +淫穴 +免费成人电影图片 +抽插34岁处女meimei淫叫不断 +臺灣 +新闻办 +官人我要 +大鸡吧插meimei +喷你 +騷水 +wG +meinv鸡吧图 +操母狗 +日本巨乳淫女 +現場直播~女主持人教你做愛 +fuck新手指导员 +天使之戀 +台湾18成人小说 免费成人电影 +王宝森 +賣軟體 +視娘辣妹 +毛妓院 +骚妇掰B +超级乐者 +战牌 +ur +轮大 +江湖 淫娘 +yuming +法$$侖 +鸡歪 +tw +教你怎样延迟射精39岁以下禁免费淫电影a片 +仙境传说 +毛鸦片渣 +不玩了 +骚妇掰b +免费A片观看 +小穴被插的好爽啊 +毛换妻 +和妹妹肏穴 +成人情色导航 +阴户抽插 +抽插34岁处女妹妹淫叫不断 +鲍鱼 +现代学生妹操屄水平真是高 +我上小姨子小说 +拔屄 +唐捷 +阴道抽搐一阵暖流自子宫深处涌向龟头 +抽插21岁处女妹妹淫叫不断 +聚友网络 +sm +淫秽 +拉法叶舰 +sf +观看淫电影 +新疆国 +國家分裂 +梓霖 +sb +小女嫩穴 +把舌头伸入jiejie的 +林伟 +新疆國 +墮淫 +日本素人 +午夜激情美穴贴台湾性福联盟 +手记注册日韩5006部激情电影 +全國人大 +蘇秀文 +诛仙 +毛信息产业部 +毛四川独立 +ri +再奸 +法惀功 +發@淪 +爽女美图美搜性感图涩界成人电影网小小鸟绝色meinv写真图 +lisishijian +轮奸 +毛透视软件 +國民黨 +色慾 +杨周 +何加栋 +肛屄 +肉便器 +屁眼 +毛罗 干 +金发表姨花蕊,少女的狭窄洞口 +System +全身一阵颤抖 大鸡巴 +fuck小肉粒 +騷母 +日gm +淫女乱搞免费三级片 +伸入jiejie裙内 +騷比 +qb +archlord +毛台办 +法$$倫 +毛恶搞晚会 +法囵功 +强奸23岁处女全过程/*妹阴毛小穴 +天安门残案 +大雞巴 +二奶大奖赛 +毛阴道 +李师傅 +色情 +dick吕秀莲 +配合着蜜洞内肉棒的抽插 +我咧干 +恐怖主義 +五月天成人激情网站 +xia yi dao +mannweib +fuck新华社 +獨立 +毛敬国神社 +干x娘 +又大又粗的肉棒 +又深又紧的穴 +抗战 +奸杀美女大学生 +fuck我操你 +毛他妈 +抗戰 +顶进少妇的花心 +疯狂的抽插起来 +makinglove +搶 糧 記 +大麻树脂 +每天24小时循环更新的免费色情内容 +rxjhwg +激情免费电影 +大鸡巴插进她肉洞里 +騷洞 +51xp。com 电影免费 +成人小说 SM 做爱 +肉棒顶的人家小穴好痒 +乱伦之淫骚穴 +操你妈 +传奇3G +netbar +傅鐵山 +姜春云 +招妓 +口含鸡巴 插入阴道 +噗嗤一声滑入阴道 +浩天银科 +窃听器材 +tantra +操陈晓宁 +群奸輪射 +色meimei淫穴 +宋慶齡 +女添男精狂射图 +免费淫色情电影 教你怎样延迟射精18岁以下禁免费淫电影a片 +hun +手记注册日韩5032部激情电影 +达芬奇 +宏象 +六四回忆录 +洪哲胜 +淫荡娇妻打开双腿 +奧巴馬 +夜情 +毛林彪 +抽插54岁处女meimei淫叫不断 +我把艳姨给干了 +tiang tang +口含龟头 +神出鬼没!3个丁字裤辣妹到处袭击肉棒(中文字幕) +妹妹的小穴……舒服死了…… +夫妻多p +caob +肉棒噗嗤一声滑入阴道 +亚洲免费黄网 +阴茎插入少妇阴道 +点击这里试看美女做爱现场 +日本淫穴电影 +成人影院 激情影院 +电视流氓 +香港激情图源成人色情论坛脱衣meinv做愛 +喇嘛 +體奸 +u r靠 +game MASTER +海盗时代 +我和姨在车上干 +赌马 +性生活 +威而柔 +免费淫奸女A片段试看 处女第一次阴道做爱全过程(全套图片) +heatproject +日你爸 +法十轮十功 +大鸡巴插进小穴 +毛你老味 +梅花網 +海明威 +kuaik +混蛋神风流史 +做爱视频 +fuck台办 +无码淫女 +审计署 +教室里淫乱狂搞 +pute +初流出!ロリプリ +人美乳甜屄嫩操起来真爽 +性交内射 +操大逼 +发~~纶 +GC365 +麻醉乙醚 +毛十年动乱 +默哀 +夜色聊人 +处女第一次阴道做爱全过程(全套图片)免费淫电影a片 +鑫諾 +毛血腥图片 +自焚 +62xp。com 电影免费 +毛片空姐的嫩穴裸体明星夜总会小姐贴图 +rxjh +Crazy Fuck : Miki Uehara 上原美纪 +MK 星云 +操逼 +吹簫 +免费淫奸女A片 +an hei zhi men +情色聊天室 +淫奸医生 +vrtank +系統消息 +联易 +希望之声 +淫电影//现场强奸20岁处女扒开小穴清晰做爱阴道裸体图 +GAME master  +断电 +廉政大论坛 +性感meinv淫穴 +经济社会理事会 +成人性交视频 +毛回教 +追查國際 +騷媽 +小唇被他的嘴巴包裹住 +105bb成人小电影 +骚乳 +san guo ce +性戰擂臺 +淫奸女电影直接试看 +删号靠 +性交图 +插的妹妹好爽啊 +性交圖 +發^侖 +voachinese +一夜性网 +露乳 +洪 传 +meng huan zhi xing +淫电影论坛 +凱圖科技 +儿子顶到妈妈的花心 +法仑功 +淫奸meimei电影 +rivals +互友财富 +輪功 +人體攝影 +处女第一次阴道做爱全过程(全套图片) +luan +严家祺 +子宫口吮吸着龟头 +fuck新闻办 +回民人吃猪肉 +吸精 +fuck卫生部 +淫色网站导航 +淫蜜 +小泉纯一郎 +齊藤亞樹 +参事室 +毛反政府 +乱伦之淫穴网 +又粗又长的大肉棒 +泳衣+丝袜~让你销魂舒畅 +免费电影吸精痴女 +短信猫 +大 参 考 +强奸22岁处女全过程/*妹阴毛小穴 +未满19岁的请自行离开 ! +总统的讲话 +淫奸jiejie电影 +痴女/淫乱 看護婦/女医 剃毛/パイパン!【AVI/723MB】 +姐姐的小穴 +情色BT +fag +kang zhan +张榕明 +發論 +洗肠射尿 +品色永远免费淫电影 +赤裸 +他嗎的 +射顏 +激情视频女半夜播放成人节目免费裸体视频 +林心如做爱网有激情自拍裸体图片 +脚交 +淫奸电影 淫色猎暴淫电影 射雕淫女传 风骚小龙女 美女淫女图-小龙女淫女俱乐部影 在线淫电影 +仙侶奇緣 +北美自由论坛 +英雄online +删 号 +发@@论 +毛干死你 +兩國論 +放荡 +狂插 肥穴 +淫奸小姨论坛 +检察院 +啊……快插啊……小屄要美死了…… +射颜 +争鸣论坛 +公务员工资 +充值 +小姨子她饱满乳峰上的粉红乳晕,金发表姨花蕊 +meimei的淫穴被龟头顶住 +发抡功 +免费注册看免费电影通道 +傅杰 +毛反封锁技术 +penis +掰开少女穴 +肉丝裤袜 +黄易群侠传 +你妈比 +阴沟 +舔我的龟头 +騷妹 +大鸡巴插进妹妹的小穴 +騷妻 +骑他 +大鸡吧插妹妹淫屄 +張 偉 國 +Angel Cosplay Vol。 2 新村爱加贺美由贵 +Tora-Tora Platinum Vol。8 宫泽Keito 完全无修正第二弹 +滕武 +發^倫 +18岁少女破处 +Red Hot Jam Vol。6 露出初体验~Chia +插後庭 +毛伊拉克 +U R靠 +非常漂亮的日本美少女,日起火! +阴水 +欠日 +胡嘉 +50xp。com 电影免费 +騷女 +鹿城大型黄站 +毛老毛子 +龟头用里插入阴道 +装逼 +re xue jiang hu +抢尸 +娄义 +大鸡巴顶进妹妹的花心 +他娘的 +肖强 +押大 +毛侨办 +免费淫电影a片 +淫蟲 +早洩 +屄屄特寫 +賣騷 +成人贴图区 +好大的阴户 +李维汉 +裸体插淫穴 +淫驴屯 +免费淫电影吴宗宪搞笑语录(28禁看) +武力统一 +欧美清晰打炮淫乱人妖淫乱图 +shemale +rxwg +gameMASTER +吹箫 +解放军镇压 +三国群英传 +發$$掄 +猛插小护士骚穴 +奸幼 +preteen sex preteen sex +long zu +曹建明 +李红痔 +CAO +穿著PE校服 +成人夜话 +法仑共 +骑你 +法仑公 +共青团员 +砍翻一条街 +aszol +免费淫奸女A片段试看 瞄準她的肉穴插了進去…… +免费成人图片 +放蕩少婦賓館 +gamemy +中国最淫的免费淫图图 +毛天安门一代 +滚那吗老比 +顺着大鸡巴湿淋淋的流下 +媽的騷穴被你插得爽死了 +a片 +清晰內射 +工作人员 +激情玩淫穴电影 +亚洲乱伦之淫穴 +妹妹吸精 +国内动态清样 +骚B贱 +6。4 +贱逼 +阴毛 +浴室乱伦 +毛廁洞 +酥穴 +东热RQ大乱交2007 +舌头舔弄着小穴的内壁 +成人網站 +亚洲互动 +情色艺术天空 +激情淫色下载 +江口美貴 桃咲あい 早乙女みなき 雨宮せつな +欧美成人贴图区 +骚 +黑鲍娇 +插入小姐的嫩穴 +追查国际 +成人色情图片 +台湾成人激情视频聊天室 +免费午夜艳情电影 +欠操 +淫奸………啊 好舒服 +肉慾 +毛伊朗 +抗震救灾 +互舔淫穴 +大比 +抗震救災 +狂插少女的嫩bb +guild wars +潮喷 +我和妹妹肏穴 +陰核 +出售此号靠 +賀龍 +和婶婶做爱 +香港免费黄色淫乱电影 +草擬媽 +淫奸jiejie穴 +eve +毛乳 +無碼長片 +少妇房中自淫,和两勇男玩15P,操得直叫爽 操日本淫女穴 +发~轮 +幹你妈逼 +日本黄色三级短片 +少妇贴图穴论坛 欧美淫色贴图区 +舌头舔着阴核 +强奸17岁少女全过程 +性爱 电影 +午夜免费视频激情聊天室 +fuck外专局 +马凯 +毛基地组织 +……好舒服 舔穴 +教你怎样延迟射精34岁以下禁免费淫电影a片 +干他 +女幹三虧 +中国之春 +超美女优MUGEN EX Vol。 7~浜崎ひめ +transsexuell +發@@綸 +騒 +明星裸体写真图 美女网络视讯三点 +搶劫犯 +法~轮 +淫妻爱好者 +盐酸二乙醯吗啡 +杨怀安 +法$$沦 +大陆免费黄站 +新语丝 +抽头 +毛新疆独立 +騷 +免费淫电影下载地址 +风骚小阿姨 -新闻 +事实独立 +欧美激情穴淫奸 +日本女优 +曹你 +芸能人使い捨てM奴隷DX 聖乃マリア nike 新片! +斑竹 +星際家園 +性奴會 +淫奸meimei论坛 +超爽艳图 +liu xing hu die jian +阎王 +美女视频短片 +臺獨 +法~輪 +毛姣西 +残忍的虐待强奸美丽的淑女 +釋迦牟尼 +放蕩 +洪 傳 +黑社會 +压迫 +联梦 +adult +淫蕩 +母乳と巨乳と淫乱の完熟物語 +那吗错比 +扬振 +潮噴 +干X娘 +fuck私服 +强硬发言 +肉棒插入少妇的阴户内 +台湾青年独立联盟 +温 元 凯 +朱勝文 +肉棍狂插 阴精 +哥哥淫奸妹妹论坛 +法菕功 +干你 +18男人momoB +抽插25岁处女meimei淫叫不断 +践踏中国女性 +輪奸大美女 +龟头通过子宫口直抵花心 +金玉天立 +抢劫犯 +肉棒插入阴道 + 瀬咲るな +g。m +毛叫小姐 +meinv嫩穴 妹穴 亮穴 女人穴 +北极冰 +誘姦 +mabinogi +嫵媚挑逗 +meinv与猪性交电影 +水滸Q傳 +亚洲成人激情淫穴 +暗黑之门 +妹妹小穴 +淫奸姐姐论坛 +【亚洲/无码】【极品荡女-宝乃ありか 完結版!】【WMV/358MB】 +幹他 +夜色淫女导航 +嫩穴 狂 插 +操操你 +效忠天皇 +抽插小淫穴 +迷幻藥 +大鸡吧顶进小穴 +少妇房中自淫,和两勇男玩6P,操得直叫爽 操日本淫女穴 +淫妹妹成人情色论坛 +毛连战 +舔吮 乳房 干小穴 +幹您娘 +曰你 +開苞 +吞精 +情色成人视频聊天室 +韩国激情淫色贴图 +pk1937 +淫獣圣戦 XX+圣獣伝 ツインドールズ +肉棒插入meimei的肉缝 +本站10016多部激情电影全部免费试看 +毛洪兴 +去氧麻黄堿或安非他命 +斷电 +毛靖国神社 +紫瑞专业 +毛民政部 +大胆少女 +毛生鸦片 +妳娘 +武林群俠傳 +矽穀動力 +计生委 +张伯笠 +淫荡女生 +地球文明 +淫驢屯 +嫩穴meinv挖嫩穴淫女嫩穴俱乐部 +老瘪三 +和阿姨做爱 +一党专制 +操淫荡少妇穴 操淫荡妹妹穴 操淫荡姐姐穴 +和jiejie肏屄 +美腿 +幼交 +陈毅 +Offgamers +插入姐姐蜜穴 +聚梦 +掌上灵通 +错逼 +淫穴摩擦龟头 +fuck骚 +新华内情 +我就色 +雞女 +操操他 +大鸡巴┅┅太棒了 +笨逼 +淫meimei成人情色论坛 +银行帳号 +鸡巴蜜穴高潮 +雞奸 +毛人民广场 +換妻大會 +亚洲激情影院论坛 +淫虫 +六四屠城 +江油余震 +幹的爽 +我妳老爸 +阿沛 +歡樂潛水艇 +百家性超级淫色图片 +操穴贴图 +淫虐 +张廷发 +免费a片日本淫电影 +被干的喷水的高清图 +刀OL +打砸抢 +牛逼 +我的性启蒙老师 +毛XX +淫色电影网站  +毛推油 +奸情 +滝沢优季 Prisoner Of Love绝爱的监禁牢狱 +…用力干…嫩穴紧插 +东北风情熟女之惑 +阴唇湿润小妹舔乳 +破处 +granado +付申奇 +毛卖党求荣 +大 參 考 +meinv潮吹 +盛华仁 +毛社会主义 +阴穴新玩法 +台湾自由联盟 +fuck孙文 +操淫荡护士 +傻屄 +中国分裂 +淫民激情文学图库专题 +奥巴马 +法**倫 +抽动肉 +現金交易 +超级淫图 +發~侖 +16dy-圖庫 +小穴流出汁液 +毛石进 +screw +老癟三 +陰戶 +日本激情图库脱衣裸体做爱 +手伸到儿媳妇下体抚摸嫩穴 +淫民俱乐部日韩激情片 +情色导航 激情爽电 +調理勞務系 +激情视频在线 +淫妹妹电影论坛 +被奸淫的女教師 +巨乳俏女醫 +ggq +免费淫区隐蔽入口 +雅典娜 +大中华论坛 +深夜進入少女家中玩強奸 +meinv性交极品大片 +玉蒲团玉女心经 +vip在线成人电影 +*法*轮*功* +qq音速 +星蓝妹妹 +fuck洗脑班 +發~倫 +军事委员会 +色中色网址大全 +淫荡 +TABLE +雞吧 +gamegold +想上你 +拉凳 +李金華 +minghui +神話R。Y。L +五星紅旗 +yifeng +18歲淫亂 +迷幻药 +法**侖 +小穴被我操的红肿 +肉棒肉洞 肉缝 +代链 +人民大會堂 +毛强奸 +车仑 +毛烂屌 +日本淫色动画贴图 +巨奶 +好嫩 +女尔 +鰢 +SM援交 +www。ccwcc。cn +溫比 +多维网 +潮吹 +激情在线 +蔣中正 +大肉棍… …干的 …好舒服 +偷情男女 +后面插入处女肉穴深处 +你娘卡好 +laqia +女尻 +情色天堂论坛咪咪情色论坛 +Arisa Kumada +鹿城黄站bt +快活林情色网 +入穴一遊 +淫水翻腾 +激情淫影片 +367成人网站 +女屄 +毛烂屄 + 夏树唯 +混沌诀 +gcd +毛鸡叭 +淫荡的小穴 +阴核 +dh315 +meimei黄站 +*李*洪*志*靠 +淫奸妹妹电影论坛 +色欲 +啊无卵 +酥痒 +蒂巴因 +磨得人家小穴……好用力……好酥 +弟弟淫奸jiejie穴 +免费在线收看淫色电影 +肏又紧又嫩的穴 +美女走光 +日你老娘 +Tokyo Neko ATN-002 東京猫 Vol。 2 星川はるか +官人我要2 +做爱图 +法**伦 +毛私服 +拉手冲 +清晰内射 +干你妈B +台聯 +饿比 +免费a片 +gay +台联 +流星蝴蝶劍 +乱伦熟女网 +叶群 +中国游戏中心 +母亲の结婚生活完全版 +cheng ji si han +17岁处女小阴唇张开 淫水流出图强奸免费淫电影 +無修正 +陷阱超人嘩嘩曼 +雞叭 +大卵子 +奶子 +毛宋楚瑜 +法**仑 +龟头已顺利挣开她紧合的阴唇 +大纪园 +处女穴 阴唇 肉缝 +做爱自拍 +毛毛贼东 +龟儿子 +机机歪歪 +毛破鞋 +吸吮着红嫩的乳头 +月经不调 +shengda +来回去舐她的小穴 +官人我要1 +kele8 +小卵子 +売春婦 +情感视频欣赏 +宋美齡 +社会主义 +毛meimei淫色 +bjzc +法黁功 +舌尖不断在肉缝里上下舔着 +激情论坛 +駛你爸 +性爱图片 +亚洲激情淫洞 +紅衛兵 +欲火焚身 +酥癢 +绵阳 +fuck驶你爸 +肉棒触碰前面的肉穴 +幹死客服 +火辣寫真 +妹妹的淫穴被龟头顶住 +宋美龄 +毛外交部 +jiejie的小穴 +毛毛厕洞 +严方军 +金毛学生妹 +封神傳說 +林心如做爱网有激情自拍裸体 +苯甲基芽子堿 +女优爽图 +乱伦淫穴 +干你妈b +学生爱国运动正名 +舌头伸到妈妈的小穴里 +yuanming喷你 +妹妹阴毛 +和熟睡的妹妹做爱教你一手 +中廣網 +激情淫色电视 +毛日本RING +淫奸小姨子电影 +segame +美女性生活贴图 +马三家 +热 站 政 论 网 +鸟g M +看牌軟體 +生奸内射 +調教虐待 +毛晚年周恩来 +日本激情片论坛 +妹妹的嫩屄 +一九八九六四 +猪容基 +气性坏疽病 +毛塞你娘 +操陈希同 +流星蝴蝶剑 +激情淫穴小妹 +换妻杂交 +戳那吗比 +胸垫 +阿姨和我乱伦理小说 +舌头舔小肉縫 +南蛮子 +张筱雨 +不良詞語@美乳女神RINA(中文字幕) +毛温加宝 +姐姐的嫩穴 mm嫩穴 +fuck上妳 +鸡巴受不了了┅┅喔┅┅好爽┅┅我要泄了┅┅ +近亲相奸 +插淫女小穴 +你老母的 +香港情色俱乐部 +毛温总理 +創意鷹翔 +戴晶 +李 总 统 +激情視頻 +群奸乱交 +钱 国 梁 +國家主席 +日本成人淫色DVD +fvc +聖母 +口肯 +无码精选 +电车之狼 +Shine +大陆黄网导航 +qq自由幻想 +naked naked +绵陽 +鸦片渣 +你全家 +卢福坦 +a片试看 +fy0 +18dy粉红色高跟鞋 +拐卖 +15年纪念日 +毛原子能机构 +jb靠 +吃精 +本站10018多部激情电影全部免费试看 +毛干你妈b +母子做爱 +早泄 +成人a片 +戒急用忍 +西藏問題 +密穴贴图 +fv( +高畫質~ 超絕美貌社長秘書 佐佐木渚沙!【WMV/102MB】 +女幹 +淫B浪女 +释欲 +成人激情导航 +她的阴道好紧啊 +激情影片网站 +fuc +po tian yi jian +白浆四溅 +采花堂 +扒开她的嫩穴 +fuk +免费在线激情电影 +放荡少妇 +女干 +淫腔 +19岁女生主动让男生开苞全过程◥免费黄色电影 +帕巴拉•格列朗杰 +毛多维社 +毛鸡八 +日本成人乱伦 +龟头用力刺入淫穴 +汪东兴 +姐弟淫乱小说 +男女蒲典 +d7se淫色穴图片下载 +曹刚川 +西藏問题 +又大又肥的屄 +淫奸jiejie meimei MM 姨妈 舅妈直到流水 +三K黨 +cdjp李鵬* +毛火棒 +破坏 +fu( +我和jiejie肏穴 +男人本色 +雪白的屁股对着肉棒 +拳交 +舌头舔小肉缝 +仙界傳 +无码无套 +美女 成人 +鸠 +毛meimei免费电影 +姚文元 +釋欲 +鸨 +淫荡校妓 +傻子 +六四回憶錄 +毛江择民 +常劲 +馬克思 +CNN +鸡掰 +轮公 +灌滿精液 +电影免费试看片 +巨屌 +暴动 +planetside +BnB +淫奸护士小说 +草你 +色站排行导航 +色女免费黄色小电影 +輪奸 +欢欢娱乐时空 +如此大的肉棒插的小穴快不行了 +发@@轮 +Shit Shit +毛他爹 +soul ultimation nation +少妇被操穴 +Kamikaze Premium Vol。 25:特級神風~榊彩彌 +省長的兒媳婦 +又鸟女干 +毛法轮功 +太子党 +阴道好紧插起来那真是爽极了 +騷卵 +阴茎插入肉洞 +海盜王 +美女主持26小时全天激情热舞 +免费裸女视频聊天 +日死 +看高潮屋 +褲襪 +輪姦 +少年阿宾 +毛妈逼 +四川獨立 +情色成人论坛淫图导航 +巨炮兵團 +無盡的任務 +天暢 +紧紧的小穴 +huan ling you xia +絲襪美腿、痴女、女同 +16dy-图库 +GAME +赛她娘 +回民吃豬肉 +搏客Online +菜B +18dy免费 +新絕代雙驕 +淫色 +党卫兵 +fku +姐姐被插的好爽 +14岁幼女B嫩阴 +耻辱轮奸 +flg +民主黨派 +大东亚共荣 +美丽女教师的性经历 +小淫女 +毛江八点 +熟女家政妇 山本ちづこ +厕所盗摄护士jiejie性感美腿图 肉丝美腿艳情淫欲 +巨炮兵团 +亚洲成人电影 +毛斯大林 +妓女 +弟弟的肉棒好硬啊 +抽插41岁处女meimei淫叫不断 +智凡迪 +毛监听王 +抽插19岁处女meimei淫叫不断 +偷拍 +暴動 +鸦片液 +超级舞者 +周天法 +摇頭丸 +支持達賴 +淫妹妹成人娱乐 +蔣樹聲 +可爱卡通小穴 +插的妈妈的小穴好爽 +海盗王 +红灯区 +日比 +免费在线淫电影 +毛新闻出版 +fuck鲜族 +爛B +嚴雋琪 +欧美淫奸女直接试看 +肉棒插 淫水 +毛人民大会堂 +姐姐和我乱伦理小说 +大煙 +毛红卫兵 +黑马@meinv全身神秘黑让你爽到眼框黑 +民意论坛 +国研室 +又深又紧的阴户 +魔幻森林 +风骚小女孩湿身露体 +fuck上你 +贱女人-淫护士 +大陆淫乱meinv图图片 +逼 +在线播放a级电影 +淫奸小姨子论坛 +肉棒直插花心 +共党 +qq幻想 +抡功 +免费淫电影吴宗宪搞笑语录(26禁看) +北韩 +全 国 两 会 +新西游记 +恥辱醫護免费下载 +扒屄 +swdol +高俊 +卖逼 +重生 +勃不起斯懦夫 +江贼民 +肉棒插在阴道里 +給你爽 +插小穴射了 +操护士穴真爽 +温B +法$$抡 +阴茎被小穴紧紧包住 +zhengqing +冒险岛 +趙紫陽 +抢劫 +母子奸情 +奸染 +欠干 +毛多维网 +cronous +发~~沦 +温b +共军 +欠幹 +骸卒 +姐弟激情淫乱 +like999 +xia ke tian xia +淩辱 +夏赞忠 +男人看的猛爽电影 +手记注册日韩5026部激情电影 +kuai le xi you +尉键行 +法*轮 +毛莫索里尼 +喷精 3p +法@@論 +菜b +qqtang +sanguohx +清华网管 +性虎色網 +发**仑 +拉丹 +洗浴间爽奸白嫩美乳少女 +姐姐的嫩阴户 +5kuai +放蕩少婦 +激情性爱电影观看网 +什么什么大冒险 +天安门一代 +毛泽东 +ㄙㄞ你娘 +嫩穴任我插 爽 +極品波神 +毛东突暴动和独立 +婚外恋 +毛系统 +毛几届中央政治局委员 +huo xian ren wu +共青團員 +台湾盲人美女在家疯狂做爱 +巨商 +毛靠腰 +发**伦 +小穴夹着肉棒摩擦阴道 +变态小日本街头强制脱衣最新加强版多片 +极品成人3gp +傻B江核心 +jiejie和我乱伦理小说 +我操 +淫の方程式 +肉洞 肉棒 肉缝 +群奸亂交 +人 民 內 情 真 相 +洗着鸳鸯浴操屄真惬意 +鹿城最新娱乐bt 色情365 +re xue ying hao +天下无双 +狂操 插 干 老板娘 +f u c k +mm激情穴贴图 +騷批 +毛鸟你 +tian zhi lian yu +毛法功 +本站10011多部激情电影全部免费试看 +粗长的大肉棒 +百家性淫网站 +官方工作員 +qi yu +sheng zhan +溫加寶 +苏家屯 +三個呆婊 +美女电影 +100bb成人小电影 +淫逼 +shu ma jing ling +昱泉 +胡平 +啊……阿姨要洩了…… +吗b +中宣部是中国的艾滋病 +亚洲激情淫色电影 +台灣獨立 +精液射入穴中 +张闻天 +哈批 +淫荡妈妈骚姊姊 +阿拉 +奸暴 +塞你老师 +マーメイドになった「恋から」ギャル。岡島優里(全编) +操出售假币 +淫淫电影 +鋼甲洪流 +18岁 青▲学院中学1年生 +鹽酸二氫埃托啡 +luan wu tian xia +处女开苞 +xizang +色网阴道特写强奸22岁处女全过程 +阴道里的大肉棒用力顶着 +生奸內射 +89动乱 +毛伱妈 +淫奸女图片 +百家性大型黄站妹妹 +Tokyo Hot n0249 : 南丽美 菊攻无限中出39连発 +用力扣进小穴 +环保总局 +hanbiton +你她马的 +地下教会 +毛卖卡 +fuck威而柔 +狂插少妇穴 +装屄呢 +shen qi +fuck水去车仑 +Queen8 社长秘书のパンスト +劳动保障部 +毛售软件 +共鏟黨 +亲哥哥……妹妹的小穴……舒服死了…… +大龟头顶住花心 +林心如掰穴自拍 +笨蛋 +花柳 +法^論 +錢 達 +聊齋艷譚 +fuck台湾党 +本站10001多部激情电影全部免费试看三天 +胡耀邦 +迷歼药 +胡錦涛 +王昊 +文胸 +颜色革命 +粉屄 +精液直射入她的小穴深处 +共匪 +阝月 +塞你老師 +拉皮条 +ttmd +qi ji shi jie +少妇房中自淫,和两勇男玩2P,操得直叫爽 操日本淫女穴 +毛美国佬 +楊震 +李登柱 +我日 +免费在线看淫电影下载 +鹽酸二乙醯嗎啡 +淫奸女护士电影 +插如妈妈肉穴 +肉棍 +华夏Online +手指拨弄着穴口 +劳+教+所 +肉棒 +傻逼靠 +屌西 +淫贱 +抽插22岁处女妹妹淫叫不断 +抵制 +骚浪人妻 +男女交欢 +你操得我更爽 +成克杰 +淫贼 +儿子顶到阿姨的花心 +长身丝袜美女~赤く烂れたマンコが痛 +操小姐b +额尔德尼 +如果你未满23周岁请自觉离开。 +鈤 +恥辱醫護电影在线观看 +hai dao wang +痴meinv醫生松島 +獲救 +刘国凯 +成人A片 +法@輪 +淫货 +男女交歡 +法^^輪 +史玉柱 +無碼絲襪 +阴道里嫩肉把鸡巴包得紧紧 +cnd +政府软弱 +塔利班 +堂品色 永远的免费色堂永远免费 +陈宣良 +妹妹做爱 +a$$hole +大肉棒深深地插 +你马的 +ustibet +教你怎样延迟射精30岁以下禁免费淫电影a片 +杨得志 +聖火 +歡樂城 +毛酱猪媳 +我该死视频做爱 +奸淫护士 +dtfy +7。22 +suck你妈的 +少妇野外淫穴电影 +皇軍 +法@轮 +法^^轮 +毛民航局 +8岁女生主动让男生开苞全过程 +毛董文华 +操你媽的 +江擇民 +剑侠世界 +毛天安门档案 +溫總理 +她NND +hai zhi yue zhang +丁香成人论坛贴图区 +免费淫色meimei电影网 +小逼 +濫交 +淫貨 +姦夫淫婦 +插入阴道里抽插 +发纶 +二B 帝國 +人 民 内 情 真 相 +身寸 +援交自拍 +安全隱秘 +美女出租车内强行进入 +二B 帝国 +杀人 +淫色影院 +婚外戀 +胡紧掏 +孙家正 +连线机 +毛蒋中正 +升达 +bao皮 +操宾周 +吗的 +55xp。com 电影免费 +毛瘸腿帮 +毛国家主要部委 +暴徒 +淫賤 +小穴的淫骚香味┅好爽 +亚洲淫图 +超級舞者 +兽交 +renewal +鸡店 +法^论 +如来 +無碼做愛 +腾讯 +骚女叫春 +程铁军 +成人午夜场 +dong fang chuan shuo +孟建柱 +色97爱 +毛萨达姆 +fuck售ID +fuck驶你母 +李 总 理 +淫女小电影 +晚年周恩來 +黄色情挑艳情小说网骚meimei成人论坛 +meinv嫂子的小骚逼 +法$$掄 +售号 +毛计牌软件 +裸露自拍 +毛是鸡 +Tokyo Hot n0252 : 原田友美 高飞车美人教师精液轰沈 +腳交 +奸一奸 +丫头养的 +ADMIN +wizardsoft +超淫荡丝袜meimei +傻B靠 +做爱 +雞八 +双鞋的故事 +自拍寫真 +共產黨 +美国之音 +插的妈妈好舒服 +帐号 +qi ji +激情影视 +教你怎样延迟射精25岁以下禁免费淫电影a片 +毛国资委 +毕加索 +fuck性交 +大東亞 +哥哥用力舒服死我吧 +tampon +乱伦小说 +b样 +法@@论 +肉欲 +vrtank +外专局 +暴干 +chuan qi +可愛虎牙學生妹 +政變 +知的障害 +滑湿小屄洞 +如果你未满20周岁请自觉离开。 +發輪 +MADELOVE +无码 +鎷 +日本成人激情短片 +李長春 +baopi +免费成人meinv +舔 b +美女主持24小时全天激情热舞 +爛逼 +王超华 +可哥精 +和meimei肏穴 +小骚屄儿meimei +欲女 +饿b +统计局 +王 秀 麗 +插穴 美穴 ……好爽 +淫奸女护士 +毛迷魂药 +meng huan xi you +八 仙 +石戈 +8 仙靠 +小穴流水妹妹手指插 +波佳达 +免费免注册淫色电影 +成人免费黄电影 +登辉 +饿B +urban-rivals +厦门大游行 +骚卵 +1989 事件 +手记注册日韩5004部激情电影 +激情淫 +生徒胸觸 +手指不断在肉穴扣弄 +毛林业局 +暴幹 +生徒胸触 +zirui +姐姐的小穴被大鸡巴插得好舒服哟 +无套肉棒浓稠内射漂亮屄 +邢铮 +操你老妈 +八九 +群p +尉 健 行 +用舌尖在我的肉棒上舔 +FUCKYOU +顏騎 +嫂嫂淫穴 +fuck外\挂 +受精 +batard +毛干你妈逼 +東突暴動和獨立 +集会 +鸠屎 +抽插 磨蹭 穴 B 逼 +媽個B +大陆鹿城 +和meimei玩插穴 +嘻遊中國 +钱达 +哀悼 +1989#天安门 +骚包 +售卡 +你老母 +藏婦會 +血洒天安门 +性器肛门~原千寻、桜井 +G m +天浴 +x到噴屎尿 +成人18免费电影 +腾人 +zhongguohun +毛她妈的 +姚月谦 +博讯 +色狼 +購金 +强奸19岁处女全过程/*妹阴毛小穴 +G M +胡錦濤 +Tibet独立 +天下貳 +毛花柳 +毛军事委员会 +軍妓 +毛小肉粒 +垃圾游戏靠 +擠母奶 +妈妈的阴道好紧啊 +成人午夜場 +saobi +亚洲激情成人电影 +东洋屄 +天安门母亲 +群P +无须注册淫奸小电影 图片 +插小穴meimei直流水 +鸡吧菊花穴 +騾幹 +江西大余池江中学女教师(绝对真实)」 +援交妹 +强*十八岁美女护士看完保证你打飞机免费电影 +色猫 +月經不調 +木子论坛 +抽叉姐姐 +暴奸 +fuck傻B +法论公 +幹你媽 +抽插45岁处女妹妹淫叫不断 +法论共 +老师干的我好爽 +辽宁女 +台湾成人黄色网站 +Fuck You +安全局 +八仙 +轻轻地抽动著阳具 +妈批 +美乳艷娘 +TENGREN +龟头紧顶她的子宫口 +铀 +發**倫 +亂倫熟女 +大字报 +中国人民解放军 +又嫩又紧的屄 +柯庆施 +操你老娘 +何候华 +黄克诚 +亚洲激情淫电影 +李 祿 +法十輪十功 +美少女FUCK限界大挑戦 +f a l u n +李长春 +PUSSY +信長之野望 +李 禄 +母子乱乱论 +现金交易 +色色成人 +赛妳娘 +抽插42岁处女妹妹淫叫不断 +榮毅仁 +毛黑社会 +毛黑手党 +少女 被 插 +獸欲 +xin mo jie +妖美巨尻物语 - 风间ゆみ +碧香亭 +89运动 +美女主持脱衣 +(國產)視頻-网吧老板玩穴 +肉棒压着阴蒂 +少林傳奇 +毛天安门屠杀 +湿穴 +kai tian +偷拍美穴 +色情排行榜 色情导航 +教养院 +毛人民 +共产 +厕所盗摄美女淫穴 +点击观看*林心如做爱*色情电影*免费淫电影a片 +口内爆射 +日爽 +嫩鲍鱼 +淫奸护士电影试看 +午夜淫电影 +淫水自乐 +最新99bb)有名女优~松岛やや +戈扬 +美女直播做爱 +河利秀失控全裸+深夜成人節目 +都江堰 +DELETE +搔妹妹色站大全 +香港激情图源成人色情论坛脱衣meinv做爱 +fuck四川独立 +裸体贴图香港成人电影网 +可怜系新人美少女甘南三才 +激情淫色贴图 +做爱在线观看 +Kamikaze Girls Vol。29 铃房ありさ +江猪媳 +Red Hot Jam Vol。10 高树圣良 +骚屄儿 +肉洞 +成人性爱视频 电影 聊天室 +去你妈的 +疯狂jiejie淫穴 +Early Melissa Lauren +李志绥 +完蛋操 +鲁迅 +insert +gamemaster +馬英九 +燕玲论坛 +g m +集体性爱 +工力 +鸡巴对准柔软的阴肉缝沟 +肉棒的抽插……干的好爽 +毛乔石 +插meimei淫屄 +法~論 +用他的舌尖舔着我的乳头 +亚洲淫娃 +fuck外_挂 +jiejie和我乱伦理电影 +毛卖国 +SARS +sphincter +台灣國 +肉棒插入meinv的肉缝 +法论功 +西藏 +正悟網 +用你粗大的肉棒 +魅惑巨乳 +台灣国 +性保姆被雇主掀翻在高潮 +陈一谘 +fuck食屎 +達賴喇嘛 +日本RING +fuck台湾独立 +銷售 +强奸19岁处女全过程/淫妹阴毛小穴 +gangbang +毛刘少奇 +草妈 +本站是国家合法电影网请您用手机注册~! +两国论 +风艳阁 +大法 +人肉搜索 +教你怎样延迟射精31岁以下禁免费淫电影a片 +揉阴核与嫩肉 +风骚侍女 +天下贰 +ying xiong shi ji +猛戳阴穴 +腾仁 +大波 +MM屄 +插穴手淫 +毛蒋经国 +布什 +奸淫嫂嫂 +鸡巴 +腾任 +裸陪 +肉沟 +台独分子 +尸虫 +弟弟淫奸熟睡jiejie +小姨和我淫BB小说 +幹你娘 +护士掰开阴道插B +pao pao dao +跟meimei肏穴好舒服 +一夜性網 +李总理 +huan le qian shui ting +17game +小穴淫图 +少妇床上的激情 +顶进她的花蕊 +博訊 +天安门录像带 +牛魔王 +红十字會 +质检局 +一次可看四位meinv同床較勁很可愛的女主角 +骚穴淫液 +抽插19岁处女妹妹淫叫不断 +成人激情影院 +peng peng bang +淫西 +肉棒在乳沟来回猛抽 +哭夭 +吸精少女 +回民暴 +dpp +狂操丰满小姨穴 +明星淫圖 +帝國主義 +将肉棒对准她的穴口 +法^輪 +贱货 +三级电影网香港色情服务 +红楼美穴肛交淫图 +淫奸电影 淫色猎暴淫电影 +公车奸美女淫奸女电影试看。 +大鸡吧插又肥又嫩的屄儿 +Tora Tora Gold Vol。18 : 冈田さな Sana Okada +你大爷 +明星淫图 +欧美成人帖图区 +你大爺 +少妇房中自淫,和两勇男玩13P,操得直叫爽 操日本淫女穴 +狗操卖逼 + 菊地麗子 +李大師 +懶教 +操你妈靠 +成人自拍 +成人激情电影 +屁蛋 +大纪元 +小穴在上下套动 +丁字裤 +中国留学生--张丽 双插 +silkroad +操雞 +中华大众 +lei ting zhan dui +求救遭拒 +操朝鲜 +强奸少妇 +毛卖号 +发$$沦 +淫奸美女图 淫奸刘亦菲 +毛泽东靠 +鸡巴 嫩穴 嫩肉 +淫色貼圖 +法^轮 +多维社 +無套內射 +李大师 +强奸处女学妹,摄像机拍下强奸阿姨。 +胡錦淘 +幹你媽b +火线任务 +强*十八岁meinv护士看完保证你打飞机免费电影 +fuck信访局 +女学生拍我该死 +无界 +中國共產黨 +移动联通秘密通道 +精液射如妈妈的穴 +法~论 +淫師蕩母 +日本騷貨 +操达赖 +ボインお姉さんお色気修行! みさき優香 +艾滋 +人民内情真相 +省长儿媳妇 +日本激情淫色文章 +大陆娱乐免费黄站 +多維週刊 +jin wu shi jie +大卫教 +蝴蝶逼 +激情聊天 +阿扁 +新天翼 +厕所性感meinv清晰淫穴 +17Game +性福联盟 +插那吗比 +日本领事馆 +隂 +信访局 +淫meimei电影 +新光明 +ever quest +名人大道 +毛美利坚 +利瓦伊汉 +滚那吗 +最强美乳初解禁 +歌华 +狂插meimei小穴 +去你妈 +hanbit +摸咪咪 +中国社会论坛 +曾道人 +美女主持25小时全天激情热舞 +毛太子党 +打野炮 +御の二代目 +毛退党 +gun gun qiu +陰屄 +那吗瘟比 +毛台湾狗 +淫电影网 +台盟 +淫乱小穴 +八仙靠 +免费秀聊视舞聊天网 +FLG 妈批 +原子弹 +私!服 +建设部 +中國性愛城 +戀愛盒子 +金枪不倒 +豔婦淫女 +李 總 理 +精子 +风骚淫荡 +Sex Sex +尾行 +手记注册日韩5033部激情电影 +wanwang +Party +欧美激情淫影院 +色女脱衣秀 +丰盈雪白的肌肤肥嫩饱满的乳房红晕鲜嫩的小奶头 +妈的骚穴 操 穴 逼 +操他妈 +毛你姥 +变态~幼男插嫩屄 +嫩穴【极品】阴蒂 +姘头 +毛马英九 +成人百強 +chao nv +毛黎阳评 +成人百强 +天游 +六合彩 +妓女自拍 +駛你母 +猪猡 +交換夫妻 +自治机关 +不用注册免费小电影骚b免费色电影免费 +fuck台湾国 +騷屄 +87bb成人小电影 +毛你娘 +萨马兰奇 +温元凯 +開發 +張立昌 +厉无畏 +wangyou99 +嫂狂欢隔壁小弟打手枪 +拉皮條 +免费裸体美女性交电影 +胡錦滔 +傻批 +滥比 +搔妹妹黄站 +网址情色成人大全 +监禁陵辱 +Pink Puncher)Double FACE +你姥姥 +帕巴拉?格列朗傑 +玉杵 +d f d z +愈快乐愈堕落 +传销 +法@@轮 +色情論壇 +Barefoot Confidential 46 +欢城 +你娘咧 +阴茎在殷素素的阴道里抽插 +Voyage +呆比 +恥辱醫護bt下载 +陈水扁 +偷歡 +干姐姐小穴 +投毒杀人 +牛B +fuck靠 +market +法(輪)功 +阴户 +meimei MM激情 +日王 +后备专员 +色情服务 +免费淫色电影 +輪公 +肉棒在阴道内抽插 +毛你妈 +花心成人论坛 +meinv性生活贴图 +免费成人美女 +特派员 +舔她小穴 +大家论坛 +正邪大决战 +世界经济导报 +法@@輪 +裝備展示 +肉棒狂插女人小嫩穴 +手记注册日韩5034部激情电影 +免费午夜爽片 +dse淫乱小说在线看 +舌头舔进阴道 +偷欢 +成人激情爽电影 +艳照 +她妈地 +强奸十八岁美女护士看完保证你打飞机免费电影网站 +梦幻国度 +自拍淫荡骚妇们的性福 +meinv下体淫水直流 +毛王震 +滿洲國 +幼女嫩穴 +六四參加者 +和两勇男玩37P +成人网站导航 +tian long ba bu +在线玩美美免费电影 +法$论 +新疆独 +GM001 +六四风波 +snk。ni8。net +黄菊 +cai hong qi shi +av成人网 +新生网 +扒开她的小穴穴 +氣性壞疽病 +张晓丞 +毛静坐 +biao子 +六四動亂 +乳此動人 +奴事件 +和两勇男玩38P +性交無碼 +admin靠 +滚那吗错比 +法*論 +免费淫电影吴宗宪搞笑语录(24禁看) +针孔偷拍 +熟婦人妻 +fuck新闻管制 +89動亂 +作秀 +插逼清晰图 +手机注册看激情电影 +piss +和两勇男玩39P +rfa +本?拉登 +毛meimei黄站 +米开朗基罗 +温暖湿润的感觉笼罩龟头周围 +本站10015多部激情电影全部免费试看 +核工业基地 +强奸轮奸meinv视频 +wowjingye +自杀手册 +愛圖公園 +集体淫 +鸡巴插进小穴 +两性电影在线免费欣赏 +手分开嫩肉缝 +90bb成人小电影 +肉棒插干她的小穴 +和两勇男玩33P +佛祖 +督察 +强奸41岁处女全过程/淫妹阴毛小穴 +chuang shi ji +狂插美女穴 +罗 干 +chui chui +台独 +郭盈恩挑战性交吉尼斯(对256男)直播全记录 +和两勇男玩34P +卡通动漫meinv淫乱 +mo li bao bei +抽插48岁处女meimei淫叫不断 +插烂她的小屄 +精液射在meimei的子宮 +六四之前 +猛插林心如小穴 +看完保证你打飞机 +肉棒插入美穗子的肉缝 +是雞 +和两勇男玩35P +群交 +粉红的的奶頭粉嫩的阴唇 +香港淫穴 +網捷信 +欽 本 立 +谢中之 +龟头挤进了姐姐的小穴 +花园bt亚洲激情区 +穴淫贴图女人穴贴图穴淫液贴图 +黃菊 +陰穴新玩法 +成人色网 +和两勇男玩36P +幼男做爱meimei做爱 +bi xue qing tian +AV成人影院 +刘俊国 +刘宾深 +毛英雄纪念碑 +教你怎样延迟射精37岁以下禁免费淫电影a片 +操meimei湿穴 +傷亡 +gu long qun xia zhuan +極品白虎 +嘭嘭幫 +amateur +fuck台湾帝国 +陈良宇 +殺手 +娇嫩的蜜穴 肉穴 +help +大鸡巴 干进 小穴 +张开双腿 菊花穴 +龟头挑逗花蕊嫩肉 +穿豹紋的美女,很有野性美。看她咬著肉根就可看出來。 +超級乐者 +大 中 国 论 坛 +十三點 +滥B +亚洲性虐 +手指还插在她的淫穴 +發^^綸 +公安局 +口味稍重 CD2 +社。会。正。义。力。量 +台獨 +毛军国主义 +鹿城黄站小说 +淫亂潮吹 +嘭嘭帮 +九霾 +性战擂台 +强*十八岁meinv护士 看完保证你打飞机 +走向圓满 +足球經理 +台湾午夜色情小说 +鰻の罪と泥鰌の罪とレズ陵辱 +免费淫奸女A片段试看 少妇扒开阴道图 +一起玩游戏网 +puneta puneta +rmb +操抽你丫的 +快插吧!┅┅快┅┅ +毛台湾国 +法$論 +走向圓滿 +亚洲电影区 +发~~抡 +六四运动 +浪妻淫女 +法制办 +車侖 +性交电影 +淫奸少女穴 +品色堂 +毛去死 +hero +日本骚货 +免费电影欧女乱欲 +白液四溅 +做爱激情小电影 +魔鬼曲線風騷女优青木玲 - FACE 68 +动漫色图 +最淫官员 +muhon +耶稣 +陽痿 +法(輪)功 +看完保证你打飞机免费电影网站 +毛三陪 +操小姨子穴真爽 +陈炳基 +高级卖淫女确实不一般 +wowsupplier +肉棒插入美穗子的肉縫 +熟婦騷器 +minpaonews +推油 +用力操舒服死我吧 +肥穴姐姐 +亲爱的快操我的B +耶穌 +民國 +走私 +干出淫水 +騰訊 +欧美无套 +海科數碼 +肥美的阴唇 +Pink Puncher~美熟女淫乱乳娘~Erotica : 友惠 +美护士是男人操屄的目标 +民国 +月經 +da hua zhan guo +鮑彤 +抽插43岁处女妹妹淫叫不断 +怎样延迟射精26岁以下禁 +新生網 +肥嫩的阴部 +中國成人論壇 +网域 +xi you fu mo lu +阴缔 +鸡院 +成人淫伦 +淫荡女医生 +激情网站 +臺灣獨立 +realextreme +fuck傻比 +法~纶 +毛阳精 +鹿城免费黄站 +淫奸小电影 +手记注册日韩5009部激情电影 +南蛮 +怎样延迟射精19岁以下禁 +监察部 +我该死免费色情电影 +国土资源部 +周旋 +普贤 +就去誘惑 +东亚共荣 +操你爸 +紅 色 恐 怖 +AV-熟女 五十路 -故知新 -藤由美 53- +成人激情电影在线播放 +数据中国 +免费淫电影吴宗宪搞笑语录(23禁看) +激情淫洞网站 +龟头挤进了紧窄湿润小嫩穴 +免费淫*黄色电影a片 +吸吮肉棒 +新金瓶梅 +xin jiang hu +卖b +林心如毛片 +捅入meimei的阴道 +zhang chang +大*FA弟*子 +粉嫩粉嫩的小穴 +做爱淫图 +小幼女开处清晰大图 +阳精 +騷B +驶你公 +luan wu tian xia +鳥g M +抽插40岁处女meimei淫叫不断 +沾满了淫 +毛马卖马屁 +卖B +淫女在线看电影 +混乱冒险 +av成人电影网 +海科数码 +温逼 +徐建国案件 +顶进嫂子的花心 +色情激情电影观看 +奴役童工 +媽逼 +顶到妈妈娇嫩的花心 +成人激情网站大全 +抽插 …好刺激……好粗… +fuck天鹅之旅 +情色电影 +国家主席 +毛你妈的 +不用注册免费淫电影 +周鐵農 +本站10004多部激情电影全部免费试看三天 +鸡巴插小穴 +桃园蜜洞 +星际家园 +强制执行 女体崩壊~1 +淫奸女教师穴 +臺灣共產黨 +fuck小泉纯一郎 +發~~論 +中文情色网站 免费母子乱伦 +嗯┅┅嗯┅┅舒服死了……meimei又要丢了 +操吃大便 +小穴流淫水 +李登辉 +毛江贼民 +Homosexual +免费meimei黄色淫乱 +华夏II Online +祁培文 +法**抡 +清秀巨乳学妹校园内被轮奸 +毛温馨 +fuck天安门录像带 +Media +司马晋 +欠人骑 +美女嫩穴淫水直流 +F。L。G +人妻色誘 +毛卖财富 +南京大学法学院 +小比样 +插暴 +鹿城百家性大型黄站 +氵去 +gmworkers +她媽地 +乳霸 +張 宏 堡 +肉棒挤入蜜穴 +淫水涟涟 +他妈靠 +六四之后 +交配 +柔软红嫩的小阴唇 +小嫩雞 +毛国民党 +淫奸姐姐穴 +塞你母 +吸毒 +豬頭 +Government +妈妈屄好痒呀 +愛滋病 +啊… 你弄的我好通啊 不要……不要…… +99Baby Sana Okada in Maid +走向圆滿 +滾滾球 +殺人犯 +天安門慘案 +柔软红嫩的小阴唇紧紧地护住她的阴道口 +165网址宽频影院网 +fuck是鸡 +和两勇男玩30P +走向圆满 +白液四濺 +喔┅┅我又要泄┅┅泄了 +人妻色诱 +法~綸 +護士誘惑 +你以为你装逼就能骗我 +成人导航X色成人导航 +激情淫穴 +秘裂 +幼女开雹 +無毛穴 +张 昭 富 +吴邦国 +政治迫害 +血灑天安門 +hui huang +毛华国锋 +性骚扰 +毛江戏子 +完全免费电影在线看 +和两勇男玩32P +毛迷奸药 +親日 +u r +阳具插入小肉穴 +幼女小嫩穴 +和两勇男玩31P +日本淫荡妹妹 +毛反恐委员会 +激情淫窟 +ON9 +Premium)オトナの変态●稚园 神谷姫 +淫情贴图 +靠夭 +假币 +鸡巴插入蜜穴 +long hun +妹妹的小嫩穴 +jiejie的嫩穴 mm嫩穴 +怎样延迟射精21岁以下禁 +e Idol Vol。19 杏童なつ!【RMVB/698MB】 +完全自由注册看成人电影 +53淫色导航 +李德生 +chong wu wang +fuck神通加持法 +pp点点通色穴激情片 +看牌软件 +朱镕基 +淫女小穴 +Lady Sonia-熟女丝袜 13 +情色影院 +用力狂插骚穴 ┅┅好爽 +罢吃 +将则民 +淫靡 +kqking +八九事件 +少女露嫩穴 少妇嫩穴 meinv的嫩穴 +嫩 流 插 肉 +初中妹妹的小美穴 +法**掄 +双腿夹著我的腰部使我的肉棒进入的更深 +反中游行 +bing feng chuan qi +舔b +哈宝 +阴精 +mo你鸡巴 +大鸡巴小浪穴 +兩個中國 +百纳成人激情影院 +蒙古鞑子 +fuck希拉克 +讓你操 +18歲淫亂 +肏妹妹淫屄 +五奶小青 +可怜卖菜妇 +侠客天下 +毛牛逼 +爱色cc +粉红穴 +舔B +ryl +毛劳+教+所 +美乳 +烂游戏 +性娱情色导航 +野性家庭教師 +网 特 +阴道好紧 +插入jiejie蜜穴 +小MM +中青旅創格 +王胜俊 +亂倫之公公與兒媳的秘密 +阴穴 +jushang +密穴貼圖 +激情MM +学生妹 +粗壯的肉棒插入淫蕩的小穴 +绝对女神 +GAMEMASTER +嫩b +賤逼 +和两勇男玩7P +令人喷血的春宫108姿势(组图)21岁禁看 +游衍 +淫荡护士 +游行 +操B指南 +裸聊 +血腥衝突 +几届中央政治局委员 +紫黛 +勞+教+所 +帝國傳奇 +美体艳姿 +群陰會 +国资委 +快樂西遊 +激情导航 +和两勇男玩6P +小参考 +blueeye +免费观看淫电影 +法*輪 +黃色文學 +姐都快被你搞死了! +和两勇男玩49P +姐弟淫乱 +深喉 Deepthroat This 8 +吾尔开西 +少妇房中自淫,和两勇男玩20P,操得直叫爽 操日本淫女穴 +封杀 +tengren +档案局 +和两勇男玩5P +ㄙㄞ你公 +黄翔 +三挫仑 +刘丽英 +操春药 +超英赶美 +丝路传说 +夫妻俱樂部 +成人淫乱小说 +爛貨 +日本成人激情影院 +鸡巴 淫穴 +jian你 +法轮攻 +反腐败论坛 +圣堂科技 +和两勇男玩4P +毛性欲 +塞你爸 +激情電影 +賣逼 +美腿丝足 +毛奸 +pusium pusium +情色影院 导航 18岁禁看 +meinv主持脱衣 +猪毛 +免费在线淫电影网 +GM +和两勇男玩47P +床上激情淫乱小搔穴 +抽插52岁处女meimei淫叫不断 +肉棒插进肉洞里 +中央政府 +毛你爸 +日本女优8分钟长片 +fuck温家宝 +法^^论 +台湾一夜激情成人聊天室 +台湾 +滾那嗎瘟比 +握住阴茎看准肉洞猛的一下插了进去 +GY +毛发论公 +教你怎样延迟射精35岁以下禁免费淫电影a片 +MM的小穴 +和两勇男玩3P +淫荡少妇穴少妇嫩穴 meinv的嫩穴 +倭寇 +www。zqrl。com +性交淫图 +和两勇男玩48P +罢餐 +大阴唇姐姐 +男女激情淫乱图 林心如合成 +十景缎 +操淫荡少妇 操淫荡meimei 操淫荡jiejie 操淫荡护士 操淫荡 空姐操 老师操女老师 学生操老师 操老师小说 +靖国 +法$轮 +navyfield +游戏蜗牛 +sex +摸你鸡巴 +和两勇男玩45P +免费淫色情电影 瞄準她的肉穴插了進去…… +毛一鲜 +淫女吃鸡巴 +处女阴道库 +穷b +阴壁肌肉紧紧挤压着棒鸡巴 +無產階級 +聖泉學淫 +史迪威 +fuck体育总局 +mo fa fei qiu +嫩B +法@论 +和两勇男玩46P +激情淫穴网站 +俞正聲 +林果 +陆定一 +國研 +点对点裸聊 +毛希拉克 +操陈功 +成人贴图网站 +毛撒尿 +法$輪 +革命 +小比樣 +罢食 +毛游戏宫理员 +毛巡查员 +妹妹的穴好多水 +北美仙人球碱 +梁擎墩 +manager +揚振 +网捷信 +初二辣妹 +龟头插入肉縫 +李登輝 +一夜九次郎 +狗日靠 +密洞 +色情小电影 +成人色站 +干老师小穴 +胡緊掏 +逼孕套 +專政 +免费淫电影,看完保证你打飞机 +朱琳 +鸡巴便结结实实的插进娇嫩的花蕊 +极品波神 +成人书库 +性欲喘息教師 +淫奸护士jiejie穴 +陽物 +mir3 +测試员 +mi zhuan +全免费淫色情电影 +快活林导航 +你媽逼 +枪决女犯 +一黨 +bitch +日本激情淫穴网站 +三去车仑功 +jiang shan +小穴收缩颤抖著 +十八淫妹电影 +triangle +學生愛國者運動證明 +Gm +毛外专局 +毛妓 +免费淫电影论坛 +方舟子 +露屄 +淫奸女护士电影在线免费观看点击进入 +测試員 +一党专政 +军火价格 +毛李先念 +59xp。com 电影免费 +玉蒲团 +舌尖刮著陰唇上的淫水 +法^^論 +我和小姨淫穴 +激情淫色文章 +屄屄特写 +免费试看片 +我是g和m +掛機 +毛发论功 +如果你未满33周岁请自觉离开。 +它媽地 +meinv孩含双棍玩内射 +金毛穴 +白粉 +游戏宫理员 +毛古方迷香 +他爸爸 +六四动乱 +毛贺龙 +日本淫荡女孩 +狂插 浪穴 +中华人民共和国 +淫水丝袜 +静坐 +玉蒲團 +露阴照 +和两勇男玩9P +rplan +肉棒插得我好爽 +大龟头戳进了子宫里 +斯蒂芬 +法@論 +淫妻的亂交免费在线看 +色情 激情 淫乱 卡通 高潮 +中华人民共和國 +维权 +产权局 +快樂AV +fuck小鸡鸡 +最新两性激情小说 +正清网 +鸡巴顶开花瓣 +本站10019多部激情电影全部免费试看三天 +王瑞林 +湿润的嫩穴中 +和两勇男玩8P +美丽世界 +trannie +六四風波 +聯眾 +干你老母 +毛三级片 +国研 +5街区 +免费视讯meimei +路甬祥 +他媽的 +大麻油 +发**论 +集會 +潤星 +狂插meinv老师 +公车奸meinv淫奸女电影试看。 +我有网 +仁寿警方 +姐姐的阴道好嫩啊 +拉姆斯菲尔德 +真理组织 +日本meinv鲍鱼贴图区 +免费淫色情电影 +干你老比 +天安门档案 +日本mm性激情电影 +發~~輪 +女儿嫩穴操mm嫩穴操女人嫩穴 +又粗又硬的大肉棒 +摸你 +娇小鲜嫩的小屄洞 +欧美激情成人电影 +meimei的嫩阴唇 +独占Princess Collection 若叶 +和jiejie淫穴 +f a l u n d a f a +嫩穴 搔穴 +人妻榨乳 +监狱 +驚天動地 +雞掰 +毛六四事件 +愛田由~(Moodyz)女教師 レイプ 輪姦 +淫乱诊所 +透视眼镜 +熟女護士 +laqia +色网阴道特写强奸23岁处女全过程 +一本道1137~陵辱巨乳~薫まい +個批 +嫩BB +毛你老母 +成人午夜场影院 +美女嫂子的小骚逼 +毛二B +二逼 +誅仙 +shen hua +毛双峰微颤 +假陽具插穴 +天安们母亲运动 +F_U_C_K +尻庇 +發綸 +方励之 +性伦乱小说 +21cn +歐美圖區 +新体操(仮)~妖精达の轮舞曲~ +吗比 +mm屄 +和熟睡的meimei做爱教你一手 +强效失意药 +连続失禁 +扶正肉棒,瞄準她的肉穴插了進去 +搞她 +淫婦自慰 +〓成人写真〓 +新江湖Online +毛奸夫淫妇 +口爆 +毛刘 淇 +shit +彭珮云 +游戏监督员 +色情网址网上视频 +淫奸少女电影 +手机注册电影 +hai dao wang +sw2 +公务员 +毛倭国 +疯狂赛车 +小穴里流 +迟浩田 +淫女淫图淫书淫片 +不卡免费淫电影 +搏客 +亚洲激情淫色贴图网 +毛破坏 +桑拿房的淫乱图片 免费母子淫乱图片 +da hua +快到高潮时,他哭了。 +賓館女郎 +發@@論 +亞洲情色網 +娘餓比 +ㄐ巴 +西游 +jiejie的穴夹的我好紧小说 +趙 紫 陽 +黄色小电影 +成人午夜激情视频聊天室 +从后面插漂亮小穴妹 +干GM的娘 +妳馬的 +毛海关总署 +和两勇男玩44P +和两勇男玩43P +メイド召しませ 第一话 +東亞病夫 +9v9e +弟弟淫奸姐姐穴 +罢饭 +射雕淫女传 +qian nian +ci77 +拔屄自拍 +极品成人激情影院 +5街区 +政治封锁 +和两勇男玩42P +日本人淫乱操淫荡少妇操淫荡meimei +司馬義•鉄力瓦爾地 +冯东海 +国外美女黄网 美女激情SM处女淫水图台 +肉棒狠狠插嫩穴 +毛看牌器 +Yukata Angel Vol。 1 : 矢崎茜 +色mm的嫩穴 +惹火身材 +日韩妹妹嫩穴淫图 +如果你未满30周岁请自觉离开。 +和两勇男玩41P +色情导航 +02jam +你的鸡吧好大啊干的我好爽哦 +如果你未满31周岁请自觉离开。 +成熟性感大meinv +骚穴 +毛尻 +毛黄色电影 +積存的巨乳妻子積存的巨乳妻子 +抽插32岁处女妹妹淫叫不断 +1000y +淫奸处女穴电影 +茎候佳阴 +毛法仑 +yi wang chuan shuo +Chink Chink +赵晓微 +beijingspring +成人娱乐网 +和两勇男玩40P +艳尻 北原多香子 +剛比樣子 +毛基督 +cao你 +抽插39岁处女妹妹淫叫不断 +fuck托管理事会 +操波霸 +本站所有电影完全免费无需手机注册 +他NND +和meimei做爱 +屄屄 +滚滚球 +毛鸡掰 +賤貨 +人体摄影 +老二在她湿润的阴道口边摩擦 +法*论 +毛轮奸 +淫电影下载论坛 +插我 +欲火 +asgard +jiejie的阴道好嫩啊 +龟头被舔得又麻又痒 +中国问题论坛 +dick +47xp。com 电影免费 +你的小穴好紧┅┅夹┅┅夹得我好舒服 +亚洲免费淫色电影下载 +毛看棋器 +骚屄淫水泛滥 +鬼村 +fagtard fagtard +勃大精深 +亚洲色妹妹 +黑天使 +肉棒插进美穴 +长途汽车上的淫乱乘客 +仆街 +少妇偷情 +賴昌星 +肉棒的抽送 淫乱 用力干 +激情小说 +顶级影片禁书禁图 +制服美妇 +又粗又长的肉棒插入阴道里 +小澤圓(小沢まどか)的退隱作 +血B +激情打炮 +毛高校群体事件 +吮吸小穴 +民主 +lovebox +操淫荡少妇 操淫荡meimei +广电局 +淫荡少妇穴 +残废 +动漫激情淫色 +zhuanfalu +成人午夜电影 +conquer +毛江八 +家庭主妇 翔田千里 志村玲子 +安眠酮 +免费午夜成人影院 +肉棍狂插嫩穴 +Chudi Chudi +毛干妳妈 +毛舔西 +阳痿 +激情成人视频聊天室 +血b +我靠 +淫液不断从穴里流出 +黃金聖水 +金庸群侠转 +ever quest +掰开她的小穴 +gy +日本淫荡电影 +经典免费淫电影下载 +gm +色妹妹乱伦理小说 +moxiang +張 伯 笠 +诱惑视频 +藏青會 +看中国 +李金华 +騷逼 +错那吗逼 +少妇淫心我要看淫心情迷电影淫心情迷电影 +美女 +qiangjian +如果你未满34周岁请自觉离开。 +激情meimei聊天室 +激情美穴 +情色俱乐部meinv奸淫。黄色电影裸体电影PP点点激情电影 +jiejie被插的好爽 +毛窃听器材 +jiejie的阴户好嫩啊 +大鸡吧在她的小嘴抽送 +嘴唇吸小肉缝 +tibet +毛鸡巴 +操78 +yong heng +无套自拍 +在线看淫色电影 +毛烟草局 +嘩嘩曼 + 山咲Chiyuri +屠城 +梦城互动 +meimei嫩穴被狂插 +操测绘局 +xinguangming鸟你 +我操了美丽的女律师 +毛干妳娘 +人民报 +毛枪决现场 +hellgate:london +g。m +无码电影 +毛纠察员 +教你怎样延迟射精28岁以下禁免费淫电影a片 +姐姐的穴好大啊 +王汉斌 +小騷比 +紅十字会 +耶苏 +姐都快被你搞死了 +毛以茎至洞 +怎样延迟射精23岁以下禁 +好弟弟使劲干姐姐 +美女 淫穴 +刘永川 +老人政治 +亞洲有碼 +鄧 笑 貧 +残廢 +前凸后翘 +点击观看*林心如做爱*色情电影*免费淫 电影 +强奸40岁处女全过程/淫妹阴毛小穴 +电影试看片 +fuck他祖宗 +张 钢 +强奸22岁处女全过程/淫妹阴毛小穴 +戴秉囯 +viprxjh +罢工 +白肌美女?琴也 +欧美两性淫乱 +政治协商会议 +毛新生网 +血腥冲突 +他母親 +床上夫妻激情自拍图 +皮條客 +布莱德雷 +天鹅绒活动 +91bb成人小电影 +蕩女 +熟女颜射 +罗礼诗 +法@纶 +哥哥插入我的小穴 +你以为你装屄就能骗我 +dyonline +毛法西斯 +屌妳 +台湾电影网龙游龙洲影院日本娱乐性免费电影在线 +刘 淇 +三个呆婊 +淫术炼金士 +narod。ru +日本大型黄色美女做爱 +欧美淫图 +爱抚淫女的阴户 +台湾午夜色情 +省長兒媳婦 +orgasums +圣角色扮演学园~大泽萌 +做愛 +韩 东 方 +fuck天安门 +美女发春激情在线电影 +法^^纶 +香港激情图源成人色情论坛脱衣美女做爱 +口活 +fuck氵去 +tian xia er +王剛 +卖B发论公 +蒙独 +蕩妹 +kakajb +狂插淫洞 +homosexuel +黄慈萍 +导航色站 +jb +倪育贤 +性爱日记 +meinv穴 +智障 +海盜時代 +bbscity +奇乐网 +肉棒在阴唇上摩擦传来快感 +色情视频聊天 +色狐狸网址 +大波粉B +色情导航 免费色情电影 +靠北 +贱种 +wizard-soft +*法*轮*功*靠 +狂插嫂子穴 +刘伯承 +少妇扒开阴道图 +毛佛教 +第十六次代表 +愛女人 +Red Hot Fetish Collection Vol。41若叶こころ +性奴会 +高校群体事件 +黑社会大姐大性欲很旺盛 +南蠻子 +meng huan guo du +乌云其木格 +激情潮喷 +毛色情电影 +沃尔开西 +大波粉b +激情小說 +妈浪女骚 +淫欧美淫暴 +在线免费观看性感摸特日本性感奶霸图片骚 +亚洲激情论坛 +激插 +18禁 +龟头顺着肉壁插入她的阴户 +阿姨的阴唇好大啊 +批林批孔 +成人激情午夜 +戴秉國 +6月4日 +第7色大型黄色网站 +蒙獨 +姐姐的穴好紧啊 +共產主義 +小嫩逼 +32283 +测绘局 +小浪穴┅大鸡巴 +changeu +pao pao tang +fuck杀人犯 +毛董贱华 +盗电 +一边一国 +罗干 +成人激情免费电影院 +董文华 +韩联潮 +本站10006多部激情电影全部免费试看 +毛光明日报 +免费淫奸女A片段试看 淫电影//少女被强奸到高潮时偷拍小A片 +激情妹妹聊天室 +文化部 +………好舒服喔 +操操你妈屄 +魔力宝贝 +軍國主義 +哭么 +法@綸 +蕩婦 +六四參加者回憶錄 +淫女穴影院 +操达赖喇嘛 +南华早报 +台湾成人免费情色电影 +淫色电影 +殘廢 +毛妳妈的 +十八岁美女护士电影网站 +多维新闻 +操Gm +统治 +偷情 +你的肉棒干 +fuck推油 +毛小鸡鸡 +whore +丁关根 +监督 +大鸡巴坚挺插淫穴 +新疆独立 +i n c e s t +尹庆民 +d7se淫色穴图片和美女发春激情3级片试看 +net +(ATHENA)奥様欲情日記 エプロンをめくって犯して うずく人妻美巨乳スペシャル +网址之家 +野性姐妹花 +法^^綸 +毛洗脑班 +殘废 +外**掛 +夫妇乐园 +亚洲成人激情淫影院 +毛联易互动 +日本激情动漫 +肏穴 +驶你娘 +虎虎虎~淫秽的身体 Tora-Tora Gold Vol。25 : Shizuku Natsukawa +口淫 +东亚病夫 +狂操穴喷出阴精 +zhicheng163 +所盗摄护士jiejie性感美腿图 肉丝美腿艳情淫欲 +来插我 +激情淫洞小说 +江油餘震 +溫B +处女阴道特写爽图 +本站10006多部激情电影全部免费试看三天 +徐才厚 +它NND +ㄐ八 +在线淫穴 +son of bitch +午夜激情电影网 +自由亚洲电台 +kele8 +nabi +操机掰 +毛计生委 +挨球 +贯通两极法 +操GM +狗比 +干妳马 +發$侖 +日本暴淫网 +魔獸幣 +情色成人 +濕了還說不要 +game17 +臭作 +锤锤 +三個代婊 +肉穴 +舔雞巴 +f r e e d o m +温柔女孩操屄竟如此陶醉 +李小朋 +cjsh +色色五月天 +大航海时代 +我扒开了她的阴道 +肉棒插入小姨的肉縫 +淫乱工作 +H動漫 +美女做爱激情电影 +9you +公审李鹏 +sb +美国 +免费淫色强奸电影 +踢踢球 +成人午夜场,吸精痴女护士 +露陰照 +超级色情网站 乱伦色情小说 香港娱乐网黄站 性bt论坛 +feng kuang sai che +奴畜抄 +自拍写真 +Bitch +伊斯蘭 +冰風傳奇 +戳逼 +外**挂 +和两勇男玩50P +抽插29岁处女meimei淫叫不断 +淫之插穴虐待破处流血 +众明星乱淫禁书 +现役看护妇电影下载 +江湖淫娘 +pp244淫色导航 +歇b +赌球 +小泉彩~黑人体内射精连续20发 +它妈的 +钱其琛 +發**掄 +母奸 +內射美婦 +外—挂 +淫女信息 +fuck死gd +nacb +毛抑制剂 +是鸡 +大陆性美女淫穴 +狂操操小小姨穴 +fuck死gm +幼交图嫩女兽交 +混沌诀靠 +情色文學 +鮮族 +中文情色网址导航 +奧美電子 +多党执政 +少妇被鸡吧操 +和两勇男玩52P +情色文学 +含住我的小鸡鸡 +臺灣帝國 +免费淫电影网址大全 +操你祖宗 +龜投 +nabi +meinv护士被奸 +毛塞你老母 +紅火女郎~真央~壓倒性的震撼力~汙染女人的快感 +嫂子的阴道好大啊 +hai dao shi dai +色迷城 +宁王府淫色 +爆草 +受灾 +和两勇男玩51P +受災 +操表妹操 +王冶坪 +梅花屄 +新疆打砸抢 +豬容基 +whoyo +淫荡少女穴 +激情淫色 +穴淫 +贱B +和阿姨淫穴 +香港成人激情影院 +外—掛 +作ai +亞洲淫图 +大膽少女 +黨中央 +干妹妹小穴 +我和小啊姨在车上做 +又肥又嫩的小骚屄儿 +华西列夫斯基 +小平 +和两勇男玩53P +淫穴 大鸡巴干 好爽 +nage +国际足坛五大 +成人激情图库 +毛李弘旨 +嫩B弓虽女干 +客户服务人员 +yuckfou +抽你丫的 +网龙 +龟头碰到子宫口 +988wow +制服美婦 +发**纶 +又大又肥的阴道 +卖软件 +刀online +毛官逼民反 +狂插小穴 +穴海 +秦 晉 +妹妹社区淫色 +秦 晋 +征服小姐 +贱b +非典 +龟投 +战牌靠 +古柯 +羅幹 +Biaozi +淫荡教师穴 +吹喇叭 +大鸡巴顶进meimei的小穴 +淫妇自慰 +套弄鸡巴 +笨屄 +獸奸 +學生愛國運動正名 +激情小浪穴 +法轮工 +淫城乱伦屋 +白嫩meinv穴 +新斷線 +Whitey Whitey +aika +淫水横流 +qqpp +qqr2 +摇头丸 +滚那吗瘟比 +Asian Hot 018 岸田香織 女陰破壊 +KOKESHI COWGIRL Vol。29 石川优季奈 +女人被迷奸的时候也很爽 +新手辅导员 +大鸡巴在她的小嘴抽送 +美女与猪性交电影 +经插进我的穴了 +dfdz +卡通美女淫乱图 +杂种 +repent +買賣 +贝肉 +百家性大型黄站 +穴爽 +激情最新网址 +肉壁包容着鸡吧很舒服啊 +fils de pute +毛分裂祖国 +毛龟孙子 +性無能 +黄色小说 +妹妹淫图 +basterd +毛麻醉乙醚 +花瓣正在潺潺地渗出蜜汁 +我和jiejie的淫乱史 +Clayton Dodge Clayton Dodge +统独 +插妻子小穴 +旅館自拍 +雞巴 +他媽ㄉ王八蛋 +法~~綸 +本站10001多部激情电影全部免费试看 +激情 +李继耐 +毛摩门教 +操插妳 +顾顺章 +牛比靠 +六四参加者 +宏法 +日本激情淫色动画片 +meng huan guo du +基督教 +亀頭 +淫奸表姐论坛 +森田めぐみ 凌辱饲育 +管裏員 +赣江学院 +免费性爱电影 +阴道夹的我好紧 +靠么 +vgbh +淫奸表妹 +在线淫影院 +嫩穴 插干 …快插我吧 +Qzone精彩由你而来 +阳物 +香港成人电影网五月成人情色论坛 +美女极品嫩穴 +多黨執政 +毛卖国求荣 +在线免费观看黄片A片 +色情网址网上做爱 +┅┅别再磨了┅┅痒死啦!┅┅快 +renminbao +粗大的肉棒………我受不了 +毒龍舔腳 +爱妻淫穴 +洪 吟 +熟女亂倫 +奸淫……好舒服 +RMB +少妇房中自淫,和两勇男玩17P,操得直叫爽 操日本淫女穴 +淫奸护士姐姐穴 +game +情色电影网站 +民主墙 +欧美淫图 成人色情网 +onair +油田总部 +iuiuu +抵制日货 +无网界 +da hua zhan guo +操你老母 +乳頭 +肉簫 +免费成人激情电影 +104bb成人小电影 +JB靠 +姐姐的肥穴 +曹剛川 +淫奸美女 +爽死你淫图 +插入小姨的子宫 +插 护士 +藤人 +猛插 +tong shi tian di +荣誉之战I--钢甲洪流 +你老妹 +jiaochuang +藤仁 +罗富和 +榮譽之戰I--鋼甲洪流 +馒头屄 +氣性坏疽病 +妖艷醫生 +陰毛 +GameMaster +春色AV激情片 +18DY性爱电影 +賽你老母 +让你操 +san guo hao xia zhuan +淫女淫洞 +刘澜涛 +老二 +hun luan mao xian +抽插26岁处女妹妹淫叫不断 +欧美淫女在线看电影 +碧雪情天 +亚洲淫色网站 +极品成人A片无码 +肉棒插到花心深处 +毛麻醉枪 +路易 +fuck台独 +莎木online +狂插日本学生妹 +耶蘇 +怪獸總動員 +淫女老师 +脑残 +tengwu +毛鸡奸 +全免费淫电影 +干你良 +街头篮球 +政治打击 +瀨名 +學潮 +露出了娇小鲜嫩的阴道 +吳德 +李禄 +fuck世界日报 +抽插55岁处女妹妹淫叫不断 +毛王昊 +陰水 +fofg媽的 +幹的你 +猫扑 +肉箫 +發*侖 +毛税务总局 +劉奇葆 +騷貨 +山口组 +fuck受虐狂 +易丹轩 +免费淫女看电影网站 +特码 +X妈牛比 +公子开 +日朱骏 +蓬浪 +王子傑 +淫护士 +插妹妹小穴 +minghuinews +手记注册日韩5010部激情电影 +毛李瑞环 +李鹏* +狗B +哥伦布 +许世友 +吴弘达 +好肥的阴户 +97sese +六四事件 +瞒报 +藤任 +群奸 +手指扒开红嫩的阴唇 +tum tum +張朝陽 +毛轮功 +狗b +鹿城最新娱乐小说 +aids +性饥渴 +捏你奶子 +毛性爱 +陳毅 +妹妹黄站 +监听王 +艷舞淫業 +華國鋒 +死亡笔记 +wg武功 +最强美乳おたま初解禁 +成人之家 +免费A片日本淫电影 +無碼精選 +阴茎把子宫顶烂 +最新99bb)有名女优~及川奈央-痴女教师 +魔法奇兵 +你妈了妹 +无界浏览 +錢運錄 +欲望 +捅比 +中青旅创格 +免费试看激情成人电影 +操 gm +比卵 +鸡吧插进肥嫩的小骚屄 +BT激情 +艳星诱惑 +操嫩穴 +日本熟母 +操你大爷 +强奸23岁处女全过程/淫妹阴毛小穴 +中原油田 +监管 +大纪元新闻网 +免费成人情色激情视频聊天 +肉缝 +QQ幻想 +黄祸 +神经病 +干她妈 +插穴图 +GOQO +整根阴茎没入她空虚已久的阴户 +法$$淪 +日本美女吃精图 +发沦 +强奸28岁处女全过程/淫妹阴毛小穴 +法@@綸 +世界都 +毛欢城互动 +95bb成人小电影 +亚洲激情网 +我的小穴好爽 +金瓶梅 +免费在线淫奸mm电影 +月经 +換妻 +毛梅花网 +紫彩乃潮吹赛红音 +马大维 +龟头挤进了jiejie的小穴 +成人色情网站 +毛十八摸 +你它妈的 +私處 +手指对她阴蒂的刺激 +中条英机 +尉健行 +免费电影未亡人柔肌 +国际法院 +王军涛 +賣號 +肛门拳交 +毛受虐狂 +吴德 +銀民吧 +2。23會議 +淫荡少妇穴少妇嫩穴 美女的嫩穴 +教你如何鉴别处男处女的方法(组图)18岁禁看 +操插你妈 +指导员 +少妇房中自淫,和两勇男玩8P,操得直叫爽 操日本淫女穴 +星戰前夜 +干洋妞穴 +遊戲監督員 +毛鸠屎 +travestido +出售此号 +裤袜 +美麗世界 +粗鸡巴 嫩穴 +和妹妹肏屄 +淫乱小说 +毛卵 +台湾18岁成人 +張宏堡 +日本精選無碼DVD +毛杀人犯 +我将肉棒狠狠插入漂亮的老师小淫嘴抽插数十次 +强奸34岁处女全过程/淫妹阴毛小穴 +少妇房中自淫,和两勇男玩19P,操得直叫爽 操日本淫女穴 +淫水横溢 +虎虎虎~ Tora-Tora Platinum Vol。2 : 魔性的meinv 鈴木麻奈美 +操淫荡少妇 操淫荡护士 激情穴贴图 +huo xian ren wu +淫女吃尿 +嫩缝 +外••挂 +fuck舔西 +亞洲淫娃 +人体炸弹 +法^纶 +亲亲小芳 色咪咪论坛 新亲密爱 六月龙盟 人间仙境情色网 +毒品 +发浪 +插妳 +教你怎样延迟射精22岁以下禁免费淫电影a片 +fuck他妈的 +天安门大屠杀 +痛批政法委 +da tang +毛南联盟 +肉縫 +傻卵 +蒋中正 +毛独立 +免费成人A片 +黑省副省長 +封从德 +淫欲日本 +山口組 +黑省副省长 +淫贱妹妹贴图论坛 +發^^論 +淫女浪穴 +内衣模特露点走光 +zhen feng shen +成人激情聊天室 +發@侖 +韓國自拍無碼系列之二) +色情电影 色情排行榜 +毛台独 +妈……你的小穴好插 +原子能机构 +江绵恒 +东西南北论坛 +曼施坦因 +成人激情淫洞网站 +中国孤儿院 +淫色贴图 +胡緊套 +淫魔 +姐姐的屄 +长身丝袜meinv~赤く烂れたマンコが痛 +李老師 +狂插淫荡女护士 +毛玉杵 +亚洲艳情男女图吧 +射屏 +法@@纶 +fuck死GM +学潮 +fuck死GD +瑪雅網 +求你插插我吧好痒 +菜逼 +社科院 +台湾民國 +曾 慶 紅 +法耣功 +外交部 +耶和华 +jin yong qun xia zhuan +傻吊 +tan ke bao bei +勃起 +步飞烟 +骚逼大型成人色站 +Tora Tora Gold Vol。16 香山圣 +教你怎样延迟射精26岁以下禁免费淫电影a片 +淫荡 穴 淫洞 +我淫我色淫色导航 +淫乱小姨子小说 +龜兒子 +令人喷血的春宫108姿势 +法~~纶 +台湾民国 +平成女忍者 奥义中出し陵辱 +法磮功 +毛叶剑英 +溫 元 凱 +猪操 +胡紧涛 +nigga nigga +审查 +龟头压挤阴道 +用劲吸吮咬舐着湿润的穴肉 +k粉 +手记注册日韩5022部激情电影 +少女床上自拍 +狂插日本美女护士 +色mm激情论坛 +嫩縫 +育碧 +李少民 +wowassist +熱 站 政 論 網 +陳曉寧 +毛小泉 +法^綸 +大波波 +江核心 +林长盛 +免费电影 美女电影 +kefu9you +激战 +f_u_c_k +89年的斗争 +廁所偷拍 +完全免费淫电影 +肉棒伸入她的口中 +幼女玩性 +法倫 +Image)ヌーディストGALビーチ +天天干贴图 +小電影 +晚年周恩来 +淫妻的穴 +大鸡巴好趐┅┅趐┅┅快┅┅别揉了 +妈个b +览叫 +咬着龟头 +feng kuang sai che +操操你八辈祖宗 +唐人街情色导航 +成人两性电影 +卖ID +迪里夏提 +毛游行 +午夜电影 +熟女乱伦 +解放軍306醫院 +PP电影 +八九学潮 +┅干的妈好爽 +色情网站 +教你怎样延迟射精18岁以下禁 +meinv口含鸡吧玩内射 +表舅妈与我 +9you +操操gM +走光偷拍 +色情导航 导航 +specialforce +义解 +sheng da fu weng +無碼淫女 +淫民欧美激情贴图 +好弟弟使劲干jiejie +目标软件 +侬着冈峦 +淫女疯狂偷情 +淫 电影 +老逼 +海洋局 +汪岷 +鹿城娱乐 +毛卖ID +狂插日本少妇 +liu xing hu die jian +露点 +屎妳娘 +fuck傻子 +粉嫩美少女穴让你插 +毛淫 +肉棒在姐姐的阴道里 +操mm嫩穴 +搞他 +甜嫩穴 +民主党派 +大花B +法侖 +插小穴的快感 +狗b新光明 +操操gm +香港色情影星meinv裸体 +瘋狂賽車 +嫩鲍 +狗杂种 +黄片 +zhengjianwang +小姨的穴 +白梦 +黑点 +幹妳馬 +亚洲激情片 +亚洲情色 +日领馆 +毛新闻办 +一本道 +赵海青 +殘疾 +猛干 添 +台湾18dy电影 +yi wang chuan shuo +陈至立 +含屌 +操吃屎 +浪女叫春成人招妓网色性网电影性暴力电影 +fuck吴仪 +午夜激情 +骚洞 +反封锁 +成人激情论坛 +相奸 +國賊 +春光外泻 +插她 +slanglist +法伦 +Red Hot Jam Vol。 藤崎夕凪 +免费电影妖艷醫生 +龟奴 +后庭 +女教師 レイプ 輪姦 +趙 海 青 +民政局 +爆乳家庭教师 +毛傻卵 +绝品meinvが恍惚颜の绝顶快感 +毛邮政局 +外*掛 +卖QQ +免费激情论坛 +艾滋病 +新石器時代 +外/挂 +美女护士被奸 +预审查 +胡乔木 +fuck小泉 +插的jiejie好爽 +mforest +pao pao +熟女顏射 +骚比 +stoneage +亚洲情色淫穴 +狂插日本meinv护士 +骚母 +用手指分开两片肥嫩的阴唇,露出了那娇小鲜嫩的小屄洞 +水扁 +司马璐 +龟头对准菊门 +袁纯清 +插你丫的 +法仑 +雜種 +毛三民主义 +外-挂 +粉红色的大阴唇正紧紧的闭合着 +奸淫空姐 +漂亮。女記者採訪時被逼姦 +星戰情緣 +断電 +屄儿好┅┅好爽!┅┅好舒服!┅┅ +毛性无能 +日逼 +18岁淫乱 +外/掛 +激情淫穴导航 +足腳交 +儿子淫奸jiejie +对著暴露的美穴狂插 +法$$论 +聶榮臻 +草你妈靠 +Bao皮 +三反五反 +龜头 +狂插 +强制浣肠 +淫兽学园 +韩日成人激情电影 +把肉茎舔乾净 +mwo +法沦功 +法婨功 +龟头 +毛恐怖主义 +mxd +天安門母親 +猖妓 +外-掛 +毛傻吊 +朱林 +韩启德 +Heterosexual +色站导航 +大鸡巴顶进妹妹的小穴 +搞你 +你馬的 +妈个B +KAO +法@@掄 +香港激情性爱影院 +練完瑜伽功做?才爽呢(國產3p) +老卵 +变态心魔女仲村 生中出 +骚水 +龜奴 +色情聊天室 +麻痹 +騷穴 +綿阳 +成人圖片 +拉登 +蔣彥永上書 +国贼 +綜聯數碼 +色情五月天 +肉棒插入meimei小穴 +魔域 +羞耻母 +免费成人两性影院 +吴仁华 +老师被干小穴 +抽插56岁处女meimei淫叫不断 +蒋彦永上书 +国外meinv黄网 meinv激情SM处女淫水图台 +性愛圖片 +色情导航 av电影 +牙齿轻咬着阴核 +淫荡姐姐勾引小弟玩操屄 +朱溶剂 +插淫妇骚穴 +李宏志 +邓笑贫 +fuck文化部 +肉棒抽插…不要 +MUGEN EX Vol。4 +她的阴道乳房真美 +毛彭真 +發論功 +煞逼 +台湾成人网站 +阳具插入小穴中 +partita +插入内射 +世界日报 +CCTV +大鸡吧塞进逼里使劲插我 +日本淫妞 +哥哥我爽晕了 +谭绍文 +邻居少妇 干邻居少妇 邻居的少妇 邻居美少妇 操淫荡少妇 +阳具对准她湿润的小穴口 +MUGEN EX Vol。 7~滨崎(MX-07) +烂人 +日本色诱女郎图库激情成人视频聊天室 +Bastard +puSSy puSSy +phuck +去死 +盖世太保 +f a 轮 +三去车仑 +sealonline +鲍岳桥 +毛美国 +情色 激情 美女 穴 +pao pao dao +法~淪 +两性淫乱小说阅读 +完美國際 +发@伦 +天上碑 +胡XX +肉棒 插得太深了 +强奸护士 +连胜德 +免费淫奸女A片段试看 强*十八岁美女护士看完保证你打飞机 +淫穴把整个龟头吸住 +狂操 +青樓 +射入阴道里 +抢 粮 记 +MASTER +女教师家访遭遇体剃毛内射肛交口爆喷尿虐待 +毛人大代表 +蜜汁 舔穴 塞入 +成人论坛导航 +极品金牌素人口交系列 +溫逼 +陽萎 +操操XX +法$$論 +hkhk68 +胸涛乳浪 +亚洲淫色俱乐部 +奴隶调教 +盤古軟體 +网星 +tnnd +毛一夜情 +好爽┅好舒服小骚穴 +网易 +f a 輪 +狂插林心如穴 +西洋美女 +狗成 +368成人网站 +乱伦父女 +國產偷拍 +Gold Angel Vol。7 纹舞らん 可爱 +发@仑 +倒台 +日軍 +性愛插穴 +15年前的“共和国卫士” +又硬又大的肉棒 +插入……大肉棒 +叫春 +台湾小穴自拍护士做爱 +潮吹喷射地狱 不行触摸的喘气 4P肉奴隶中出 +毛卖B +吗的靠 +将手指插入她的穴里 +法@@抡 +抽插20岁处女meimei淫叫不断 +北京之春 +不要!嗯──啊啊、啊啊!” +亚洲激情帖图 +法(轮)功 +轩辕二 +獸交 +毛吴仪 +无码炮图 +大中国论坛 +同房 +美幼 +毛穆斯林 +肉棒就顺着湿滑的阴道口插进去了一半 +cdjp +台灣狗 +哦……再快……小屄要美死丁…… +性色俱乐部 +发$$轮 +zl-fm。com +倫功 +女学生嫩B +外@挂 +风尘劫 +fuck他马的 +自民党 +毛一中一台 +毛吕秀莲 +青天白日旗 +t2dk +骚浪 +封神 +58xp。com 电影免费 +大鸡巴用力的往小穴里面狠插 +陵辱面接4人淫乱娘 +earthciv +春藥 +毛罗干 +庆 红 +她的阴道好深啊 +本站10020多部激情电影全部免费试看 +鸡8 +和阿姨作爱 +nnd +地藏 +九評 +毛卖QQ +操藏独 +淫语连连 +賤種 +如果你未满19周岁请自觉离开。 +戳那吗逼 +18摸 +插的meimei流淫水 +三去车侖 +臭机八 +膏药旗 +GAME MASTER +jiang wang +外?挂 +日本激情电影 +qqtang +柳下惠 +。gm +莖候佳陰 +令人喷血的春宫108姿势(组图)22岁禁看 +猪头 +让我操高潮淫水一直流溅 +新闻管制 +無界流覽 +外?掛 +好大的阴户啊 +性感动感美女日本幼少女性感写真 +援助交际 +亚洲激情影院 +陰蒂 +强奸38岁处女全过程/淫妹阴毛小穴 +成人电影 淫穴嫩穴骚穴 +海之乐章 +小骚娘们的小嫩骚屄 +89风波 +蔣彥勇 +c a o靠 +我日靠 +玫瑰园 +鸡巴对准穴口猛地插进去 +嫩鮑 +毛滚 +毛管理员 +亞洲瘋情 +4-Jun +淫奸表姐 +在线淫电影 看完保证你打飞机 +淫水狂喷 +万钢 +肉茎 +外@掛 +好……小……小骚穴 +發倫功 +……好爽喲 插穴 +fuck傻屄 +操插你 +ri ni ma +亲美 +日本激情淫影院 +ayawawa +日你妈啦逼 +免费黄色淫电影一社会男子在宾馆里强奸一 +如果你未满27周岁请自觉离开。 +台湾成人黄色电影 +老兵 +大鸡巴插小穴 +八九年那个春夏之交 +卖号靠 +小穴疯狂地吮吸着我的阳精 +援助交際 +青楼 +三去车仑工力 +18dy村妓 +本站10008多部激情电影全部免费试看 +tui tui xia +胸濤乳浪 +毛国土资源部 +骚棍 +刘华清 +盗窃犯 +手指抠肉洞 肉缝 +骚棒 +强奸美女狂插处女阴道 +大跃进 +插淫屄 +毛贱逼 +陰阜高聳 +月光宝盒 +周六性吧 +儿子的肉棒好长啊 +红色的小穴 +下贱 +梦幻之星 +本站10011多部激情电影全部免费试看三天 +tianxungame +抽插51岁处女妹妹淫叫不断 +VIP激情成人电影 +89暴乱 +三级电影淫电影艳情电影 +毛穆罕默德 +杀手 +處女 +坐脸 +淫水爱液 +辅助程序 +純情尤物由美(中文字幕) +鸡巴抽插好……爽 +25dy淫色贴图 +民警当副院长 +肉莖 +杨巍 +運营者 +鸡芭 +婊子养的 +我湿淋淋的阴道 +陷阱超人哗哗曼 +欧美成人漫画贴图区 +壓制 +如果你未满35周岁请自觉离开。 +和平演变 +ji zhan +爱神之传奇 +狗操 +lastchaos +她的阴户好嫩啊 +meimei的穴好紧 +鄒德威 +法$纶 +教你怎样延迟射精32岁以下禁免费淫电影a片 +妓女靠 +肉棒狠狠地插进小淫穴中 +刷钱 +淫穴电影 +毛氵去 +龟头插小穴 +MAKELOVE +机掰 +毛舆论钳制 +啊┅┅用力┅┅用力插烂我的淫穴 +下賤 +meimei的嫩阴户 +来干 +明星捐款 +毛卖比 +粗制吗啡 +插进 小穴 嫩穴 +新手輔導員 +Tora Tora Gold Vol。15 香山圣 +海洛因 +毛他母亲 +meinv极品嫩穴 +龟头顶破了处女膜 +口內爆射 +龟头插进了小穴 +悲惨-双胞胎一起被奸 +红十字会 +365情色网 +靠你妈 +meimei的阴唇好嫩啊 +玉乳 +法*綸 +小屄又湿又滑 +王丹 +少女被强奸到高潮时偷拍小A片免费淫电影a片 +淫乱插穴好爽 +懶趴 +淫浪少妇和医生疯狂做爱 +操操Gm +淫电影//教你怎样延迟射精 +呂秀蓮 +风骚欲女爽爽网 +情色图片成人小说 +虐奴 +陰莖 +教你怎样延迟射精41岁以下禁免费淫电影a片 +插 干姐姐 好爽 +淫色贴图小说 +狂插老师穴 +大*FA 弟*子 +8 仙 +大 中 國 論 壇 +操操GM +屙民 +完美国际 +猛將 +猛将 +色情小说 BT限制级电影 +激情淫穴小站 +美女淫图 +無碼體驗 +不像我讓你打~ +cctv +露毛 +项怀诚 +成人午夜剧场 +老土 +50zhou +把我的穴插烂了 +睪丸 +一元激情电影 +46xp。com 电影免费 +鹿城娱乐情色 +wan wang zhi wang +抽插27岁处女meimei淫叫不断 +中天萬方 +代理 +亮穴 +机战 +成人 激情 淫 另类 +狗日 +欧美做爱 +香港激情淫色贴图网 +发^仑 +台幣 +狂插处女穴 +巡府媳 +国家主要部委 +台湾独立 +色网阴道特写强奸24岁处女全过程 +jue dui nv shen +东方红时空 +迷姦雙胞妹妹 +龟头挤进了她的阴道 +毛东亚病夫 +成人免费 +免费成人图片 色情美女做爱美女小穴写真 +Groove Party +我跟妹妹肏穴 +性之站 +去你媽的 +台湾十八两性电影 +獨占動畫~肛門 1~長谷川 +好紧的阴道啊 +淫色全免费 +抠穴 +陰茎 +痛经 +杨元元 +操XX +日本黄色电影 +餘震 +本站10007多部激情电影全部免费试看三天 +成人激情性爱电影 +大鸡吧插人阴户 +毛鸦片 +色mm激情图片 +吃屎 +睡着的武神 +發$$綸 +用肥嫩的小穴套弄着我的阳具 +毛吗啡 +包pi +拒绝食堂 +谢非 +毛淫靡 +討伐 +疯狂jiejie教弟弟小说 +妹妹乱伦理淫穴 +情色视频聊天 +se淫乱姐姐小说 +法*纶 +鹿城黄站 +無網界 +李 錄 +三角裤 +Kao +吊子 +六月四日 +情色天崖 +丝诱 +成人 激情 淫乱 另类 高潮 +发抡 +十五周年 +都市2046 +抽插37岁处女妹妹淫叫不断 +林保华 +狗日的 +乳腺 +讨伐中宣部 +發~~綸 +89暴亂 +法崘功 +佛教 +淫奸少妇论坛 +文革 +日本免费激情学生美 +圣泉学淫 +成人情色论坛导航 +黄色网站 +日本天皇 +基督基督教 +Pajawa Pajawa +色mm穴激情图片 +残疾 +抽插26岁处女meimei淫叫不断 +张春桥 +反社會 +林樵清 +反攻 +少女激情自拍 +屄毛 +FLG妈B发抡 +亚洲淫穴电影 +舔屁眼 +18淫书 +剑网2 +日本激情淫色下载 +剑网3 +插穴淫图 +猛干 +劉延東 +精液射在妹妹的子宮 +我日你妈 +mo li bao bei +Tibet国 +wan mei shi jie +你老味 +『第一爽图区』 +用舌头舔着他的马 眼 +災区 +激情美女贴图九九情色 +青 天 白 日 旗 +強制飲尿便器小野悠美 +毛明慧网 +江山 +18dy电影 +操曹刚川 +未满20岁的请自行离开 ! +中機電 +大鸡巴插进了的小穴 +灾区 +raycity +日本激情淫色影院 +很黄很暴力 +災區 +小犬蠢一狼 +王勝俊 +纳粹 +17岁处女小阴唇张开 +老味 +藏独靠 +宋书元 +外$掛 +万维读者论坛 +下身 +瘟B +銷魂洞 +Anal Asspirations 7 +親 美 +毛卖淫 +小穴被插 +灾區 +寫真 +高级应招女 +肉棍子 +发^伦 +毛唐家璇 +抽插53岁处女妹妹淫叫不断 +情色成人基地 +連続失禁 +外*挂 +空姐护士淫荡图片 淫荡女护士 淫荡少妇穴 +guild wars +在线免费观看性感mo特日本性感奶霸图片骚 +瘟b +反日 +教你如何鉴别处男处女的方法(组图)18岁禁看免费淫电影a片 +皮條 +臺灣黨 +百家乐 +又长又大的肉棒 +潮吹喷射地狱 不行触mo的喘气 4P肉奴隶中出 +61xp。com 电影免费 +风雨神州论坛 +麥角酸二乙基醯胺 +骚b +钓鱼台 +虎虎虎~ Tora-Tora Platinum Vol。2 : 魔性的美女 鈴木麻奈美 +山本 +男人阁-套图站 +陸肆 +我和姐姐 +李录 +裸體少婦 +毛密洞 +淫乱熟女 +幹你媽逼 +抽插23岁处女meimei淫叫不断 +毛meimei贴图区 +毛东突组织 +美女激情视频聊天室 +春药 +鸡吧阴茎插嫩穴小穴 +同床 +賽維創世 +奸杀meinv大学生 +放荡少妇宾馆 +轩辕剑 +比毛 +游戏指导员 +fuck驶你公 +回民暴動 +一面做愛 +娇小鲜嫩的小屄 +温家保 +biaozi +毛体育总局 +代开发票 +18成人网 +屌毛 +手记注册日韩5007部激情电影 +教你怎样延迟射精29岁以下禁免费淫电影a片 +毛手机复制 +黃片 +龟头缓慢地从我的阴道中戳入拉出 +少妇房中自淫,和两勇男玩12P,操得直叫爽 操日本淫女穴 +meinv主持27小时全天激情热舞 +骚B +手机注册激情网站 +手记注册日韩5016部激情电影 +信不信我撞死你 +十年动乱 +毛宋祖英 +沦功 +激情潮噴 +大鸡巴紧紧的插穴 +……插的……好舒服 +法$綸 +浪女淫水 +车牌反光 +两岸关系 +操gm +meimei的小穴好紧啊 +神甲奇兵 +淫乱jiejie小说 +掰开嫩穴 淫液 +gun gun qiu +贱bi +肏姐姐屄 +纪念松岛MM引退大作-松岛枫合集4 +爽穴 +淫护士小说 +比水 +她的阴道真紧 +王刚 +毛骚B +發浪 +東熱空姐 +免费在线成人电影 +免费淫色电影网站 +超恶い状态10人の俗人たち +睾丸 +免费淫女骚穴在线看电影 +操gM +com流氓 +皮条 +回民暴动 +流出大量淫水 +淫乱 爽电影 +淫奸女教师 +台湾帝国 +银行账号 +东土耳其斯坦 +on9 +毛胡锦涛 +飞扬论坛 +激情动漫成人 +Marc Dorcel)Jesse & Jenna expertes du vice +王克 +如果你未满24周岁请自觉离开。 +亚洲淫色 +琼浆玉液 +司马义•铁力瓦尔地 +靠你媽 +干的爽 +援交 +美女网站脱衣美女百分百作爱 +赛维创世 +百海 +抽插到高潮 +两腿之间 +王八 +哥哥的大肉棒 +扒开她的嫩阴道 +免费桃色电影不需注册 +六四運動 +点击观看*林心如做爱*色情电影 +熱血英豪 +三级淫水写真 +掩埋 +麦叫酸 +于浩成 +日本情色电影 +寇晓伟 +外$挂 +毛胡锦淘 +wg99 +先奸后杀 +惊天动地 +毛圣女峰 +游戏发奖员 +性感誘惑 +發淪 +一码中特 +坦克寶貝 +臺灣建國 +moxiang +要色色 +气象局 +女儿的阴道好大啊 +fuck賣.國 +TENGWU +18Chinese Japanese AV Girls +倭国 +毛三个代婊 +王兆国 +阿姨的阴户好肥啊 +白烂 +和两勇男玩18P +張 昭 富 +屠杀 +社會主義 +免费淫色情电影 20岁女大学生被强#(组图)全过程 +姐姐的阴户 +成人淫图 +王兆國 +醬豬媳 +狼友 +情色导航 +台湾盲人meinv在家疯狂做爱 +錯比 +外~挂 +中宣部是中國的愛滋病 +18岁少女处夜激情性爱电影 +毛六?四 +和两勇男玩17P +taip +择民 +淫色贴图导航 +魔幣 +淫电影//教你如何鉴别处男处女的方法(组图)18岁禁看 +cnouc +鳳舞天驕 +GAME master +梦~ 总辑篇-GONZO Vol。 4 Rio +代练 +倚天 +手记注册日韩5025部激情电影 +操插深些 +激情淫穴影院 +抽插27岁处女妹妹淫叫不断 +娘饿比 +威而钢 +150m。com +法@@沦 +射爽 +巨灵神 +成人网我该死免费视频 +fuck税务总局 +娘個比 +入穴一游 +猥亵 +89風波 +肛門噴水 +wen dao +劲舞 +和两勇男玩19P +张大权 +jhwg +bt淫色电影 +绿色环保手机 +毛阴蒂 +中国共产党 +在线免费淫电影 +陈蒙 +sex +野雞 +好粗的大肉棒 +插那吗逼 +da hai zhan +张 志 清 +射雕淫女传9 +李洪 +王兆囯 +私立淫乱学园 完全版(中文字幕) +好硬的大肉棒 +胡緊濤 +我和女大学生在公共汽车上做爱 +教你怎样延迟射精20岁以下禁免费淫电影a片 +jiejie的肥穴 +jie tou lan qiu +小穴套着鸡巴 +ma chang da heng +免费淫电影吴宗宪搞笑语录(19禁看) +毛温家宝 +胡喬木 +卖淫 +又嫩又紧的穴 +j8 +告全體線民書 +毛妳娘的 +日本激情漫画贴图 +武林外轉 +狂插小浪妹 +盜撮 +大B私服 +抽插36岁处女meimei淫叫不断 +遲浩田 +快乐到死 +乳丰穴嫩激情性电影 +jhsz +浪穴被你插得爽死了 +法**淪 +老师含住我的小弟弟 +運營組 +毛倭寇 +淫絲蕩襪 +武林外转 +毛工商局 +泡沫经济 +傅作義 +大史 +新黨 +宫泽Keito无修正第二弹 +u r靠 +rape +鸡鸡插入穴嫩 +精液浴 +发廊 +彈 劾 +极景 +干骚女 +強姦犯 +meimei的大阴唇好嫩啊 +綠色數码 +毛硬挺 +狂插美女护士小说 +凸肉优 +龟头插入肉洞里 +和两勇男玩10P +滥逼 +少妇小穴被操的很爽 +谋略高手 +用我的舌头刮着她的阴蒂 +long yu di xia cheng +一对熟女间的性虐游戏 +极品嫩穴 淫穴嫩穴 扒开嫩穴 抚摩她的嫩穴 +妹妹的穴好紧 +恐怖份子 +放蕩熟女 +双龙入洞 +弟弟的肉棒好大啊 +游龙在线 +法**沦 +腾武 +长长的肉棒插进我的阴道里 +毛叫床 +捅我 +品色堂永远免费开放注册中 +本站10020多部激情电影全部免费试看三天 +装B +淫水直流 +xzhonline +淫奸meimei的屄 +fuck温家保 +阿姨的肥阴唇 +Gold Angel Vol。8 仲村りお +免费黄色淫奸电影3级片a片手握着我的大鸡巴 +湿了还说不要 +吸精痴女护士 +香港激情图源成人色情论坛脱衣美女做愛 +杀你全家 +插妹妹淫屄 +自制手枪 +jiba +操b指南 +手机激情淫色网址 +盗撮 +av电影 色情导航 +毛托管理事会 +美女野兽做爱淫图 +赖昌星 +hong bao shi +无需手机注册激情电影 +又顶到我的子宫 +和两勇男玩12P +就去诱惑 +舔奶 +戳那吗B +汕頭頻傳擄童割器官 +口射 +民族分裂 +裸体小姐作爱视频彩福联盟社区 大奶妹脱 +龜公 +放荡少女少妇 +台湾免费淫电影 +11月更新成人导航 +master +亚洲激情meimei +mixmaster +钟山风雨论坛 +alod +全国人大 +和两勇男玩11P +ora-Tora Gold Vol。4~~ささきふう香~~92cm G罩杯美爆乳 +法^沦 +我与网吧老板娘 +makelove +毛新闻出版总署 +密穴 +dragon +27dy淫色贴图 +十八岁禁入电影 +WEB牌戰 +The Best by Private 71: The Best Little Horny Asians +和两勇男玩14P +龟公 +毛你爷爷的 +奸淫电车 +包皮 +厕所盗摄护士jiejie +舌头穴 +毛贱货 +淫奸阿姨论坛 +毛僵贼民 +淫奸小姨子 +滾那嗎B +itembay +和两勇男玩13P +台湾成人19贴图 +肉棒好粗 插 +韩光 +熟女護士亂舞 +痴美女醫生松島 +豐唇豔姬 +吗啡 +基督 +经典炮图 +日片罕见3P加肛交 +爱液 +全家死光光 +和两勇男玩16P +屄……爽死……了……嗯……嗯……快……快 +精选明星扒b图 +灵游记 +運营組 +淫液沾满阴道 +做爱大全 +田纪雲 +毛仆街 +cdjp李鹏* +大鸡巴干妹妹 +ti ti qiu +色情 导航 +三民主义 +毛阴茎 +私¥服 +毛一国两制 +和两勇男玩15P +jiao chun +贩毒 +igxe +情色导航 激情爽电影 +插入蜜穴 +毛嫩b +作爱 +阴茎插小穴 +高級逼 +美少婦 +射精女皇系列Ladies In Lust +高潮 +fuck外 挂 +免费激情网 +淫液从密穴 骚穴 嫩逼里流出来 +氢弹 +俄罗斯美少女惨遭蹂躏-嫩的不能再嫩 +漂亮女站着撒尿躺下被操 +發$$論 +朝天穴 +创世之子猎艳之旅 +阴茎被火热而湿润的阴道所包含着 +毛嫩B +毛六-四 +jinku +劍俠情緣OnlineII +蒋彦永 +av貼圖 +陈良 +MM视频聊天室 +萬里 +中国激情淫色贴图 +12岁处女开包现场 +髙潮 +中俄边界 +欲望成人3GP视频 +虎虎虎~ Tora-Tora Platinum Vol。1 金沢文子 +挂机 +毛发抡 +呆卵 +毛六。四 +外卦 +肉棒插入风骚少妇穴 +MM嫩穴 +少妇房中自淫,和两勇男玩3P,操得直叫爽 操日本淫女穴 +正清網 +好紧的阴户 +被10个猛男轮奸草得血直流 +情欲奸岳母 +林文漪 +狂插处女穴 淫水流 +情色導航 +激情套图 +倖存 +pussy +發掄功 +民意 +吳 官 正 +一面打電話給現任男友 +運營组 +操女人穴 色情贴图 性交贴图 +白石ひより-完全攻略 +狗娘 +新疆獨立 +邓 笑 贫 +陰締 +mland +下體 +插进鲜嫩的小穴 +你爺 +fuck尉健行 +迷魂药 +mai骚 +科洛斯 +淫色俱乐部 +小嫩鸡 +红 色 恐 怖 +张昭富 +你爷 +奇淫宝鉴 +韩桂芝 +18dy淫间道 +勁舞 +午夜免费爽电影 +发愣 +大陆激情淫穴小说 +汕尾事件 +严家其 +粗大肉棒插入蜜穴 +103bb成人小电影 +最牛钉子户 +强奸21岁处女全过程/淫妹阴毛小穴 +干少妇小穴 +信号拦截器 +舔吮她的阴唇 +嫩穴狂插还流水 +zhan guo ying xiong +圣角色扮演学园 +色图乡 +a$shole +暴力虐待 +轮盘赌 +網龍 +艳乳 +淫奸熟睡的妈妈亚洲床上色情图库少女做爱 +杨林 +弟弟淫奸熟睡姐姐 +蝴蝶谷黄站 +又硬又粗的肉棒 +陽精 +Dick +法~~論 +变态 +毛二乙基酰胺 +爱滋 +日本成人激情 +fuck他母亲 +makelove +法@淪 +操淫荡 极品嫩穴操淫荡少妇 +抽插43岁处女meimei淫叫不断 +迅雷下载免费淫乱电影 +絲襪高跟 +春夏自由论坛 +20岁女大学生被强#(组图)全过程 +插他 +骚逼小姨 +抵制奥运 +全 國 兩 會 +观看淫电影 看完保证你打飞机 +汉奸 +美女嫩穴 +未满18岁的请自行离开 ! +日本成人激情淫穴 +封神榜 +操meimei +裙下風光 +两岸三地论坛 +牛B,牛比 +阳萎 +激情成人影院 +肉棒在阴道中疯狂抽射 +毛狗b +首長 +臺幣 +喔…快…爽死 +暴操淫荡小妹妹 +免费性爱电影网 +免費偷窺網 +窩窩客 +淫B浪穴 +强奸犯 +首长 +哪有a片 百万美女贴图夫妻激情免费视频 +又肥又紧的屄 +李宏旨 +xi you fu mo lu +避孕套 +黄色免费电影美女 +孫逸仙 +张伟国 +教你怎样延迟射精18岁以下禁 免费淫 电影a片 +新石器时代 +毛田纪云 +激情视频聊天论坛 +藏青社 +陰精 +RED HOT IDOL Vol。3 Concentrated Sex : 山咲舞 Mai Yamasaki 4 +成人激情asp电影通道 +乳此絲襪 +大鸡吧插meimei淫屄 +干您娘 +On Air +你他媽的 +淫水从穴门流出 +弟弟摸姐姐胸部小说 +阿旺晋美 +嫩bb +日本無碼o ~幼齒女學生 +法^^淪 +G。M +吸毒犯 +三个代表 +綠色數碼 +温家宝 +肉棒插入子宫 +快干我!快干我┅┅我要被干 +我含着阴茎 +插你 +龔學平 +jinv +联众 +朱容基 +全球公審江澤民 +岡巒 +雞巴暴脹 +激情淫色网站导航 +抽插36岁处女妹妹淫叫不断 +MUGEN EX Vol。3 魅惑美少女 : 小日向葵 有码女优首度无码隆重登场 +复员 +激情裸聊 +亚洲淫影院 +欧美两性淫乱图片 +小雞巴 +穴口挤出淫水 +她的小穴插了进去 +porn +毛信访局 +外~掛 +比样 +運營者 +法~~论 +聚丰 +新绝代双骄 +手指插的进小淫穴 +肥嫩的阴穴 +捏弄 +联合国 +黃色影視 +倚天屠龙别记 殷素素 +蒙古達子 +阴蒂 +mythos +狂插 鸡巴狂插 +完全免费淫色电影 +美騷婦 +台湾 18 成人网 +弟弟淫奸jiejie论坛 +淫奸熟睡的妈妈 +窃听器 +独夫 +免费色情激情电影网站 +三級片 +eqsf +温家寶 +艳情小说 +fuck王乐泉 +外\挂 +鎮壓 +fuck温馨 +女友下班后被别人献花接走给操了 +抽插46岁处女meimei淫叫不断 +操你八辈祖宗 +中机电 +世界日報 +插你娘 +情色六月天mm淫乱 +39CK +王八蛋 +xinsheng +血逼 +裙下风光 +自慰 +下流地帶 +鸡巴插进了的小穴 +小泉 +亚洲/无码 +fuck小穴 +熟女乱伦联盟 +下流地带 +阴茎 +爱国者 +贼民 +哥白尼 +賤B +校园激情淫色 +爽女美图 +大便 +12次下跪 +王太華 +魏 新 生 +乳此动人 +淫亂軍團 +冈村宁次 +臺灣民國 +和条友做爱 +扒穴 +www。gpchina。com。cn +cao靠 +田紀云 +舔屄 +誘色uu +肏又嫩又紧的穴 +嫩穴肉縫 +賣B +985985 +txsanguo +美女主持27小时全天激情热舞 +干你媽b +流星學院 +少女嫩穴被插出血 +昏迷 +和两勇男玩29P +毛伊斯兰 +se淫乱jiejie小说 +舔舔私处meimei嗷嗷叫 +陆肆 +狗屁 +马的 +狂操搔逼妈妈 +狗屎 +炮友 +骚妹爽图 +阿芙蓉 +mbs +鸡巴 插 嫩穴 +刘少奇 +週六性吧 +做ai +AV女优 +阴莖 +日本激情淫穴电影 +吴仪 +毛反日 +挖挂 +愛妻淫穴 +淫荡老师穴 +无网界浏览 +18男人摸摸B +生命奇迹 +毛佛祖 +┅舒服死大鸡巴插 +舐她的小穴 +激情淫色视屏 +发~~仑 +淫奸处女穴论坛 +色空寺 +臺灣民国 +靖国神社 +毛学潮 +廖承志 +插你媽 +换妻 +meimei乱伦理淫穴 +崔英杰 +桃園蜜洞 +嫩逼 +他ㄇㄉ +大龟头在花心深处 +爆乳美脚RQ中出し鬼輪姦-- 森高レナ +爱的奉獻 +捅进了她的阴道 +台湾女人裸体贴图 +戴红 +毛观世音 +喷雾型迷药 +抽插31岁处女meimei淫叫不断 +王辅臣 +sm女王 +春光外瀉 +大学骚乱 +苯甲醯甲荃芽子堿 +啊雅娃娃 +二乙基酰胺 +牛比 +亚洲激情 贴图区 +黑白无常 +fuck性爱 +本站10003多部激情电影全部免费试看三天 +发~~伦 +性飢渴 +惹火自拍 +黄色免费超级淫图 +大乳 +美女插穴 +毛厕洞 +林彪 +极品成人电影 +和两勇男玩24P +傅铁山 +粗长的肉棒粉嫩的玉门里进出 +日本淫图 +龔学平 +幹GM +ㄐ掰 +军民冲突 +法~沦 +人肉 +萬鋼 +淫水流出图强*免费淫电影 +刘千石 +免费淫电影吴宗宪搞笑语录(18禁看) +哗哗曼 +性爱 图库 +共产主义 +抽插18岁处女meimei淫叫不断 +九评 +乱伦淫书丝袜淫图 +和两勇男玩23P +毛后庭 +免费淫奸女A片段试看 令人喷血的春宫108姿势(组图)18岁禁看 +小姐打飞机 +华通时事论坛 +迷姦雙胞meimei +免费淫奸黄色电影 +美少妇 +和两勇男玩22P +計牌軟體 +激情XXX电影( +徐匡迪 +生孩子没屁眼 +全球公审江泽民 +我草 +色弟弟 +无码片 +国民党万岁 +伸入姐姐裙内 +(盗摄)女子公共澡堂! +avi免费淫电影下载 +onewg +她妈的 +和两勇男玩21P +成人色网站 +少女一丝不挂做爱淫水直流! +爱的奉献 +朱毛 +亚洲黄站 +近親相姦 +点卡 +刘正荣 +开放杂志 +嫩穴肉缝 +妹妹等你大鸡吧来插 +毛客服 +肥西 +meimei┅┅爽快┅┅死了 +护士穴 +luan shi san guo +pp点点激情播放 +斧头镰刀 +胸罩 +公车淫奸meimei +裸聊日本成人电影 +毛狂操你全家 +日本淫色贴图区 +meinv做爱激情电影 +毛拉姆斯菲尔德 +淫奸嫂子穴 +和两勇男玩28P +胡主席 +三陪 +烂鸟 +(SOD)芸能人 範田紗の超高級ソープ嬢 +小骚比 +下阴 +桑國衛 +蔵獨 +ying xiong wang zuo +弟弟mojiejie胸部小说 +盛大富翁 +台湾成人18贴图 +手记注册日韩5013部激情电影 +圣者无敌 +和两勇男玩27P +天主教 +龟头 磨蹭 插入 小嫩穴 +淫穴 夹 好爽 +弟弟淫奸jiejie +炼功 +免费淫奸女A片 +江八 +俏臀摄魄 +操薄一波 +作爱聚会 +和两勇男玩26P +cheng ji si han +品香堂 +李雪峰 +下陰 +kjking +近親相奸 +如果你未满32周岁请自觉离开。 +赣您娘 +驶你母 +貝肉 +國產AV +操操你妈 +365情色 +台湾身份证 +毛新义安 +肉棒在小穴里好爽 +濫比 +和两勇男玩25P +白癡 +吳邦國 +成人黄色电影 +毛台湾党 +我考 +於天瑞 +zlywy +漏B +插入內射 +國家領導人 +NND +肉棒刺入我的小穴 +免费淫奸女A片段试看 令人喷血的春宫108姿势 +册那娘饿比 +Poon Poon +法~~轮 +流星学院 +毛妈卖妈屁 +值勤 +打砲 +无关键词(导航搜索) +國軍 +鸡巴 嫩穴 淫荡 +SUCK +依星 +淫蕩 大雞巴 嫩穴 +simple +falundafa +亚洲激情妹妹 +大肉茎插进小肉洞 +毛亲民党 +國 賊 +教你怎样延迟射精33岁以下禁免费淫电影a片 +cabal +小姐打飛機 +黄色免费电影 +政治犯 +温家堡 +法$$纶 +wgpj +歡迎G12情色電影院 +倒塌 +手记注册日韩5015部激情电影 +唐人電視臺 +淫民俱乐部和meinv发春激情3级片试看 +滥货 +廖锡龙 +多人轮 +dse淫乱小姨小说 +13点 +海盗的悠闲生活 +公子冲 +偷情 乱伦 +狗干 +野外操B更刺激 +法^淪 +cao b +狗幹 +贱比 +老鸨 +凸肉優 +T。M。D +狂插meinv穴 +吞精騷妹 +发$仑 +新闻出版署 +白痴 +插 干jiejie 好爽 +妈的b +保监会 +美乳鬥豔 +滚那吗B +多人輪 +fuck王兆国 +笨比 +卖比 +操淫荡少妇 操淫荡妹妹 操淫荡姐姐 操淫荡护士 操淫荡 空姐操 老师操女老师 学生操老师 操老师小说 +妹妹美图网 +斐得勒 +娇妻偷欢超爽日本电影 +Red Hot Fetish Collection Vol。30 森田めぐみ +久遊 +和两勇男玩20P +杨月清 +成人午夜 +高文谦 +RI NI MA +激情爽电影,夜夜最消魂! +色网联盟 +吳儀 +zhengjian皮条 +超淫荡丝袜妹妹 +毛二逼 +YOUXIKA +妈的B +佳静安定片 +14se淫色图片 免费vagaa电影 免费电影 +NMD +毛恩格斯 +寂寞自摸 +生命奇跡 +欧美激情淫色贴图区 +新任教师の淫行物语 +610辦公室 +Red Hot Fetish 纹舞らん--スケパン刑事 +基地組織 +学生妹meinv在野外偷情 +援助交易 +23dy淫色贴图 +吳邦囯 +法~~輪 +BlowJobs +学生暴动 +淫荡少妇露逼自拍 +梦幻西游 +郭 羅 基 +齐墨 +吾爾開希 +cao ni ma +幻靈遊俠 +fuck投毒杀人 +何候華 +雞歪 +手记注册日韩5000部激情电影 +激情玩穴网 +妹妹的嫩阴唇 +butthole +毛妳老母的 +meimei的屄 +马场大亨 +肉棒插入穴中 +学联 +淫荡妈妈之办公室助理 +发$伦 +计生风暴 +外_掛 +毛买财富 +肉蒲团 +发*仑 +做爱爽图 +法$$綸 +tian zhi you xia +tom在线 +t2dk +taobao靠 +插你妈 +母子乱伦 +东条英机 +杨振 +周百刚 +毛主席复活 +亞洲互動 +站前留學 外國人英語會話教師的癡態紀錄 (3月作品) +浓浓的精液喷入了子宫 +mir +極品奶妹 +肉蒲團 +发$$论 +吞食天地 +中华养生益智功 +用手指玩弄着阴户 +法@@淪 +Biao子 +堕淫 +代練 +f_u_c_k +亲吻小屄 +Himiko 010 Riko Kurusu 来栖! 中出 +日本第一av女优武藤兰被10男糟蹋全记录1小时 +操濫妳那騷穴 +制服诱惑 +精液榨取 +毛澤東 +ALERT +cha你 +外_挂 +2。23会议 +boxun +產黨 +网爱 +陈破空 +Pink Puncher~生中出SEX Ais Cumshot Inside Sex !! : 姬野爱 +色网阴道特写强奸31岁处女全过程 +操淫荡护士 操淫荡 空姐操 +壮汉给纯情处女开苞 +fa轮 +政府無能 +去你的 +黄色影视 +熟妇骚器 +天安門事件 +毛吴官正 +毛食捻屎 +红楼绮梦 +asktao +毛发正念 +香港顶极淫片 +臺灣共和國 +色區 +色区 +网特 +外\掛 +小澤瑪利亞~~誘惑色情 +盐酸二氢埃托啡 +免费淫电影网址 +劍俠世界 +bt成人 +帝国主义 +大龟头碰到阴户底部最敏感的地方 +66xp。com 电影免费 +强*十八岁美女护士 看完保证你打飞机 +三唑仑 +成人图片 +zhengjian皮條 +李昌 +大肉棒干我的小穴和屁眼 +钓鱼岛 +吳 宏 達 +前凸後翹 +306醫院 +气性壞疽病 +戴相龙 +发*伦 +那嗎B +那娘错比 +21世纪中国基金会 +long hun +毛干七八 +插穴 +rxjhhvip +強姦物語 逢乃 +黑鮑娇 +老虎机 +fuck +蒋介石 +乱伦熟睡的jiejie +就去色色 +爆炸 +毛狗日 +六四死難者 +meinv +肉棒顶到花心 +Tora-Tora Platinum Vol。11 持田茜 +赵南 +毛社科院 +亚洲淫色图 +来爽我 +肉棒插进阴户内 +沈彤 +大鸡巴操得我好爽啊 +干阿姨的骚穴 +韓啟德 +推推俠 +在线清晰日本超爽mm毛 +好紧的小穴 +meinv视频短片 +苏晓康 +滕文生 +操射 +淫荡女mm的嫩穴 老师嫩穴 +sm调教 +郭 岩 華 +美乳看護學生 +毛胡耀邦 +netdream +幹死你 +何 德 普 +陰部 +柴玲 +毛死gd +免费淫奸女A片段 +插烂妹妹小屄 +外陰 +銀行帳号 +操草你妈 +两性午夜激情电影 +fuck售软件 +跳大神 +毛死gm +毛生孩子没屁眼 +汤光中 +日你妈啦屄 +推推侠 +小穴好紧 +女做爱光盘亚洲 +色魔 +天鹅绒行动 +发*沦 +乱伦熟睡的姐姐 +淫奸妹妹论坛 +香港GHB水 +高潮白漿 +淫色成人网址导航 +jing tian dong di +干老师的穴好爽 +色鬼 +和少妇做爱好爽 +法^倫 +震级 +万岁 +澳洲光明网 +淫洞 贴图 +一夜情交友 +咪咪圖片 +street of EROS 07 +street of EROS 08 +发~抡 +国产幼女屄屄套图 +淫女床上的自慰 +圓滿 +毛江泽民 +姐弟激情淫色 +狗城 +非常三国 +Red Hot Jam Vol。6 Chiaの露出初体験 +黄色图片 +20岁女大学生被强#(组图)全过程免费淫 电影 +好色妹妹电影做爱论坛 +bukake +平反六四 +非常三國 +姐姐的阴唇好大啊 +最淫成人贴图区 +da qing di guo +fuck吴 仪 +小鸡鸡 +成人网站 +fuck社会主义 +肉棒 ……好舒服喔 +圓满 +邪恶的党 +阴部翻过来看超拽 +千年 +张钢 +meinv插穴 +掰穴皮卡丘 +免注册台湾18dy +弟弟的大肉棒 +三国策 +WANZ)强制猥亵 非合法ドラッグ +妹妹的阴道真紧 +毛妈批 +东突暴动和独立 +精液射进小姨的子宫 +舔舐着阴道内壁 +少女免费激情电影 +毛皮条 +鹿城激情淫色贴图 +強制浣腸 +操打炮 +毛身份生成器 +毛睾丸 +法^侖 +红卫兵 +操抽插 +美仙子 美乳+美腳 天中梨子 +o2jam +免费淫奸女A片段试看 20岁女大学生被强#(组图)全过程 +生殖器 +小穴任由大鸡吧来回抽插 +美脚残酷物语膣壁浸透汁 +毛强效失意药 +處女小穴 阴毛 +淫奸处女 +yutong +亂武天下 +乱伦 +幹砲 +西游伏魔录 +和妈妈玩插穴 +萨斯 +大胆出位 +meretriz +毛肉洞 +大衛教 +黃色網站 +发$沦 +秘密調教凌辱 +fuck西藏独立 +三句硬话 +澳洲光明網 +快活林黄站 +fuck煞逼 +免费黄色网站电影 +幹你良 +hotsex +買月卡 +LineageⅡ +熱血江湖 +去妳妈 +日韩meimei嫩穴淫图 +乳交 +在线激情电影 - 会员注册 +fuck台湾共产党 +美體豔姿 +毛精子 +蠢猪 +mm美图 +女友坊 +肉棒快速抽插 +林心如做爱*色情电影*免费淫电影a片 +林肯 +淫乱军团 +法^伦 +毛小乳头 +中國 +免费淫 电影 +好色cc +台湾色色导航 +毛澤东 +抚弄后插入小穴 +中国 +淫奸电影 +推翻 +vaameline +日本美女图库 +亚洲成人激情影院 +超级樂者 +毛阳具 +抽插50岁处女meimei淫叫不断 +连邦 +露穴 +激情文学区 暴乳母娘 国外淫色贴图网址 +DICK +卖。国 +淫乱秘史 +台湾裸体贴图成人免费电影 +男人最爱的淫图 +裸体少妇 +mm美圖 +di guo chuan qi +乱交 +如果你未满22周岁请自觉离开。 +不用注册淫电影网站 +肉棒好粗 +天安門屠殺 +黄色免费电影meinv +内射魅惑の美少女精液滋滋往外冒 +肉棒插入嘴 +絲路傳說 +天閹 +毛弓虽女干 +蒸汽幻想 +林业局 +新唐人電視臺 +毛孙逸仙 +李 旺 阳 +操屄 +毛丫头养的 +妹妹的屄好紧啊 +Gold Angel Vol。8 Super Erotic Girl : Rio Nakamura 仲村りお +操陈水扁 +我和小姨淫 +姚依林 +你的小穴好温暖… +群阴会 +遊戲指導員 +毛国务院 +两个中国 +毛工力 +妹妞露穴 +毛枪决女犯 +在线淫洞影院 +操尼 +thsale +最新娱乐黄站 +处女性开苞 +孤儿 +pk1937 +毛片 +発射 +成人午夜激情电影 +发@沦 +装屄 +金发表姨子的鲜嫩蜜穴 +恋爱盒子 +台湾成人23贴图 +凯图科技 +九評共產黨 +RED HOT JAM 7 Eeos Note 姬崎水希 +aion +江折民 +肉棒插入肥肥的淫道 +孤兒 +粗大的龟头 +黄色漫画 +王涵万 +台湾党 +插婷婷小穴 +奸淫少妇穴 +天安门惨案 +疯狂抽插嫩穴 +日本淫色贴图 +肉棒插进蜜穴 +天阉 +meinv激情性交射精电影 +2逼靠 +那吗B +李 旺 陽 +香港成人色网址大全 +爛比 +法^仑 +总理 +妳媽的 +圆滿 +unixbox +肉棒的抽插淫荡少妇穴 +军转 +欧美成人激情网站 +毛日你娘 +抽插25岁处女妹妹淫叫不断 +毛新党 +被老师强奸的小初中生 +手记注册日韩5018部激情电影 +黄色免费电影淫电影在快要射精时迅速地将 +慰安婦 +高麗棒子 +姐的嫩阴道 +顶到花蕊 +Ttmd +Gate To Heavens +压/无码 +棒阴道好痒痒 +弟弟的肉棒好粗 +用力刺激小穴 +干小姐小穴 +taobao +我的小屄儿好痒 +阴道图片 +私**服 +sars +张震 +性交課 +免费淫虫在线看电影 +麻醉钢枪 +强奸29岁处女全过程/淫妹阴毛小穴 +性爱擂台 +激情 少女 成人论坛 乱伦 +星際online +柯慶施 +法^^沦 +真理教 +中国美女淫色贴图 +gc365 +21cn +高潮白浆 +人民報 +成人午夜激情聊天室 +毛日你妈 +幹穴 +精子射到妈妈的穴里 +毛狗操 +中宣部 +毛佛展千手法 +王希哲 +妈妈你的穴好紧 +摩门教 +龙虎 +操淫荡妹妹穴 +妈个比 +GM美国 +血洒 +美利坚 +淫meimei电影论坛 +wai gua +血洗 +中天万方 +┅┅妈舒服死了 +GM美國 +毛金日成 +龟头抵制花心顶住子宫口 +李 少 民 +亚洲贴图区月宫 +狂插 嫩穴 +搜狐 +meinv主持24小时全天激情热舞 +勾魂少妇 +caoB +勾魂少婦 +KISS +免费在线淫电影欣赏 +Red Hot Idol Vol 1 +毛六四 +蒙古达子 +干炮插穴 +冊那 +解放军306医院 +共产党靠 +肉棒插入浪穴 +to173 +外@@掛 +性病 +女儿的阴道好嫩啊 +免费淫电影a片。母子淫*乱轮现场看扶正肉棒 +香港免费淫电影 +上妳 +毛苹果日报 +范田紗~120%!H喜不自禁住在一起日記 +阴茎把淫穴塞满 +教你怎样延迟射精18岁以下禁免费淫电影a片 +Priston Tale +先审后贴 +卓奥 +soma +K他命 +李文斌 +钦 本 立 +卓奧 +奥运 +新诗年鉴 +globalrescue +免费淫色电影下载 +压制 +淫荡家族群体性交 +meinv激情视频聊天室 +干全家 +互联经纬 +脫衣舞 +吴 百 益 +藏妇会 +分家在 +毛美国之音 +933cn +五星红旗 +插你老母 +淫奸护士穴 +鸡吧刺入她肛门 +中国娱乐黄站 +骚浪淫水的小屄儿 +麥角酸二乙基酰胺 +qi ji shi jie +色色连 +龍與地下城 +社。會。正。義。力。量 +弓雖 +慰安妇 +嗯…… 啊… 不要停…… 啊…… 插的再深一点… +yxzbw +奧運 +干穴 +指点江山论坛 +幼男做爱妹妹做爱 +淫奸阿姨穴 +八九风波 +白小姐 +毛董建华 +毛外\挂 +错那吗比 +pp241淫色导航 +毛外汇局 +假阳具插穴 +艳妇淫女 +本站10002多部激情电影全部免费试看三天 +哥哥淫奸meimei穴 +交换夫妻 +兴奋剂 +风月大陆 +东正教 +扎卡维是英雄 +成人电影 +無碼炮圖 +法功 +淫水嫩穴 +國 家 安 全 +靈遊記 +毛迷歼药 +弓虽女干 +亚洲成人激情视频 +94bb成人小电影 +家庭乱伦小说 +mforest +圣母 +马巧珍 +毛外_挂 +情报 +创网 +册那 +可爱双胞胎美幼少女的性趣[亚无][402mb] +毛铁道部 +game588 +大鸡巴狠狠插进了她那又肥又嫩的小骚屄儿 +高治联 +二穴中出 +无码体验 +汶川 +实现你的幻想 +塞你公 +外@@挂 +日本18淫电影网 +咪咪图片 +情色谷 +奸淫护士穴 +卡通美女淫色贴图 +剑网 +发^抡 +口交 +自由民主论坛 +扒开她两扇阴唇 +免注册在线淫电影 +反党 +毛死GD +大血比 +kqking +泄密 +骚鸡 +淫荡痴女贴图 +幹你老母 +一邊一國 +成人色情网站初中女生偷拍 +毛死GM +dick呂秀蓮 +発妻 +外教上课迟到就挨操 +fuck射精 +幹你老比 +mm乱淫自拍图片 +激情淫色mp3 +儿子的肉棒顶到妈妈的花心 +毛狂操 +水浒 +爱女人 +新华社 +71776 +法@倫 +垃圾游戏 +……浪穴……大肉棍 +巴赫 +分裂 +毛李登辉 +pp点点激情 +淫色搔女网 +鸡巴对准淫穴 +毛李红志 +淫女穴 +美乳斗艳 +毛天鹅之旅 +凌辱 +勁爆 +狗卵 +nana无修正AV女优ハメ撮り +弟大物勃 +北京当局 +天天干貼圖 +戴 相 龍 +88jb +roi world +共和国卫士 +fuck审计署 +汇款 +反共 +领取 +游戏橘子 +性交课 +煙膏 +大鸡巴干meimei +六合采 +anal +分裂国家 +姐弟淫乱还玩3P +毛系统公告 +法*功 +免费妹妹黄色淫乱电影 +淫賤少女 +光之國度 +火麻 +戴 相 龙 +騷妹妹 +金鱗豈是池中物 +男女激情淫乱图片穴 +肉把鸡巴包得紧紧 +東北xx網 +closeupsof。us +洪传 +受虐狂 +毛警匪一家 +毛龟公 +操操蛋 +毛睾 +毛五星红旗 +拉姆斯菲爾德 +fuck西藏天葬 +狗狼養的 +買春 +fuck王岐山 +免费淫色情电影 教你怎样延迟射精18岁以下禁 +阴道图打手枪专用 +媽媽的 +又肥又紧的阴道 +高清性愛 +淫奸处女电影 +克林顿 +办理证件 +毛发抡功 +毛傻比 +成人图片导航 +激爽电影VIP会员注册区 +刀剑•英雄 +色情工厂 +ji女 +不要注册激情免费电影 +午夜成人场 +陳水扁 +你媽的 +毛煞逼 +納粹 +毛游戏管理员 +毛性虐待 +康生 +超級樂者 +雞8 +亚洲成人午夜场 +fuck王刚 +注册通道看情色电影 +色网阴道特写强奸26岁处女全过程 +布雷尔 +受傷 +gamemaster +人妻交换 +抽插29岁处女妹妹淫叫不断 +乱伦都市 +fuck系统讯息 +olgad +淫妻浪女 +男人若妻夢交 +秦晋 +Tokyo Hot n0156~160合集收藏版 +操淫荡少妇 +戈万钧 +wg886 +捅逼 +走光 +Suck +父女激情淫色 +操你八輩祖宗 +毛何候华 +保卫台湾 +肉棒插蜜穴 +抽插53岁处女meimei淫叫不断 +白虎嫩B +达尔富尔 +毛阴唇 +法@侖 +政协 +激情自拍小电影 +趙 曉 微 +政協 +抽插55岁处女meimei淫叫不断 +高橋英4套片合共 +少妇自慰 +狗剩 +操淫荡少妇 操淫荡妹妹 +白虎嫩b +儿子淫奸姐姐 +八九民运 +毛升达毕业证 +被幹 +王炳章 +卵子 +本拉登 +翘臀嫩穴 +被干 +毛肉棒 +哥哥干的人家好舒服啊 +沧澜曲 +月宫套图社 +法lun功 +教你怎样延迟射精36岁以下禁免费淫电影a片 +操mm穴交 +陰門 +催情药 +激情淫影院 +日本灌肠 +suck你媽的 +在线淫电影,免费淫色情电影 +激情四川方言版 +高 潮 喷精 +姦淫電車 +姬胜德 +蔣經國 +韓正 +手记注册日韩5012部激情电影 +李 月 月 鳥 +人妻交換 +transexual +低價金幣 +台湾成人24贴图 +hardcore +女儿淫奸妈妈穴 +日本顶级淫片 +摸擦小肥穴 +卡卡金币 +14色se成人站 +性学教授 +小阴唇被鸡巴猛的塞进去 +法@伦 +龙腾工作室 +妳老母的 +李紅志 +現役看護婦 +毛肉棍 +大鸡巴插入肉穴 +8。9 +軍民衝突 +中功 +精品性交图 +瑞士金融大学 +邻居美少妇 操淫荡少妇 +成人色情导航 +完全免费在线淫电影 看完保证你打飞机 +色狼俱乐部 +滾那嗎老比 +孫中山 +陰阜 +淫电影//居然花钱请人教性爱姿势(组图) +可卡因 +色情电影 +张林 +税务总局 +meinv淫图 +qqyinsu +mystina +淫图新社区 +鲍戈 +妈妈嫩穴…痒 +血比 +piao liu huan jing +天之煉獄 +顏射 +午夜激情妹妹 +馬巧珍 +姑妈的阴道好紧啊 +处女开包 +现役看护妇 +亞洲性虐 +法@仑 +日你全家 +她媽的 +發~~掄 +去她妈 +姐姐的阴道好紧啊 +分裂國家 +毛淫荡 +365 sex +毛联合国 +…你的穴太紧了 +tie jia zheng xiong +招鸡 +久遊網 +fuck倭寇 +本站10022多部激情电影全部免费试看 +大 史 记 +若叶~Princess Collection(1163) +极品波霸 +丁香社区 +发仑 +张志清 +毛钱其琛 +特种部队 +狠狠地肏 +丁香社區 +李 月 月 鸟 +┅我要泄了┅┅喔 +无毛穴 +camon +王 冶 坪 +操我 +金鳞岂是池中物 +发伦 +hai dao shi dai +long yu di xia cheng +干七八 +毛高丽棒子 +天骄 +ezgaming +日本灌腸 +X媽牛比 +少妇的骚穴淫液 +你的大鸡巴好粗 +成人激情论坛导航 +李洪智 +狗养 +赤匪 +xin chang zhi ye wang +处女淫荡色情网址大全 +混 沌决靠 +陳雲 +美女小穴贴图偷拍少女乳房 +江独裁 +lihongzhi +小乳頭 +大话战国 +性色社区 +淫荡俱乐部 +街头对抗 +母子乱伦之淫穴 +兆鸿 +敬國神社 +杜鲁门 +毛回民暴动 +扎卡维 +国家总理 +那吗老比 +賽妳阿母 +天龍八部 +法腀功 +台獨分子 +鲍彤 +六四平暴 +野合 +酥胸誘惑 +大法弟子 +公审江泽民 +可卡叶 +韓啓德 +毛江主席 +光之国度 +在线免费激情裸聊 +搞B +拿破仑 +法西斯 +赤化 +政变 +AV足球賽11男VS11女大對決 +毛环保总局 +洞洞淫水清晰大图 +针对台湾 +独立台湾会 +儿子顶到姐姐的花心 +傭兵傳說 +懆您娘 +四海龙女 +发^^仑 +帳號 +领土 +穴图 +xing kong huan xiang +webgame。com。cn +色链 +杨尚昆 +阴唇 黏液流下 +粗大的鸡巴插入穴洞 +強姦處女 +法*倫 +現役看護婦下载 +圣火 +办理文凭 +公交车上操女大学生 +强暴 +淫荡女护士 +穴圖 +少妇房中自淫,和两勇男玩1P,操得直叫爽 操日本淫女穴 +亚洲午夜成人影院中心 +三K党 +克林頓 +护士脱衣图台湾激情电影 +免费淫电影 看完保证你打飞机 +fuck网管 +少妇嫩穴扒开嫩穴扒开嫩穴 +pcik +薩達姆 +色情小说 +手记注册日韩5023部激情电影 +成人电影免费成人电影 +法国 +发^^伦 +激情成人淫片 +妳她妈的 +人大代表大會 +成人论坛 +張震 +逼你老母 +李 文 斌 +操日本淫女穴 +精蟲 +中共 +毛三陪女 +啊……快插啊……小屄美死了 +陳奎元 +大波騷婦 +小骚洞 蜜穴 +本。拉登 +成人导航 +黑星女侠 +纪登奎 +毛管理人员 +牛逼靠 +刘亦菲淫阴道流血色片 +懆您妈 +发**轮 +黄色免费淫乱电影强奸片 +毛共匪 +扒开嫩穴 抚摩她的嫩穴 下身也不停的抽插着 +rxjhvip +ハイパー×潮吹きハイパ 麻美ゆま +U/R靠 +媽B +habbo +japansweet +dekaron +淫色小说网短片色情 +阿扁萬歲 +香港激情淫色区 +鸡巴插进娇嫩的花蕊 +法*侖 +阿姨的阴道好大啊 +兆鴻 +u r靠 +妈逼 +情色照片 +紧穴 +神州天戈 +瞳-饮精地狱!监禁无限中出 +哥哥使劲插我 +野鸡 +贺国强 +強暴 +毛看棋软件 +免注册淫电影爱的色放 +血腥图片 +民航局 +処女強奪3穴串挿輪姦 +毛日你 +53xp。com 电影免费 +法$倫 +操那吗比 +鹽酸二氢埃托啡 +射进小穴 +粗硬大肉棍… 抽动…好舒服 +本站10013多部激情电影全部免费试看三天 +视频聊天导航 +騷婦掰B +模拟机 +乳此丝袜 +掰穴打洞 +死全家 +法^^抡 +偷情宝鉴 +安南 +58jb +傻× +吴方城 +宋楚瑜 +森水Cocoa +立即登陆观看激情爽片 +上海孤儿院 +强奸 +肉棒噗嗤一声插入阴道 +工自联 +日本成人贴图区论坛 +午夜剧场成人视频聊天 +淫荡美眉就喜欢玩男人 +做愛寫真集 +阴道 +直操她嘴射精 +强奸44岁处女全过程/淫妹阴毛小穴 +xing zuan wu yu +project +淫水四益 +阴茎在子宫口游荡 +淫水絲襪 +幹炮 +人民币 +公车淫奸jiejie +装逼靠 +小穴被大鸡吧胀的好痒 +卡弗蒂 +色狼论坛 +免费淫色贴图 +烂逼 +中南海 +昝愛宗 +骚穴怒放 +毛他妈的 +干进妹妹的小穴 +鸡巴用力深度插入 +淫奸jiejie论坛 +媽比 +姐弟激情淫秽 +计牌软件 +伊拉克 +成人影視 +下载黄色淫乱电影 +都市乱伦 +日本情色淫电影 +垮台 +VIP特区 激情在线 +fgmtv +肉棒深深插入纖弱的肉洞裡 +青天白日 +feng wu tian jiao +鹿城娛樂 +傻b +穴居人淫色贴图 +共黨 +B博士 +新魔界 +封神传说 +東方資通 +免费在线淫电影网站 +宾馆女郎 +性感肉丝 +中共中央中华人民共和国 +毛多维新闻 +打倒中國共產黨 +caobi +18dy影院 +舔哥哥鸡巴 +情妇 +杨白冰 +成人影视 +清纯派美女可爱的让人想狂干她!【RMVB/195MB】 +hero108 +淫语痴女 +大 史 記 +日你妈靠 +色天堂18禁 +毛淫货 +眾志成城 +肉棒狂插好爽 插我 +華夏II Online +干爆 +华建敏 +毛淫贱 +你妈靠 +少女被强奸到高潮时偷拍小A片 +毛肉棍子 +街頭籃球 +毛人代会 +他吗的 +韓桂芝 +人民幣 +自由亚洲 +湿润的花蕊 +jiejie的小穴被大鸡巴插得好舒服哟 +毛发轮 +靠母 +發~~淪 +法鯩功 +厕所偷拍 +強姦 +欧美淫乱美女论坛 清晰的窥阴图 +六四参加者回忆录 +大粗肉棒插入阴户 +本站10014多部激情电影全部免费试看 +四清 +FUCK +qeeloo +江氏 +达赖 +台湾分裂 +肏我的小屄 +卫生棉条真人使用图 +李弘旨 +色情淫图 +做愛自拍 +mm在线电影a片3级片 +极欲燃烧 +中国人都在上的四大当 +东热空姐 +儿届中央政治局委员 +操穴喷水 +fuck十八摸 +金币网 +杀人犯 +校花沉沦记 +少妇野外淫穴 +免费淫色妹妹电影 +干炮 +叼你 +插在小穴里的肉棒 +吴百益 +功夫online +teen +真三國無雙OL +免费淫奸女A片段试看 教你如何鉴别处男处女的方法(组图)18岁禁看 +肉棒在阴道内喷射 +梦中的女孩 +怎样延迟射精25岁以下禁 +testicle +非洲 +肉棒深入花心 +天皇陛下 +bignews +色妹妹大型黄站 +哲 民 +淫奸少女贴图淫奸女护士贴图淫暴亚洲 +破鞋 +賣淫 +地震局 +暴行白書女 +好死不如赖活着 +自由亞洲 +mm电影小片段试看免费淫影片 +体育总局 +达賴 +fuck威而钢 +天安门屠城 +免费激情电影 爽电影 +激情书屋男女做爱片段 +幼齿 +迷藥 +灼热的龟头紧顶住柔嫩的菊花口 +朱蒙 +午夜激爽电影网【成人电影色区】 +歐美無套 +毛外-挂 +鸡巴狠狠插入娇嫩夹紧的阴道中 +馬萬祺 +淫色电影论坛 +safeweb +SpecialForce +曰GM +紅頂商人 +肉棒深插 +狗乘 +丝袜淫妇 +咪咪情色 +私服 +傻B +hun luan mao xian +淫乱金发meinv +亂世三國 +阴部 +插嫩穴 淫水流 +玩弄她的骚屄嫩肉 +幹bi +你姥姥的 +爽爽爽台湾成人贴图 +曰Gm +毛外/挂 +《金瓶梅》的巨著 +插我 用力插 好爽 +webgame。com。cn靠 +无码内射 +淫荡痴女 +大鸡吧寸寸深入直顶她小屄的花心 +女同志淫乱贴图 +性爱频道 +激情淫色动画片 +操你全家 +掌上书城 +毛妓女 +毛水去车仑 +操操 +英雄纪念碑 +双峰微颤 +妹妹穴 +教你怎样延迟射精19岁以下禁免费淫电影a片 +毛国际法院 +毛黄 菊 +大鸡巴顶进meimei的花心 +nigger nigger +磕药 +情報 +wg17173 +买卖枪支 +強衛 +fuck五星红旗 +哥哥的肉棒好长啊 +专制 +火線任務 +幸运抽奖 +洗脑班 +教你怎样延迟射精24岁以下禁免费淫电影a片 +毛胡紧套 +塞你娘 +灭绝罪 +尖阁列岛 +龙 虎 门 +舔的下体湿润阴毛 +丽春苑 +陈晓宁 +乳 +骚屄娘们儿 +发~沦 +激情热舞 +prostituta +禁断少女 +老少乱伦 +hang hai shi ji +激情小电影 +幹妳媽 +手记注册日韩5001部激情电影 +郑万通 +成人小說 +强奸30岁处女全过程/淫妹阴毛小穴 +狂操你全家 +按摩棒 +台湾成人21贴图 +孫家正 +郑源 +美女口含鸡吧玩内射 +赛你娘 +小电影免费看高潮屋贴图做爱视频表演 +日本美女鲍鱼贴图区 +av贴图 +民主潮 +(人妻。com)人妻の情事2 夫以外の男に中出しされた妻たち +装备展示 +婷婷淫色贴图 +做爱视频下载 +毛切七 +鹿城色妹妹大型黄站 +106bb成人小电影 +中国大型免费成人黄色图片区 +毛牛比 +操博讯 +免费免注册淫电影 +姨妈和我乱伦理小说 +猛插小嫩穴 +台湾成人视频聊天 +meinv激情SM处女淫水 +雪山狮子 +民猪 +豖者 +錢其琛 +毛官商勾结 +台灣倫亂網 +天之游侠 +美女穴 +煞筆 +黄色靠 +freenet +毛贾庆林 +开房 +操催情药 +怀念十五年前的大学生 +冰锋 +mankind +子宮 +本站10017多部激情电影全部免费试看 +子宫 +次郎 +吕秀莲 +玩3p色链 +希拉克 +特別公告 +煞笔 +youxika +吸精痴女 +你把妈的穴穴插满了 +一夜情 +肉缝 小肉穴 +仆 +sealonline +巡查员 +回民 +毛王八蛋 +mierda +大麻 +xin chang zhi ye wang +激情解码两性电影 +亞洲風暴情色 +交通部 +毛狗屁 +赛妳阿母 +狂插meimei穴 +毛毛XX +对日强硬 +五月四日 +遗精 +毛狗屎 +毛温家保 +洪兴 +弓雖女幹 +轮流执政 +發掄 +流亡 +操大*FA弟*子 +最大的性虐待及另類性生活網站 +粉嫩淫臀 +韩国三级电影 +无码做爱 +反华 +欧美激情淫色贴图 +淫东方 +淫語痴女 +nude nude +新唐人电视台 +毛奶子 +毛军委 +毛新光明 +叛党 +法^^掄 +毛王岐山 +民进党 +廖晖 +香港激情论坛 +黃易群俠傳 +qi xia +李沛瑶 +王洪文 +ling tu +龟头顶在花心深处 +丁字褲翹臀 +廖暉 +又骚又大的屄 +姣西 +巡查員 +激情淫穴小说 +信长之野望 +六四死难者 +姐姐的阴户好嫩啊 +免费成人电影 +驶你老师 +美女下体淫水直流 +口交靠 +小姨令我射了好几次 +极品奶妹 +淫戰群P +毛鸡芭 +毛严方军 +林心如做爱网 +兩腿之間 +那嗎老比 +干爽 +坐庄 +三国群英传OL +烂货 +免费淫奸女A片段试看 强*十八岁meinv护士 +和姐姐肏屄 +成人小说 +幹妳娘 +天天情色 +磕藥 +干牠 +反動 +色书库 +六。四事件 +13點 +反动 +epochtime +厕奴 +女醫師過度輪姦陰道麻痺+大量中出強制飲尿小便斗 +鸡巴插入肉洞 +教你怎样延迟射精21岁以下禁免费淫电影a片 +佣兵传说 +foutre +mao xian dao +親 日 +發**綸 +弹 劾 +silkroad +厕所盗摄护士姐姐性感美腿图 肉丝美腿艳情淫欲 +十年動亂 +漢 奸 +萬歲 +毛军妓 +百家性黄站 +家乐福 +田紀雲 +又猛插几下 +儿子淫奸jiejie穴 +王永生将军 +本站10016多部激情电影全部免费试看三天 +jiejie的阴户 +si lu chuan shuo +美女激情SM处女淫水 +大揭露 +于大海 +操大便 +粗大的肉棒 +盛大 +弟大勿勃 +李兰菊 +阴道口湿淋淋的 +家庭乱伦 +少妇操尿穴 +東突 +本站10015多部激情电影全部免费试看三天 +大富翁 +捐款名单 +毛胡乔木 +口圭 +将肉棒插在阴道里面 +討伐中宣部 +淫meimei成人娱乐 +fuck傻吊 +米青 +ghost +大 紀元 +藏青会 +反人类 +吾爾開西 +又肥又嫩的阴户 +政治協商會議 +日本激情淫影片下载 +劍俠情緣 +遊戲蝸牛 +它妈地 +又骚又淫的屄 +Kamikaze Girls Vol。 27高清晰版本 +Archlord +爆操 +皮条客 +免费淫奸女护士图片 +淘宝靠 +儿子淫奸姐姐穴 +肉棒狂插流出淫液 +丁元 +淫民激情文学图库 +龟头直抵子宫口 +远程偷拍 +bt淫色电影免费下载 +meimei淫图 +国产无码 +操林 +毛斧头镰刀 +淫阴贴图 +fuck you +法~倫 +古龙群侠传 +共产党 +星鑽物語 +淫水狂流 +白立忱 +抽插33岁处女妹妹淫叫不断 +毛王太华 +毛龟头 +aids +一中一台 +带练 +fuck天安门一代 +一党 +操meinv穴 +张万年 +神淚 +激情成人午夜 +99bb成人小电影 +毛他祖宗 +那娘瘟比 +粉穴嫩逼 +粉嫩粉嫩的小穴流水 +精液喷射小穴 +勁舞團 +死刑枪毙 +至淫绝地 +农业部 +fuck fuck +扶不起的阿斗 +插后庭 +淫荡美女医生 +meimei的穴好多水 +和阿姨玩插穴游戏 +看棋軟體 +石首 +公審李鵬 +洛奇 +密传 +真主 +手指用力扣进小穴 +阴茎被肉壁紧紧的夹着 +毛驶你老母 +淫液流入穴 +姊姊的小骚屄 +无疆界 +雨星网 +东亚 +apex +性感美女淫穴 +阴唇 口含鸡巴 +艾森豪威尔 +淫液顺着肉洞流下 +日本激情淫穴片 +自插小穴 +urban +自慰摳穴 +一根材激情五月天 +毛狗娘 +极品激情电影 +干 …插我的穴 +美女鸡吧图 +韩日成人激情影院 +硕大的肉棒 +夢~ Pure Idol Vol。 20 : 望月なな +色情电影免费看 +毛外—挂 +军国主义 +淫乱姐姐小说 +hacking +在线淫电影 免费淫奸女A片段试看 +操护士的穴 +自拍美穴 +成人黄色网站 +不玩了靠 +上海帮 +啊 ……用你的鸡吧插我 +法~侖 +叛國 +学生爱国者运动 +婁義 +日本淫色动画片 +粗……肉洞 +挺进小穴 +强奸25岁处女全过程/*妹阴毛小穴 +倚天二 +叛国 +大鸡巴 用力地干 +wg666 +莲花逼 +毛监察部 +操大东亚共荣 +将肉棒插进她身体的最深处 +夫妻俱乐部 +欧美淫乱meinv论坛 清晰的窥阴图 +戳B +狼族淫色群交蜜穴 +fuck圣女峰 +台湾建国运动组织 +黑鬼 +wulin2 +抽插49岁处女meimei淫叫不断 +一股滚热的精液从插得紫红的龟头马眼里激射而出 +淫电影 强*十八岁meinv护士看完保证你打飞机 +fuck文物局 +国家机密 +婷婷激情俱乐部 +保密局 +1989 事件 +英雄王座 +肉棒狂插 浪穴 嫩穴 +毛发论 +肉棒顶开阴唇 +男女激情电影 +它爸爸 +情色藝術天空 +Red Hot Fetish Collection Vol。 34 : Saito真央 +激情淫色网站 +下作 +日韩淫女电影 +龟头在阴道里抽插 +下体 +meinv发春激情在线电影 +行房 +shao lin chuan qi +爆乳娘 +大东亚 +曰gM +哥哥粗大的肉棒 +我漂亮的老师狗爬式做爱现场 +戳b +傅作义 +发展研究中心 +奶頭 +七五事件 +曰gm +法愣 +干进她穴内的龟头 +LIHONGZHI +陰部特寫 +插进少女粉红阴道 +Fuck +生春袋 +素人娘 +抽插31岁处女妹妹淫叫不断 +MAKINGLOVE +羅富和 +ㄙㄞ你老师 +色meimei乱伦理小说 +enculer +スクールガール 直美 +母子淫奸乱轮现场看 +猛嫩穴把肉棒包得紧紧 + Maki +儿子的大肉棒 +妹妹的嫩阴户 +jian xia qing yuan +毛蒙古独立 +靠爸 +淫师荡母 +教你怎样延迟射精 +露B +发奖使者 +YGBH +激情网址导航 +女馬 +嗎逼 +狂插淫洞 明星陰穴 +karma +淫护士电影 +啊呀娃娃 +毛联易 +りすぎ家庭教師 ほしのキララ +震級 +露b +52淫色导航 +足球經理線上 +学生与警察 +海盜王ONLINE +大使馆 +Kamikaze Girls Vol。30-中野美奈 +香港激情淫电影 +帶练 +Tora-Tora Platinum Vol。11 S级圣女 持田茜 +熟妇人妻 +淫电影 +小穴……好爽 菊穴 +多维周刊 +古方迷香 +中华真实报道 +又大又硬的肉棒 +高校暴乱 +匯款 +白虎少妇 +色猫情色论坛 +刘宾雁 +你媽比 +侦探设备 +好长的肉棒 +乔冠华 +法~伦 +黄色三级片 +蔡崇国 +jianghu +温加宝 +学习班 +chuan shuo +反革命暴亂 +插妈妈的小穴 +lei ting zhan dui +濫B +发^沦 +废物 +李瑞環 +mo huan sen lin +唐家璇 +又鳥女幹 +www。qq965。com +台湾成人22贴图 +阴阜 +刚发育好的处女就这么被干 +歇逼 +本站可能有不适合未成年人观看的内容 +噴精 +穴门美女图库 +蜜穴贴图 +淫奸mm电影 +护士诱惑 +郭罗基 +放尿 +放屁 +成人在线免费淫电影 +狂风暴雨 +不举 +法~仑 +星钻物语 +它妈 +shaolincn +鲜族 +阴门 +三夫妻结伴旅游换妻大乱交 +淫民激情文学图库欣赏 +反革命暴乱 +毛我操你 +毛欢城 +劍俠情緣II +mo擦小肥穴 +值勤帳號 +淫虎成人导航 +エロい女中出し20連発姫野愛 +淫奸小姨电影 +本站绝无任何形式木马病毒 +骚姐乱伦 +無套自拍 +白虎少婦 +test +毛麻醉药 +wu jin de ren wu +粗大的阴茎与紧窄的阴道壁之间的剧烈磨擦 +jiejie的嫩阴唇 +賣比 +張榕明 +口合 +慰春情 +偷窥无罪 +幼男 +凌锋 +xyd +黃色電影 +offgamers +贞操 +迅雷下载淫乱电影 +xyj +陰道 +盐酸二氫埃托啡 +台办 +姫野爱 +バコバコ风俗 W指名 遥めぐみ×美优千奈 A +賤比 +xyq +夫妻激情自拍图 +歡迎G10情色電影院 +插B +洪吟 +看单亲妈妈给儿子的性启蒙 +坦克宝贝 +性交靠 +ma chang da heng +懂文华 +售软件 +國權 +雞芭 +毛公安 +放荡熟女 +肉穴肥肥的裹着阴茎 +激情裸体 +抠 插 磨蹭 穴 +性免费电影 +黄色做爱电影 +西藏喇嘛 +六四以後 +插b +劍網 +王从吾 +麻醉药 +烫的大鸡巴在小穴里来回抽插 +免费视频裸聊 +丰满的视频聊天主持 +熊焱 +大鸡巴 插 少妇 +性爱 +处女膜 +吗个 +Pure Idol Vol。20 望月なな !【RMVB/543MB】 +和嫂嫂淫穴 +网络创世纪 +everstar +狂插妹妹穴 +小騷貨 +砍翻一條街 +操插gm +厕所盗摄护士姐姐 +李瑞环 +插你全家 +广电 +popkart +第九城市 +鬼畜輪奸 +fuck傻卵 +插小穴妹妹直流水 +出售账号 +迷药 +婷婷激情网 +肉棒插入又大又深的穴 +瘟比 +我使劲快速抽插龟头好麻 +插入她的搔B爽死了 +肉摩擦她处女的肉穴深处 +纶功 +插妹妹图 +外 挂 +激情淫贴图网 +狂插护士穴 +吮吸肉棒 +毛一党专制 +午夜情人 +BIAOZI +fei chang san guo +我操靠 +陈昌智 +操操逼 +妓院 +huan ling you xia +阳具在她的蜜穴里抽插 +卖国求荣 +他马的 +熊炎 +香港激情淫色贴图区 +8仙靠 +女马 +亲 美 +毛喷你 +大众成人网站 +捅进她的阴道 +政府无能 +姐姐被轮奸 +舌頭穴 +新闻出版总署 +催眠悪用集団轮奸30连発 +骚嫩的蜜穴紧紧地裹着大鸡巴 +操插gM +TTMD +Pink Puncher Premium Angel 光咲玲奈 +李洪志 +立花里子のレズビアン母乳M女コレクション +八九風波 +西藏獨立 +日本无码成人电影 +阿片烟 +大陆鹿城黄站 +操护士 +杭州二元 +共铲党 +激情淫色论坛 +激情淫穴小少妇 +法錀功 +亚洲色meimei +hellgate +www。gpchina。com。cn +王沪宁 +狂操空姐 +毛高校骚乱 +世模 +法轮功 +仙劍 +xiao yu er yu hua wu que +騷雞 +卫生巾 +fofg妈的 +干妳妈 +chinesenewsweek +彭佩云 +六-四 +淫meimei +粗硬 大 龟头 狂插 +rjwg +喷 +幹拎娘 +feng shen bang +教育部 +婷婷淫女小说 +荣毅仁 +Apexsoft +什麼什麼大冒險 +shen zhou tian ge +抽插小穴 +8仙 +豔照門 +仙剑 +臭西化 +熟母 +d7se淫色贴图 +騷B熟女 +免费淫电影在线观看 +H淫乱乳娘 Tora Tora Gold Vol。23 星之雪 +法@掄 +homosexuell +豬操 +江猪 +新義安 +万淫堂 +令人喷血的春宫108姿势(组图)19岁禁看 +BT亚洲无码影片 +肉棒小浪穴┅ +爱幼阁 +布莱尔 +JHSZ +lastchaos +臺灣狗 +打手槍 +不良少女日记 +淫荡的嫂子 +爹娘 +宁王府淫图导航 +成人图库,操女人穴,色情贴图,性交贴图,操MM穴,超级淫图 +嘉联 +肉棒顶入小穴口 +你色吗 +干妳娘 +稻生美纪 - miki +做愛電影 +女儿的阴道好紧啊 +操妳妈 +歪逼 +淫水四濺 +激情淫色贴图论坛 +我受不了啦!┅┅好勇猛的鸡巴 +冉英 +免费午夜电影 +毛台湾帝国 +黄家骁 +抽插39岁处女meimei淫叫不断 +狗狼养的 +六。四 +builtfree。org +張 林 +美国小姐淫荡舔乳照 +大力丸 +炮友之家 +色情网站 色情导航 +干一干 +好嫩的屄啊 +免费淫色电影论坛 +網管 +毛射精 +歡歡娛樂時空 +毛西藏独立 +激情 乱伦 性 +asshole +人大代表 +h站靠 +浪叫 +mei li shi jie +法抡功 +逼痒 +情兽 +mo huan sen lin +夏夏娱乐免费黄站 +免费淫色情电影 免费淫奸女A片段试看 +法轮大法 +林心如特级片 +你弄得阿姨爽死了 +毛膏药旗 +麗春苑 +狂乳激揺 +钱 达 +緊穴 +超美少女系列 蛯原舞 +本站10019多部激情电影全部免费试看 +激情电影 +宾周 +激情成人桃色电影 +爸干得你┅┅舒服 +台湾情色網 +在乳房和阴道摸弄 +美乳美穴 +大史记 +女卫生间盗摄图 +淫水四溅 +MAD MAD +毛去你妈的 +毛李宏旨 +毛妳马的 +免费黄色电影/色情电影/激情电影/黄色电影/我该死/A片 +乌兰夫 +肉棒精液淫液阴精 +免费淫色影院 +肉棒好粗啊 +清華同方 +花和尚成人论坛 成娱情色导航 +摸你雞巴 +劉少奇 +flyfff +日本激情片 +怎么能知道女性手淫过 +大龟头顶住了她的花心深处 +巨骚 +干X +小泉恶搞 +大肉棒插入阴户内 +給處女開苞 +新聞出版署 +插护士穴真爽 +金瓶梅4 +弓虽 +黑逼 +金瓶梅5 +こどもの时间VOL。1-7 +內衣 +金瓶梅1 +妹妹的阴道好紧啊 +金瓶梅2 +六。四 +金瓶梅3 +怎样延迟射精18岁以下禁 +亚洲穴贴图激情自拍穴 +曲線消魂 +毛经社理事会 +法(轮)功 +淫女教师小说 +枪淫少妇 +巨騷 +本站10021多部激情电影全部免费试看三天 +牛头马面 +日本av女优 +bastard +逼癢 +伦乱小说大全 +亚洲美女 +三极试看片 +少妇自淫 +欠骑 +鄭萬通 +淫水橫溢 +肉棒插进子宫了 +毛阴户 +Baichi +又紧又嫩的屄儿 +大型黄站 +bankai +huang yi qun xia zhuan +毛塞白 +激情黄色在线 +傻鳥 +fuck新疆独立 +基地组织 +抽插47岁处女妹妹淫叫不断 +meinv穴自拍 +二屄 +妈卖妈屁 +操车仑 +吊 +回教 +大鸡吧来回抽插着小穴 +毛克林顿 +牲口 +事屎 +fuck透视眼镜 +mo yu +毛可待因 +爱图公园 +六四民運 +黃色漫畫 +朱骏 +毛傻屄 +干机掰 +媽的 +毛日他娘 +U-R +卫星遭黑客攻击 +抢火炬 +吳 邦 國 +少婦偷情 +MUGEN EX VOL 9 人体喷泉!强烈な潮吹きホール!(MX-09) +贱人 +jiangdongriji +色网阴道特写强奸32岁处女全过程 +在线黄色电影 +毛发展研究中心 +成人激情视频聊天室秘密入口 +东条 +东方传说 +色聊人午夜激情聊天 +巨炮肉穴 +老师的淫液 +wetback +手记注册日韩5029部激情电影 +龟头抽插小穴 +TMD +周總理 +乳峰 +fuck我干 +毛马克思 +成人导航网 +聯 總 +姫辱 +乳房急促而有节奏的起伏着 +操他 +毛耶和华 +肥嫩嫩的大陰唇粉紅色的小陰唇 +操插Gm +zu qiu jing li +裹本 +一边一国独裁 +朝鲜 +插你爸 +色网阴道特写强奸28岁处女全过程 +娇妻超市被奸 +张 伯 笠 +射了 +肉棒 乱伦 肉洞 +东京物语Vol。 3 优质美少女 +龟头在阴道中抽插 +大鸡吧狠狠插进了她那又肥又嫩的小骚屄儿 +二奶大赛 +操插GM +98bb成人小电影 +雞院 +摸陰蒂 +wtf +激情淫少女穴 +打飞机 +操得直叫爽 +妈个老比 +f r e e n e t +阴阜高耸 +强奸20岁处女全过程/*妹阴毛小穴 +天鹅之旅 +淫影院论坛 +铁道部 +丰满肥大有阴唇湿润了 +红宝石 +六四民运 +唐人电视台 +打手枪 +di qiu wen ming +现场做爱偷拍电影 +欧美乱淫贴图 +宮路ナオミ - 美腳★角度 (超美) +wyd +毛骡干 +淫荡少妇白洁 +麻醉枪 +法抡 +Sex +每日公告 +T浓厚中出FUCK Red Hot Fetish Collection Vol。44 : 夏川Saya +六四平反 +顶到阿姨的花心 +歡迎G9情色電影院 +娘b +法*掄 +射你 +发^^抡 +山本五十六 +如果你未满26周岁请自觉离开。 +tian yi zhi lian +淫荡女护士 淫荡少妇穴 +淫奸护士论坛 +乳尻 +色情工廠 +棒插到妈妈的穴里 +xin shi qi +遊戲送獎員 +fuck售号 +中國政府 +娘B +激情淫色小穴 +tiao zhan +抽插淫水 +毛肛 +劍網2 +劍網3 +無碼無套 +phuc +妈的靠 +烟膏 +乳尖 +成人午夜影院 +魔兽金库 +droiyan +雞雞 +强奸24岁处女全过程/淫妹阴毛小穴 +大波骚妇 +少妇扒开阴道图-淫賤少女阴唇特写图免费淫电影a片 +淫水橫流 +色电影 +fuck唐家璇 +西藏天葬 +极品激情影院 +狗娘养的 +食捻屎 +又硬又大的肉棒插入阴户 +程真 +天之炼狱 +龟头在她的阴户里抽插 +仑功 +魔兽金币 +kan66免费电影 +顶级学妹美穴淫图 +地震捐款 +巨乳俏女医 +捐款名單 +美女含双棍玩内射 +luanshi +賣國 +san guo +正見網 +转法轮 +发@@仑 +六四以后 +吳桂賢 +开粉红小阴唇 +日本大型黄色meinv做爱 +發~輪 +台灣豬 +亚洲激情淫贴图 +南联盟 +寻仙 +淫水淋湿的阴毛 +亂倫熟女網 +肉棒捅入阴道里 +淫荡小护士 +fuck社保基金会 +大陆性meinv淫穴 +童屹 +操布雷尔 +毛想上你 +风骚小护士 +朝鮮 +tian jiao +@sshole靠 +cha你 +带链 +厕所盗摄护士姐姐性感 +龟头狂插肉洞 +亚洲激情淫搔穴贴图 +fuck外挂 +毛情色 +李弘志 +法@抡 +骆 冰 淫 传 +泡365免费电影 +董建華 +处女流水淫图 +草你媽 +小浪穴 插死 人家了 +台湾 18 成人网站 +淫色网址导航 +剃毛 +毛老母 +朱駿 +Groove +羞恥母 +淫浪女 淫妻浪女 于东 浪女淫叫 淫妻……漫画 淫色贴图东方淫色 +遺忘傳說 +汽车爆炸案 +看棋器 +抽插50岁处女妹妹淫叫不断 +插比 +張梅穎 +萬人暴 +法掄 +激情淫色贴图网址 +红海湾 +本站10010多部激情电影全部免费试看 +wstaiji +cunt cunt +粉红色的小嫩逼淫 +妈要吃你的肉棒 +操你奶奶 +jin wu shi jie +董必武 +狡猾的风水相师 +粗挺的阴茎上沾满了处子的鲜血 +性器 +插gm +蓋世太保 +U/R +阿姨的阴道好大 +上海交警 +林榮一 +癡乳 +性感妖娆 +肥嫩的阴唇 +妹妹嫩穴被狂插 +哥哥使劲插我 爽死了 啊 啊 +外交论坛 +毛妹妹免费电影 +梁保华 +发@@伦 +毛小穴 +插gM +99bb +Fuzz Vol11 Ririko Asahina 朝日奈りりこ 加藤つばさ +1989#事件 +骚妹妹 +母子淫奸乱轮现场看,瞄準她的肉穴插了進去…… +扬震 +韦国清 +成人激情电影通道 +湿淋淋的阴道被肉棒插出血 +河 殤 +夏夏娱乐 黄站电影 +淫民俱乐部做爱顶级 +激情淫咪咪贴图区 +毛检察院 +东京热5月新片 +癟三 +瘋狂抽送 +華夏Online +小泽玛丽亚7~淫乱的肉体 +淫少妇 +鸡巴靠 +免费视频激情聊天室 +台湾18黄网亚洲华人bbs性论坛 +毛窃听器 +美国淫女在线看电影欣赏mm乱淫自拍图片 +賓周 +河 殇 +胡景涛 +WEB战牌靠 +東京熱最受歡迎長腿meinv~藤澤安奈~腿長人又漂亮 +激凸走光 +法~~掄 +操女人穴 +干的你 +魔性的美女 鈴木麻奈美 +强制执行 女体崩壊~YUU Vol。1 +孙文 +草你娘 +令人喷血的春宫108姿势(组图)18岁禁看 +四我周 +毛摇头玩 +fuck四人帮 +午夜的诱惑网友自拍 +少女艳星诱惑色图 +国权 +法$抡 +BT无码区 激情电影 +干八个meinv的小穴 +免费淫爆影片 +电监会 +劳拉 +山西黑砖窑 +mimi淫色贴图 +大海战II +shaiya +毛肉壁 +深愛色色 +mo jian +meimei的阴道好嫩啊 +狂插meinv护士小说 +毛台联 +粮食局 +口爆吞精 +经社理事会 +20dy淫色贴图 +sanguohx +淫色贴图网 +小便 +性感妖嬈 +少儿不宜 +公媳乱 +毛独立台湾会 +蒋震文 +扒开嫩穴 +大龟头在我的阴道口来回磨擦 +發^輪 +淫奸姐姐小说 +台湾黄色成人电影 +草你妈 +日本姐弟乱伦小说 +阿姨的阴户好紧 +免费成人激情视频聊天 +公媳亂 +少女被插 +婷婷成人激情网站 +21dy淫色贴图 +奶大屄肥 +黃色圖片 +李鵬 +狗雜種 +免費A片 +淫荡贵妇 +獨立臺灣會 +奇淫的老板娘 +meimei穴 +fuck生孩子没屁眼 +温暖的冬夜老师拼命亲吻我 +免费电影 成人电影 激情电影 +肉棒抽插……的爽死了 +feng shen +圣战 +台湾政论区 +朱胜文 +dekaron +恶搞晚会 +吾尔开希 +钱运录 +秦真 +Tora Tora Gold Vol。24~伊泽夕 +插 10p +高自联 +du shi 2046 +毛经济社会理事会 +操陈至立 +爆乳人妻 +迷奸药 +狂插处女血流不止! +童顏巨乳 +饱满的乳房肥嫩的阴唇又肥又嫩的小骚屄儿 +操财政部 +智能H3 +毛国研室 +北大三角地论坛 +民联 +财政部 +热血江湖 +发~仑 +大鸡巴干进妹妹的小穴 +舆论钳制 +bi样 +品嘗不倫主婦 +插 11p +小姨子穴 +粉嫩小淫穴 +铁血三国志 +无尽的任务 +捅入她的阴道里 +白立朴 +妹妹 MM激情 +帶链 +婊子靠 +肉棒乱插 好舒服 +霍金 +meinv出租车内强行进入 +fuck死全家 +猛舔她的肥穴 +扉之陰 +操大法 +插 12p +尋仙 +又粗又大的肉棒 +江八点 +李至伦 +张磊 +petrealm +淫奸meimei电影论坛 +阿弥陀佛 +台湾建国 +莫伟强 +免费淫电影,免费淫色情电影 +馬万祺 +Gold Angel Vol。7 Super Erotic Girl : Ran Monbu 紋舞らん +插 14p +激情淫片 +哥哥淫奸妹妹穴 +插 13p +本站10012多部激情电影全部免费试看 +宋平 +你爺爺的 +发~伦 +成人色情网 +姐弟激情淫影片 +毛傻子 +大龟头顶住子宫深处 +干GM +王文京 +洪志 +内衣 +接班 +九评共产党 +中共/中共中央 +乳射 +插 15p +大花逼 +濕身誘惑 +手记注册日韩5020部激情电影 +教室炉轮奸精液过剰注入 若月秋穂 +真 善 忍 +美媚穴贴图 +杀你一家 +又大又嫩的穴 +淫乱电影 +【亚洲/无码】【生奸中出无套内射-相沢、夏樹、 美月遥】【AVI/1220MB】 +脱衣舞 +淫色电影免费在线观看 +日本激情淫 +艳舞淫业 +强奸17岁处女全过程 +法$掄 +淫奸电影少妇扒开阴道 +杜冷丁 +肉棒插入肉缝 +你它马的 +扒开嫩阴道 +法*抡 +Ninn Worx - Fem LAmour +liu xing xue yuan +邪教 +俏臀攝魄 +徐邦秦 +奴隸調教 +淫水漣漣 +無碼 +少妇房中自淫,和两勇男玩9P,操得直叫爽 操日本淫女穴 +操你 +transsexual +口含鸡巴 +KEFU +国安局 +淫电影//处女第一次阴道做爱全过程(全套图片) +淫妻乱交 +免费色情电影 +林心如淫电影 +色meimei成人论 +热血英豪 +mes couilles +U R +内裤 +幹GM +干鸡 +光通 +毛麻醉钢枪 +毛社。会。正。义。力。量 +bt 色情工厂 +华盛顿 +Jiaochun +扉之阴 +Yellows Vol。2 女体天国 2 天然素人娘18人 +毛共产主义 +龟孙子 +赵 紫 阳 +專制 +淫奸meinv图 淫奸刘亦菲 +毛特别公告 +urban靠 +av成人 +日韩成人激情电影 +h r i c h i n a +她奶奶的 +激情淫贴图 +朱嘉明 +食屎 +毛国防部 +露逼 +transsexuel +骚货 +任弼时 +ctracer +大妈油 +情色小电影 +宁王府导航 +强奸林心如扒开阴道 +周铁农 +插你祖宗 +ai滋 +溫泉室的男女 +淫屄儿 +胡景濤 +射进女儿的屁眼里 +fuck透视软件 +舔她的花蕊 +我和小少妇乱伦理淫穴 +PP一点通 - 成人电影 +母子交歡 +天安門大屠殺 +日本卡通淫色动画片 +公车淫奸姐姐 +大陆淫乱美女图图片 +無界 +嗎b +鬼畜轮奸 +让我的肉棒缓缓的插进潮湿饥饿的娇嫩的肉洞里 +炮打中宣部 +于永波 +走资派 +內褲 +网游久久金币 +性奴 +成人文學 +明斯克号 +操吹箫 +精液喷涌而出 +毛日X妈 +六月four日 +骚姐姐 +毛外挂 +宝德 +成人文学 +轮盘机 +华义 +三個代表 +系統公告 +免费成人激情视频聊天室 +日本黄色小电影 +da tang hao xia +中央电视台 +插少女阴道 +抽插 捅 挺 阴唇 处女膜 +母子交欢 +中国天使成人网我该死免费视频 +江獨裁 +滾那嗎 +毛懒教 +丁關根 +国产偷拍 +肉棒弄得湿溜溜的 +猪聋畸 +全裸 +楊帆 +卐 +刘全喜 +满洲国 +毛普京 +疯狂抽送 +SEX +區 +淫电影//少妇扒开阴道图-淫賤少女阴唇特写图 +猪毛1 +89bb成人小电影 +中国meinv淫色贴图 +傻鸟 +抗震 +大紀元 +剛比 +Tokyo Hot n0188 田中爱 +毛国民党万岁 +和护士jiejie淫穴 +操你妈屄 +毛屁眼 +小穴插的紧紧 +淫穴淫水流 +張 志 清 +55sss偷拍区 +55sss偷拍區 +脱内裤 +發~論 +媽祖 +毛卖逼 +插 操 干 骚穴 嫩穴 小穴 密穴 淫水流 +兔meimei色色贴图区 +毛夜情 +宁王府成人论坛导航 +岩崎 Sky Angel Vol。27 +天地玄門 +淫荡口交 +www。gpchina。net +聚友網路 +摩門教 +他馬的 +个批 +賣卡 +专政 +人妻熟女 +小骚穴┅┅好舒服 +64xp。com 电影免费 +操陈毅 +安息 +蜜穴肉棒肉縫 +少妇大穴VS驴吊 +把舌头伸入姐姐的 +發~~倫 +日本免费黄站 +一黨獨裁 +於永波 +64事件 +tranny +郭平 +肛門拳交 +毛强硬发言 +務 +法车仑工力 +輪流執政 +法~~抡 +灨你娘 +動 +我讓朋友強姦我的小姨子 +大城舞衣子(有碼無碼)大合輯~~~超優!!(可分開下載哦!!!) +操妳娘 +合成淫色贴图 +Qqyinsu +fuck晚年周恩来 +小穴┅┅好棒┅┅好爽 +孔雀王 +操医生小穴 +淫妹妹电影 +强奸42岁处女全过程/淫妹阴毛小穴 +妈逼靠 +lineage2 +大肉棒刺入肉穴 +吴桂贤 +成人激情视频聊天 +GMworker +segame +阴道好肥啊 +Taiwan国 +neosteam +日本淫色电影 +joyxy +色情靠 +無毛美少女 +毛王乐泉 +小魚兒與花無缺 +中宣部是中国社会的艾滋病 +乳头 +epochtimes +河殇 +插GM +女秘书做爱吞精图 +少妇房中自淫,和两勇男玩14P,操得直叫爽 操日本淫女穴 +黑五类 +毛法(轮)功 +厲無畏 +摩力遊 +店長推薦最新強片Sky Angel Vol。43最新強片 +操妹妹 +杨震 +發**論 +法轮公 +爽图网 +出售账号靠 +法轮共 +穴太紧了 插进 +你他妈的 +毛神通加持法 +毛我干 +免费操小姨子 操小姨 +性欲 +voa +含 肉棒 插 小穴 +潘金莲全传 +发改委 +今晚我把表姐操上了 +欧美激情 +天天任我淫 +网址大全 +mo shou shi jie +阿沛•阿旺晋美 +够酷GOQO +统独论坛 +毛阝月 +激情淫色故事 +fuck新闻出版 +打飛機 +操妳媽 +佛展千手法 +龙 虎 门靠 +欧美暴淫 rsync 月宫成人贴图区 +国产AV +chinesenewsnet +xin xi you ji +jin yong qun xia zhuan +插Gm +啊……我的小屄……给你……肏得好……舒服……啊 +金新月 +靓穴meinv +feltch +幹全家 +中共中央 +操那嗎逼 +子女任职名单 +卖卡 +谷牧 +幹逼 +東方傳說online +無需刷卡 +俞正声 +淫穴小说 +台湾成人25贴图 +梅毒 +騷浪美女 +致幻劑 +法沦 +毛乡巴佬 +自由亚州 +黄色做爱小说 +成人激情影视区在线视频脱衣服 +game master +昝爱宗 +歐美大乳 +淫秽小电影 +致幻剂 +法輪功 +肥嫩的小骚屄儿阴部 +meinv淫色贴图区 +弟弟粗大的肉棒 +人民代表大会 +天地玄门 +圣女峰 +成人激情电影网 +worms +臭b +大……鸡巴……操得……很……很……舒服 +淫奸jiejie +江择民 +xiao77 +baichi +大亂交 +农村公公与媳妇乱伦 +曾 庆 红 +超激情电影快速注册 在线观看爽!爽!爽!! +毛水利部 +恥辱醫護免费 +风骚女秘书 +我也要泄了 +操产权局 +毛国管局 +法~掄 +浪婦 +肏妹妹屄 +毛投毒杀人 +搖頭丸 +庆红 +看着有点舍不得操 +89學潮 +亚洲激情 +法@@仑 +伦理淫穴小说 +阿呀娃娃 +tian xia wu shuang +姘頭 +Itsuka_part2 +毛三唑仑 +性交自拍 +无码做爱淫图 +好紧的阴道 +妹妹的小阴户 +火辣辣免费爽片 +用手指分开两片肥嫩的阴唇 +肉棒插入妹妹小穴 +傲神傳 +毛徐光春 +她妈靠 +自由亞州 +姨妈的肥阴唇 +1989 天安門 +法*淪 +强 奸 +免费淫奸女A片段试看 少妇扒开阴道图-淫賤少女阴唇特写图 +1989 天安门 +挺着硬梆梆的肉棒 +干逼 +網路公祭 +欧女乱欲 +kart +骚姨妈 +5jq +电影小片段试看免费淫影片 +賣幣 +一夜情聊天室 +天安门屠杀 +龚学平 +六四之後 +毛哈批 +嫂嫂我要 +鞭王 +最淫熟女网 +肉棒插入淫荡少妇穴 +陰道圖片 +後庭 +把精液射进我的小穴里 +亚洲激情淫色网址 +huang yi qun xia zhuan +韩正 +邓力群 +性交贴图 +乱伦淫书成人网 +三级片看美国女人的性交 +莫索里尼 +sheng zhe wu di +淫逼嫩穴清晰图 +恥辱醫護 +奇侠XIAH +屙 +手记注册日韩5030部激情电影 +操女人嫩穴 +總書記 +毛游戏发奖员 +總理 +屍 +妈妈美穴 +屌 +福尔摩萨 +屄 +男女激情淫影片播放 +淫女刮毛 +乱伦禁书 +尻 +毒販 +少妇房中自淫,和两勇男玩0P,操得直叫爽 操日本淫女穴 +激情日本电影_成人情色电影_成人小电影 +meimei淫水 流 +卢跃刚 +余英时 +tianji +激情做爱色情淫妇做爱 +經血 +密宗 +美女偷拍成人小说激情网 +亚洲成人激情 +神话R。Y。L +毛卫生部 +polla +共*党 +日九城 +卡通动漫美女淫乱 +毛胡主席 +台湾共产党 +UR靠 +先烈的电话 +反日活动 +毛贺国强 +台湾国 +抽插48岁处女妹妹淫叫不断 +捏你雞巴 +fuck温加宝 +疆独 +李師父 +护士淫乱 +新唐人 +插得好爽啊 +发@抡 +任你淫 +鄧小平 +小骚货 +周鉄農 +两片暗紅的陰唇一張一合 +soundofhope +幼逼 +熟美婦淫交實錄 +美少妇的哀羞 +硕大龟头紧紧顶著她的阴道 +肉洞深处不断地蠕动 +盘古软件 +王秀丽 +淫乱色情小说 +fuck王昊 +24dy淫色贴图 +安拉 +卖号 +星光伴我淫 +和姐姐插穴 +共軍 +午夜激情免费电影免费看激情小电影 +zhuanfalun +打倒中国 +激情贴图 +淫荡妖艳女医生 +少妇做爱小说 +核潜艇 +原千寻~白领迷奸 Finger Charm +怎样延迟射精20岁以下禁 +毛网管 +qq视频脱衣秀亚洲少女韩国无码片 +淫奸姐姐 +亦凡 +肉棒插入肉穴 +法@沦 +恐怖分子 +干meimei小穴 +毒贩 +水浒Q传 +167网址宽频影院网 +日本激情免费小电影 +(无)导航网站连接 +李大钊 +SOD 厳选!残虐レイプ集 +帝国传奇 +薑春雲 +你他马的 +赵 晓 微 +毛多维周刊 +免费meimei黄色淫乱电影 +法淪 +草拟妈 +疆獨 +如果你未满18周岁请自觉离开。 +日韩淫乱美女图 +滾那嗎錯比 +GAME MASTER +人民之声论坛 +se中国 +厕所盗摄meinv +光明日报 +fuck统计局 +毛高俊 +他妈地 +蒙古独立 +鐵甲爭雄 +日本情色无码光碟 +搞比 +劳改 +大肉棒插进我的肉屄 +如果你未满25周岁请自觉离开。 +動漫色圖 +看牌器 +性感乳娘 +新人调教 Red Hot Jam Vol。9彻底调教凌辱人靓逼美 +情色成人大全 +淫荡的妈妈8淫荡护士9淫荡空姐 +海天英雄传 +好紧的屄 +9之遊 +鹿城百家性大型网站 +爽你 +全国两会 +成人视频 +武雷 +大乱交 +欲仙欲死 +干你媽逼 +淫奸护士穴论坛 +身份生成器 +法@@倫 +欧洲男女激情淫乱穴 mm贴图网 +明慧網 +52xp。com 电影免费 +mei li shi jie +阴道夹裹住阴茎 +卖淫女全过程 +未满21岁的请自行离开 ! +民航 +操小姨子 +淫奸小姨淫水流 +毛联大 +强奸20岁处女全过程/淫妹阴毛小穴 +日本有码 +毛威而柔 +fuck王太华 +那吗逼 +免费看三级电影淫电影艳情电影 +拉案) +搞死 +毛六合彩 +64動亂 +arcane +欧美靓穴小小论坛帖图母子姐弟淫……男男激情欧美淫贴图 +下载淫电影 +淫电影艳情电影 +起义 +骚B熟女 +贾育台 +张伟华 +富人与农民工 +毛台湾共产党 +金日成 +法$沦 +性愛擂臺 +新聞出版總署 +免费黄色淫秽 +Lady Sonia-熟女絲襪 3 +司馬義?鐵力瓦爾地 +东京热 n0151 工藤裕子 美丽子宫大精液轮奸教室 +日本有碼 +百家性大型黄站meimei +又解开乳罩 ┅鸡巴 +黑手黨 +赌博 +造爱 +龟毛 +豔照 +赛他娘 +免费情色电影情色五月天 +毛售号 +阳具在他的穴里大幅抽插 +客报 +宁王府 +亚洲激情淫影院 +薛伟 +肏肉~X屄爽歪歪 +强奸大奶嫩逼meinv +毛王宝森 +屌七 +淫奸妹妹电影 +苯丙胺 +法碖功 +中华时事 +红楼 绮梦 +素人著エロ俱樂部 こももちゃん +办公室性欲 +大肉棒在妈妈的阴道 +朱熔基 +毛审计署 +fuckyou +怎样免费看淫电影 +毛世界日报 +插姐妹小穴 +meteor academy +胡锦濤 +色情 娱乐 导航 +风骚女友浴室放荡 +ㄙㄞ你老母 +Mysupersales +小穴里抽插 +網络公祭 +糖糖小穴 +八路 +售ID +小泽玛丽亚~闷绝痉挛无限制潮吹 +毛阴核 +AYAWAWA +干jiejie小穴 +fuck倭国 +强奸43岁处女全过程/淫妹阴毛小穴 +劫机 +黎阳评 +集體性愛 +大j8 +少妇激情电影 +解放軍鎮壓 +国产av +龚學平 +fuck无界浏览器 +美国成人激情淫洞网站 +开苞 +骚b熟女 +浪妇 +嫩穴 小穴 花心 +wu lin wai zhuan +三去車仑 +幹死CS +浪女 +fuck十年动乱 +性交 +法*沦 +傳奇3G +旅馆自拍 +粉饰太平 +少妇房中自淫,和两勇男玩18P,操得直叫爽 操日本淫女穴 +独裁政治 +淫妇周艳茹和儿子的性战 +毛特码 +奥马尔 +高校骚乱 +毛驶你老师 +法@@伦 +小嫩穴贴图 +法~~淪 +统战 +马良骏 +苯環已哌啶 +法~抡 +絲襪寫真 +免费淫奸女直接试看 +手机注册色情电影网站 +美國之音 +江八条 +淫荡女优放荡插逼 +妹妹的大阴户 +大 纪 元 +超性感裸体艳舞 孔裏唾梦 DANCE 2 アナリズ现场收音 +九城 +成人片 +幾芭 +罗 干 +绵恒 +laghaim +10 Little Asians Vol。 14 +@sshole +把你的小穴夹紧……用力…… +总局 +天安門 +mo fa qi bing +不得入内 +不用注册免费淫 电影 +小姨子的阴道好紧啊 +d7se淫色穴图片和meinv发春激情3级片试看 +幹死GM +强奸33岁处女全过程/淫妹阴毛小穴 +GameMaste +淫奸阿姨电影 +插入 嫩穴 +正见网 +法$淪 +法@@侖 +bedclip。com +jing tian dong di +插死你 +公车淫奸妹妹 +teensexy +一夜情异物插穴性爱网 +暗黑之門:倫敦 +成人激情色情电影 +亲情淫乱 +骚逼 +粗肉棒 大鸡巴 +淫奸女同事穴 +9城 +我就去色 +林心如被疯狂轮奸 +在线淫电影网站 +尸体 +舌头在小穴周围舔弄 +郭岩华 +肉棒插进了湿湿的阴道 +淫奸姐姐 妹妹 MM 姨妈 舅妈直到流水 +性佣 +免费淫水流 +彩虹骑士 +天安門屠城 +ling you ji +法^掄 +歡迎光臨亞洲瘋情 +游戏道 +無碼小處女 +龟头顶开阴户 +周子玉 +凤舞天骄 +刀劍?英雄 +破天一劍 +淫荡少妇 +老騷比 +台湾19岁成人 +陳希同 +肛门喷水 +dafa +强奸46岁处女全过程/淫妹阴毛小穴 +NPC靠 +畜生 +大陆温州鹿城黄站 +王子淫传 +親民黨 +re xue jiang hu +奸 +E块冒险 +余秋里 +爆吧 +biaozi +未成年人禁入 +毛短信群发器 +蔣彥永 +射奶 +fuck台联 +毛欲火焚身 +成人影院 +欲仙欲浪 +徐向前 +发论公 +干妈妈的小穴穴 +counselor +廁所盜攝 +fuck外交部 +三去車侖 +我和网吧老板娘 +胡锦淘 +365淫色贴图 +QQtang +免费淫 色电影 +meimei嫩穴 +毛你大爷 +TMD靠 +密室淫行 +日本激情淫骚穴 +干 淫洞 +嗑药 +fuck兴奋剂 +强奸17岁处女全过程/淫妹阴毛小穴 +小穴好爽 +泽民 +妓 +蜜穴被阴茎插入 +劉伯承 +鸡巴全根没入 阴道 +姦 +淫色宝贝导航 +禽獸 +明慧网 +jiejie +嫩穴 +床上激情自拍图 +完美世界 +透視軟體 +瞄準她的肉穴插了進去…… +merde +WG武功 +A片大放送 +用手指挖她的小穴,弄得她娇喘连连 +哦……你插的好深啊……又顶到我的子宫……啊 +毛燕玲论坛 +肏meimei淫屄 +香港成人激情论坛 +吴宏达 +毛肛交 +死刑过程 +妹妹的阴唇好嫩啊 +卖国 +遊龍線上 +姘 +免费品嘗不倫主婦 +抽插28岁处女meimei淫叫不断 +皇军 +操吹喇叭 +捅B +毛鸟gM +婷婷激情淫液 +六四以前 +大肉棒插进了她的体内 +用舌头对着阴道阴蒂等地方用力地舔着 +毛发奖使者 +毛我日你 +萬稅 +测拿 +本站10005多部激情电影全部免费试看 +荡妖艳女医生 +chinamz +fuck希望之声 +淫电影//令人喷血的春宫108姿势(组图)18岁禁看 +幼女口交 +嫩穴 +屍体 +狂插嫩穴 浪穴 骚穴 +宗教 +meimei小穴好紧 +madelove +阴道深处 +天安門事件1989 +郁慕明 +建国党 +外$$挂 +fuck小乳头 +fuck天安门屠杀 +慈善会 +国外A片电影-美国色情电影一点点激情下载 +性愛 +偷窺圖片 +毛驶你爸 +免费成人聊天室 +jiejie的嫩阴户 +胡启立 +apexon +激情淫色漫画论坛 +亚洲成人激情网站 +falun +qi shi +素人初撮り生中出し 观月雏乃 +去氧麻黃碱或安非他命 +强奸18岁处女全过程/*妹阴毛小穴 +免费淫乱卡通动画片 +淫荡家教 +性傭 +张萬年 +365成人贴图 +毛黄菊 +44lian色站大全 +亞甲二氧基甲基安非他明 +情色图片 +少妇白洁 +床上功夫 +日本淫荡少妇 +毛公安部 +江core +亚洲meinv +幼女情色论坛 +积克馆 +鸡巴插肉缝 淫荡 小穴 +舔着两片湿润的阴唇 +反人民 +龙洲影院日本娱乐性免费 +萨拉托加 +胡锦滔 +金瓶梅情色網 +淫蕩貴婦 +发论功 +tui tui xia +插入妈妈的穴好爽 +肉棒插入乱伦射精 +婷婷成人激情淫洞 +万润南 +老师嫩穴 极品嫩穴 淫穴嫩穴 +戀愛盒子OL +逼樣 +大话西游 +干丰满少妇 +買幣 +干妳老母 +掰穴 +鸡巴猛插 +江八條 +插进小穴射了 +新人调教 Red Hot Jam Vol。9 Myuu +毛奸你 +恐怖主义 +勁樂 +性爱插穴 +你呀的鸡巴长歪了吧 +採花堂 +毛鸟gm +干一家 +反政府 +姐姐和我乱伦理电影 +异见人士 +淫荡┅插 小穴 +法~~沦 +少妇房中自淫 +韩 联 潮 +youxia +短信群发器 +發倫 +毛孙中山 +爱图公园论坛 +butthead +毛希望之声 +六?四 +wowcaifu +Ezgaming +絲襪 +富豪们的疯狂做/爱方式 +肏烂你的屄 +成人小电影 +天安门录影带 +皓宇互動 +狂舔少妇两腿之间 +jie tou lan qiu +操婊 +365情色小说 +淫乱护士激情电影 +肏meimei屄 +PENIS +大奶骚女 +招雞 +亂交 +免费黄色淫乱电影 +日本风骚女电影 +皓宇互动 +法^^侖 +你爷爷的 +在线观看淫电影 +弟弟的肉棒又粗又大 +Red Hot Fetish Collection Vol。28 +肉棒又粗又大少女又痛又爽 +被操 +女老板一丝不挂躺在我身边 +阻无通畅 +骚妇露逼 +meng huan xi you +和親jiejie作愛 +見到這個美女就會有性欲 +把肉棒抽出来 +咬着她的奶头干了她 +在线淫电影 +几芭 +H动漫 +laghaim +無需入會 +幻灵游侠 +毛商务部 +貞操 +日本淫色漫画 淫色少妇小说 淫色少妇 +tmd +品色激情电影 +fuck特码 +……好舒服 ……好爽 +大鸡巴 +肉棒抽出她嘴中 +林心如色情贴图 性交贴图 +发$抡 +曰gM +任建新 +毛贱 +GAMEMASTER +鑽插 +肉棒插进来肉穴 +妈妈挺动雪白的肥臀 +鸡巴顶在女儿的嫩穴 +李紅智 +大型色站 +新鄭和 +U-R靠 +和妹妹玩插穴 +翹臀嫩逼 +在线激情淫电影 +乳此丰满 +法^^仑 +勁暴 +蒙尘药 +張筱雨 +毛胡紧掏 +舔她的小洞洞 +免费淫奸女A片段试看 欢迎点击进入观看/林/心如/20岁处女偷拍 +鞭神 +免费淫色meimei电影 +免费成人娱乐電影 +小骚逼 +Tora Tora Gold Vol。23 : ほしのゆき Yuki Hoshino +法^^伦 +性交极品大片 美腿少妇 +共榮圈 +学生淫图 +毛鬼村 +毛塞你老师 +毛淫秽 +89学潮 +毛色情服务 +弟弟淫奸姐姐论坛 +阎明复 +Tmd +淫色护士小说 淫色故事 淫色文章 +熟睡中的妹妹 +强*十八岁meinv护士看完保证你打飞机免费电影网站 +外$$掛 +性教育片-性教育电影 +劉淇 +snatch +全球华人春节联欢晚会 +毛湿透的内裤 +日本av +精子射到姐姐的穴里 +公车上干女司机 +学生爱国者运动证明 +他奶奶的 +貓撲 +北川 +jian xia qing yuan +偷窥拍摄 +夏夏小说黄站 +注册免费淫电影 +曹长青 +Red Hot Jam Vol。8 让你用子宫感觉 藤崎夕凪 +干的好爽……要爽死我了 +盜竊犯 +damn +damm +操她妈 +百家性大型bt黄站 +娼 +李建國 +宁王府成人导航 +survivalproject +海底水中插屄~Aqua Sex +李淑娴 +毛教育部 +劲樂 +都市情爱乱伦淫妻古典武侠制服明星性爱宝典24式教材 +毛阴水 +动漫激情淫色贴图 +发伦功 +好大的肉棒 +发*抡 +少女bb图 +64动乱 +不斷收緊陰道來吞噬我的龟头 +婊 +神通加持法 +MM被干小穴 +甲基苯丙胺 +教師禁斷接吻 +胡锦涛 +强奸meinv狂插处女阴道 +免费色情电影 强奸小说 +操淫荡 空姐 +浴尿 +处女性开苞 免费黄色淫乱电影bt下载试看 +操她 +被插 +神雕外传之郭襄 +公公狂操儿媳妇小穴 +102bb成人小电影 +婬 +幹機掰 +kai tian +溫傢寳 +少妇操b图 操农村少妇 少妇操尿图 +n0255 三国冬子 - 不用厌牝中出し廃弃処分 _k7 +苯甲酰甲荃芽子堿 +毛阴毛 +抽插44岁处女meimei淫叫不断 +周恩來 +东南西北论谈 +發侖 +大 紀 元 新 聞 網 +再用力插…。啊 +狂插小浪穴 +┅插┅小穴┅插我 +13点靠 +公交车上淫乱小穴狂插 +女死囚 +干小蜜洞 +操妳 +輪奸大meinv +毛枪支弹药 +钱国梁 +一个事实 +操妻 +毛李宏志 +www。gpchina。com +亂倫 +日本淫虫在线看电影 +淫亂 +毛王刚 +heterosexuell +毛江猪媳 +嫖 +法^抡 +h动漫 +江澤民 +淫乱 +赵洪祝 +法^^倫 +倚天屠龙别记 +西藏独立 +靠腰 +蒋彦勇 +逼毛 +華義 +淫书 +血灑 +你色嗎 +毛吴邦国 +握着他的鸡巴上下套弄 +六四周年祭 +淫液流入 +administrator +肉棒狂插嫩穴 +san guo yan yi +巨乳meinvRINA无码第2弹 +董建华 +crazyspeed +去妳的 +AV女优-杏子 +封淫 Sky Angel Vol。50 宫泽Keito 超美系模特儿初无修正引退纪念作 +淫女 喷精 +骚浪美女 +毛卖。国 +迅雷下载免费黄色淫乱电影 免费淫奸女A片段 +毛江青 +成人情色贴图 +51yxb +大粗鸡巴插进小穴 +日韩免费午夜电影 +鸡巴在她的阴道里抽插 +毛国防科工委 +中国社会进步党 +姐弟淫穴小说 +爆乳 +淫丝荡袜 +毛骚逼 +大鸡吧插进阴道 +lateinos +阿兵哥艳遇录 +逼样 +出租汽车罢工 +成人激情 +哥哥淫奸meimei论坛 +digimagics +本站10003多部激情电影全部免费试看 +烂游戏靠 +淫*女电影片段试看 +毛乳交 +阿兵哥言语录 +王震 +日本淫蕩孕婦 +天皇 +格老子 +塞你老母 +Jap Jap +日死你 +大鸡巴在她的蜜穴里抽插 +日屄 +免费台湾18电影 +日本淫乱漫画图片 欧美母子淫乱图片 +中华人民实话实说 +huanet +车臣 +淪功 +阿里布达年代记 +小穴 肉棒 插穴用力插 +紅 燈 區 +全免费淫色电影 +抽插22岁处女meimei淫叫不断 +香港激情淫色影院 +女教師赤版免费下载 +成人 性爱 +迷奸系列 +法輪大法 +在乳房和阴道mo弄 +婊zi +发@论 +带套肛交 +毛售ID +强奸大奶嫩逼美女 +操布莱尔 +18dy淫色贴图 +淫花宫色女中心 +欢迎点击进入观看/林/心如/20岁处女偷拍/免费A。B片 +无毛美少女 +精水 +国产熟女做爱深喉肛交无码 +濫逼 +屌鸠 +张立昌 +嫩B弓雖女幹 +激情淫色文章论坛 +幼女狗交 +私#服 +花样性交 +無網界流覽 +郭伯雄 +男人若妻夢交下载 +厕所盗摄meinv性感 +做雞 +教你如何延迟射精 +FUCK YOU +艷情小說 +亲日 +黑鲍娇 +梅德韦杰夫 +欧美尤物炮图图库 +发$轮 +想不到的黑幕 +色狼論壇 +20岁处女偷拍/免费A。B片 +私%服 +法蜦功 + Kurumi +欧美清晰打炮能看的淫乱 +毛神经病 +没有人权 +孙中山 +妈的穴让你插 +幼妓 +色猪猪成人导航 +(現映社)女の最強は30代エロ真っ只中 +應招 +冰毒 +hai tian ying xiong zhuan +那媽 +強姦你 +毛恐怖份子 +达癞 +神風痴女生中出!【MKV/767MB】 +隐窝窝 +免费偷窥网 +妈比 +宋任穷 +街头扒衣 +非常不错的人妻轮奸 +SM女王 +姦淫未成年的小女护士 +台湾岛国 +精液射进小穴里到了高潮 +jiejie的肥阴户 +鸡巴插进穴 +欣赏特级毛片pp 点点毛片 meinv毛片 大陆毛片 +万税 +三个代婊 +窝窝客 +毛三个呆婊 +那可汀 +禽兽 +rivals靠 +干老师的穴 +奸淫 +台湾是主权国家 +操操比 +操那吗逼 +賣党求榮 +嫩嫩 小肉缝 小肉穴 +少女被操喷精图 +抽插20岁处女妹妹淫叫不断 +人學生妹妹 埼玉援交 vol。2 なな&まい +色魔堂电影论坛 +丁香欧美成人贴图区 +僵賊民 +骚女淫频乐园 +免费淫电影下载 +姦情 +幹她 +强奸meinv +多維社 +毛高校暴乱 +日本女优激情电影 +四川独立 +颜射自拍 +嫩女~嫩屄~插的红肿喷浆 +誘惑視頻 +私*服 +fuck天皇陛下 +熟婦 +郭 罗 基 +阴茎在我阴道里急速抽送 +多位东热女优参演 +幹七八 +免费淫电影 +鸡吧勃起插入阴道 + 七海りあ +插的小穴都流水了 +回民吃猪肉 +激情人体18禁 +liu xing xue yuan +狂插meimei的小穴 +fuck吴官正 +發~綸 +幹妳 +piao liu huan jing +kk粉 +毛上妳 +幼女性交 +謝長廷 +挺动阿姨雪白肥臂 +册那娘比 +强奸39岁处女全过程/淫妹阴毛小穴 +日X妈 +大奶騷女 +向忠发 +中公網 +愛幼閣 +曾庆紅 +欧美淫色贴图 +MUGEN EX Vol。 8 美脚痴女 红音まい +我和meimei肏穴 +性福联盟 淫宝贝导航 +私/服 +日X 妈 +法**論 +操布什 +Alod +私-服 +苏兆征 +system +六月联盟 +色情电影 免费电影 成人影院 +淫水翻騰 +强奸美女 +xian jing chuan shuo +航海世纪 +六四點擊 +a 片成人免费激情小电影 +宁王府娱乐 +真三国无双OL +陈慕华 +真孔雀王 +yeeplay +东突 +毛鸟GM +淫穴兽交 +胡锦涛靠 +蔡和森 +痴乳 +干娘 +风骚护士 +东方互通 +少妇 淫穴 +4。25 +阴茎在子宫喷射黏液 +阴部特写 +毛鸟Gm +高丽樸 +我也要泄了┅┅喔 +大 紀 元 +人权 +免费淫电影吴宗宪搞笑语录(27禁看) +通用娼婦 +peachall +神婆 +成人聊天室 +onlineworms +成人漫畫 +一夜情的免费电影 +15768 +欧美激情淫电影 +日她 +红嫩的小肉穴 +日本激情淫穴 +Tokyo Hot n0248 菊池奈津美 本物RQ体内汁注入22连发六月联 +勁乐 +江戲子 +做爱图片 +蒋彦勇上书 +我奸 +狂插荡护士 +Administrator +美神ルナ Runa Mikami +毛傻逼 +瘸腿幫 +李铁映 +操淫荡少妇穴 操淫荡meimei穴 操淫荡jiejie穴 +騷浪人妻 +登 辉 +毛军长发威 +法轮大法靠 +婷婷淫色 +丰唇艳姬 +嗎的 +BT色工厂 +川岛芳子 +淫叫 +中年美婦 +本站10007多部激情电影全部免费试看 +阴道好紧啊 +外~~挂 +淫民堂 +道县公安 +孙逸仙 +merde +CUP爆乳家庭教师 +fuck商务部 +成人漫画 +小姨子淫色导航 +MM激情视频聊天 +台湾情色香港顶级淫片 +毛妹妹淫色 +少妇房中自淫,和两勇男玩7P,操得直叫爽 操日本淫女穴 +22park +抢粮记 +午夜激情宽频影院 +插屁眼 +反革命 +干她 +我和jiejie +小骚屄儿妹妹 +极品做爱套图 +强奸你 +江湖使者 +僕街 +支持台湾 +婷婷激情小说 +毛生春袋 +爷爷顶到嫂子的花心 +天畅 +新疆分裂 +Kefu +搖头丸 +法**论 +毛胡紧涛 +強姦媽媽…肉缝 +乳溝 +610办公室 +苯比 +发$$抡 +大奶头 +中公网 +韩杼滨 +登 輝 +毛私—服 +亚洲最大激情电影 +6-4tianwang +小嫩穴流血了 流水了 +eight仙靠 +刘文胜 +又长粗的肉棒 +i3hun +好嫩的阴户 +挺入阴道 +董贱华 +…你的鸡巴 用力干 +亚洲激情淫少妇贴图 +瘸腿帮 +阴茎挺进狭窄的阴户 +日本激情视频聊天室 +好色meimei电影做爱论坛 +歡迎G8情色電影院 +妹妹小穴好紧 +嚮導 +屍體 +網星艾尼克斯 +淫穴电影网 +八九年那個春夏之交 +wangce +武林群侠传 +恼杀美巨乳美女~吉川萌 +肉棒沾满了唾液 +成人 激情 性爱 午夜 高潮 情色 +MUGEN EX Vol。4 吉川萌 +舆论反制 +亞洲自然超可愛美巨乳 +幼图 +毛强奸犯 +77bbb +男男激情影院 +外~~掛 +淫欲世家 +…好棒啊……好舒服 +毛广电局 +幼圖 +小屄儿里又暖又紧 +亚洲激情淫色文章 +waigua +日本小泉 +奸污 +江流氓 +meimei的嫩屄 +asgard +jiejie被轮奸 +18dy免费观看 +免费放淫电影**日本高校女生性交 +好紧的屄啊 +祁建 +18岁少女处夜激情性爱电影下载中心 +美神ルナ +毛系统讯息 +Kamikaze Girls Vol。 30~中野美奈 +阴道夹的好紧 +发*论 +嫩穴把肉棒包得紧紧 +太王四神记 +freedom +午夜激情美穴 +激情淫乱图片穴欧美男人淫色贴图 +麦司卡林 +铁甲争雄 +舔脚 +馬場大亨 +eight仙 +┻┼ +地下刊物 +鬼轮奸 +操赤匪 +插入meimei穴中 +淫色释放贴图 +性交吞精 +肉棒插入湿淋淋的肉洞 +三民主義 +田纪云 +麦角酸二乙基酰胺 +淫奸处女论坛 +8?9靠 +日本成人激情电影 +fuck湿透的内裤 +欧美激情淫色下载 +发$论 +阿姨的阴道好紧啊 +星战情缘 +fuck升达毕业证 +周恩来 +pangya +wow711 +免费bb电影 +naive +野性家庭女教师 +母女雙飛 +舔腳 +黄色电影 +囘良玉 +sh!t +wg9996 +針孔偷拍 +毛妈B +我淫我色导航 +免费淫色情电影 处女第一次阴道做爱全过程(全套图片) +私?服 +突破封锁 +張萬年 +操戳你 +同性恋 +少妇房中自淫,和两勇男玩3P,操得直叫爽 +asshole +TNND +沈阳公安 +娼妓 +娼妇 +我日你 +Kamikaze Girls Vol。29 : Arisa Suzufusa +毛嫖客 +色界 +經典炮圖 +吴 邦 国 +令人喷血的春宫108姿势(组图)20岁禁看 +ha bao +激情电影免费下载裸体meinv乳房图 +幹妳老母 +射了还说要 +安纳咖 +成人電影 +bastard +出售神符 +大鸡巴 干进 花心 +美女潮吹 +吴 方 城 +買財富 +黄色激情电影 +午夜激情电影 +掰开MM嫩穴 +鸡吧顶住阴道口 +日本性爱电影 +穿豹紋的meinv,很有野性美。看她咬著肉根就可看出來。 +黑毛屄 +meinv电影 +日本人淫乱操淫荡少妇操淫荡妹妹 +性欲喘息女教師 +尼克松 +李 瑞 環 +夫妻作爱电影 +ASS李弘旨 +肉棒插入肉洞 +幾巴 +妹妹张开双腿等你操  +色网阴道特写强奸27岁处女全过程 +插淫穴的快感 +操腫 +你是鴨 +賣ID +免费激情电影 +操丰满小穴 +小嘴吞吐的肉棒 +batard +东北独立 +petgirl +肏jiejie屄 +日X 媽 +喷精 +本站的免费成人电影 +草嫣 +少妇床上欲火难耐自mo图 +作弊器 +操淫女穴贴图 +强奸36岁处女全过程/淫妹阴毛小穴 +镇压学生 +毛鸡鸡 +免费淫电影网站 +小姨的嫩阴道 +裸体meimei林心如穴 +不需付费的色情电影 +淫电影//令人喷血的春宫108姿势 +弟弟的肉棒好长啊 +剛癟三 +乱伦小荡妇 +最新一本道~超级名模系列第13弹 : 真乃瞳 +成人免费影院 +掯 +轻舟快讯 +硅谷动力 +草的你媽 +湿淋淋的阴道 +SM处女淫水图 +久游 +臭鸡巴 +Paki Paki +绕过封锁 +午夜成人 +玩逼 +mysupersales +魔兽世界 +保证你打飞机 +香港激情片色情工厂直播香港彩福联盟激情 +發^綸 +激情黄色电影 +毛国家主席 +Gamemanger +足球经理在线 +无套内射 +毛共狗 +百家性大型黄站视频 +蜜洞 +激情3级片试看 +鸡毛信文汇 +FLG 媽批 +张小平 +针孔摄像机 +避孕 +野性家庭女教師 +法* +免费顶级欲图禁片 +26dy淫色贴图 +同性戀 +肉棒狂插穴口 ┅好爽┅┅ +鸟你 +毛蒙独 +天安门母亲运动 +fuck石进 +干妈妈的爽 +Client Server +步非烟 +干保姆小穴 +我幹 +da hang hai +本站10013多部激情电影全部免费试看 +免费淫色电影-无需注册 +淫骚穴电影 +搓揉裸露在外的那对奶子 +去氧麻黄碱或安非他命 +淫奸meimei穴 +李 瑞 环 +抽插32岁处女meimei淫叫不断 +淫乱潮吹 +168www +DJMAX +慾火 +午夜影院秘密通道_免费不需注册看电影 +毛妹妹黄站 +江豬媳 +伦功 +和护士姐姐淫穴 +meinv淫水狂流 +鲜嫩蜜穴 +烂b +两性激情电影 +香港激情淫色贴图 +felch +999日本妹 +母子淫奸乱轮现场看……扶正肉棒 +xinguangming +吸精痴女護士 +中文搜性網 +黄色免费淫电影网 +夜色城 +老师小穴 +烂B +他妈ㄉ王八蛋 +18岁女生主动让男生开苞全过程◥免费黄色电影 +國民黨萬歲 +……太舒服了 淫肉穴 +日本激情淫色贴图 +猛烈 挺送 肉棒 激烈 撞击 +毛华建敏 +激情视频聊天 +肉棒插入骚穴 +肉棒好大啊 +淫电影免费在线观看 +发~纶 +奇迹世界 +联易互动 +十七大 +fuck想上你 +chi long jian xin +毛吗啡片 +操少妇嫩穴 +白漿四濺 +原味絲襪 +酣乐欣 +狂插儿媳妇的阴道 +駛你老師 +妩媚挑逗 +天翼之鏈 +美女吞精 +东热美女一个比一个强 +台湾成人电影 +仙界传 +jiejie的穴好大啊 +福摩薩 +大鸡巴 插入 肉缝 +强奸25岁处女全过程/淫妹阴毛小穴 +狂插妹妹的小穴 +阿雅娃娃 +夫妻3p +少妇扒开阴道图-淫賤少女阴唇特写图 +fuck台湾共和国 +抽插54岁处女妹妹淫叫不断 +江则民 +免费dse淫乱图片 +懒教 +成人免费电影 +毛威而钢 +淫电影//教你怎样延迟射精18岁以下禁免费淫电影a片 +亞無碼 +操成人片 +法× +新手指導員 +淫声浪语 +李 嵐 清 +又大又嫩的阴户 +江戏子 +干他妈 +淫色少妇狗小说大全 +淫图淫片全部免费 +DROP +┅大力插┅大鸡巴 +MM的小嫩穴 +台湾狗 +Parade Vol。57:巨乳絞りボンデージ +用你的阴茎插我的阴道 +鴉片 +fuck乡巴佬 +咪咪色界 +最淫大陆成人贴图电影区 处女一丝不挂自慰图片 +台湾身材一流美女楼梯性爱 +插你奶奶 +台湾独 +淫民激情文学图库下载淫民激情文学图库专题 +毛驶你母 +88科技 +流氓 +淫奸少妇穴 +顶级乱伦高潮淫水 +毛靠 +免费妹妹黄色淫乱 +女教师禽兽轮奸陷阱 +亚洲有码 +X到喷屎尿 +毛賊東 +李 淑 嫻 +六月聯盟 +動亂 +天翼之链 +家庭教师は女子校生 藤沢美歩 +大史纪 +操陈良宇 +海天英雄傳 +bxqt +鹿城娱乐成人俱乐部 +射 精 +朱容雞 +刚比样子 +处女淫水图台湾女人裸 +falun +毛胡XX +刘山青 +兔妹妹贴图区 +動乱 +大肉棒 +愛液橫流 +最新成人激情电影网站 +女干三亏 +di guo chuan qi +撅起大白腚 +fuck社科院 +操肿 +濫貨 +强奸32岁处女全过程/淫妹阴毛小穴 +大阳具从后面插入她的小穴 +賀國強 +亲民党 +龟头喷射出浓浓的精液 +淫亂工作 +陆委会 +免费淫色妹妹电影网 +毛发改委 +淫圖 +KeFu +苏振华 +(Waap)女教師 盗撮 - 志保 +荡女 +萨达姆 +操婊子 +earthciv +傻逼 +毛傻B +亚洲激情淫穴 +淫图 +夠酷GOQO +大鸡吧在小穴内壁摩擦 +老B +要射了 +肉棒已经整根插入穴中 +大众色情成人网 +fuck双峰微颤 +操肏 +光宇華夏 +江山美人志 +ボディフェティッシュ 桜子 DVDISO +tian shi +毛干妳老母 +中文搜性网 +毛青天白日 +民運 +黄 菊 +毛监管局 +抽插30岁处女meimei淫叫不断 +李月月鳥 +在线淫电影 淫奸电影 黄色电影 +龟头 花心 骚屄 +毛希特勒 +午夜成人影院 +日韩淫女 +他干 +童颜巨乳 +淫女论坛 +精子射到jiejie的穴里 +鸡巴小穴 +手伸到两腿间 +法埨功 +私\服 +荡妹 +插白洁小穴 +鸡八 +露點 +免费成人十八影院 +消滅共產黨 +黄永胜 +肉缝 嫩嫩 +整个龟头插入小穴 +干尼 +淫女贴图区 +濕透的內褲 +lineage2 +男女激情淫影片图片 +肉棒插入 嫩穴 +荡妇 +麦克阿瑟 +银行帳號 +礼品机 +把大龟头对准她的阴道口 +妹妹的阴蒂 +馬凱 +妹妹骚图 +毛迷药 +淫妞 +大鸡巴好粗… +免注册淫电影在线观看 +賤人 +萬淫堂 +萬王之王 +你的小穴好紧 +及びタイトル ?(Calen)セーラー服とマシンガン 柚木ティナ +wu jin de ren wu +粉穴 +全免激情聊天室 +毛食屎 +父女激情淫色文章 +戳你 +肮脏美学 +揉搓淫骚穴 +22dy淫色贴图 +淫妻 +他奶娘的 +姦染 +天纵 +minhui +鳥gm +淫妹 +ray-city +下载免费淫色强奸电影 +宇明网 +媚藥少年 +毛卖软件 +遊戲新斷線 +淫间道 +爽mm +黄色免费淫电影母子淫奸电影 +李鹏 +淫姐 +陈总统 +群交亂舞 +内射美妇 +摸阴蒂 +去他妈 +抽叉jiejie +淫电影//少女被强奸到高潮时偷拍小A片 +布雷爾 +淫娃 +18禁-空中小姐的淫荡性生活(无码)。 +欧美淫图片 咪咪爱论坛 +智冠 +淫乱金发美女 +他妈 +蒙古獨立 +新郑和 +官逼民反 +李 淑 娴 +内测帐号 +meinv含双棍玩内射 +騷婦露逼 +發^論 +嫩穴里他的鸡巴 +蔓ぺ +Waigua +偷拍掰开阴唇做爱 +性无能 +天縱 +fuck私\服 +龌龊 +我淫我色网站 +meimei的阴道好紧啊 +遥想当年春衫薄 +毛共产党 +社保基金会 +天堂2 +抽插49岁处女妹妹淫叫不断 +輪子功 +政治避难 +买春 +法*輪*功 +消息公告 +民進黨 +street of EROS 07 小泉リカ +webmaster +俄罗斯 +水去车仑 +毛天安门 +Mugen Vol。11 Ai Hazawa羽沢愛!【AVI/ 699MB】 +淫婦 +婊子 +肉棒猛烈拔插 +荡母淫儿 +精液射入了她的体内 +色图专区 +fofg +mes couilles +女激情淫影片下载 +107bb成人小电影 +谭政 +亞情 +吕京花 +淫妹妹贴图 +身份证生成 +101bb成人小电影 +觀世音 +滛 +鷄巴 +手记注册日韩5002部激情电影 +干死你 +渡口 +毛回良玉 +又黑又粗长的鸡巴 +f r e e c h i n a +鸡巴插入拔出 真舒服 +瘪三 +欧美激情淫色 +电影淫电影艳情电影 +毛妈祖 +最新黄站 +龟头抽插很紧的处女阴道 +fuck卖.国 +龟头 插进 阴户 +她马的 +悔过书 +shyt +日他娘 +少妇床上欲火难耐自摸图 +毛法轮 +性感诱惑 +毛死全家 +张潮阳 +阴茎在我的肉洞中抽送着 +核武器 +性虐待 +成人贴图区论坛 +WEB战牌 +fuck新生网 +发^轮 +性免費電影 +激情meinv贴图九九情色 +教你怎样延迟射精23岁以下禁免费淫电影a片 +成人网址导航 +Painful Groins Getting Pounded : Akira Shiratori 白鸟あきら +mo你 +中华人民正邪 +抽B淫穴 +∪R +xin jue dai shuang jiao +伍凡 +(Tokyo Neko) Tokyo Neko GN Vol。1 Ibuki XVID+Ogg +淫人情色导航 +sm調教 +毛社保基金会 +妹妹的阴唇好大啊 +大鸡巴 大肉棒狂插嫩穴 +中央军委 +释迦牟尼 +大阴唇jiejie +柯賜海 +干Gm +煞笔靠 +常委 +邱会作 +fuck他爹 +天天免费成人 +做鴨 +水去车侖 +操蛋 +穴门meinv图库 +干GM +发~论 +鸡叭 +阴唇阴道大图三级 +連戰 +性视频聊天图幼女日屄视频脱衣聊天室明星 +易当 +jiejie的阴唇好大啊 +幾八 +淫乱图片 +所盗摄护士姐姐性感美腿图 肉丝美腿艳情淫欲 +淫色BT娱乐导航 +干勒 +徐和柴学友 +肉缝 蜜穴 肉棒 +流淫 +混亂冒險 +毛人体炸弹 +刘杰 +半夜我把龟头插进meimei的深处 +江西田园置业集团 +豆豆秀 +手记注册日韩5014部激情电影 +干小姨子小穴 +性趣 +亚洲成人情色网站 +你妈的 +EVENT +国外A片电影 +胡耀帮 +淫奴 +法陯功 +淫女 +淫奸 +钱 其 琛 +龟头插进 +少妇被强奸密穴流水 +肉棒插入美女的肉缝 +hellgate:london +抽插42岁处女meimei淫叫不断 +白嫩騷婦 +jiangshan +淫妇 +大鸡吧操小逼 +傳銷 +王润生 +免费看淫电影 +淫奸熟睡小姨子 +MUGEN EX Vol。7 濱崎(MX-07) +毛刘淇 +邹家华 +湿透的内裤 +乳房 小穴 鸡巴 +肉棒插进阴道里 +濕了還說要 +成人色情乱伦影院 +激情淫色合成贴图 +一本道~松下美里 +插入穴 爽 +redmoon +毛鮑 +┅┅啊┅┅好舒服啊 +kjking +meimei社区淫色 +Red Hot Jam 9 ミュウの新人调教 +李贵鲜 +妳妈的 +港澳成人午夜激情 +免费淫 电影a片 +傅申奇 +毛李岚清 +毛傅鹏 +插入媽媽…肉缝 +中華人民共和國 +di qiu wen ming +八老 +膏藥旗 +她的小屄不紧 +中華人民共和国 +鸡吧 +桃色星期五 +putain +群交乱舞 +fuck我日 +邓发 +毛摇头丸 +baichi +漢娃娃 +BLOW +遺囑 +騷B賤 +外 挂 +Mix Studio Vol。 7女医 +妹妹的小淫穴 +在线免费成人电影 +moyu +淫屄 +卡斯特罗 +达赖喇嘛 +草的你妈 +李立三 +d7se +厕所盗摄 +女教師赤版 +27军军长 +gong fu xiao zi +高丽棒子 +肉棒在jiejie的阴道里 +遗忘传说 +愛滋 +天聯世紀 +KOKESHI COWGIRL Vol。24 炎的10番勝負2 前編 : 工藤Hatsumi +美国激情淫色网站 +幼女淫图 +法綸 +成熟性感大美女 +根正苗红 +诱色uu +大阳具 +shen zhi ling yu +彭珮雲 +黄色淫乱电影 +江豬 +大乳頭 +xian jie zhuan +本站10008多部激情电影全部免费试看三天 +谋杀 +津瑞 +6。4事件 +国家民委 +【亚洲/无码】极品女优-姬野愛!【RMVB/488MB】 +日韩免费成人电影 +mao xian dao +猛男狂干meinv +值勤帐号 +老骚比 +毛江核心 +女教师淫乱课堂 +懶叫 +造愛 +urban-rivals靠 +日批 +大話西遊 +tie jia zheng xiong +护士嫩穴扒开嫩穴嫩穴 +遺嘱 +毛疆独 +天安們母親運動 +毛旅游局 +桃色 激情电影 +5173 +强奸26岁处女全过程/*妹阴毛小穴 +銀行账號 +goqo +巨乳素人 +毛淫毛 +幹你 +陳總統 +pp点点激情片播放 +他娘 +毛骚 +妹妹騷圖 +邓小平 +永恒之塔 +三国豪侠传 +%共产党烂逼 +妹妹的小屄好痒 +乳暈 +fuck我操 +僵贼 +姐姐的小屄 +布希 +彩票机 +激情貼圖 +智傲 +明星裸体写真图 meinv网络视讯三点 +淫告白 +插穴止痒 +梦幻情人射了10次的强片 +支持达賴 +刘延东 +毛蒙尘药 +发^^沦 +拔出来 +绿色數碼 +熟女玩3P内射来满足欲望 +fosaon +發~~侖 +發@輪 +精液射进妈妈穴里面 +乳晕 +鸡巴受不了了┅┅要泄 +完全免费在线淫电影? +插 小姐 +teen sexy +楊振 +毛蒙古达子 +毛淫水 +他媽 +禁书 +最新 Queen8 无修正素人 +多维 +米田共 +锦天 +少林传奇 +乳波臀浪 +吃雞巴 +凸点装 +大力抽送 +极品黑丝 +绿色數码 +安非他命 +高莺莺 +毛港澳办 +猛烈的挺送、肉体激烈的撞击 +支持达赖 +习仲勋 +脸盘美身材好就是屄丑点 +39仓Ku +roiworld +插穴止癢 +淫 +淪 +肏妹妹的小骚屄 +强*十八岁meinv护士看完保证你打飞机免费淫电影a片 +在线淫色电影 +天安门英雄纪念碑 +儿子添着妈妈肥大湿润阴唇 +免费电影 meinv电影 +她的阴道好紧 +日本激情淫色贴图区 +暴亂 +图片不爽你砍我 +fuck邪教 +白嫩丰腴的大腿掰开成大字形,肥嫩的小骚屄儿 +无码长片 +亚洲成人网 鹿城最新娱乐网 +tian shang bei +添 穴 两腿间 +和阿姨乱伦 +龙虎靠 +手记注册日韩5035部激情电影 +抽插45岁处女meimei淫叫不断 +發^^倫 +現貨 +淫*女电影片段试看淫mm +365激情淫色贴图 +cocksucker cocksucker +情色导航 成人电影 +毛老逼 +激情淫色文章网站 +日本AV女優 +毛法*轮*功 +3p炮图 +性感动感meinv日本幼少女性感写真 +鳥Gm +搜神记 +60xp。com 电影免费 +歡樂數碼 +黄色情挑艳情小说网骚妹妹成人论坛 +淫語連連 +苏东解体 +日你九城 +色男淫女 +顏射自拍 +暴乱 +润星 +台湾身材一流meinv楼梯性爱 +暴乳 +鳥GM +tnnd +痴女吸精 +免费操小姨子 操小姨 操小姐图片 操小姐小说 操小姐自拍 按摩洗浴操小姐 操外国小姐b +zhenshanren +真封神 +小日本 +shen me shen me da mao xian +毛上你 +仿真假钞 +亚洲**联盟激情视频 免费下载做爱图片 +她爸爸 +新华通论坛 +保證很像學生妹 +好大的阴唇 +应召 +絲襪淫婦 +鸡吧猛的抽插嫩穴 +popoming +操日风骚少妇穴 +黎安友 +淫荡护士穴 +fuck小日本 +毛我日 +綸功 +马时敏 +hua hua man +狂插儿媳 +三级小电影 +性爱电影网 +公车淫奸女学生 +1989天安门 +激情色情 +台湾女人裸体贴图香港成人电影网 +亞洲色 +温州鹿城成人网 +使劲插我啊 +东北xx网 +蕾丝内裤被龟头顶穿 +发@@抡 +艳照門 +则民 +射了還說要 +淫女嫩穴图 +Duty Vol 50背徳の近亲相奸 +劳动教养所 +潘国平 +朱可夫元帅 +军民血腥冲突 +免费淫奸女A片段试看 20岁女大学生被强 +免费观看美女裸体贴图 +輪奸內射 +西遊伏魔錄 +毛淫欲 +meinv极品穴 +毛鸡 +舔西 +绿色数码 +毛鸠 +pp242淫色导航 +a片/A片下载/毛片/毛片下载 +毛江Core +sofben sofben +淫水也流湿了我干进她穴内的龟头 +干bi +暴操淫荡小meimei +管里 +民阵 +卖财富 +runstar +逼孕 +麦角酸二乙基醯胺 +毛天皇陛下 +自由之門 +日本娱乐性免费电影在线 +又肥又大的穴 +刚比 +中國分裂 +SYSTEM +电影免费试看 +仙侣奇缘 +中国大学 高清女厕盗拍 vol。01 +K房 +视频自拍 +独占动画~潮崎~高校女教师陵辱1+2 +免费聊天室 +刚瘪三 +騷女叫春 +成人社区 +党主席 +西藏问題 +成人社區 +中國恐怖組織 +fei chang san guo +手记注册日韩5024部激情电影 +sperm +三国世纪 +毛鲍 +chinaliberal +阴精喷向龟头 +少妇房中自淫,和两勇男玩16P,操得直叫爽 操日本淫女穴 +sm援交 +幹x娘 +下注 +mo xiang +强奸45岁处女全过程/淫妹阴毛小穴 +女巨乳女教師 +翘臀嫩逼 +新闻出版 +錯B +捅进她的阴道里 +bitch +抽插38岁处女meimei淫叫不断 +艳照门 +巡查 +吸精小少女 +89-64cdjp +干gM +淫秽男女激情淫乱 +hanbitsoft +西藏问题 +18岁处女床上开苞 +more +白虎小穴 +bukakke +欢乐城美国在线 咪咪爱论坛 +香港马会 +嫩穴狂插直到痉挛 +李 岚 清 +人大代表大会 +毛日本鬼子 +午夜激情情色网 +肉棒进入肉洞 +自由之门 +caobi +fuck王震 +肉棍干騷婦 +啊 啊 啊 好哥哥 +日本meinv图库 +毛强卫 +淫奸少妇电影 +墨索里尼 +免费免注册在线看电影 +交媾 +東北獨立 +法纶 +肉棒的抽插 ……啊 +下流 +色网阴道特写强奸29岁处女全过程 +发^论 +品色永远免费堂pin6 meinv发春激情3级片试看 +兔妹妹色色贴图区 +叶剑英 +乱伦+都市+制服 +毛懂文华 +二五互联 +发@轮 +姦汙 +國家機密 +毛肉缝 +yuanming +干gm +淫水大量流出 +metin +由喜贵 +谢长廷 +三去車侖工力 +大鸡巴插进meimei的小穴 +二五互聯 +娇妻超市被奸,淫荡妈妈之办公室助理 +江贼 +鸡吧插到嫩穴 +美女激情性交射精电影 +买春堂 +奴隷女教師-女尻狩り 吉野あゆみ +淫蕩少婦好色老師 +gate to heavens +册老 +麦角酸 +他祖宗 +fuck新光明 +操蠢猪 +88bb成人小电影 +fuck铁道部 +欢乐城 +亮屄 +大唐风云 +宋祖英 +傅全有 +神之领域 +龟头插入淫荡少妇 +混沌靠 +巧淫奸戏 +……媽的騷穴癢死了 +發$輪 +幾叭 +蒙哥马利 +大话春秋 +一股淫液从肉洞喷出 +淫荡少妇穴 操淫荡少妇 +曾培炎 +kefu +花心大型色站 +meinv偷拍成人小说激情网 +断水 +冊老 +xian jing chuan shuo +免费注册激情视频聊天 +transvestite +性情中人 +刘凯中 +狂插空姐 +操冰毒 +妹妹的大阴唇好嫩啊 +毛我操 +日本AV女优 +抽插37岁处女meimei淫叫不断 +湿了 +毛吴 仪 +售號 +朱容鸡 +日韩淫乱meinv图 +酥胸诱惑 +lian ai he zi +法**輪 +含着龟头 +分裂祖國 +meng huan zhi xing +Tora-Tora-Tora Vol。22 : 冬月ひな +Ji女 +淫水和精液浸濡的小穴里 +秘密通道 +fuck驶你老母 +烂比 +新视野工作室 +狂操小姐 +分裂祖国 +陈随便 +鲍鱼贴图妖色成年网电影 +大哥 等等 我尿完后 再给你干肉穴 +操b +学生妹同男友夜晚做爱并轮插 +hypermart。net +狂插妹妹穴 淫水流 +巧淫奸戲 +fuck水利部 +何德普 +成人午夜激情 +操B +海盗王ONLINE +ying xiong wang zuo +遗囑 +毛抢劫 +大東亞共榮 +*李*洪*志* +辛灏年 +保证你打飞机免费电影网站 +kaixuan +毛新唐人 +發*輪 +AV OPEN)(TOD129)近亲3姐妹狂乱夜 +尸體 +别他妈的装 +fuck私—服 +虎虎虎~变态心Tora Tora Gold Vol。17 : Mako Takeda +一贯道 +fuck宋祖英 +台灣民國 +肉棒插入阴户 +J-Girl 双穴~水原 小笠原崎 +屎你娘 +妳她媽的 +出售手枪 +喵的 +365免费情色网欢欢成人娱乐 +fuck天安门档案 +逼奸 +鸡巴磨得舒服 +遗嘱 +白嫩美女穴 +fuck私-服 +灌满精液 +桑国卫 +操妳全家 +玖玖金币 +your mom your mom +creaders +搞大肚婆爽+口交泻水淫图 +张 宏 堡 +斷水 +人妻 +shit +我和姐姐肏穴 +Aids +ling you ji +插的妹妹流淫水 +瓜娃子 +jing ling +賣月卡 +刘淇 +你他馬的 +发*轮 +鸡奸 +王俊博 +鸡女 +乳房 +僵贼民 +公务员调资 +制服美少女 鮎川なお +新聞管制 +fuck私/服 +毛他马的 +阴壁的嫩肉夹得我非常舒服 +淫店 +黄色淫电影/大幅的陰毛覆蓋著她的迷人洞 +Tokyo Hot n0232 : 真宫梨沙子 +台灣民国 +硕大的龟头 +毛吗啡碱 +操你爷爷 +renmingbao +meimei的屄好紧啊 +分裂中国 +欢城互动 +57xp。com 电影免费 +消灭共产党 +王 秀 丽 +UPDATE +分裂中國 +天安門檔案 +日本顶级淫女 +傅鹏 +68wow +无产阶级 +贾廷安 +bt免费淫电影下载 +毛交通部 +高丽朴 +偷操嫂嫂 +mm要我使劲插它的穴 +鲜红小嫩屄被群奸真可惜 +du shi 2046 +妈b +喬石 +Lateinos +严隽琪 +淫穴 大鸡巴 +狂插我的小嫩穴 +街上钓个漂亮马子回家玩 +meinv主持25小时全天激情热舞 +輿論鉗制 +蒋正华 +遭警察殴打 +本拉丹 +房事 +妈B +美女性交极品大片 +红肿的小穴摩弄 +跨下呻吟 +毛骚货 +插小穴 +啊…我的亲丈夫…用他的手…插…啊…啊…进了人家的小穴 +最新一本道)超正MODEL系列 仲里愛 +精液 +红 灯 区 +天然むすめ~08-15 素人むすめたち +qq堂 +peacehall +肉棒……插死浪穴了 +快操我快操我的小B电影 +把阴户内塞得满满 +大肉棒干进小穴 +鄧朴方 +大幅的陰毛覆蓋著她的迷人洞 +教你怎样延迟射精40岁以下禁免费淫电影a片 +19dy淫色贴图 +少女露嫩穴 少妇嫩穴 美女的嫩穴 +徐建國案件 +龟头插入阴唇 +appie +玉女心經 +罗荣桓 +精液喷射在子宫上 +又粘又湿的阴户 +弹劾 +日韩激情电影 +發@@倫 +巨乳女教師 +迷奸熟妇怎样抚摩女性的私处更刺激 +午夜激情剧场 +瞳 +法**綸 +我和她 +扒开淫女的骚逼 +b毛 +Obama +發~淪 +龟头插入蜜穴 +共荣圈 +肉穴 大鸡巴 ……骚穴 +发$纶 +毛民运 +恥辱醫護下载 +快乐AV +邮政局 +我和小姨子 +插嫩逼 +李洪宽 +操小穴 +哪有a片 百万meinv贴图夫妻激情免费视频 +如何推翻中共 +血洗天安門 +渣波波 +李兆焯 +表姐含我小鸡鸡 +情色淫电影 +herogame +騷乳 +教你怎样延迟射精27岁以下禁免费淫电影a片 +妹妹┅┅爽快┅┅死了 +毛毛泽东 +神泣 +dick +戴海静 +神泪 +打倒中华人民共和国 +枪决现场 +成人禁书 +插入穴爽死了 +保钓 +fuck食捻屎 +骯髒美學 +釣魚島 +干……干我……用力地干我…… +毛西藏天葬 +免费色站 +毛干你 +毛兴奋剂 +SHIT +89六四 +淫情 +金尧如 +雪腿玉胯 +(Nadeshiko)夢の超高級癒し系Wおでかけソープ嬢 完全版 +干嫂子 +法溣功 +NEWSPACE +狂插秘书穴 +Kamikaze Girls Vol。23 : Haruka Kaede 枫はるか +可愛均整清純派meinv可愛均整清純派meinv +韩天石 +吸吮套弄了起来 +奥美电子 +免费台湾18 电影 +东方资通 +騷小浪女 +無碼電影 +我和老板娘 +淫穴更紧紧将我的肉棒吸住 +fuck他妈 +男女激情图片 +國家安全 +浴室亂倫 +虎门靠 +megaone。com +cronous +叼你媽 +毛狗卵 +牛鬼蛇神 +冊那娘餓比 +儂著岡巒 +我要性交 +将肉棒插入漂亮的老师小淫嘴抽插数十次 +群奸轮射 +全球第一淫图城 +san guo hao xia zhuan +夜夜色大型网站 +毛靠你妈 +bing feng chuan qi +fuck我日你 +洗腦班 +fuck吴邦国 +groove party +贾庆林 +娇嫩的小阴核 +mo fa fei qiu +福呵定 +毛肉穴 +虎騎 +疯狂的抽插 +敬国神社 +kong que wang +zhen kong que wang +干死GM +徐炳慧 +肉棍 嫩穴 肉洞 +操大B +手记注册日韩5028部激情电影 +meimei美图网 +妹妹的屄 +母子乱淫贴图 +色咪咪 +干比 +毛十五周年 +生孩子沒屁眼 +情色激情论坛 +性虐 +免费成人午夜电影 +日本淫贴图 淫妻贴图 +性虎 +阴茎被她紧紧地夹住感到肉洞急促地收缩 +居家女人的淫荡性事 +温州黄站 +抽插56岁处女妹妹淫叫不断 +华岳时事论坛 +儿子粗大的肉棒 +淫电影 强*十八岁美女护士看完保证你打飞机 +张开的小阴唇 +李小鹏 +玉女心经 +毛机八 +家人一起凌辱母亲和叔母 +激情成人乐园 +xia ke tian xia +rape +盛宣鳴 +黄色淫穴电影 +乘骑按摩 +xin zheng he +壮汉给纯情处女开苞见血 +應召 +免费淫色情电影 淫电影//少女被强奸到高潮时偷拍小A片 +台湾18成人网站 +本土无码 +賣B發論公 +司徒华 +apesoft +温总理 +迷人阴部护士meimei也疯狂 +情獸 +骚妹妹成人导航 +作愛 +抽插28岁处女妹妹淫叫不断 +神汉 +美丽素女の性游戏 +色网阴道特写强奸35岁处女全过程 +新西遊記 +西藏國 +回民人吃豬肉 +干死CS +反攻大陆 +证监会 +西藏国 +杜智富 +毛塞你爸 +毛气象局 +反攻大陸 +又大又紧的阴户 +激情成人聊天室 +秘书自慰被偷拍 +一夜欢 +妈妈的 +强卫 +毛邪教 +胡志明 +狂插小嫩穴 +咪咪爱大型黄站 +东热meinv一个比一个强 +迷人小穴好紧好湿 +蝉童 +免费台湾激情片 +Trickster +激情淫色贴图网 +发*纶 +18歲少女 +情色电影注册观看 +小穴夹的我好紧 +撒切尔 +hua xia +江泽慧 +中国性爱城 +騰仁 +空中小姐的淫荡性生活 +一夜歡 +以茎至洞 +亲 日 +品色永远免费堂pin6 美女发春激情3级片试看 +王太华 +磨蹭阴道阴毛 +妹的穴 +两会报道 +毛工作人员 +你妈逼 +fuck斯大林 +淫色bb贴图 +無碼彩圖 +於幼軍 +内挂 +精液射进她的小洞 +慶 紅 +日本插穴 +hongzhi +懒8 +淫电影//富豪们的疯狂做/爱方式 +新党 +免费淫奸女A片段试看 母子淫奸乱轮现场看…… +淫荡少妇激情自拍 成人激情 +免费成人两性电影 +抽插大淫穴 +邹德威 +飘流幻境 +大FA弟子 +小淫穴 +淫奸秘书电影 +剑侠情缘OnlineII +SKY宫泽Keito 超美系模特儿初无修正引退纪念作 +毛反革命 +龟头插入少妇阴道 +手记注册日韩5031部激情电影 +黃孟複 +盛宣鸣 +疯狂姐姐淫穴 +wg8800 +上访 +壓迫 +大B +王乐泉 +tta2 +运營组 +人民代表大會 +刘军 +愛色cc +博白县 +抽插35岁处女meimei淫叫不断 +死亡人數 +李鐵映 +鹽酸二乙酰吗啡 +毛淫叫 +丝袜 +connard +popkart +天安门事件1989 +处女小穴 +成人爽电影网站 +MM的诱人双峰 +超强护士团 +东方传说online +他爹 +怎样延迟射精22岁以下禁 +午夜影院 +十八dy毛电影 BTA片 免费激爽电影 +美穴張開貼圖區 +毛南蛮子 +两性小说 +尖閣列島 +如果你未满28周岁请自觉离开。 +精液喷入穴 +项英 +林心如合成淫照图片林心如淫照图片 +脫內褲 +肉棒 小穴里抽送 +丝袜高跟 +淫女炮圖 +金泽辰 +穆罕默德 +我跟meimei肏穴 +本站10000多部激情电影全部免费试看三天 +日本meinv吃精图 +秋本純菜 +操日本淫女 +helbreath +粉红嫩穴 鲍鱼嫩穴=3 +粉红嫩穴 鲍鱼嫩穴=1 +抽插51岁处女meimei淫叫不断 +粉红嫩穴 鲍鱼嫩穴=2 +天晴数码 +倪志福 +万晓东 +色色婷婷 +(最新一本道)独占动画~薰~陵辱巨乳 +手伸到下体抚摸嫩穴 +八 仙靠 +儿子的肉棒好硬 +本站10000多部激情电影全部免费试看 +sm舔穴 +人民代表 +素人之中的极品漂亮妹 +小癟三 +feng wu tian jiao +大血B +刘刚 +成人激情淫影院 +爽女美图美搜性感图涩界成人电影网小小鸟绝色美女写真图 +用舌尖插着阴道口 +我占有了妈妈和阿姨 +情色六月天 人间仙境情色网 +xin shi qi +熟女网爱记 +姐姐的穴夹的我好紧小说 +乱淫自拍图片 +俄国 +操比 +淫女炮图 +运營者 +TokyoHot之极品妹妹 +ttee +毛新华社 +天晴數碼 +610办公室靠 +陈伯达 +赤裸天使 +虎骑 +台聯黨 +毛龟儿子 +白嫩骚妇 +毛傅作义 +小穴的周围不断地缠绵着 +台湾18成人 +毛尉健行 +阿姨的穴┅好爽 +韩东方 +媽個老比 +毛毛主席 +tth2 +和jiejie插穴 +華建敏 +精童 +毛李长春 +香港两性激情文学区 +fuck身份生成器 +死亡人数 +插入妹妹穴中 +狂操淫荡女 +干你妈逼 +华语世界论坛 +天葬 +pet520 +夫妻自拍 +色诱 +毛文化部 +秦基伟 +宋xx +陈锡联 +山不过来 +逃亡艳旅 +11。xp。com成人影院 +meimei小穴 +激情裸聊 性爱电影 +BT成人无码 +血洗天安门 +人妻做爱 +fuck新党 +可憐賣菜婦 +遊戲宮理員 +情色 激情 meinv 穴 +mir3 +湿了还说要 +zhengjian +免费裸体meinv性交电影 +洗腸射尿 +gang jia hong liu +诱惑女教师 +dick dick +顶到了欣虹阴道最深处 +zheng qi huan xiang +阿罗约 +口交放尿 +连战 +…好深啊…操我 插我 +da hua chun qiu +b样 +性福源亚洲激情 +中国恐怖组织 +温家宝靠 +乳罩 +meimei吸精 +操死 +色聊激情视屏聊天室 +戰國英雄 +蔣介石 +海关总署 +帶炼 +姦淫 +懒八 +午夜免费成人黄色 +妈祖 +农民伯伯乡下妹 +强奸十八岁meinv护士看完保证你打飞机免费电影网站 +U R靠 +風豔閣 +lihongzhi +玉蒲团 玉女心经 +王力雄 +lian ai he zi +阿姨的阴户好大啊 +jiaochuang +淫奸少女论坛 +新金瓶梅成人片 +B毛 +香港激情夜 +香港激情淫穴 +草芝麻 +大 史 紀 +网星艾尼克斯 +淫奸meinv穴 +meimei张开双腿等你操  +舔逼 +wg2222 +毛妹妹贴图区 +龜頭 +浩天銀科 +hai zhi yue zhang +知障 +fuck希特勒 +援交薄碼 +処女 +欣赏特级毛片pp 点点毛片 美女毛片 大陆毛片 +激情电影在线注册 +免费我该死淫水流出图 +淫女与猪乱搞图 +郭 岩 华 +龟头插入少妇 +激情视频 +懶八 +星际online +发^^纶 +韩国成人激情影院 +金庸群侠传 +粉紅穴 +毛驶你娘 +操狗 +插穴好舒服 +好爽……顶得好深啊…… +龟頭 +駭客 +毛劳动保障部 +丁字裤翘臀 +虎门 +色成人 +可卡葉 +51vip +纠察员 +遊戲橘子 +儂著卵拋 +黑马@美女全身神秘黑让你爽到眼框黑 +淫战群p +毛黄色小电影 +肉棒在阴道口游荡 +你的 嫩穴 好粗 +basterd +肉淫器吞精 +食精 +强奸24岁处女全过程/*妹阴毛小穴 +钢甲洪流 +松花江污染 +免費成人網站 +騷包 +淫战群P +叫小姐 +诱惑骚妹 +人妖@Lady Sonia-熟女丝袜 12 +林心如做爱网有激情 +操嫂嫂 +淫乱的女老板 +肏穴好舒服 +激情淫色电影 +獸 +老少亂倫 +成人淫穴导航 +老毛子 +你祖宗 +毛乳头 +体育练习场盗撮スポーツジム(4カメ洋式) +插meimei图 +膣穴大陵辱 松岛 +籐原紀香Norika Fujiwara SEX +錯那嗎逼 +獨 +精童欲女 +高级逼 +李 總 統 +mingpaonews +淫肉诱惑 +毛烂逼 +┅插┅小穴 肉缝 +粉紅愛液 +浪女自慰诱惑你操 +nnd= +魏新生 +援交薄码 +免费操小姨子 操小姨 操小姐图片 +狗養 +操爽 +日你祖宗 +少妇淫图电影网 +免费激情影院 +毒龙舔脚 +上山下乡 +busterd busterd +狗娘養的 +警匪一家 +15年前的“共和國衛士” +激情聊天室 +大话 +厕所盗摄美女 +丁香成人社區 +穴里嫩肉把鸡巴包得紧紧 +日韩成人电影 +sex大型色站 +胡总书记 +操爛 +去氧麻黃堿或安非他命 +闹事 +梦遗 +彭冲 +本站10014多部激情电影全部免费试看三天 +抽插38岁处女妹妹淫叫不断 +激爱贴图 加西激情中文网 +女性私处锻炼法 +我的穴 +税力 +裝備演示 +毛叫鸡 +好大阴户 +陈永贵 +流淫水 +操mm穴 +asshole asshole +免费淫电影吴宗宪搞笑语录(20禁看) +丁香成人社区 +粗大肉棒从后面插入 +插進 +妳娘的 +free style +插逼 +撒泡尿 +秘书的大乱交 +手记注册日韩5005部激情电影 +学生妹美女在野外偷情 +赵品潞 +坐台的 +无码H漫 +rong yao +毛鲜族 +祭日 +吳官正 +口含住鸡巴 精液 +成人午夜激情视频 +色狼小說 +扒开小穴 +激情淫色组图 +捐赠排行 +ygbh +見到這個meinv就會有性欲 +as$hole +菊花洞 +黄色免费淫奸电影我和女友干爽后再她妹妹 +运營組 +裸体妹妹林心如穴 +蘚鮑 +愛液 +Transformaition 栗田Hiromi +插进 +疯狂姐姐教弟弟小说 +轮流干 +365成人网站 +删号 +阿姨的小穴 +guang zhi guo du +肉棒全部插入 +少妇房中自淫,和两勇男玩11P,操得直叫爽 操日本淫女穴 +淫meimei贴图 +戴维教 +亚洲成人无码 +台湾成人20贴图 +大肉棒……好粗 +牙齿轻咬他的龟头 +免费淫奸女A片段试看 居然花钱请人教性爱姿势(组图) +小瘪三 +午夜激情meimei +毛寇晓伟 +手机注册看性爱电影 +肉棒插入妹妹的肉缝 +快乐西游 +fuck司法部 +百家性大型娱乐黄站 +爛 +林心如做爱我该死快乐情感乐园 +大b +毛联合国大会 +ke luo si +原味丝袜 +日你 +肉棒摩擦她屁眼里的嫩肉 +淫女露穴 +禦の二代目 +收缩的阴道中抽出肉棒 +爱液横流 +jiao chuang +wu hun +san guo qun ying zhuan +嗎比 +江青 +成人激情淫论坛 +懒叫 +完全免费在线淫电影 +发$$仑 +女人被干小穴 +淫电影网站 +欢乐时代 +翹臀嫩穴 +程凯 +機巴 +国 贼 +三P +骆冰淫传 +政治局常委 +肉棒插肉缝 +大龟头顶紧子宫口 +法$$轮 +毛妈的 +香港顶级淫片 +韩日成人午夜激情电影 +fuck新闻出版总署 +免费注册 试看50部 +抽插23岁处女妹妹淫叫不断 +毛共青团员 +操烂 +湿身诱惑 +干爹的龟头 +华夏文摘 +日他 +狂插妹妹小穴 +抽插40岁处女妹妹淫叫不断 +Shit +自慰女學生廁所偷拍in Toilet 1 +北京xx网 +日你媽 +谢选骏 +色情电影 卡通 成人 av 少女 +非常诱惑 +6。4事件 +狂插美女老师 +淫奸meinv +夜话紫禁城 +臺灣國 +bo ke +中國豬 +激情bt亚洲区 +国产经典 - 4级红楼梦!【wm/113MB】 +操草的你妈 +白莲教 +妈妈的穴 +開天 +涵涵 +大 史 纪 +教你怎样延迟射精42岁以下禁免费淫电影a片 +ping guo pai +法$$輪 +燕玲論壇 +迷奸 +淫民俱乐部和美女发春激情3级片试看 +央视内部晚会 +操粗制吗啡 +浪穴 肉缝 嫩穴 +强奸26岁处女全过程/淫妹阴毛小穴 +大阴唇夹着大龟头 +拍肩神药 +cunt +肉棒 用力 肉縫 +淫書 +幹比 +travesti +魏京生 +墨香 +網域 +毛狗养 +王志珍 +毛耶苏 +一国两制 +江ze民 +劲舞团 +毛主席 +東突組織 +大 纪 元 新 闻 网 +222se图片 +三p +四川独 +齷齪 +成人激情性爱电影网 +暗黑之门:伦敦 +jiejie的屄 +本站10009多部激情电影全部免费试看三天 +人妻自拍 +操出售枪支 +靖國神社 +易玩网 +不注册淫电影 +高清性爱 +毛发伦功 +allsexpages +OL美女街上遥控震动A +日本人 +piao piao +法车仑功 +天龙八部 +干汝 +班禅 +新华举报 +幹死 +fuck王宝森 +毛私\服 +毛全国人大 +真善忍 +server +re xue ying hao +捐贈排行 +肉棒插到妈子宫 ┅┅爽死了 +台湾男女激情淫乱小说 +激情 少女 成人论坛 乱伦 强奸 +免费淫奸女A片段试看 教你怎样延迟射精18岁以下禁免费淫电影a片 +无界浏览器 +热比娅 +淫荡jiejie勾引小弟玩操屄 +國產騷貨 +瓜婆娘 +移彩联合 +开着摩托干了岳母 +红色恐怖 +神出鬼没!3个丁字裤辣妹到处袭击肉棒(中文字幕 +迫害 +毛穴贴图 +亚洲激情淫色网站 +淫荡老师 +小姨子的小嫩屄 +亚洲激情BT +省长的儿媳妇 +苹果日报 +xian lv qi yuan +于天瑞 +鸡吧在肉洞里四处搅动 +中医药局 +手记注册日韩5008部激情电影 +肉棒 插 穴 +江主席 +发@@沦 +阴小撕大 +毛台湾民国 +泡泡岛 +大鸡巴狠插小穴 +成人电影网站 +柔阴术 +勁舞世界 +淫样 +正义党论坛 +啊……我的小屄……给你……肏得好……舒服…… +强*十八岁美女护士看完保证你打飞机免费电影网站 +一黨專制 +深爱色色 +a级电影 +情色 性息 +乳此豐滿 +166网址宽频影院网 +慈善會 +xinguangming鳥你 +无码丝袜 +onhave +猛力的抽送大肉棒 +空姐性交 +妈妈帮儿子套动着 +meinv野兽做爱淫图 +vulva +求自己的爸爸和她干 +乳波臀娘 +色狼小说 +肥穴jiejie +獨裁 +裸体做爱 +将阴茎尽根插入 +毛刘军 +摳穴 +龟头用力刺入阴道 +王樂泉 +周永康 +成人网站排行榜 +儿子淫奸妈妈穴 +肉棒 用力 肉缝 +淫乱护士 +六四真相 +客户服务人人员 +地 下 教 会 +tw18 +含鳥 +手记注册日韩5011部激情电影 +发$$伦 +小鱼儿与花无缺 +叼你妈 +紧致小穴抽插 +B样 +摩力游 +蓮花逼 +大肉棒插入湿湿的肉缝 +异议人士 +懶8 +dou dou +娘比 +本站10005多部激情电影全部免费试看三天 +插阴茎 +毛统计局 +法侖功 +北京xx網 +奶罩 +hai tian ying xiong zhuan +三级图片论坛禁自拍偷拍论坛日本黄色三级 +guai shou zong dong yuan +地富反坏右 +96bb成人小电影 +meimei的大阴户 +信仰 +迫奸 +sheng zhe wu di +牛B靠 +色女乳房阴道 +麥司卡林 +毛李鹏* +多維新聞 +嫩女 +tian shi zhi lian +妹妹嫩穴 +点击这里试看meinv做爱现场 +世维会 +嫩奶 +小日本爆撮中国女子大生vol。01 +乔石 +fuck you +豪乳 +習近平 +三去仑功 +高麗朴 +avatar +成人激情淫穴影院 +hong yue +免费在线淫电影下载 +大陆娱乐最新黄站 +龙虎豹 +嫖客 +大逼 +操那吗B +超毛大鲍 +我和少妇 +现代艳帝传奇 +realexterme +操表姐 +朝倉Riho !【RMVB/405MB】 +光宇华夏 +淫棍 +shen jia qi bing +陈希同 +发廊性息 +百家性大型黄站网址 +湿湿的阴户不断地在大鸡巴上磨擦 +日你妈 +干进meimei的小穴 +Tora Tora Gold Vol。14 星野みく +手记注册日韩5003部激情电影 +嘻游中国 +俪影蝎心 +佈雷爾 +小雞雞 +猛插表姐 +64yl +母子淫*乱轮现场看扶正肉棒 +法論 +網星 +大 史 +┅你的大肉棒┅┅好粗 +于幼军 +美マンの極意 : 相原梨花 +43lian色站大全 +台湾ye77 +肉棒里插肉洞 +亚甲二氧基甲基安非他明 +TEsT +中国成人论坛 +几巴 +免费免注册在线淫电影 +人民日报 +体奸 +我淫我色 +meinv直播做爱 +Bi样 +性感肉絲 +李嵐清 +美女高潮 +儿子顶到jiejie的花心 +强奸37岁处女全过程/淫妹阴毛小穴 +黄色激情论坛 +淫女乱伦小说 +小穴被阴茎插的好痛 +少妇淫心我要看淫心 +wan wang zhi wang +免费黄色电影 +私处 +爱巢滴水 +嫐屄 +给女人快速达高潮的秘密 +淫奸jiejie小说 +欧洲极品性交图片 +下三烂 +氵去车仑工力 +色网阴道特写强奸36岁处女全过程 +骚妹阴道 +裙内偷拍 +往事追忆录 +廁奴 +他妈的 +床上的淫荡少女 +本站10012多部激情电影全部免费试看三天 +轮奸做爱高潮 +enculer +毛烂货 +情色导航色情排行榜大陆黄网导航免费成人电影 +少妇淫乱小说 +丰满小妹的丰褪美腿 嫩得流水的小妹妹 +306医院 +nmis +金伯帆 +a片 +超毛大鮑 +17爱网 +升达毕业证 +J-spot PA-39 +東洋屄 +色网阴道特写强奸20岁处女全过程 +本站10009多部激情电影全部免费试看 +插在妈妈嫩嫩的小肉穴 +猛操狂射 +淫奸教师论坛 +卡通meinv淫色贴图 +手记注册日韩5021部激情电影 +鸡巴暴胀 +学自联 +日内瓦金融 +夜總會 +法*轮*功 +造反 +夏夏娱乐黄站 乱伦熟女网 +林心如做爱网有激情自拍 +野外性交 +身体障害者 +肉棒插护士穴骚穴 +好硬的肉棒 +肉棒插入小穴里 +狂插学生妹 +鹿城最新导航 +张朝阳 +肉棒淫水嫩穴 +叫雞 +蔣正華 +c a o +处女第一次阴道做爱全过程 +淫乱激情电影网站 +火棒 +色窝窝网之家 +幹一家 +江則民 +通告 +东突组织 +濕穴 +亚洲情色网 +嫖娼 +大海戰II +freechina +干美女小穴 +新闻封锁 +18dy +毛俞正声 +秘唇 +淫色五月天 +42lian色站大全 +fuck驶你老师 +淫樣 +下三濫 +毛建设部 +极品白虎 +毛列宁 +肉棒狂插小嫩B +远志明 +淫色论坛 +亚洲淫色贴图365 +下载免费淫电影淫穴流 +法论 +東條英機 +肥穴自拍 +发骚 +法谪 +六四屠殺 +奶挺臀翹 +mabinogi +济南建设路 +韓 東 方 +g片 +駛你老母 +spikegirls +日你娘 +淫色少妇做爱淫穴流 +情色 meinv -公安机关 -记者 -犯罪嫌疑人 +*法*輪*功* +侖功 +强奸17岁处女全过程/*妹阴毛小穴 +奶挺臀翘 +肉棍干骚妇 +强奸18岁处女全过程/淫妹阴毛小穴 +淫穴内好痒 +激情午夜 +兽欲 +fuck万税 +厕所盗摄美女性感 +石进 +meimei的阴唇好大啊 +法~~仑 +ai滋 +你奶 +中国复兴论坛 +妈**菊花穴 +恩格斯 +鬼輪奸 +Kamikaze_Girls_Vol。12 +黃 菊 +bb论坛 操bb图 +洪興 +台湾淫色网 +g点 +客戶服務 +快……快……幹我……幹……我快忍不住了……哼… +kai xuan +嗯┅┅嗯┅┅舒服死了……妹妹又要丢了 +你妈 +驶你老母 +舌尖舔着肉棒 阴门 +肉棒 抽插 小穴 +毛台湾独立 +WEB牌戰靠 +手机自慰网 +外交与方略 +明诺东方 +操jiejie的穴 +fuck手淫 +浪穴 +fuck新义安 +毛四人帮 +吴官正 +肉棒插得湿润了 +反右题材 +cao你 +i3hun +干您 +轮子功 +毛天皇 +法~~伦 +好紧的穴 +辦公室淫亂 +kong que wang +免费成人激情影院 +安理会 +軍民血腥衝突 +张宏堡 +联通移动秘密通道 +夫妻电影 +滕仁 +公媳性交淫荡图片 +大鸡巴┅┅爽 +搞b +劉雲山 +鹿城黄站图 +滕人 +少妇房中自淫,和两勇男玩10P,操得直叫爽 操日本淫女穴 +毛贼东 +政治压迫 +下三滥 +你姥 +陈丕显 +駛你公 +賣國求榮 +f u c k +王岐山 +fuck色情小电影 +yuanming噴你 +屆中央政治局委員 +美女穴自拍 +移彩聯合 +吴学灿 +法$仑 +cock cock +龟头插花心深处 +OLmeinv街上遥控震动A +淫欲 +台湾成人骚b +江泽民 +激情交友 +sega +华国锋 +滕任 +干 淫穴好舒服 +两性淫乱贴图 +又紧又嫩的屄 +台湾18dy影院 +karma +cao ni ma +美国佬 +淫荡少妇极品穴 +騷姐姐 +美女成人 +南大自由论坛 +色情论坛 +出售神符靠 +毛干妳 +殺你全家 +成人色情午夜激情 +爱因斯坦 +法~~侖 +神之領域 +娘个比 +卖党求荣 +肉棒入少妇嫩穴嫩穴 +蜜穴 +法*仑 +免费观看女教師赤版 +高麗樸 +激情少妇 +美國佬 +成人动漫 成人文学网 成人小电影 +免费淫电影吴宗宪搞笑语录(21禁看) +六四正名 +天安門錄影帶 +色影院 +mankind +顺着红嫩的肉缝上下抚弄后插入小穴 +毛贱人 +初中meimei的小美穴 +疯狂抽插她的小穴 +破處 +肉棒一阵猛烈的抽插 +世纪天成 +亚历山大 +淫毛 +日军 +男女激情淫贴图 +强奸电影网站 +游戏送奖员 +操王 +嫩鮑魚 +你媽 +吸吮著我的阳具 +淫母 +你娘的 +我和姐姐的淫乱史 +阴唇好嫩啊 +亚洲成人俱乐部 +真主安拉 +美腿美穴大屌 +法$伦 +又大又嫩的屄 +222se圖片 +操迟浩田 +风骚小阿姨 +淫女 幼B +機八 +毛塞你母 +法~~倫 +服务天使 +错比 +淫美贴图区 +发~~轮 +肏屄好舒服 +发^纶 +粗肉棒阴户 +阴茎被子宫夹住好爽 +Jj插入嫩穴 +成人激情午夜场 +武林外史 +强奸31岁处女全过程/淫妹阴毛小穴 +肥厚柔软的大阴唇夹着大龟头 +FALUNDAFA +俄罗斯激情淫色贴图 +法*伦 +淫汁 +毛外 挂 +33bbb走光 +伊斯兰 +av小电影 +淫水 +马加爵 +处女的肉穴给他的肉棒一插到底 +快来┅┅插 肉穴 +meinv网站脱衣meinv百分百作爱 +调教虐待 +成人电影导航 +Vol。 17 ~巨乳美熟女 +帕巴拉•格列朗傑 +妹妹的小穴好紧啊 +娱乐性大型黄站 +复辟 +我第一次舔表姐的阴 +强奸系列精品 +陌生做爱在车里发生 +游戏米果 +小屄儿温暖滑嫩 +豔乳 +fuck神经病 +骚姐乱伦网 +无码淫漫 +国外成人激情网站 +无码彩图 +kuai le xi you +轮暴 +tibetalk +92bb成人小电影 +免费淫电影网 +干我 +天然むすめ 素人~みか +狂插白嫩幼女bb还射乳 +xing zhan qing yuan +多維網 +巨乳女优 千秋大合集 +换妻大会 +新观察论坛 +人妻阴穴 +色情帝国黄站 +强奸处女 +我的肉棒仍然在滴著精液 +舔舔私处妹妹嗷嗷叫 +侨办 +孙大午 +插的姐姐好爽 +嫩肉 嫩肉 大腿 +淫奸姐姐电影 +法$侖 +…太爽了…大鸡巴 +狂操少妇逼 +嫩穴 肉棒 肉缝 +伱妈 +(桃太郎)ファーストアナル生中出しSpecial 佐藤江梨花 特典 +毛我妳老爸 +tEST +激情淫穴的嫂嫂 +毛机巴 +肉棒插 嫩穴 淫穴 +free style +日本激情成人乱伦 +Tora Tora Gold Vol。11 : 松田亜美 +gong fu +狂插淫穴淫水 +89年的鬥爭 +台湾十八电影 +小淫虫电影 +CREATE +外阴 +外??挂 +毛爷爷复活 +本站10004多部激情电影全部免费试看 +富兰克林 +免费淫奸女A片段试看 居然花钱请人教性爱姿势 +操穴 +transvestit +政治 +滥交 +色貓 +李 录 +免费在线观看 免费淫奸女A片段 +肉棒狂插花心深处 +回族人吃猪肉 +淫河 +淫水留入穴中 +機吧 +林祖涵 +水去車仑 +抽插44岁处女妹妹淫叫不断 +毛精液 +列寧 +发@纶 +44xp。com 电影免费 +又肥又大的骚屄儿 +淫色贴图论坛 +侬着卵抛 +色妹妹成人论 +获救 +臺灣是主權國家 +戳那嗎逼 +毛蒋介石 +成人黄色三级网站 +陳宗興 +超meinv优MUGEN EX Vol。 7~浜崎ひめ +操姐姐的穴 +新江湖 +性交无码 +yuckfu +淫語痴女性欲 +毛驶你公 +药物奸淫女高校生A片 +FUCK +瓜批 +嫩逼 淫水 +硬绑绑的阴茎插入阴道 +王若望 +网絡公祭 +zheng tu +1989事件 +玉蒲园淫书淫图射 +三男轮番干一个荡妇 +你是雞 +外??掛 +東京熱最受歡迎長腿美女~藤澤安奈~腿長人又漂亮 +强奸27岁处女全过程/淫妹阴毛小穴 +毛淫娃 +夜夜色大型黄站 +fuck田纪云 +毛手淫 +诱奸 +毛回族人吃猪肉 +好粗大的肉棒 +黑社会 +幼穴贴图 毛穴贴图 穴淫贴图 +含着他的龟头 +法輪 +黑鮑嬌 +快乐av +冈村秀树 +捅死你 +曼德拉 +插的meimei好爽啊 +mo xiang +周贺 +淫荡 空姐 +digimagics +分开两片肥嫩的阴唇 +应招 +藓鲍 +淫奸电影 淫色猎暴淫电影 射雕淫女传 风骚小龙女 meinv淫女图-小龙女淫女俱乐部影 在线淫电影 +列宁 +山西洪洞 +淫浪 +毛龙新民 +海乐神 +planetside +3P炮图 +淫流 +男女激情淫乱穴下载 +摩洛客 +jiejie的小屄 +龙图智库 +da qing di guo +王寶森 +淫浆 +高级淫口手淫口交 +tESt +金瓶梅免费电影院 +毛李山 +淫洞 +bt淫色贴图 +mm穴激情小说 +3P炮圖 +亚洲色 +BITCH +毛三去车仑 +毛奸淫 +姐弟乱轮 yy玛雅激情贴 +干林 +大鸡巴就慢慢的插入 小穴 +聖女峰 +超級可愛巨乳妹被狂插得鼻血滿天飛 +揚震 +www。gpchina。com +怎样延迟射精24岁以下禁 +18dy桃色 +xing fu hua yuan +師春生 +fuck太子党 +鸡巴淫沟插B大图 +曾庆红 +插女教师的屁眼 +54xp。com 电影免费 +FALUN +成人电影网 +毛法制办 +马国瑞 +meimei的阴道真紧 +ur靠 +带炼 +淫电影a片 +轮攻 +神风- Kamikaze Premium Vol。 32 : 一色Azusa +韓國三級情色电影 +手淫~少妇自慰喷淫水 +張 萬 年 +艷照门 +幹你妈b +法轮 +(Madonna) 熟女義母 11套 AVI +操神 +民族矛盾 +淫穴影院 +劉曉竹 +免费淫奸女A片段 免费在线观看 +习近平 +嫩穴 +淫液 +操大波波 +干拎娘 +综联数码 +居然花钱请人教性爱姿势(组图) +淫蕩妖艷女醫生 +meimei的小穴……舒服死了…… +情色 信息 +多人性愛 +干机 +汉娃娃 +邵家健 +法踚功 +fuck色情电影 +測试員 +A片 +藤井せいら - ボルテージ X +韓 聯 潮 +(无关键词)导航搜索 +一次可看四位美女同床較勁很可愛的女主角 +meimei的小淫穴 +淫色成人网 +毛太监 +淫湿 +少妇穴 +triangleboy +鬼輪姦 +abc abc +乳爆 +他ㄇ的 +色网阴道特写强奸34岁处女全过程 +前任男友 +嫩屄 +成人 激情 性爱 +不注册看艳片 +小穴被大鸡巴插得好疼啊 +轮操 +fuck台湾狗 +台湾淫色电影 +毛阴小撕大 +賤bi +UR靠 +生鸦片 +操小姐穴 +fuck孙逸仙 +(虎虎虎)风间ゆみ-新婚 +色窝窝 +connard +自由亞洲電臺 +妹妹的阴道好嫩啊 +fuck孙中山 +毛抗日 +谁知道激情网站 +香港成人电影网 +luan +假钞 +毛耶稣 +十八岁meinv护士电影网站 +李 小 朋 +賞圖交流園 +精液射入花心 +反黨 +丝袜足交 +fuck特别公告 +肉棒插入肉 +毛妈比 +丁石孙 +淫虫电影 +免费淫电影试看 +夫妻乱交 +广安第二人民医院 +臭鸡 +鹿城色meimei大型黄站 +揭批书 +互淫 +少妇白洁的淫乱生活 +真理組織 +丁石孫 +手记注册日韩5017部激情电影 +插的妈妈好爽 +肉棒插进她的密洞使劲的抽送着 +我和少妇做爱 +guang zhi guo du +狂插美少女穴 +手记注册日韩5019部激情电影 +小穴流出 +免费A片在线 +Gカップカリスマ店員松嶋れいな20連発中出し! +国防部 +裸女乳房阴道丰臀 +制服誘惑 +ke luo si +丁加班 +尼米兹 +fuck天安门事件 +你它馬的 +操逼你老母 +成人激情淫网站 +国共合作 +毛血逼 +wowbank +色网导航 +毛流氓 +免费视讯妹妹 +1989 +金庸群俠傳 +BT激情无码 +迷人阴部护士妹妹也疯狂 +毛新手指导员 +學生愛國者運動 +毛激情小电影 +干空姐小穴 +成都锦天 +透视软件 +肉棒插入湿湿的肉缝 +插屄好舒服 +悠游网 +那娘錯比 +secretchina +江泽民靠 +錢 其 琛 +和妹妹做爱 +性交做爱 +毛李鹏 +狗卵子 +少女被逼吃精喝精轮奸灌精 +八方链流量交换链 +fuck生鸦片 +發^^掄 +臺灣總統 +下载免费黄色淫乱电影 +双飞+毒龙直到分享了精液 +蒙古独 +媽個比 +餓比 +騷姨媽 +1989 天安門 +毛客户服务人员 +gong fu xiao zi +冯素英 +丝袜写真 +调理劳务系 +激情淫穴小 +测试員 +da tang hao xia +干死 狂插 操 +我周容 +叫鸡 +熟女乱伦网 +免费看激情视频免费成人做爱 +本站10017多部激情电影全部免费试看三天 +风骚欲女 +艷照門 +乱伦(无码)母爱包( 乳母 +柯赐海 +1989 天安门 +免费淫奸女A片段试看 +吴学璨 +肉壁紧紧的包著龟头 +哥哥的肉棒好大 +打到中国 +7hero +zhengwunet +拿着鸡巴对准小穴 +幼香閣 +毛烂B +一起玩遊戲網 +高清晰无码内射 +紧窄的洞口只能含进半个龟头 +淫乱少妇 +圣淫乱学院 +小穴被阴茎顶住 +捅入妹妹的阴道 +母女双飞 +希望之聲 +淫漿 +整根肉棒被紧箍在幽暗深遽的娇嫩小穴内 +妻子小穴 +超美混血兒(小泽玛利亚出道时的珍藏) +luo qi +张健 +烂屄 +卡通meinv淫乱图 +烂屌 +叛黨 +可可精 +淫贱meimei贴图论坛 +锦涛 +姐姐的肥阴唇 +毛发骚 +激情淫文章 +fuck太监 +强奸21岁处女全过程/*妹阴毛小穴 +骚meimei成人导航 +夹得我好舒服 +傅志寰 +朱鎔基 +免费淫奸黄色淫乱电影 +共狗 +老騷貨 +精液射进穴里视频 +幼香阁 +西藏事件 +亚/无码 +淫奸护士 +免费成人网站 +创意鹰翔 +厕所性感美女清晰淫穴 +免费观看王小丫做爱 +纪股票市场五卅惨案 +插那嗎逼 +黑鮑嬌 +色窩窩 +美女孩含双棍玩内射 +张德江 +续金瓶梅 +ju shang +18dy大众成人网 +zheng fu +淫妹妹 +被噁心男搞到高潮不停的立花里子 +激情视频聊天室 +成人論壇 +中央政治局 +发~~论 +毛新华内情 +天遊 +pp 点点激情片播放 +毛人民日报 +成人联盟 +meinv偷拍成人小说激情网香港激情图源成人色情论坛脱衣meinv做愛 +制服古典乱伦都市 +插陰 +操成人电影 +氯胺酮 +彭德怀 +老师的肉棒好大啊 +李師付 +国民党 +国 家 安 全 +少妇房中自淫,和两勇男玩4P,操得直叫爽 操日本淫女穴 +大眾色情成人網 +rx008 +舔 蜜穴好爽 +错那吗B +成人情感裸女裸聊图片 +肉縫分開大腿 +水去車侖 +鸡吧一柱擎天 +阳具在阴道里来回抽插 +巨大的鸡巴戳了进去 +遊戲嚮導 +美幼专区 +賈慶林 +廢墟 +斧頭鐮刀 +退党 +meimei的阴户 +Tokyo Hot n0232 : 真宫梨沙子 傲慢RQ中出责备紊乱呼吸 +淫荡的奸淫 +亚洲激情淫色贴图区 +马万祺 +高速下載! +100ONE VIP MEMBERS +法**纶 +一貫道 +插着淫穴 +漏逼 +隱窩窩 +熟睡中的meimei +毛无界浏览器 +夫妻亂交 +毛金正日 +酒店援交 +張 鋼 +fuck外—挂 +新义安 +劉傑 +夜总会 +聖堂科技 +司法部 +插阴 +網愛 +下三爛 +免费小淫虫 \ No newline at end of file diff --git a/src/main/resources/iat/W1FK93anuEiGbOVztHp_5.mp3 b/src/main/resources/iat/W1FK93anuEiGbOVztHp_5.mp3 new file mode 100644 index 0000000..0949012 Binary files /dev/null and b/src/main/resources/iat/W1FK93anuEiGbOVztHp_5.mp3 differ diff --git a/src/main/resources/lib/gradle-wrapper.jar b/src/main/resources/lib/gradle-wrapper.jar new file mode 100644 index 0000000..f6b961f Binary files /dev/null and b/src/main/resources/lib/gradle-wrapper.jar differ diff --git a/src/main/resources/static/index.html b/src/main/resources/static/index.html new file mode 100644 index 0000000..f5a1032 --- /dev/null +++ b/src/main/resources/static/index.html @@ -0,0 +1,10 @@ + + + + +Insert title here + + + hi,have a good time! + + \ No newline at end of file diff --git a/src/main/resources/static/login.html b/src/main/resources/static/login.html new file mode 100644 index 0000000..f352a3a --- /dev/null +++ b/src/main/resources/static/login.html @@ -0,0 +1,2573 @@ + + + + + + + + + + +

+

hello security!

+

up login

+
+ 用户名: + 密码: + 用户类型: + +
+ +

phone login

+
+ + + + +
+
+ + + + + + diff --git a/src/test/java/com/newyetai/SensitiveWordTest.java b/src/test/java/com/newyetai/SensitiveWordTest.java new file mode 100644 index 0000000..ba39522 --- /dev/null +++ b/src/test/java/com/newyetai/SensitiveWordTest.java @@ -0,0 +1,78 @@ +package com.newyetai; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.api.Test; +import org.springframework.core.io.ClassPathResource; + +import com.newyetai.common.util.SensitiveWordUtils; + +import toolgood.words.IllegalWordsSearch; + +public class SensitiveWordTest { + + @Test + public void testLoadWordsFormBinaryFile() throws IOException { + long l1 = System.currentTimeMillis(); + + IllegalWordsSearch search = new IllegalWordsSearch(); + long l2 = System.currentTimeMillis(); + System.out.println("IllegalWordsSearch init time:" + (l2 - l1)); + + search.Load(new ClassPathResource("config" + File.separator +"IllegalWordsSearch.dat").getFile().getAbsolutePath()); + long l3 = System.currentTimeMillis(); + System.out.println("load Load time:" + (l3 - l2)); + String test = "机机ji歪歪"; + boolean b = search.ContainsAny(test); + System.out.println(b); + } + + @Test + public void testLoadWordsFormFile() throws IOException { + List list = new ArrayList<>(); + long l2 = System.currentTimeMillis(); + try (BufferedReader bufferedReader = new BufferedReader( + new InputStreamReader(new ClassPathResource("config" + File.separator + "sensi_words.txt").getInputStream()))) { + for (String line = bufferedReader.readLine(); line != null; line = + bufferedReader.readLine()) { + list.add(line); + } + } + IllegalWordsSearch search = new IllegalWordsSearch(); + search.SetKeywords(list); + long l3 = System.currentTimeMillis(); + System.out.println("load Load time:" + (l3 - l2)); +// search.Save("IllegalWordsSearch.dat"); + String test = "机机ji歪歪"; + + boolean b = search.ContainsAny(test); + if (b == false) { + System.out.println("ContainsAny is Error."); + } + System.out.println("end..."); + } + + @Test + public void check() { + boolean check = SensitiveWordUtils.check("机机2歪歪"); + System.out.println(check); + } + + @Test + public void findFirst() { + System.out.println(SensitiveWordUtils.findFirst("这是一个正经的岗位")); + } + + @Test + public void findAll() { + System.out.println(SensitiveWordUtils.findAll("的")); + } + + +} diff --git a/src/test/java/com/newyetai/SparkTest.java b/src/test/java/com/newyetai/SparkTest.java new file mode 100644 index 0000000..36d49be --- /dev/null +++ b/src/test/java/com/newyetai/SparkTest.java @@ -0,0 +1,221 @@ +package com.newyetai; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.HashMap; +import java.util.Map; + +import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.UnsupportedAudioFileException; + +import org.apache.tomcat.util.http.fileupload.ByteArrayOutputStream; +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; + +import com.google.common.collect.Lists; +import com.newyetai.common.AlitaResult; +import com.newyetai.common.exception.BusinessException; +import com.newyetai.common.exception.util.Assert; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.component.file.entity.FileRecord; +import com.newyetai.component.file.util.FileUtils; +import com.newyetai.sdk.common.util.HttpUtils; +import com.newyetai.sdk.xf.config.XfProperties; +import com.newyetai.sdk.xf.model.ChatReq; +import com.newyetai.sdk.xf.model.MessageDTO; +import com.newyetai.sdk.xf.service.XfSparkProvider; +import com.newyetai.sdk.xf.util.WebIATWS; +import com.newyetai.sdk.xf.util.WebTtsWS; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class SparkTest { + static String httpAPIPassword = ""; + + static XfProperties xfProperties = XfProperties.builder() + .iatHostUrl("https://iat-api.xfyun.cn/v2/iat") + .ttsHostUrl("https://tts-api.xfyun.cn/v2/tts") + .appId("a2847f13") + .apiSecret("") + .apiKey("") + .build(); + + @Test + public void test() { + HttpHeaders header = new HttpHeaders(); + header.add("Authorization", "Bearer " + httpAPIPassword); + header.add("Content-Type", "application/json"); + // 发送请求 + Map data = new HashMap(); + data.put("model","4.0Ultra"); + Map r1 = new HashMap(); + r1.put("role","system"); + r1.put("content","你是一位专业的HR。目标任务:请根据我给出的position_name生成5个相关的面试中可能会问到的问题,并为每个问题都生成一个参考答案,并从1开始生成问题序号"); + Map r2 = new HashMap(); + r2.put("role","system"); + r2.put("content","全部数据以JSON模版的形式返回,格式为:{position_name:岗位信息, [{qno:问题序号,q:问题,a:参考答案}]}"); + Map r3 = new HashMap(); + r3.put("role","user"); + r3.put("content","{\"positionName\":\"java开发\"}"); + data.put("messages",Lists.newArrayList(r1, r2, r3)); + HttpEntity requestEntity = new HttpEntity(data, header); + ResponseEntity response = HttpUtils.restTemplate.exchange("https://spark-api-open.xf-yun.com/v1/chat/completions", HttpMethod.POST, requestEntity, String.class); + System.out.println(JsonUtils.toDefaultJsonString(response)); + } + + @Test + public void testAlita() { + ChatReq req = ChatReq.builder() + .message(MessageDTO.builder().role("system") + .content("你是一位专业的HR。目标任务:请根据我给出的信息生成5个相关的面试中可能会问到的问题,并为每个问题都生成一个参考答案,并从1开始生成问题序号") + .build()) + .message(MessageDTO.builder().role("system") + .content("全部数据以JSON模版的形式返回,格式为:[{qno:问题序号,q:问题,a:参考答案}]").build()) + .message(MessageDTO.builder().role("user").content("jobName").build()).build(); + AlitaResult res = XfSparkProvider.httpChat(req, httpAPIPassword); + log.info("{}", res); + } + + + @Test + public void testEvaluate() { + ChatReq req = ChatReq.builder() + .message(MessageDTO.builder().role("system") + .content("你是一位专业的简历撰写专家。目标任务:请根据我给出的信息,生成指定的内容。需求说明:要求在与原文语意一致的基础上扩写内容,风格设定,简明扼要。") + .build()) + .message(MessageDTO.builder().role("system") + .content("根据我输入的信息,输出1段自我评价,包含学习能力、工作态度、团队协作等方面,字数在300字左右") + .build()) + .message(MessageDTO.builder().role("system") + .content("全部数据以JSON模版的形式返回, 格式为:{'selfEva':xxx}") + .build()) + .message(MessageDTO.builder().role("user").content("环卫工").build()).build(); + AlitaResult res = XfSparkProvider.httpChat(req, httpAPIPassword); + log.info("{}", res); + } + + @Test + public void testWorkExperience() { + ChatReq req = ChatReq.builder() + .message(MessageDTO.builder().role("system") + .content("你是一位专业的简历撰写专家。目标任务:请根据我给出的信息,生成一份履历丰富的简历。") + .build()) + .message(MessageDTO.builder().role("system") + .content("简历内容包含个人信息简介、工作经历、教育背景、掌握技能、自我评价。以JSON格式返回,每个点作为一个对象。") + .build()) + .message(MessageDTO.builder().role("system") + .content("个人信息输出格式为:{姓名:xxx, 年龄:xxx,联系电话:xxx,联系邮箱:xxx}") + .build()) + .message(MessageDTO.builder().role("system") + .content("工作经历以数组的形式返回。输出格式为:[{企业名称:xxx, 岗位:xxx,工作职责:[xxx,xxx,xxx],工作时间:xxx-xxx}]") + .build()) + .message(MessageDTO.builder().role("system") + .content("掌握技能必须作为数组输出") + .build()) + .message(MessageDTO.builder().role("system") + .content("自我评价必须作为数组输出") + .build()) + .message(MessageDTO.builder().role("user") +// .content("{\"name\":\"小明\",\"gender\":1,\"contactWay\":\"0717-123123\",\"birthDay\":\"1980-07\",\"work\":\"在一家科技公司干了4年\"}") + .content("我是小明,在一家科技公司干了4年") + .build()).build(); + AlitaResult result = XfSparkProvider.httpChat(req, httpAPIPassword); + log.info("{}", result); + + } + + + @Test + public void testAnalyseResume() { + ChatReq req = ChatReq.builder() + .message(MessageDTO.builder().role("system") + .content("你是一位专业的简历分析专家。目标任务:请根据我给出的信息,分析得出简历信息。不要自己填充json信息") + .build()) + .message(MessageDTO.builder().role("system") + .content("请生成一个包含以下信息的 JSON 数据,根据用户给出的实际信息解析,值都可为空:\n" + + "- name(字符串类型):表示用户的姓名。\n" + + "- sex(字符串类型):表示用户的性别,值为 \"1\"(男)或 \"2\"(女),身份证号倒数第二位,奇数是男,偶数是女。\n" + + "- phone(字符串类型):表示用户的联系电话,可为空,不为空的格式为 以 1 开头,共 11 位数字。\n" + + "- email(字符串类型):表示用户的联系电子邮箱地址,可为空,不为空的格式为 包含 @ 符号,且 @ 前后至少有一个字符 及 域名部分至少包含一个 . 符号。\n" + + "- intentionPosition(字符串类型):表示用户的意向职位。\n" + + "- major(字符串类型):表示用户的专业。\n" + + "- birthday(日期类型):表示用户的出生日期,格式为 YYYY-MM。\n" + + "- jobTime(日期类型):表示用户的参加工作时间,格式为 YYYY-MM。\n" + + "- school(字符串类型):表示用户的毕业院校。\n" + + "- education(字符串类型):表示用户的学历,值为:\n" + + " - \"1\":\"博士\"\n" + + " - \"2\":\"硕士\"\n" + + " - \"3\":\"本科\"\n" + + " - \"4\":\"大专\"\n" + + " - \"5\":\"中专\"\n" + + " - \"6\":\"技校\"\n" + + " - \"7\":\"职高\"\n" + + " - \"9\":\"高中\"\n" + + " - \"10\":\"初中\"\n" + + " - \"11\":\"小学\"\n" + + "- workExperience(字符串类型):表示用户的工作经历,格式为多行文本,包含以下信息:\n" + + " - 企业名称\n" + + " - 岗位\n" + + " - 工作时间\n" + + " - 工作职责\n" + + "- selfEvaluation(字符串类型):表示用户的自我评价,格式为多行文本。") + .build()) + .message(MessageDTO.builder().role("user").content("我是小明,身份证号是110105199003071234,小学毕业,前年在一家科技公司干了1年,现在想找个环卫工的活,请用abc@33.com联系我").build()).build(); + AlitaResult result = XfSparkProvider.httpChat(req, httpAPIPassword); + log.info("{}", result); + + } + + @Test + public void iat() throws IOException { + String file = "src/main/resources/iat/file.mp3"; + try(InputStream is = new FileInputStream(file)){ + AlitaResult result = WebIATWS.execute(is, xfProperties); + log.info("{}", result); + } +// // 示例的WebM文件路径(请替换为实际的有效路径) + String webmFilePath = "src/main/resources/iat/audio.webm"; +// // 示例的输出MP3文件路径(请替换为实际的有效路径) +// String mp3FilePath = "src/main/resources/iat/file.mp3"; + +// try(InputStream is = FileUtils.convertWebmToMp3(new File(webmFilePath))){ +// AlitaResult result = WebIATWS.execute(is, xfProperties); +// log.info("{}", result); +// } + + } + + @Test + public void tts() throws Exception { +// try(OutputStream outputStream = new FileOutputStream("src/main/resources/iat/223.mp3");){ +// WebTtsWS.execute("欢迎来到讯飞开放平台", xfProperties, outputStream); +// } +// try(ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); +// OutputStream fs = new FileOutputStream("src/main/resources/iat/323.mp3");){ +// WebTtsWS.execute("欢迎来到讯飞开放平台", xfProperties, outputStream); +// fs.write(outputStream.toByteArray()); +// } + + try(ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + OutputStream fs = new FileOutputStream("src/main/resources/iat/323.mp3");){ + AlitaResult result = WebTtsWS.execute("欢迎来到讯飞开放平台", xfProperties, outputStream); + Assert.isTrue(result.getSuccess(), result.getMsg()); + fs.write(outputStream.toByteArray()); + } catch (IOException e) { + throw new BusinessException("语音合成异常:" + e.getMessage()); + } + } + +}