From 719f02bdad79f42477741b2070ca267a96a0f004 Mon Sep 17 00:00:00 2001 From: wkc <978997012@qq.com> Date: Wed, 11 Feb 2026 15:28:35 +0800 Subject: [PATCH 1/7] =?UTF-8?q?feat:=20=E5=88=9B=E5=BB=BA=E4=BF=A1?= =?UTF-8?q?=E8=B4=B7=E5=AE=A2=E6=88=B7=E5=AE=B6=E5=BA=AD=E5=85=B3=E7=B3=BB?= =?UTF-8?q?=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sql/ccdi_cust_fmy_relation.sql | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sql/ccdi_cust_fmy_relation.sql b/sql/ccdi_cust_fmy_relation.sql index 76f06f9..7c2443e 100644 --- a/sql/ccdi_cust_fmy_relation.sql +++ b/sql/ccdi_cust_fmy_relation.sql @@ -30,6 +30,8 @@ CREATE TABLE IF NOT EXISTS `ccdi_cust_fmy_relation` ( `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '记录更新时间', PRIMARY KEY (`id`), UNIQUE KEY `uk_person_cert` (`person_id`, `relation_cert_no`) COMMENT '信贷客户身份证号+关系人证件号码唯一', - KEY `idx_person_id` (`person_id`), - KEY `idx_relation_cert_no` (`relation_cert_no`) + KEY `idx_person_id` (`person_id`) COMMENT '信贷客户身份证号索引', + KEY `idx_relation_cert_no` (`relation_cert_no`) COMMENT '关系人证件号码索引', + KEY `idx_status` (`status`) COMMENT '状态索引', + KEY `idx_data_source` (`data_source`) COMMENT '数据来源索引' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='信贷客户家庭关系表'; From b3e0f97f71c9641c87cee90506e95f6e91c17f16 Mon Sep 17 00:00:00 2001 From: wkc <978997012@qq.com> Date: Wed, 11 Feb 2026 15:29:20 +0800 Subject: [PATCH 2/7] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E4=BF=A1?= =?UTF-8?q?=E8=B4=B7=E5=AE=A2=E6=88=B7=E5=AE=B6=E5=BA=AD=E5=85=B3=E7=B3=BB?= =?UTF-8?q?=E5=AE=9E=E4=BD=93=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ccdi/domain/CcdiCustFmyRelation.java | 109 ++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/CcdiCustFmyRelation.java diff --git a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/CcdiCustFmyRelation.java b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/CcdiCustFmyRelation.java new file mode 100644 index 0000000..5ef8037 --- /dev/null +++ b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/CcdiCustFmyRelation.java @@ -0,0 +1,109 @@ +package com.ruoyi.ccdi.domain; + +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.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; + +/** + * 信贷客户家庭关系对象 ccdi_cust_fmy_relation + * + * @author ruoyi + * @date 2026-02-11 + */ +@Data +@TableName("ccdi_cust_fmy_relation") +public class CcdiCustFmyRelation implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** 主键ID */ + @TableId(type = IdType.AUTO) + private Long id; + + /** 信贷客户身份证号 */ + private String personId; + + /** 关系类型 */ + private String relationType; + + /** 关系人姓名 */ + private String relationName; + + /** 性别:M-男,F-女,O-其他 */ + private String gender; + + /** 出生日期 */ + private Date birthDate; + + /** 关系人证件类型 */ + private String relationCertType; + + /** 关系人证件号码 */ + private String relationCertNo; + + /** 手机号码1 */ + private String mobilePhone1; + + /** 手机号码2 */ + private String mobilePhone2; + + /** 微信名称1 */ + private String wechatNo1; + + /** 微信名称2 */ + private String wechatNo2; + + /** 微信名称3 */ + private String wechatNo3; + + /** 详细联系地址 */ + private String contactAddress; + + /** 关系详细描述 */ + private String relationDesc; + + /** 状态:0-无效,1-有效 */ + private Integer status; + + /** 生效日期 */ + private Date effectiveDate; + + /** 失效日期 */ + private Date invalidDate; + + /** 备注 */ + private String remark; + + /** 数据来源:MANUAL-手工录入,IMPORT-批量导入 */ + private String dataSource; + + /** 是否是员工亲属:0-否 */ + private Boolean isEmpFamily; + + /** 是否是客户亲属:1-是 */ + private Boolean isCustFamily; + + /** 创建时间 */ + @TableField(fill = FieldFill.INSERT) + private Date createTime; + + /** 更新时间 */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private Date updateTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createdBy; + + /** 更新人 */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updatedBy; +} From ddec208f0d002bdb31c3effcbcb02998ec287f27 Mon Sep 17 00:00:00 2001 From: wkc <978997012@qq.com> Date: Wed, 11 Feb 2026 15:39:50 +0800 Subject: [PATCH 3/7] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E4=BF=A1?= =?UTF-8?q?=E8=B4=B7=E5=AE=A2=E6=88=B7=E5=AE=B6=E5=BA=AD=E5=85=B3=E7=B3=BB?= =?UTF-8?q?DTO=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/dto/CcdiCustFmyRelationAddDTO.java | 119 +++++++++++++++++ .../dto/CcdiCustFmyRelationEditDTO.java | 125 ++++++++++++++++++ .../dto/CcdiCustFmyRelationQueryDTO.java | 53 ++++++++ 3 files changed, 297 insertions(+) create mode 100644 ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/dto/CcdiCustFmyRelationAddDTO.java create mode 100644 ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/dto/CcdiCustFmyRelationEditDTO.java create mode 100644 ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/dto/CcdiCustFmyRelationQueryDTO.java diff --git a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/dto/CcdiCustFmyRelationAddDTO.java b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/dto/CcdiCustFmyRelationAddDTO.java new file mode 100644 index 0000000..89e00bf --- /dev/null +++ b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/dto/CcdiCustFmyRelationAddDTO.java @@ -0,0 +1,119 @@ +package com.ruoyi.ccdi.domain.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; + +/** + * 信贷客户家庭关系新增DTO + * + * @author ruoyi + * @date 2026-02-11 + */ +@Data +@Schema(description = "信贷客户家庭关系新增") +public class CcdiCustFmyRelationAddDTO implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** 信贷客户身份证号 */ + @NotBlank(message = "信贷客户身份证号不能为空") + @Pattern(regexp = "^[1-9]\\d{5}(18|19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[\\dXx]$", message = "信贷客户身份证号格式不正确") + @Schema(description = "信贷客户身份证号") + private String personId; + + /** 关系类型 */ + @NotBlank(message = "关系类型不能为空") + @Size(max = 50, message = "关系类型长度不能超过50个字符") + @Schema(description = "关系类型") + private String relationType; + + /** 关系人姓名 */ + @NotBlank(message = "关系人姓名不能为空") + @Size(max = 100, message = "关系人姓名长度不能超过100个字符") + @Schema(description = "关系人姓名") + private String relationName; + + /** 性别 */ + @Pattern(regexp = "^[MFO]$", message = "性别只能是M、F或O") + @Schema(description = "性别:M-男,F-女,O-其他") + private String gender; + + /** 出生日期 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Schema(description = "出生日期") + private Date birthDate; + + /** 关系人证件类型 */ + @NotBlank(message = "关系人证件类型不能为空") + @Size(max = 50, message = "关系人证件类型长度不能超过50个字符") + @Schema(description = "关系人证件类型") + private String relationCertType; + + /** 关系人证件号码 */ + @NotBlank(message = "关系人证件号码不能为空") + @Size(max = 100, message = "关系人证件号码长度不能超过100个字符") + @Schema(description = "关系人证件号码") + private String relationCertNo; + + /** 手机号码1 */ + @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号码1格式不正确") + @Schema(description = "手机号码1") + private String mobilePhone1; + + /** 手机号码2 */ + @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号码2格式不正确") + @Schema(description = "手机号码2") + private String mobilePhone2; + + /** 微信名称1 */ + @Size(max = 50, message = "微信名称1长度不能超过50个字符") + @Schema(description = "微信名称1") + private String wechatNo1; + + /** 微信名称2 */ + @Size(max = 50, message = "微信名称2长度不能超过50个字符") + @Schema(description = "微信名称2") + private String wechatNo2; + + /** 微信名称3 */ + @Size(max = 50, message = "微信名称3长度不能超过50个字符") + @Schema(description = "微信名称3") + private String wechatNo3; + + /** 详细联系地址 */ + @Size(max = 500, message = "详细联系地址长度不能超过500个字符") + @Schema(description = "详细联系地址") + private String contactAddress; + + /** 关系详细描述 */ + @Size(max = 500, message = "关系详细描述长度不能超过500个字符") + @Schema(description = "关系详细描述") + private String relationDesc; + + /** 生效日期 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Schema(description = "生效日期") + private Date effectiveDate; + + /** 失效日期 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Schema(description = "失效日期") + private Date invalidDate; + + /** 状态 */ + @Schema(description = "状态:0-无效,1-有效") + private Integer status; + + /** 备注 */ + @Schema(description = "备注") + private String remark; +} diff --git a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/dto/CcdiCustFmyRelationEditDTO.java b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/dto/CcdiCustFmyRelationEditDTO.java new file mode 100644 index 0000000..557501d --- /dev/null +++ b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/dto/CcdiCustFmyRelationEditDTO.java @@ -0,0 +1,125 @@ +package com.ruoyi.ccdi.domain.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; + +/** + * 信贷客户家庭关系编辑DTO + * + * @author ruoyi + * @date 2026-02-11 + */ +@Data +@Schema(description = "信贷客户家庭关系编辑") +public class CcdiCustFmyRelationEditDTO implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** 主键ID */ + @NotNull(message = "ID不能为空") + @Schema(description = "主键ID") + private Long id; + + /** 信贷客户身份证号 */ + @NotBlank(message = "信贷客户身份证号不能为空") + @Pattern(regexp = "^[1-9]\\d{5}(18|19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[\\dXx]$", message = "信贷客户身份证号格式不正确") + @Schema(description = "信贷客户身份证号") + private String personId; + + /** 关系类型 */ + @NotBlank(message = "关系类型不能为空") + @Size(max = 50, message = "关系类型长度不能超过50个字符") + @Schema(description = "关系类型") + private String relationType; + + /** 关系人姓名 */ + @NotBlank(message = "关系人姓名不能为空") + @Size(max = 100, message = "关系人姓名长度不能超过100个字符") + @Schema(description = "关系人姓名") + private String relationName; + + /** 性别 */ + @Pattern(regexp = "^[MFO]$", message = "性别只能是M、F或O") + @Schema(description = "性别:M-男,F-女,O-其他") + private String gender; + + /** 出生日期 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Schema(description = "出生日期") + private Date birthDate; + + /** 关系人证件类型 */ + @NotBlank(message = "关系人证件类型不能为空") + @Size(max = 50, message = "关系人证件类型长度不能超过50个字符") + @Schema(description = "关系人证件类型") + private String relationCertType; + + /** 关系人证件号码 */ + @NotBlank(message = "关系人证件号码不能为空") + @Size(max = 100, message = "关系人证件号码长度不能超过100个字符") + @Schema(description = "关系人证件号码") + private String relationCertNo; + + /** 手机号码1 */ + @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号码1格式不正确") + @Schema(description = "手机号码1") + private String mobilePhone1; + + /** 手机号码2 */ + @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号码2格式不正确") + @Schema(description = "手机号码2") + private String mobilePhone2; + + /** 微信名称1 */ + @Size(max = 50, message = "微信名称1长度不能超过50个字符") + @Schema(description = "微信名称1") + private String wechatNo1; + + /** 微信名称2 */ + @Size(max = 50, message = "微信名称2长度不能超过50个字符") + @Schema(description = "微信名称2") + private String wechatNo2; + + /** 微信名称3 */ + @Size(max = 50, message = "微信名称3长度不能超过50个字符") + @Schema(description = "微信名称3") + private String wechatNo3; + + /** 详细联系地址 */ + @Size(max = 500, message = "详细联系地址长度不能超过500个字符") + @Schema(description = "详细联系地址") + private String contactAddress; + + /** 关系详细描述 */ + @Size(max = 500, message = "关系详细描述长度不能超过500个字符") + @Schema(description = "关系详细描述") + private String relationDesc; + + /** 状态 */ + @Schema(description = "状态:0-无效,1-有效") + private Integer status; + + /** 生效日期 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Schema(description = "生效日期") + private Date effectiveDate; + + /** 失效日期 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Schema(description = "失效日期") + private Date invalidDate; + + /** 备注 */ + @Schema(description = "备注") + private String remark; +} diff --git a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/dto/CcdiCustFmyRelationQueryDTO.java b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/dto/CcdiCustFmyRelationQueryDTO.java new file mode 100644 index 0000000..5b224aa --- /dev/null +++ b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/dto/CcdiCustFmyRelationQueryDTO.java @@ -0,0 +1,53 @@ +package com.ruoyi.ccdi.domain.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; + +/** + * 信贷客户家庭关系查询DTO + * + * @author ruoyi + * @date 2026-02-11 + */ +@Data +@Schema(description = "信贷客户家庭关系查询") +public class CcdiCustFmyRelationQueryDTO implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** 信贷客户身份证号 */ + @Schema(description = "信贷客户身份证号") + private String personId; + + /** 关系类型 */ + @Schema(description = "关系类型") + private String relationType; + + /** 关系人姓名 */ + @Schema(description = "关系人姓名") + private String relationName; + + /** 状态 */ + @Schema(description = "状态:0-无效,1-有效") + private Integer status; + + /** 数据来源 */ + @Schema(description = "数据来源") + private String dataSource; + + /** 生效日期开始 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Schema(description = "生效日期开始") + private Date effectiveDateStart; + + /** 生效日期结束 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Schema(description = "生效日期结束") + private Date effectiveDateEnd; +} From 5992502f2f3b915fdadb1bebeae753974f8e015e Mon Sep 17 00:00:00 2001 From: wkc <978997012@qq.com> Date: Wed, 11 Feb 2026 15:41:50 +0800 Subject: [PATCH 4/7] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E4=BF=A1?= =?UTF-8?q?=E8=B4=B7=E5=AE=A2=E6=88=B7=E5=AE=B6=E5=BA=AD=E5=85=B3=E7=B3=BB?= =?UTF-8?q?VO=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ccdi/domain/vo/CcdiCustFmyRelationVO.java | 140 ++++++++++++++++++ .../vo/CustFmyRelationImportFailureVO.java | 41 +++++ 2 files changed, 181 insertions(+) create mode 100644 ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/vo/CcdiCustFmyRelationVO.java create mode 100644 ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/vo/CustFmyRelationImportFailureVO.java diff --git a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/vo/CcdiCustFmyRelationVO.java b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/vo/CcdiCustFmyRelationVO.java new file mode 100644 index 0000000..abfae1f --- /dev/null +++ b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/vo/CcdiCustFmyRelationVO.java @@ -0,0 +1,140 @@ +package com.ruoyi.ccdi.domain.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; + +/** + * 信贷客户家庭关系VO + * + * @author ruoyi + * @date 2026-02-11 + */ +@Data +@Schema(description = "信贷客户家庭关系") +public class CcdiCustFmyRelationVO implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** 主键ID */ + @Schema(description = "主键ID") + private Long id; + + /** 信贷客户身份证号 */ + @Schema(description = "信贷客户身份证号") + private String personId; + + /** 关系类型 */ + @Schema(description = "关系类型") + private String relationType; + + /** 关系人姓名 */ + @Schema(description = "关系人姓名") + private String relationName; + + /** 性别 */ + @Schema(description = "性别:M-男,F-女,O-其他") + private String gender; + + /** 性别名称 */ + @Schema(description = "性别名称") + private String genderName; + + /** 出生日期 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Schema(description = "出生日期") + private Date birthDate; + + /** 关系人证件类型 */ + @Schema(description = "关系人证件类型") + private String relationCertType; + + /** 关系人证件号码 */ + @Schema(description = "关系人证件号码") + private String relationCertNo; + + /** 手机号码1 */ + @Schema(description = "手机号码1") + private String mobilePhone1; + + /** 手机号码2 */ + @Schema(description = "手机号码2") + private String mobilePhone2; + + /** 微信名称1 */ + @Schema(description = "微信名称1") + private String wechatNo1; + + /** 微信名称2 */ + @Schema(description = "微信名称2") + private String wechatNo2; + + /** 微信名称3 */ + @Schema(description = "微信名称3") + private String wechatNo3; + + /** 详细联系地址 */ + @Schema(description = "详细联系地址") + private String contactAddress; + + /** 关系详细描述 */ + @Schema(description = "关系详细描述") + private String relationDesc; + + /** 生效日期 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Schema(description = "生效日期") + private Date effectiveDate; + + /** 失效日期 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Schema(description = "失效日期") + private Date invalidDate; + + /** 状态 */ + @Schema(description = "状态:0-无效,1-有效") + private Integer status; + + /** 状态名称 */ + @Schema(description = "状态名称") + private String statusName; + + /** 备注 */ + @Schema(description = "备注") + private String remark; + + /** 数据来源 */ + @Schema(description = "数据来源:MANUAL-手工录入,IMPORT-批量导入") + private String dataSource; + + /** 是否是员工亲属 */ + @Schema(description = "是否是员工亲属:0-否") + private Boolean isEmpFamily; + + /** 是否是客户亲属 */ + @Schema(description = "是否是客户亲属:1-是") + private Boolean isCustFamily; + + /** 创建时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Schema(description = "创建时间") + private Date createTime; + + /** 更新时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Schema(description = "更新时间") + private Date updateTime; + + /** 创建人 */ + @Schema(description = "创建人") + private String createdBy; + + /** 更新人 */ + @Schema(description = "更新人") + private String updatedBy; +} diff --git a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/vo/CustFmyRelationImportFailureVO.java b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/vo/CustFmyRelationImportFailureVO.java new file mode 100644 index 0000000..e6cc3e8 --- /dev/null +++ b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/vo/CustFmyRelationImportFailureVO.java @@ -0,0 +1,41 @@ +package com.ruoyi.ccdi.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + +/** + * 信贷客户家庭关系导入失败VO + * + * @author ruoyi + * @date 2026-02-11 + */ +@Data +@Schema(description = "信贷客户家庭关系导入失败记录") +public class CustFmyRelationImportFailureVO implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** 行号 */ + @Schema(description = "行号") + private Integer rowNum; + + /** 信贷客户身份证号 */ + @Schema(description = "信贷客户身份证号") + private String personId; + + /** 关系类型 */ + @Schema(description = "关系类型") + private String relationType; + + /** 关系人姓名 */ + @Schema(description = "关系人姓名") + private String relationName; + + /** 错误消息 */ + @Schema(description = "错误消息") + private String errorMessage; +} From 74f3c04146f202501c4a730c247ab86eee0c7d27 Mon Sep 17 00:00:00 2001 From: wkc <978997012@qq.com> Date: Wed, 11 Feb 2026 15:45:05 +0800 Subject: [PATCH 5/7] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E4=BF=A1?= =?UTF-8?q?=E8=B4=B7=E5=AE=A2=E6=88=B7=E5=AE=B6=E5=BA=AD=E5=85=B3=E7=B3=BB?= =?UTF-8?q?Mapper=E3=80=81Service=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../excel/CcdiCustFmyRelationExcel.java | 117 +++++++++++++++++ .../mapper/CcdiCustFmyRelationMapper.java | 65 ++++++++++ .../ICcdiCustFmyRelationImportService.java | 40 ++++++ .../service/ICcdiCustFmyRelationService.java | 94 ++++++++++++++ .../mapper/ccdi/CcdiCustFmyRelationMapper.xml | 118 ++++++++++++++++++ 5 files changed, 434 insertions(+) create mode 100644 ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/excel/CcdiCustFmyRelationExcel.java create mode 100644 ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/mapper/CcdiCustFmyRelationMapper.java create mode 100644 ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/ICcdiCustFmyRelationImportService.java create mode 100644 ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/ICcdiCustFmyRelationService.java create mode 100644 ruoyi-ccdi/src/main/resources/mapper/ccdi/CcdiCustFmyRelationMapper.xml diff --git a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/excel/CcdiCustFmyRelationExcel.java b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/excel/CcdiCustFmyRelationExcel.java new file mode 100644 index 0000000..edc3d4f --- /dev/null +++ b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/excel/CcdiCustFmyRelationExcel.java @@ -0,0 +1,117 @@ +package com.ruoyi.ccdi.domain.excel; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.ruoyi.common.annotation.DictDropdown; +import com.ruoyi.common.annotation.Required; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; + +/** + * 信贷客户家庭关系Excel导入导出对象 + * + * @author ruoyi + * @date 2026-02-11 + */ +@Data +public class CcdiCustFmyRelationExcel implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** 信贷客户身份证号 */ + @ExcelProperty(value = "信贷客户身份证号*", index = 0) + @ColumnWidth(20) + @Required + private String personId; + + /** 关系类型 */ + @ExcelProperty(value = "关系类型*", index = 1) + @ColumnWidth(15) + @DictDropdown(dictType = "ccdi_relation_type") + @Required + private String relationType; + + /** 关系人姓名 */ + @ExcelProperty(value = "关系人姓名*", index = 2) + @ColumnWidth(15) + @Required + private String relationName; + + /** 性别 */ + @ExcelProperty(value = "性别", index = 3) + @ColumnWidth(10) + @DictDropdown(dictType = "ccdi_indiv_gender") + private String gender; + + /** 出生日期 */ + @ExcelProperty(value = "出生日期", index = 4) + @ColumnWidth(15) + private Date birthDate; + + /** 关系人证件类型 */ + @ExcelProperty(value = "关系人证件类型*", index = 5) + @ColumnWidth(15) + @DictDropdown(dictType = "ccdi_certificate_type") + @Required + private String relationCertType; + + /** 关系人证件号码 */ + @ExcelProperty(value = "关系人证件号码*", index = 6) + @ColumnWidth(20) + @Required + private String relationCertNo; + + /** 手机号码1 */ + @ExcelProperty(value = "手机号码1", index = 7) + @ColumnWidth(15) + private String mobilePhone1; + + /** 手机号码2 */ + @ExcelProperty(value = "手机号码2", index = 8) + @ColumnWidth(15) + private String mobilePhone2; + + /** 微信名称1 */ + @ExcelProperty(value = "微信名称1", index = 9) + @ColumnWidth(15) + private String wechatNo1; + + /** 微信名称2 */ + @ExcelProperty(value = "微信名称2", index = 10) + @ColumnWidth(15) + private String wechatNo2; + + /** 微信名称3 */ + @ExcelProperty(value = "微信名称3", index = 11) + @ColumnWidth(15) + private String wechatNo3; + + /** 详细联系地址 */ + @ExcelProperty(value = "详细联系地址", index = 12) + @ColumnWidth(30) + private String contactAddress; + + /** 关系详细描述 */ + @ExcelProperty(value = "关系详细描述", index = 13) + @ColumnWidth(30) + private String relationDesc; + + /** 生效日期 */ + @ExcelProperty(value = "生效日期", index = 14) + @ColumnWidth(15) + private Date effectiveDate; + + /** 失效日期 */ + @ExcelProperty(value = "失效日期", index = 15) + @ColumnWidth(15) + private Date invalidDate; + + /** 备注 */ + @ExcelProperty(value = "备注", index = 16) + @ColumnWidth(30) + private String remark; +} diff --git a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/mapper/CcdiCustFmyRelationMapper.java b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/mapper/CcdiCustFmyRelationMapper.java new file mode 100644 index 0000000..88a4a41 --- /dev/null +++ b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/mapper/CcdiCustFmyRelationMapper.java @@ -0,0 +1,65 @@ +package com.ruoyi.ccdi.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.ccdi.domain.CcdiCustFmyRelation; +import com.ruoyi.ccdi.domain.dto.CcdiCustFmyRelationQueryDTO; +import com.ruoyi.ccdi.domain.vo.CcdiCustFmyRelationVO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 信贷客户家庭关系Mapper接口 + * + * @author ruoyi + * @date 2026-02-11 + */ +public interface CcdiCustFmyRelationMapper extends BaseMapper { + + /** + * 分页查询信贷客户家庭关系 + * + * @param page 分页对象 + * @param query 查询条件 + * @return 信贷客户家庭关系VO列表 + */ + Page selectRelationPage(Page page, + @Param("query") CcdiCustFmyRelationQueryDTO query); + + /** + * 根据ID查询信贷客户家庭关系详情 + * + * @param id 主键ID + * @return 信贷客户家庭关系VO + */ + CcdiCustFmyRelationVO selectRelationById(@Param("id") Long id); + + /** + * 查询已存在的关系记录(用于导入校验) + * + * @param personId 信贷客户身份证号 + * @param relationType 关系类型 + * @param relationCertNo 关系人证件号码 + * @return 已存在的关系记录 + */ + CcdiCustFmyRelation selectExistingRelations(@Param("personId") String personId, + @Param("relationType") String relationType, + @Param("relationCertNo") String relationCertNo); + + /** + * 批量插入信贷客户家庭关系 + * + * @param relations 信贷客户家庭关系列表 + * @return 插入条数 + */ + int insertBatch(@Param("relations") List relations); + + /** + * 根据证件号码查询关系数量 + * + * @param relationCertNo 关系人证件号码 + * @return 关系数量 + */ + int countByCertNo(@Param("relationCertNo") String relationCertNo); +} diff --git a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/ICcdiCustFmyRelationImportService.java b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/ICcdiCustFmyRelationImportService.java new file mode 100644 index 0000000..10e28cb --- /dev/null +++ b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/ICcdiCustFmyRelationImportService.java @@ -0,0 +1,40 @@ +package com.ruoyi.ccdi.service; + +import com.ruoyi.ccdi.domain.excel.CcdiCustFmyRelationExcel; +import com.ruoyi.ccdi.domain.vo.CustFmyRelationImportFailureVO; + +import java.util.List; + +/** + * 信贷客户家庭关系导入Service接口 + * + * @author ruoyi + * @date 2026-02-11 + */ +public interface ICcdiCustFmyRelationImportService { + + /** + * 异步导入信贷客户家庭关系 + * + * @param excels Excel数据列表 + * @param taskId 任务ID + */ + void importRelationsAsync(List excels, String taskId); + + /** + * 校验单条数据 + * + * @param excel Excel数据 + * @param rowNum 行号 + * @return 错误消息,为null表示校验通过 + */ + String validateExcelRow(CcdiCustFmyRelationExcel excel, Integer rowNum); + + /** + * 获取导入失败记录 + * + * @param taskId 任务ID + * @return 失败记录列表 + */ + List getImportFailures(String taskId); +} diff --git a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/ICcdiCustFmyRelationService.java b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/ICcdiCustFmyRelationService.java new file mode 100644 index 0000000..b29d752 --- /dev/null +++ b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/ICcdiCustFmyRelationService.java @@ -0,0 +1,94 @@ +package com.ruoyi.ccdi.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.ccdi.domain.dto.CcdiCustFmyRelationAddDTO; +import com.ruoyi.ccdi.domain.dto.CcdiCustFmyRelationEditDTO; +import com.ruoyi.ccdi.domain.dto.CcdiCustFmyRelationQueryDTO; +import com.ruoyi.ccdi.domain.excel.CcdiCustFmyRelationExcel; +import com.ruoyi.ccdi.domain.vo.CcdiCustFmyRelationVO; + +import jakarta.servlet.http.HttpServletResponse; +import java.util.List; + +/** + * 信贷客户家庭关系Service接口 + * + * @author ruoyi + * @date 2026-02-11 + */ +public interface ICcdiCustFmyRelationService { + + /** + * 分页查询信贷客户家庭关系 + * + * @param query 查询条件 + * @param pageNum 页码 + * @param pageSize 每页条数 + * @return 分页结果 + */ + Page selectRelationPage(CcdiCustFmyRelationQueryDTO query, + Integer pageNum, Integer pageSize); + + /** + * 根据ID查询信贷客户家庭关系详情 + * + * @param id 主键ID + * @return 信贷客户家庭关系VO + */ + CcdiCustFmyRelationVO selectRelationById(Long id); + + /** + * 新增信贷客户家庭关系 + * + * @param addDTO 新增DTO + * @return 是否成功 + */ + boolean insertRelation(CcdiCustFmyRelationAddDTO addDTO); + + /** + * 修改信贷客户家庭关系 + * + * @param editDTO 编辑DTO + * @return 是否成功 + */ + boolean updateRelation(CcdiCustFmyRelationEditDTO editDTO); + + /** + * 删除信贷客户家庭关系 + * + * @param ids 主键ID数组 + * @return 是否成功 + */ + boolean deleteRelationByIds(Long[] ids); + + /** + * 导出信贷客户家庭关系 + * + * @param query 查询条件 + * @param response HTTP响应 + */ + void exportRelations(CcdiCustFmyRelationQueryDTO query, HttpServletResponse response); + + /** + * 生成导入模板 + * + * @param response HTTP响应 + */ + void importTemplate(HttpServletResponse response); + + /** + * 批量导入信贷客户家庭关系 + * + * @param excels Excel数据列表 + * @return 导入任务ID + */ + String importRelations(List excels); + + /** + * 获取导入失败记录 + * + * @param taskId 任务ID + * @return 失败记录列表 + */ + List getImportFailures(String taskId); +} diff --git a/ruoyi-ccdi/src/main/resources/mapper/ccdi/CcdiCustFmyRelationMapper.xml b/ruoyi-ccdi/src/main/resources/mapper/ccdi/CcdiCustFmyRelationMapper.xml new file mode 100644 index 0000000..d147cd2 --- /dev/null +++ b/ruoyi-ccdi/src/main/resources/mapper/ccdi/CcdiCustFmyRelationMapper.xml @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + INSERT INTO ccdi_cust_fmy_relation ( + person_id, relation_type, relation_name, gender, birth_date, + relation_cert_type, relation_cert_no, mobile_phone1, mobile_phone2, + wechat_no1, wechat_no2, wechat_no3, contact_address, relation_desc, + status, effective_date, invalid_date, remark, data_source, + is_emp_family, is_cust_family, created_by, create_time + ) VALUES + + ( + #{item.personId}, #{item.relationType}, #{item.relationName}, + #{item.gender}, #{item.birthDate}, #{item.relationCertType}, + #{item.relationCertNo}, #{item.mobilePhone1}, #{item.mobilePhone2}, + #{item.wechatNo1}, #{item.wechatNo2}, #{item.wechatNo3}, + #{item.contactAddress}, #{item.relationDesc}, #{item.status}, + #{item.effectiveDate}, #{item.invalidDate}, #{item.remark}, + #{item.dataSource}, #{item.isEmpFamily}, #{item.isCustFamily}, + #{item.createdBy}, #{item.createTime} + ) + + + + + + + From 38ef48f656d21d1beab221bcc5137386f0232e86 Mon Sep 17 00:00:00 2001 From: wkc <978997012@qq.com> Date: Wed, 11 Feb 2026 15:51:59 +0800 Subject: [PATCH 6/7] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E4=BF=A1?= =?UTF-8?q?=E8=B4=B7=E5=AE=A2=E6=88=B7=E5=AE=B6=E5=BA=AD=E5=85=B3=E7=B3=BB?= =?UTF-8?q?Service=E5=AE=9E=E7=8E=B0=E7=B1=BB=E5=92=8CController?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CcdiCustFmyRelationImportServiceImpl.java | 165 ++++++++++++++++++ .../impl/CcdiCustFmyRelationServiceImpl.java | 160 +++++++++++++++++ 2 files changed, 325 insertions(+) create mode 100644 ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiCustFmyRelationImportServiceImpl.java create mode 100644 ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiCustFmyRelationServiceImpl.java diff --git a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiCustFmyRelationImportServiceImpl.java b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiCustFmyRelationImportServiceImpl.java new file mode 100644 index 0000000..448ff19 --- /dev/null +++ b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiCustFmyRelationImportServiceImpl.java @@ -0,0 +1,165 @@ +package com.ruoyi.ccdi.service.impl; + +import com.alibaba.excel.EasyExcel; +import com.ruoyi.ccdi.domain.CcdiCustFmyRelation; +import com.ruoyi.ccdi.domain.excel.CcdiCustFmyRelationExcel; +import com.ruoyi.ccdi.domain.vo.CustFmyRelationImportFailureVO; +import com.ruoyi.ccdi.mapper.CcdiCustFmyRelationMapper; +import com.ruoyi.ccdi.service.ICcdiCustFmyRelationImportService; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.StringUtils; +import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.concurrent.TimeUnit; + +/** + * 信贷客户家庭关系导入Service实现 + * + * @author ruoyi + * @date 2026-02-11 + */ +@Service +public class CcdiCustFmyRelationImportServiceImpl implements ICcdiCustFmyRelationImportService { + + private static final Logger log = LoggerFactory.getLogger(CcdiCustFmyRelationImportServiceImpl.class); + + @Resource + private CcdiCustFmyRelationMapper mapper; + + @Resource + private RedisTemplate redisTemplate; + + private static final String IMPORT_TASK_KEY_PREFIX = "import:custFmyRelation:"; + private static final String IMPORT_FAILURE_KEY_PREFIX = "import:custFmyRelation:failures:"; + + @Async + @Override + @Transactional(rollbackFor = Exception.class) + public void importRelationsAsync(List excels, String taskId) { + List validRelations = new ArrayList<>(); + List failures = new ArrayList<>(); + + try { + for (int i = 0; i < excels.size(); i++) { + CcdiCustFmyRelationExcel excel = excels.get(i); + Integer rowNum = i + 2; // Excel行号从2开始(第1行是表头) + + String errorMessage = validateExcelRow(excel, rowNum); + if (errorMessage != null) { + CustFmyRelationImportFailureVO failure = new CustFmyRelationImportFailureVO(); + failure.setRowNum(rowNum); + failure.setPersonId(excel.getPersonId()); + failure.setRelationType(excel.getRelationType()); + failure.setRelationName(excel.getRelationName()); + failure.setErrorMessage(errorMessage); + failures.add(failure); + continue; + } + + CcdiCustFmyRelation relation = convertToRelation(excel); + validRelations.add(relation); + } + + // 批量插入有效数据 + if (!validRelations.isEmpty()) { + mapper.insertBatch(validRelations); + } + + // 保存失败记录到Redis(24小时过期) + if (!failures.isEmpty()) { + redisTemplate.opsForValue().set( + IMPORT_FAILURE_KEY_PREFIX + taskId, + failures, + 24, + TimeUnit.HOURS + ); + } + + // 更新任务状态 + redisTemplate.opsForValue().set( + IMPORT_TASK_KEY_PREFIX + taskId, + "COMPLETED:" + validRelations.size() + ":" + failures.size(), + 1, + TimeUnit.HOURS + ); + + } catch (Exception e) { + log.error("导入失败", e); + redisTemplate.opsForValue().set( + IMPORT_TASK_KEY_PREFIX + taskId, + "FAILED:" + e.getMessage(), + 1, + TimeUnit.HOURS + ); + } + } + + @Override + public String validateExcelRow(CcdiCustFmyRelationExcel excel, Integer rowNum) { + if (excel.getPersonId() == null || excel.getPersonId().trim().isEmpty()) { + return "信贷客户身份证号不能为空"; + } + + if (excel.getRelationType() == null || excel.getRelationType().trim().isEmpty()) { + return "关系类型不能为空"; + } + + if (excel.getRelationName() == null || excel.getRelationName().trim().isEmpty()) { + return "关系人姓名不能为空"; + } + + if (excel.getRelationCertType() == null || excel.getRelationCertType().trim().isEmpty()) { + return "关系人证件类型不能为空"; + } + + if (excel.getRelationCertNo() == null || excel.getRelationCertNo().trim().isEmpty()) { + return "关系人证件号码不能为空"; + } + + // 检查是否已存在相同的关系 + CcdiCustFmyRelation existing = mapper.selectExistingRelations( + excel.getPersonId(), + excel.getRelationType(), + excel.getRelationCertNo() + ); + + if (existing != null) { + return "该关系已存在,请勿重复导入"; + } + + return null; // 校验通过 + } + + @Override + @SuppressWarnings("unchecked") + public List getImportFailures(String taskId) { + Object obj = redisTemplate.opsForValue().get(IMPORT_FAILURE_KEY_PREFIX + taskId); + if (obj != null) { + return (List) obj; + } + return new ArrayList<>(); + } + + private CcdiCustFmyRelation convertToRelation(CcdiCustFmyRelationExcel excel) { + CcdiCustFmyRelation relation = new CcdiCustFmyRelation(); + org.springframework.beans.BeanUtils.copyProperties(excel, relation); + + relation.setIsEmpFamily(false); + relation.setIsCustFamily(true); + relation.setStatus(excel.getStatus() != null ? excel.getStatus() : 1); + relation.setDataSource("IMPORT"); + relation.setCreatedBy(SecurityUtils.getUsername()); + relation.setCreateTime(new Date()); + + return relation; + } +} diff --git a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiCustFmyRelationServiceImpl.java b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiCustFmyRelationServiceImpl.java new file mode 100644 index 0000000..164207a --- /dev/null +++ b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiCustFmyRelationServiceImpl.java @@ -0,0 +1,160 @@ +package com.ruoyi.ccdi.service.impl; + +import com.alibaba.excel.EasyExcel; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.ccdi.domain.CcdiCustFmyRelation; +import com.ruoyi.ccdi.domain.dto.CcdiCustFmyRelationAddDTO; +import com.ruoyi.ccdi.domain.dto.CcdiCustFmyRelationEditDTO; +import com.ruoyi.ccdi.domain.dto.CcdiCustFmyRelationQueryDTO; +import com.ruoyi.ccdi.domain.excel.CcdiCustFmyRelationExcel; +import com.ruoyi.ccdi.domain.vo.CcdiCustFmyRelationVO; +import com.ruoyi.ccdi.mapper.CcdiCustFmyRelationMapper; +import com.ruoyi.ccdi.service.ICcdiCustFmyRelationImportService; +import com.ruoyi.ccdi.service.ICcdiCustFmyRelationService; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.StringUtils; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.beans.BeanUtils; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +/** + * 信贷客户家庭关系Service实现 + * + * @author ruoyi + * @date 2026-02-11 + */ +@Service +public class CcdiCustFmyRelationServiceImpl implements ICcdiCustFmyRelationService { + + @Resource + private CcdiCustFmyRelationMapper mapper; + + @Resource + private ICcdiCustFmyRelationImportService importService; + + @Resource + private RedisTemplate redisTemplate; + + private static final String IMPORT_TASK_KEY_PREFIX = "import:custFmyRelation:"; + private static final String IMPORT_FAILURE_KEY_PREFIX = "import:custFmyRelation:failures:"; + + @Override + public Page selectRelationPage(CcdiCustFmyRelationQueryDTO query, + Integer pageNum, Integer pageSize) { + Page page = new Page<>(pageNum, pageSize); + return mapper.selectRelationPage(page, query); + } + + @Override + public CcdiCustFmyRelationVO selectRelationById(Long id) { + return mapper.selectRelationById(id); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean insertRelation(CcdiCustFmyRelationAddDTO addDTO) { + CcdiCustFmyRelation relation = new CcdiCustFmyRelation(); + BeanUtils.copyProperties(addDTO, relation); + + // 关键设置:客户家庭关系 + relation.setIsEmpFamily(false); + relation.setIsCustFamily(true); + relation.setStatus(1); + relation.setDataSource("MANUAL"); + + return mapper.insert(relation) > 0; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean updateRelation(CcdiCustFmyRelationEditDTO editDTO) { + CcdiCustFmyRelation relation = new CcdiCustFmyRelation(); + BeanUtils.copyProperties(editDTO, relation); + + return mapper.updateById(relation) > 0; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean deleteRelationByIds(Long[] ids) { + return mapper.deleteBatchIds(List.of(ids)) > 0; + } + + @Override + public void exportRelations(CcdiCustFmyRelationQueryDTO query, HttpServletResponse response) { + // 查询所有符合条件的数据(不分页) + Page page = new Page<>(1, 10000); + Page result = mapper.selectRelationPage(page, query); + + List excels = result.getRecords().stream() + .map(this::convertToExcel) + .toList(); + + // 使用EasyExcel导出 + try { + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + response.setCharacterEncoding("utf-8"); + String fileName = URLEncoder.encode("信贷客户家庭关系", StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"); + response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); + + EasyExcel.write(response.getOutputStream(), CcdiCustFmyRelationExcel.class) + .sheet("信贷客户家庭关系") + .doWrite(excels); + } catch (Exception e) { + throw new RuntimeException("导出失败", e); + } + } + + @Override + public void importTemplate(HttpServletResponse response) { + try { + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + response.setCharacterEncoding("utf-8"); + String fileName = URLEncoder.encode("信贷客户家庭关系导入模板", StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"); + response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); + + EasyExcel.write(response.getOutputStream(), CcdiCustFmyRelationExcel.class) + .sheet("模板") + .doWrite(Collections.emptyList()); + } catch (Exception e) { + throw new RuntimeException("模板下载失败", e); + } + } + + @Override + public String importRelations(List excels) { + String taskId = UUID.randomUUID().toString(); + + // 保存任务状态到Redis + redisTemplate.opsForValue().set(IMPORT_TASK_KEY_PREFIX + taskId, "PROCESSING", 1, TimeUnit.HOURS); + + // 异步导入 + importService.importRelationsAsync(excels, taskId); + + return taskId; + } + + @Override + public List getImportFailures(String taskId) { + return importService.getImportFailures(taskId); + } + + private CcdiCustFmyRelationExcel convertToExcel(CcdiCustFmyRelationVO vo) { + CcdiCustFmyRelationExcel excel = new CcdiCustFmyRelationExcel(); + BeanUtils.copyProperties(vo, excel); + return excel; + } +} From 7b1ddeae8ae50ed9992e81958568c77f05dd6223 Mon Sep 17 00:00:00 2001 From: wkc <978997012@qq.com> Date: Wed, 11 Feb 2026 15:52:48 +0800 Subject: [PATCH 7/7] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E4=BF=A1?= =?UTF-8?q?=E8=B4=B7=E5=AE=A2=E6=88=B7=E5=AE=B6=E5=BA=AD=E5=85=B3=E7=B3=BB?= =?UTF-8?q?=E8=8F=9C=E5=8D=95=E6=9D=83=E9=99=90=E5=92=8CController?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CcdiCustFmyRelationController.java | 158 ++++++++++++++++++ sql/ccdi_cust_fmy_relation_menu.sql | 37 ++++ 2 files changed, 195 insertions(+) create mode 100644 ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/controller/CcdiCustFmyRelationController.java create mode 100644 sql/ccdi_cust_fmy_relation_menu.sql diff --git a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/controller/CcdiCustFmyRelationController.java b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/controller/CcdiCustFmyRelationController.java new file mode 100644 index 0000000..c2011cd --- /dev/null +++ b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/controller/CcdiCustFmyRelationController.java @@ -0,0 +1,158 @@ +package com.ruoyi.ccdi.controller; + +import com.alibaba.excel.EasyExcel; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.ccdi.domain.dto.CcdiCustFmyRelationAddDTO; +import com.ruoyi.ccdi.domain.dto.CcdiCustFmyRelationEditDTO; +import com.ruoyi.ccdi.domain.dto.CcdiCustFmyRelationQueryDTO; +import com.ruoyi.ccdi.domain.excel.CcdiCustFmyRelationExcel; +import com.ruoyi.ccdi.domain.vo.CcdiCustFmyRelationVO; +import com.ruoyi.ccdi.domain.vo.CustFmyRelationImportFailureVO; +import com.ruoyi.ccdi.service.ICcdiCustFmyRelationService; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.enums.BusinessType; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; + +/** + * 信贷客户家庭关系Controller + * + * @author ruoyi + * @date 2026-02-11 + */ +@Tag(name = "信贷客户家庭关系管理") +@RestController +@RequestMapping("/ccdi/custFmyRelation") +public class CcdiCustFmyRelationController extends BaseController { + + @Resource + private ICcdiCustFmyRelationService relationService; + + @Resource + private RedisTemplate redisTemplate; + + /** + * 查询信贷客户家庭关系列表 + */ + @Operation(summary = "查询信贷客户家庭关系列表") + @PreAuthorize("@ss.hasPermi('ccdi:custFmyRelation:query')") + @GetMapping("/list") + public TableDataInfo list(CcdiCustFmyRelationQueryDTO query) { + startPage(); + Page page = relationService.selectRelationPage(query, getPageNum(), getPageSize()); + return getDataTable(page.getRecords(), page.getTotal()); + } + + /** + * 根据ID查询信贷客户家庭关系详情 + */ + @Operation(summary = "查询信贷客户家庭关系详情") + @PreAuthorize("@ss.hasPermi('ccdi:custFmyRelation:query')") + @GetMapping("/{id}") + public AjaxResult getInfo(@PathVariable("id") Long id) { + CcdiCustFmyRelationVO relation = relationService.selectRelationById(id); + return success(relation); + } + + /** + * 新增信贷客户家庭关系 + */ + @Operation(summary = "新增信贷客户家庭关系") + @PreAuthorize("@ss.hasPermi('ccdi:custFmyRelation:add')") + @PostMapping + public AjaxResult add(@Validated @RequestBody CcdiCustFmyRelationAddDTO addDTO) { + return toAjax(relationService.insertRelation(addDTO)); + } + + /** + * 修改信贷客户家庭关系 + */ + @Operation(summary = "修改信贷客户家庭关系") + @PreAuthorize("@ss.hasPermi('ccdi:custFmyRelation:edit')") + @PutMapping + public AjaxResult edit(@Validated @RequestBody CcdiCustFmyRelationEditDTO editDTO) { + return toAjax(relationService.updateRelation(editDTO)); + } + + /** + * 删除信贷客户家庭关系 + */ + @Operation(summary = "删除信贷客户家庭关系") + @PreAuthorize("@ss.hasPermi('ccdi:custFmyRelation:remove')") + @DeleteMapping("/{ids}") + public AjaxResult remove(@PathVariable Long[] ids) { + return toAjax(relationService.deleteRelationByIds(ids)); + } + + /** + * 导出信贷客户家庭关系 + */ + @Operation(summary = "导出信贷客户家庭关系") + @PreAuthorize("@ss.hasPermi('ccdi:custFmyRelation:export')") + @PostMapping("/export") + public void export(HttpServletResponse response, CcdiCustFmyRelationQueryDTO query) { + relationService.exportRelations(query, response); + } + + /** + * 下载导入模板 + */ + @Operation(summary = "下载导入模板") + @PreAuthorize("@ss.hasPermi('ccdi:custFmyRelation:import')") + @PostMapping("/importTemplate") + public void importTemplate(HttpServletResponse response) { + relationService.importTemplate(response); + } + + /** + * 导入信贷客户家庭关系 + */ + @Operation(summary = "导入信贷客户家庭关系") + @PreAuthorize("@ss.hasPermi('ccdi:custFmyRelation:import')") + @PostMapping("/importData") + public AjaxResult importData(@RequestParam("file") MultipartFile file) throws IOException { + List excels = EasyExcel.read(file.getInputStream()) + .head(CcdiCustFmyRelationExcel.class) + .sheet() + .doReadSync(); + + String taskId = relationService.importRelations(excels); + return success("导入任务已提交,任务ID: " + taskId); + } + + /** + * 查询导入状态 + */ + @Operation(summary = "查询导入状态") + @PreAuthorize("@ss.hasPermi('ccdi:custFmyRelation:query')") + @GetMapping("/importStatus/{taskId}") + public AjaxResult getImportStatus(@PathVariable("taskId") String taskId) { + // 从Redis获取任务状态 + Object status = redisTemplate.opsForValue().get("import:custFmyRelation:" + taskId); + return success(status); + } + + /** + * 查询导入失败记录 + */ + @Operation(summary = "查询导入失败记录") + @PreAuthorize("@ss.hasPermi('ccdi:custFmyRelation:query')") + @GetMapping("/importFailures/{taskId}") + public TableDataInfo getImportFailures( + @PathVariable("taskId") String taskId) { + startPage(); + List failures = relationService.getImportFailures(taskId); + return getDataTable(failures, (long) failures.size()); + } +} diff --git a/sql/ccdi_cust_fmy_relation_menu.sql b/sql/ccdi_cust_fmy_relation_menu.sql new file mode 100644 index 0000000..1dc7bd2 --- /dev/null +++ b/sql/ccdi_cust_fmy_relation_menu.sql @@ -0,0 +1,37 @@ +-- 信贷客户家庭关系菜单权限 +-- 创建时间: 2026-02-11 + +-- 添加信贷客户家庭关系菜单(父菜单为信息维护) +INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, remark) +SELECT @parent_id := menu_id FROM sys_menu WHERE menu_name = '信息维护' LIMIT 1; +INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) +VALUES ( + '信贷客户家庭关系', + @parent_id, + 5, + 'custFmyRelation', + 1, + 0, + 'C', + '0', + '0', + 'ccdi:custFmyRelation:list', + 'peoples', + 'admin', + NOW(), + '', + '信贷客户家庭关系菜单' +); + +-- 获取刚插入的菜单ID +SET @cust_menu_id = LAST_INSERT_ID(); + +-- 添加按钮权限 +INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) +VALUES + ('信贷客户家庭关系查询', @cust_menu_id, 1, '#', '', 1, 0, 'F', '0', '0', 'ccdi:custFmyRelation:query', '#', 'admin', NOW(), ''), + ('信贷客户家庭关系新增', @cust_menu_id, 2, '#', '', 1, 0, 'F', '0', '0', 'ccdi:custFmyRelation:add', '#', 'admin', NOW(), ''), + ('信贷客户家庭关系修改', @cust_menu_id, 3, '#', '', 1, 0, 'F', '0', '0', 'ccdi:custFmyRelation:edit', '#', 'admin', NOW(), ''), + ('信贷客户家庭关系删除', @cust_menu_id, 4, '#', '', 1, 0, 'F', '0', '0', 'ccdi:custFmyRelation:remove', '#', 'admin', NOW(), ''), + ('信贷客户家庭关系导出', @cust_menu_id, 5, '#', '', 1, 0, 'F', '0', '0', 'ccdi:custFmyRelation:export', '#', 'admin', NOW(), ''), + ('信贷客户家庭关系导入', @cust_menu_id, 6, '#', '', 1, 0, 'F', '0', '0', 'ccdi:custFmyRelation:import', '#', 'admin', NOW(), '');