This commit is contained in:
wkc
2026-04-17 16:01:41 +08:00
parent e0629f22e5
commit c278d11390
37 changed files with 3722 additions and 4 deletions

View File

@@ -0,0 +1,146 @@
package com.ruoyi.info.collection.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.PageDomain;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.page.TableSupport;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.info.collection.domain.dto.CcdiEnterpriseBaseInfoAddDTO;
import com.ruoyi.info.collection.domain.dto.CcdiEnterpriseBaseInfoEditDTO;
import com.ruoyi.info.collection.domain.dto.CcdiEnterpriseBaseInfoQueryDTO;
import com.ruoyi.info.collection.domain.excel.CcdiEnterpriseBaseInfoExcel;
import com.ruoyi.info.collection.domain.vo.CcdiEnterpriseBaseInfoVO;
import com.ruoyi.info.collection.domain.vo.EnterpriseBaseInfoImportFailureVO;
import com.ruoyi.info.collection.domain.vo.ImportResultVO;
import com.ruoyi.info.collection.domain.vo.ImportStatusVO;
import com.ruoyi.info.collection.service.ICcdiEnterpriseBaseInfoImportService;
import com.ruoyi.info.collection.service.ICcdiEnterpriseBaseInfoService;
import com.ruoyi.info.collection.utils.EasyExcelUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.util.ArrayList;
import java.util.List;
/**
* 实体库管理 Controller
*
* @author ruoyi
* @date 2026-04-17
*/
@Tag(name = "实体库管理")
@RestController
@RequestMapping("/ccdi/enterpriseBaseInfo")
public class CcdiEnterpriseBaseInfoController extends BaseController {
@Resource
private ICcdiEnterpriseBaseInfoService enterpriseBaseInfoService;
@Resource
private ICcdiEnterpriseBaseInfoImportService enterpriseBaseInfoImportService;
@Operation(summary = "查询实体库列表")
@PreAuthorize("@ss.hasPermi('ccdi:enterpriseBaseInfo:list')")
@GetMapping("/list")
public TableDataInfo list(CcdiEnterpriseBaseInfoQueryDTO queryDTO) {
PageDomain pageDomain = TableSupport.buildPageRequest();
Page<CcdiEnterpriseBaseInfoVO> page = new Page<>(pageDomain.getPageNum(), pageDomain.getPageSize());
Page<CcdiEnterpriseBaseInfoVO> result = enterpriseBaseInfoService.selectEnterpriseBaseInfoPage(page, queryDTO);
return getDataTable(result.getRecords(), result.getTotal());
}
@Operation(summary = "获取实体库详细信息")
@PreAuthorize("@ss.hasPermi('ccdi:enterpriseBaseInfo:query')")
@GetMapping("/{socialCreditCode}")
public AjaxResult getInfo(@PathVariable String socialCreditCode) {
return success(enterpriseBaseInfoService.selectEnterpriseBaseInfoById(socialCreditCode));
}
@Operation(summary = "新增实体库信息")
@PreAuthorize("@ss.hasPermi('ccdi:enterpriseBaseInfo:add')")
@Log(title = "实体库管理", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@Validated @RequestBody CcdiEnterpriseBaseInfoAddDTO addDTO) {
return toAjax(enterpriseBaseInfoService.insertEnterpriseBaseInfo(addDTO));
}
@Operation(summary = "修改实体库信息")
@PreAuthorize("@ss.hasPermi('ccdi:enterpriseBaseInfo:edit')")
@Log(title = "实体库管理", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@Validated @RequestBody CcdiEnterpriseBaseInfoEditDTO editDTO) {
return toAjax(enterpriseBaseInfoService.updateEnterpriseBaseInfo(editDTO));
}
@Operation(summary = "删除实体库信息")
@PreAuthorize("@ss.hasPermi('ccdi:enterpriseBaseInfo:remove')")
@Log(title = "实体库管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{socialCreditCodes}")
public AjaxResult remove(@PathVariable String[] socialCreditCodes) {
return toAjax(enterpriseBaseInfoService.deleteEnterpriseBaseInfoByIds(socialCreditCodes));
}
@Operation(summary = "下载导入模板")
@PostMapping("/importTemplate")
public void importTemplate(HttpServletResponse response) {
EasyExcelUtil.importTemplateWithDictDropdown(response, CcdiEnterpriseBaseInfoExcel.class, "实体库管理");
}
@Operation(summary = "导入实体库信息")
@PreAuthorize("@ss.hasPermi('ccdi:enterpriseBaseInfo:import')")
@Log(title = "实体库管理", businessType = BusinessType.IMPORT)
@PostMapping("/importData")
public AjaxResult importData(MultipartFile file) throws Exception {
List<CcdiEnterpriseBaseInfoExcel> list = EasyExcelUtil.importExcel(file.getInputStream(), CcdiEnterpriseBaseInfoExcel.class);
if (list == null || list.isEmpty()) {
return error("至少需要一条数据");
}
String taskId = enterpriseBaseInfoService.importEnterpriseBaseInfo(list);
ImportResultVO result = new ImportResultVO();
result.setTaskId(taskId);
result.setStatus("PROCESSING");
result.setMessage("导入任务已提交,正在后台处理");
return AjaxResult.success("导入任务已提交,正在后台处理", result);
}
@Operation(summary = "查询导入状态")
@PreAuthorize("@ss.hasPermi('ccdi:enterpriseBaseInfo:import')")
@GetMapping("/importStatus/{taskId}")
public AjaxResult getImportStatus(@PathVariable String taskId) {
ImportStatusVO status = enterpriseBaseInfoImportService.getImportStatus(taskId);
return success(status);
}
@Operation(summary = "查询导入失败记录")
@PreAuthorize("@ss.hasPermi('ccdi:enterpriseBaseInfo:import')")
@GetMapping("/importFailures/{taskId}")
public TableDataInfo getImportFailures(@PathVariable String taskId,
@RequestParam(defaultValue = "1") Integer pageNum,
@RequestParam(defaultValue = "10") Integer pageSize) {
List<EnterpriseBaseInfoImportFailureVO> failures = enterpriseBaseInfoImportService.getImportFailures(taskId);
int fromIndex = (pageNum - 1) * pageSize;
if (fromIndex >= failures.size()) {
return getDataTable(new ArrayList<>(), failures.size());
}
int toIndex = Math.min(fromIndex + pageSize, failures.size());
return getDataTable(failures.subList(fromIndex, toIndex), failures.size());
}
}

View File

@@ -138,4 +138,30 @@ public class CcdiEnumController {
}
return AjaxResult.success(options);
}
/**
* 获取实体风险等级选项
*/
@Operation(summary = "获取实体风险等级选项")
@GetMapping("/enterpriseRiskLevel")
public AjaxResult getEnterpriseRiskLevelOptions() {
List<EnumOptionVO> options = new ArrayList<>();
for (EnterpriseRiskLevel level : EnterpriseRiskLevel.values()) {
options.add(new EnumOptionVO(level.getCode(), level.getDesc()));
}
return AjaxResult.success(options);
}
/**
* 获取企业来源选项
*/
@Operation(summary = "获取企业来源选项")
@GetMapping("/enterpriseSource")
public AjaxResult getEnterpriseSourceOptions() {
List<EnumOptionVO> options = new ArrayList<>();
for (EnterpriseSource source : EnterpriseSource.values()) {
options.add(new EnumOptionVO(source.getCode(), source.getDesc()));
}
return AjaxResult.success(options);
}
}

View File

@@ -0,0 +1,46 @@
package com.ruoyi.info.collection.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_intermediary_enterprise_relation
*/
@Data
@TableName("ccdi_intermediary_enterprise_relation")
public class CcdiIntermediaryEnterpriseRelation implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@TableId(type = IdType.AUTO)
private Long id;
private String intermediaryBizId;
private String socialCreditCode;
private String relationPersonPost;
private String remark;
@TableField(fill = FieldFill.INSERT)
private String createdBy;
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private String updatedBy;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
}

View File

@@ -0,0 +1,107 @@
package com.ruoyi.info.collection.domain.dto;
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-04-17
*/
@Data
@Schema(description = "实体库管理新增DTO")
public class CcdiEnterpriseBaseInfoAddDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "统一社会信用代码")
@NotBlank(message = "统一社会信用代码不能为空")
@Pattern(regexp = "^[0-9A-HJ-NPQRTUWXY]{2}\\d{6}[0-9A-HJ-NPQRTUWXY]{10}$", message = "统一社会信用代码格式不正确")
private String socialCreditCode;
@Schema(description = "企业名称")
@NotBlank(message = "企业名称不能为空")
@Size(max = 200, message = "企业名称长度不能超过200个字符")
private String enterpriseName;
@Schema(description = "企业类型")
@Size(max = 50, message = "企业类型长度不能超过50个字符")
private String enterpriseType;
@Schema(description = "企业性质")
@Size(max = 50, message = "企业性质长度不能超过50个字符")
private String enterpriseNature;
@Schema(description = "行业分类")
@Size(max = 100, message = "行业分类长度不能超过100个字符")
private String industryClass;
@Schema(description = "所属行业")
@Size(max = 100, message = "所属行业长度不能超过100个字符")
private String industryName;
@Schema(description = "成立日期")
private Date establishDate;
@Schema(description = "注册地址")
@Size(max = 500, message = "注册地址长度不能超过500个字符")
private String registerAddress;
@Schema(description = "法定代表人")
@Size(max = 100, message = "法定代表人长度不能超过100个字符")
private String legalRepresentative;
@Schema(description = "法定代表人证件类型")
@Size(max = 50, message = "法定代表人证件类型长度不能超过50个字符")
private String legalCertType;
@Schema(description = "法定代表人证件号码")
@Size(max = 50, message = "法定代表人证件号码长度不能超过50个字符")
private String legalCertNo;
@Schema(description = "股东1")
@Size(max = 100, message = "股东1长度不能超过100个字符")
private String shareholder1;
@Schema(description = "股东2")
@Size(max = 100, message = "股东2长度不能超过100个字符")
private String shareholder2;
@Schema(description = "股东3")
@Size(max = 100, message = "股东3长度不能超过100个字符")
private String shareholder3;
@Schema(description = "股东4")
@Size(max = 100, message = "股东4长度不能超过100个字符")
private String shareholder4;
@Schema(description = "股东5")
@Size(max = 100, message = "股东5长度不能超过100个字符")
private String shareholder5;
@Schema(description = "经营状态")
@NotBlank(message = "经营状态不能为空")
@Size(max = 50, message = "经营状态长度不能超过50个字符")
private String status;
@Schema(description = "风险等级")
@NotBlank(message = "风险等级不能为空")
private String riskLevel;
@Schema(description = "企业来源")
@NotBlank(message = "企业来源不能为空")
private String entSource;
@Schema(description = "数据来源")
@NotBlank(message = "数据来源不能为空")
private String dataSource;
}

View File

@@ -0,0 +1,107 @@
package com.ruoyi.info.collection.domain.dto;
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-04-17
*/
@Data
@Schema(description = "实体库管理编辑DTO")
public class CcdiEnterpriseBaseInfoEditDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "统一社会信用代码")
@NotBlank(message = "统一社会信用代码不能为空")
@Pattern(regexp = "^[0-9A-HJ-NPQRTUWXY]{2}\\d{6}[0-9A-HJ-NPQRTUWXY]{10}$", message = "统一社会信用代码格式不正确")
private String socialCreditCode;
@Schema(description = "企业名称")
@NotBlank(message = "企业名称不能为空")
@Size(max = 200, message = "企业名称长度不能超过200个字符")
private String enterpriseName;
@Schema(description = "企业类型")
@Size(max = 50, message = "企业类型长度不能超过50个字符")
private String enterpriseType;
@Schema(description = "企业性质")
@Size(max = 50, message = "企业性质长度不能超过50个字符")
private String enterpriseNature;
@Schema(description = "行业分类")
@Size(max = 100, message = "行业分类长度不能超过100个字符")
private String industryClass;
@Schema(description = "所属行业")
@Size(max = 100, message = "所属行业长度不能超过100个字符")
private String industryName;
@Schema(description = "成立日期")
private Date establishDate;
@Schema(description = "注册地址")
@Size(max = 500, message = "注册地址长度不能超过500个字符")
private String registerAddress;
@Schema(description = "法定代表人")
@Size(max = 100, message = "法定代表人长度不能超过100个字符")
private String legalRepresentative;
@Schema(description = "法定代表人证件类型")
@Size(max = 50, message = "法定代表人证件类型长度不能超过50个字符")
private String legalCertType;
@Schema(description = "法定代表人证件号码")
@Size(max = 50, message = "法定代表人证件号码长度不能超过50个字符")
private String legalCertNo;
@Schema(description = "股东1")
@Size(max = 100, message = "股东1长度不能超过100个字符")
private String shareholder1;
@Schema(description = "股东2")
@Size(max = 100, message = "股东2长度不能超过100个字符")
private String shareholder2;
@Schema(description = "股东3")
@Size(max = 100, message = "股东3长度不能超过100个字符")
private String shareholder3;
@Schema(description = "股东4")
@Size(max = 100, message = "股东4长度不能超过100个字符")
private String shareholder4;
@Schema(description = "股东5")
@Size(max = 100, message = "股东5长度不能超过100个字符")
private String shareholder5;
@Schema(description = "经营状态")
@NotBlank(message = "经营状态不能为空")
@Size(max = 50, message = "经营状态长度不能超过50个字符")
private String status;
@Schema(description = "风险等级")
@NotBlank(message = "风险等级不能为空")
private String riskLevel;
@Schema(description = "企业来源")
@NotBlank(message = "企业来源不能为空")
private String entSource;
@Schema(description = "数据来源")
@NotBlank(message = "数据来源不能为空")
private String dataSource;
}

View File

@@ -0,0 +1,45 @@
package com.ruoyi.info.collection.domain.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 实体库管理查询 DTO
*
* @author ruoyi
* @date 2026-04-17
*/
@Data
@Schema(description = "实体库管理查询DTO")
public class CcdiEnterpriseBaseInfoQueryDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "企业名称")
private String enterpriseName;
@Schema(description = "统一社会信用代码")
private String socialCreditCode;
@Schema(description = "企业类型")
private String enterpriseType;
@Schema(description = "企业性质")
private String enterpriseNature;
@Schema(description = "行业分类")
private String industryClass;
@Schema(description = "经营状态")
private String status;
@Schema(description = "风险等级")
private String riskLevel;
@Schema(description = "企业来源")
private String entSource;
}

View File

@@ -0,0 +1,33 @@
package com.ruoyi.info.collection.domain.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 中介关联机构新增DTO
*/
@Data
@Schema(description = "中介关联机构新增DTO")
public class CcdiIntermediaryEnterpriseRelationAddDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "统一社会信用代码")
@NotBlank(message = "统一社会信用代码不能为空")
@Size(max = 18, message = "统一社会信用代码长度不能超过18个字符")
private String socialCreditCode;
@Schema(description = "关联角色/职务")
@Size(max = 100, message = "关联角色/职务长度不能超过100个字符")
private String relationPersonPost;
@Schema(description = "备注")
@Size(max = 500, message = "备注长度不能超过500个字符")
private String remark;
}

View File

@@ -0,0 +1,38 @@
package com.ruoyi.info.collection.domain.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 中介关联机构编辑DTO
*/
@Data
@Schema(description = "中介关联机构编辑DTO")
public class CcdiIntermediaryEnterpriseRelationEditDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "主键ID")
@NotNull(message = "主键ID不能为空")
private Long id;
@Schema(description = "统一社会信用代码")
@NotBlank(message = "统一社会信用代码不能为空")
@Size(max = 18, message = "统一社会信用代码长度不能超过18个字符")
private String socialCreditCode;
@Schema(description = "关联角色/职务")
@Size(max = 100, message = "关联角色/职务长度不能超过100个字符")
private String relationPersonPost;
@Schema(description = "备注")
@Size(max = 500, message = "备注长度不能超过500个字符")
private String remark;
}

View File

@@ -0,0 +1,72 @@
package com.ruoyi.info.collection.domain.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 中介亲属新增DTO
*/
@Data
@Schema(description = "中介亲属新增DTO")
public class CcdiIntermediaryRelativeAddDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "姓名")
@NotBlank(message = "姓名不能为空")
@Size(max = 100, message = "姓名长度不能超过100个字符")
private String name;
@Schema(description = "人员类型")
private String personType;
@Schema(description = "亲属关系")
@NotBlank(message = "亲属关系不能为空")
@Size(max = 50, message = "亲属关系长度不能超过50个字符")
private String personSubType;
@Schema(description = "性别")
private String gender;
@Schema(description = "证件类型")
private String idType;
@Schema(description = "证件号码")
@NotBlank(message = "证件号码不能为空")
@Size(max = 50, message = "证件号码长度不能超过50个字符")
private String personId;
@Schema(description = "手机号码")
@Size(max = 20, message = "手机号码长度不能超过20个字符")
private String mobile;
@Schema(description = "微信号")
@Size(max = 50, message = "微信号长度不能超过50个字符")
private String wechatNo;
@Schema(description = "联系地址")
@Size(max = 200, message = "联系地址长度不能超过200个字符")
private String contactAddress;
@Schema(description = "所在公司")
@Size(max = 200, message = "所在公司长度不能超过200个字符")
private String company;
@Schema(description = "企业统一信用码")
@Size(max = 50, message = "企业统一信用码长度不能超过50个字符")
private String socialCreditCode;
@Schema(description = "职位")
@Size(max = 100, message = "职位长度不能超过100个字符")
private String position;
@Schema(description = "备注")
@Size(max = 500, message = "备注长度不能超过500个字符")
private String remark;
}

View File

@@ -0,0 +1,75 @@
package com.ruoyi.info.collection.domain.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 中介亲属编辑DTO
*/
@Data
@Schema(description = "中介亲属编辑DTO")
public class CcdiIntermediaryRelativeEditDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "人员ID")
@NotBlank(message = "人员ID不能为空")
private String bizId;
@Schema(description = "姓名")
@NotBlank(message = "姓名不能为空")
@Size(max = 100, message = "姓名长度不能超过100个字符")
private String name;
@Schema(description = "人员类型")
private String personType;
@Schema(description = "亲属关系")
@NotBlank(message = "亲属关系不能为空")
@Size(max = 50, message = "亲属关系长度不能超过50个字符")
private String personSubType;
@Schema(description = "性别")
private String gender;
@Schema(description = "证件类型")
private String idType;
@Schema(description = "证件号码")
@Size(max = 50, message = "证件号码长度不能超过50个字符")
private String personId;
@Schema(description = "手机号码")
@Size(max = 20, message = "手机号码长度不能超过20个字符")
private String mobile;
@Schema(description = "微信号")
@Size(max = 50, message = "微信号长度不能超过50个字符")
private String wechatNo;
@Schema(description = "联系地址")
@Size(max = 200, message = "联系地址长度不能超过200个字符")
private String contactAddress;
@Schema(description = "所在公司")
@Size(max = 200, message = "所在公司长度不能超过200个字符")
private String company;
@Schema(description = "企业统一信用码")
@Size(max = 50, message = "企业统一信用码长度不能超过50个字符")
private String socialCreditCode;
@Schema(description = "职位")
@Size(max = 100, message = "职位长度不能超过100个字符")
private String position;
@Schema(description = "备注")
@Size(max = 500, message = "备注长度不能超过500个字符")
private String remark;
}

View File

@@ -0,0 +1,106 @@
package com.ruoyi.info.collection.domain.excel;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.ruoyi.common.annotation.DictDropdown;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 实体库管理 Excel 导入模板对象
*
* @author ruoyi
* @date 2026-04-17
*/
@Data
public class CcdiEnterpriseBaseInfoExcel implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ExcelProperty(value = "统一社会信用代码*", index = 0)
@ColumnWidth(24)
private String socialCreditCode;
@ExcelProperty(value = "企业名称*", index = 1)
@ColumnWidth(30)
private String enterpriseName;
@ExcelProperty(value = "企业类型", index = 2)
@ColumnWidth(18)
@DictDropdown(dictType = "ccdi_entity_type")
private String enterpriseType;
@ExcelProperty(value = "企业性质", index = 3)
@ColumnWidth(18)
@DictDropdown(dictType = "ccdi_enterprise_nature")
private String enterpriseNature;
@ExcelProperty(value = "行业分类", index = 4)
@ColumnWidth(18)
private String industryClass;
@ExcelProperty(value = "所属行业", index = 5)
@ColumnWidth(18)
private String industryName;
@ExcelProperty(value = "成立日期", index = 6)
@ColumnWidth(16)
private Date establishDate;
@ExcelProperty(value = "注册地址", index = 7)
@ColumnWidth(36)
private String registerAddress;
@ExcelProperty(value = "法定代表人", index = 8)
@ColumnWidth(18)
private String legalRepresentative;
@ExcelProperty(value = "法定代表人证件类型", index = 9)
@ColumnWidth(22)
@DictDropdown(dictType = "ccdi_certificate_type")
private String legalCertType;
@ExcelProperty(value = "法定代表人证件号码", index = 10)
@ColumnWidth(24)
private String legalCertNo;
@ExcelProperty(value = "股东1", index = 11)
@ColumnWidth(18)
private String shareholder1;
@ExcelProperty(value = "股东2", index = 12)
@ColumnWidth(18)
private String shareholder2;
@ExcelProperty(value = "股东3", index = 13)
@ColumnWidth(18)
private String shareholder3;
@ExcelProperty(value = "股东4", index = 14)
@ColumnWidth(18)
private String shareholder4;
@ExcelProperty(value = "股东5", index = 15)
@ColumnWidth(18)
private String shareholder5;
@ExcelProperty(value = "经营状态*", index = 16)
@ColumnWidth(16)
private String status;
@ExcelProperty(value = "风险等级*", index = 17)
@ColumnWidth(16)
private String riskLevel;
@ExcelProperty(value = "企业来源*", index = 18)
@ColumnWidth(18)
private String entSource;
@ExcelProperty(value = "数据来源*", index = 19)
@ColumnWidth(18)
private String dataSource;
}

View File

@@ -0,0 +1,85 @@
package com.ruoyi.info.collection.domain.vo;
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-04-17
*/
@Data
@Schema(description = "实体库管理VO")
public class CcdiEnterpriseBaseInfoVO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "统一社会信用代码")
private String socialCreditCode;
@Schema(description = "企业名称")
private String enterpriseName;
@Schema(description = "企业类型")
private String enterpriseType;
@Schema(description = "企业性质")
private String enterpriseNature;
@Schema(description = "行业分类")
private String industryClass;
@Schema(description = "所属行业")
private String industryName;
@Schema(description = "成立日期")
private Date establishDate;
@Schema(description = "注册地址")
private String registerAddress;
@Schema(description = "法定代表人")
private String legalRepresentative;
@Schema(description = "法定代表人证件类型")
private String legalCertType;
@Schema(description = "法定代表人证件号码")
private String legalCertNo;
@Schema(description = "股东1")
private String shareholder1;
@Schema(description = "股东2")
private String shareholder2;
@Schema(description = "股东3")
private String shareholder3;
@Schema(description = "股东4")
private String shareholder4;
@Schema(description = "股东5")
private String shareholder5;
@Schema(description = "经营状态")
private String status;
@Schema(description = "风险等级")
private String riskLevel;
@Schema(description = "企业来源")
private String entSource;
@Schema(description = "数据来源")
private String dataSource;
@Schema(description = "创建时间")
private Date createTime;
}

View File

@@ -0,0 +1,48 @@
package com.ruoyi.info.collection.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
*/
@Data
@Schema(description = "中介关联机构VO")
public class CcdiIntermediaryEnterpriseRelationVO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "主键ID")
private Long id;
@Schema(description = "所属中介ID")
private String intermediaryBizId;
@Schema(description = "所属中介姓名")
private String intermediaryName;
@Schema(description = "所属中介证件号")
private String intermediaryPersonId;
@Schema(description = "统一社会信用代码")
private String socialCreditCode;
@Schema(description = "机构名称")
private String enterpriseName;
@Schema(description = "关联角色/职务")
private String relationPersonPost;
@Schema(description = "备注")
private String remark;
@Schema(description = "创建时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
}

View File

@@ -0,0 +1,69 @@
package com.ruoyi.info.collection.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
*/
@Data
@Schema(description = "中介亲属VO")
public class CcdiIntermediaryRelativeVO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "人员ID")
private String bizId;
@Schema(description = "所属中介ID")
private String relatedNumId;
@Schema(description = "姓名")
private String name;
@Schema(description = "人员类型")
private String personType;
@Schema(description = "亲属关系")
private String personSubType;
@Schema(description = "性别")
private String gender;
@Schema(description = "证件类型")
private String idType;
@Schema(description = "证件号码")
private String personId;
@Schema(description = "手机号码")
private String mobile;
@Schema(description = "微信号")
private String wechatNo;
@Schema(description = "联系地址")
private String contactAddress;
@Schema(description = "所在公司")
private String company;
@Schema(description = "企业统一信用码")
private String socialCreditCode;
@Schema(description = "职位")
private String position;
@Schema(description = "备注")
private String remark;
@Schema(description = "创建时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
}

View File

@@ -0,0 +1,51 @@
package com.ruoyi.info.collection.domain.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 实体库导入失败记录 VO
*
* @author ruoyi
* @date 2026-04-17
*/
@Data
@Schema(description = "实体库导入失败记录")
public class EnterpriseBaseInfoImportFailureVO {
@Schema(description = "企业名称")
private String enterpriseName;
@Schema(description = "统一社会信用代码")
private String socialCreditCode;
@Schema(description = "企业类型")
private String enterpriseType;
@Schema(description = "企业性质")
private String enterpriseNature;
@Schema(description = "行业分类")
private String industryClass;
@Schema(description = "所属行业")
private String industryName;
@Schema(description = "法定代表人")
private String legalRepresentative;
@Schema(description = "经营状态")
private String status;
@Schema(description = "风险等级")
private String riskLevel;
@Schema(description = "企业来源")
private String entSource;
@Schema(description = "数据来源")
private String dataSource;
@Schema(description = "错误信息")
private String errorMessage;
}

View File

@@ -0,0 +1,56 @@
package com.ruoyi.info.collection.enums;
/**
* 实体风险等级枚举
*
* @author ruoyi
*/
public enum EnterpriseRiskLevel {
HIGH("1", "高风险"),
MEDIUM("2", "中风险"),
LOW("3", "低风险");
private final String code;
private final String desc;
EnterpriseRiskLevel(String code, String desc) {
this.code = code;
this.desc = desc;
}
public String getCode() {
return code;
}
public String getDesc() {
return desc;
}
public static String getDescByCode(String code) {
for (EnterpriseRiskLevel value : values()) {
if (value.code.equals(code)) {
return value.desc;
}
}
return null;
}
public static boolean contains(String code) {
for (EnterpriseRiskLevel value : values()) {
if (value.code.equals(code)) {
return true;
}
}
return false;
}
public static String resolveCode(String value) {
for (EnterpriseRiskLevel item : values()) {
if (item.code.equals(value) || item.desc.equals(value)) {
return item.code;
}
}
return null;
}
}

View File

@@ -0,0 +1,58 @@
package com.ruoyi.info.collection.enums;
/**
* 企业来源枚举
*
* @author ruoyi
*/
public enum EnterpriseSource {
GENERAL("GENERAL", "一般企业"),
EMP_RELATION("EMP_RELATION", "员工关系人"),
CREDIT_CUSTOMER("CREDIT_CUSTOMER", "信贷客户"),
INTERMEDIARY("INTERMEDIARY", "中介"),
BOTH("BOTH", "兼有");
private final String code;
private final String desc;
EnterpriseSource(String code, String desc) {
this.code = code;
this.desc = desc;
}
public String getCode() {
return code;
}
public String getDesc() {
return desc;
}
public static String getDescByCode(String code) {
for (EnterpriseSource value : values()) {
if (value.code.equals(code)) {
return value.desc;
}
}
return null;
}
public static boolean contains(String code) {
for (EnterpriseSource value : values()) {
if (value.code.equals(code)) {
return true;
}
}
return false;
}
public static String resolveCode(String value) {
for (EnterpriseSource item : values()) {
if (item.code.equals(value) || item.desc.equals(value)) {
return item.code;
}
}
return null;
}
}

View File

@@ -1,7 +1,10 @@
package com.ruoyi.info.collection.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.info.collection.domain.CcdiEnterpriseBaseInfo;
import com.ruoyi.info.collection.domain.dto.CcdiEnterpriseBaseInfoQueryDTO;
import com.ruoyi.info.collection.domain.vo.CcdiEnterpriseBaseInfoVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@@ -16,6 +19,16 @@ import java.util.List;
@Mapper
public interface CcdiEnterpriseBaseInfoMapper extends BaseMapper<CcdiEnterpriseBaseInfo> {
/**
* 分页查询实体库列表
*
* @param page 分页参数
* @param queryDTO 查询条件
* @return 分页结果
*/
Page<CcdiEnterpriseBaseInfoVO> selectEnterpriseBaseInfoPage(Page<CcdiEnterpriseBaseInfoVO> page,
@Param("queryDTO") CcdiEnterpriseBaseInfoQueryDTO queryDTO);
/**
* 批量插入实体中介
*

View File

@@ -0,0 +1,23 @@
package com.ruoyi.info.collection.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.info.collection.domain.CcdiIntermediaryEnterpriseRelation;
import com.ruoyi.info.collection.domain.vo.CcdiIntermediaryEnterpriseRelationVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 中介关联机构关系Mapper
*/
@Mapper
public interface CcdiIntermediaryEnterpriseRelationMapper extends BaseMapper<CcdiIntermediaryEnterpriseRelation> {
List<CcdiIntermediaryEnterpriseRelationVO> selectByIntermediaryBizId(@Param("bizId") String bizId);
CcdiIntermediaryEnterpriseRelationVO selectDetailById(@Param("id") Long id);
boolean existsByIntermediaryBizIdAndSocialCreditCode(@Param("bizId") String bizId,
@Param("socialCreditCode") String socialCreditCode);
}

View File

@@ -0,0 +1,29 @@
package com.ruoyi.info.collection.service;
import com.ruoyi.info.collection.domain.CcdiEnterpriseBaseInfo;
import com.ruoyi.info.collection.domain.excel.CcdiEnterpriseBaseInfoExcel;
import com.ruoyi.info.collection.domain.vo.EnterpriseBaseInfoImportFailureVO;
import com.ruoyi.info.collection.domain.vo.ImportStatusVO;
import java.util.List;
import java.util.Set;
/**
* 实体库管理导入 Service 接口
*
* @author ruoyi
* @date 2026-04-17
*/
public interface ICcdiEnterpriseBaseInfoImportService {
void importEnterpriseBaseInfoAsync(List<CcdiEnterpriseBaseInfoExcel> excelList, String taskId, String userName);
ImportStatusVO getImportStatus(String taskId);
List<EnterpriseBaseInfoImportFailureVO> getImportFailures(String taskId);
CcdiEnterpriseBaseInfo validateAndBuildEntity(CcdiEnterpriseBaseInfoExcel excel,
Set<String> existingCreditCodes,
Set<String> processedCreditCodes,
String userName);
}

View File

@@ -0,0 +1,34 @@
package com.ruoyi.info.collection.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.info.collection.domain.dto.CcdiEnterpriseBaseInfoAddDTO;
import com.ruoyi.info.collection.domain.dto.CcdiEnterpriseBaseInfoEditDTO;
import com.ruoyi.info.collection.domain.dto.CcdiEnterpriseBaseInfoQueryDTO;
import com.ruoyi.info.collection.domain.excel.CcdiEnterpriseBaseInfoExcel;
import com.ruoyi.info.collection.domain.vo.CcdiEnterpriseBaseInfoVO;
import java.util.List;
/**
* 实体库管理 Service 接口
*
* @author ruoyi
* @date 2026-04-17
*/
public interface ICcdiEnterpriseBaseInfoService {
Page<CcdiEnterpriseBaseInfoVO> selectEnterpriseBaseInfoPage(Page<CcdiEnterpriseBaseInfoVO> page,
CcdiEnterpriseBaseInfoQueryDTO queryDTO);
CcdiEnterpriseBaseInfoVO selectEnterpriseBaseInfoById(String socialCreditCode);
int insertEnterpriseBaseInfo(CcdiEnterpriseBaseInfoAddDTO addDTO);
int updateEnterpriseBaseInfo(CcdiEnterpriseBaseInfoEditDTO editDTO);
int deleteEnterpriseBaseInfoByIds(String[] socialCreditCodes);
List<CcdiEnterpriseBaseInfoExcel> selectEnterpriseBaseInfoListForExport(CcdiEnterpriseBaseInfoQueryDTO queryDTO);
String importEnterpriseBaseInfo(List<CcdiEnterpriseBaseInfoExcel> excelList);
}

View File

@@ -0,0 +1,225 @@
package com.ruoyi.info.collection.service.impl;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.info.collection.domain.CcdiEnterpriseBaseInfo;
import com.ruoyi.info.collection.domain.excel.CcdiEnterpriseBaseInfoExcel;
import com.ruoyi.info.collection.domain.vo.EnterpriseBaseInfoImportFailureVO;
import com.ruoyi.info.collection.domain.vo.ImportResult;
import com.ruoyi.info.collection.domain.vo.ImportStatusVO;
import com.ruoyi.info.collection.enums.DataSource;
import com.ruoyi.info.collection.enums.EnterpriseRiskLevel;
import com.ruoyi.info.collection.enums.EnterpriseSource;
import com.ruoyi.info.collection.mapper.CcdiEnterpriseBaseInfoMapper;
import com.ruoyi.info.collection.service.ICcdiEnterpriseBaseInfoImportService;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* 实体库管理导入 Service 实现
*
* @author ruoyi
* @date 2026-04-17
*/
@Service
@EnableAsync
public class CcdiEnterpriseBaseInfoImportServiceImpl implements ICcdiEnterpriseBaseInfoImportService {
@Resource
private CcdiEnterpriseBaseInfoMapper enterpriseBaseInfoMapper;
@Resource
private RedisTemplate<String, Object> redisTemplate;
@Override
@Async
public void importEnterpriseBaseInfoAsync(List<CcdiEnterpriseBaseInfoExcel> excelList, String taskId, String userName) {
List<CcdiEnterpriseBaseInfo> successRecords = new ArrayList<>();
List<EnterpriseBaseInfoImportFailureVO> failures = new ArrayList<>();
Set<String> existingCreditCodes = getExistingCreditCodes(excelList);
Set<String> processedCreditCodes = new HashSet<>();
for (CcdiEnterpriseBaseInfoExcel excel : excelList) {
try {
CcdiEnterpriseBaseInfo entity = validateAndBuildEntity(excel, existingCreditCodes, processedCreditCodes, userName);
successRecords.add(entity);
processedCreditCodes.add(entity.getSocialCreditCode());
} catch (Exception e) {
EnterpriseBaseInfoImportFailureVO failureVO = new EnterpriseBaseInfoImportFailureVO();
BeanUtils.copyProperties(excel, failureVO);
failureVO.setErrorMessage(e.getMessage());
failures.add(failureVO);
}
}
if (!successRecords.isEmpty()) {
saveBatch(successRecords, 500);
}
if (!failures.isEmpty()) {
redisTemplate.opsForValue().set(buildFailuresKey(taskId), failures, 7, TimeUnit.DAYS);
}
ImportResult result = new ImportResult();
result.setTotalCount(excelList.size());
result.setSuccessCount(successRecords.size());
result.setFailureCount(failures.size());
updateImportStatus(taskId, failures.isEmpty() ? "SUCCESS" : "PARTIAL_SUCCESS", result);
}
@Override
public ImportStatusVO getImportStatus(String taskId) {
String key = buildStatusKey(taskId);
Boolean exists = redisTemplate.hasKey(key);
if (Boolean.FALSE.equals(exists)) {
throw new RuntimeException("任务不存在或已过期");
}
Map<Object, Object> statusMap = redisTemplate.opsForHash().entries(key);
ImportStatusVO statusVO = new ImportStatusVO();
statusVO.setTaskId((String) statusMap.get("taskId"));
statusVO.setStatus((String) statusMap.get("status"));
statusVO.setTotalCount((Integer) statusMap.get("totalCount"));
statusVO.setSuccessCount((Integer) statusMap.get("successCount"));
statusVO.setFailureCount((Integer) statusMap.get("failureCount"));
statusVO.setProgress((Integer) statusMap.get("progress"));
statusVO.setStartTime((Long) statusMap.get("startTime"));
statusVO.setEndTime((Long) statusMap.get("endTime"));
statusVO.setMessage((String) statusMap.get("message"));
return statusVO;
}
@Override
public List<EnterpriseBaseInfoImportFailureVO> getImportFailures(String taskId) {
Object failuresObj = redisTemplate.opsForValue().get(buildFailuresKey(taskId));
if (failuresObj == null) {
return Collections.emptyList();
}
return JSON.parseArray(JSON.toJSONString(failuresObj), EnterpriseBaseInfoImportFailureVO.class);
}
@Override
public CcdiEnterpriseBaseInfo validateAndBuildEntity(CcdiEnterpriseBaseInfoExcel excel,
Set<String> existingCreditCodes,
Set<String> processedCreditCodes,
String userName) {
if (excel == null) {
throw new RuntimeException("导入数据不能为空");
}
if (StringUtils.isEmpty(excel.getEnterpriseName())) {
throw new RuntimeException("企业名称不能为空");
}
if (StringUtils.isEmpty(excel.getSocialCreditCode())) {
throw new RuntimeException("统一社会信用代码不能为空");
}
if (!excel.getSocialCreditCode().matches("^[0-9A-HJ-NPQRTUWXY]{2}\\d{6}[0-9A-HJ-NPQRTUWXY]{10}$")) {
throw new RuntimeException("统一社会信用代码格式不正确");
}
if (StringUtils.isEmpty(excel.getStatus())) {
throw new RuntimeException("经营状态不能为空");
}
String riskLevel = EnterpriseRiskLevel.resolveCode(StringUtils.trim(excel.getRiskLevel()));
if (riskLevel == null) {
throw new RuntimeException("风险等级不在允许范围内");
}
String entSource = EnterpriseSource.resolveCode(StringUtils.trim(excel.getEntSource()));
if (entSource == null) {
throw new RuntimeException("企业来源不在允许范围内");
}
String dataSource = resolveDataSourceCode(StringUtils.trim(excel.getDataSource()));
if (dataSource == null) {
throw new RuntimeException("数据来源不在允许范围内");
}
if (existingCreditCodes.contains(excel.getSocialCreditCode())) {
throw new RuntimeException(String.format("统一社会信用代码[%s]已存在,请勿重复导入", excel.getSocialCreditCode()));
}
if (processedCreditCodes.contains(excel.getSocialCreditCode())) {
throw new RuntimeException(String.format("统一社会信用代码[%s]在导入文件中重复,已跳过此条记录", excel.getSocialCreditCode()));
}
CcdiEnterpriseBaseInfo entity = new CcdiEnterpriseBaseInfo();
BeanUtils.copyProperties(excel, entity);
entity.setRiskLevel(riskLevel);
entity.setEntSource(entSource);
entity.setDataSource(dataSource);
entity.setStatus(StringUtils.trim(excel.getStatus()));
entity.setCreatedBy(userName);
entity.setUpdatedBy(userName);
return entity;
}
private Set<String> getExistingCreditCodes(List<CcdiEnterpriseBaseInfoExcel> excelList) {
List<String> creditCodes = excelList.stream()
.map(CcdiEnterpriseBaseInfoExcel::getSocialCreditCode)
.filter(StringUtils::isNotEmpty)
.collect(Collectors.toList());
if (creditCodes.isEmpty()) {
return Collections.emptySet();
}
LambdaQueryWrapper<CcdiEnterpriseBaseInfo> wrapper = new LambdaQueryWrapper<>();
wrapper.in(CcdiEnterpriseBaseInfo::getSocialCreditCode, creditCodes);
return enterpriseBaseInfoMapper.selectList(wrapper).stream()
.map(CcdiEnterpriseBaseInfo::getSocialCreditCode)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
}
private int saveBatch(List<CcdiEnterpriseBaseInfo> list, int batchSize) {
int total = 0;
for (int i = 0; i < list.size(); i += batchSize) {
int end = Math.min(i + batchSize, list.size());
total += enterpriseBaseInfoMapper.insertBatch(list.subList(i, end));
}
return total;
}
private void updateImportStatus(String taskId, String status, ImportResult result) {
Map<String, Object> statusData = new HashMap<>();
statusData.put("status", status);
statusData.put("successCount", result.getSuccessCount());
statusData.put("failureCount", result.getFailureCount());
statusData.put("progress", 100);
statusData.put("endTime", System.currentTimeMillis());
if ("SUCCESS".equals(status)) {
statusData.put("message", "全部成功!共导入" + result.getTotalCount() + "条数据");
} else {
statusData.put("message", "成功" + result.getSuccessCount() + "条,失败" + result.getFailureCount() + "");
}
redisTemplate.opsForHash().putAll(buildStatusKey(taskId), statusData);
}
private String resolveDataSourceCode(String value) {
for (DataSource source : DataSource.values()) {
if (source.getCode().equals(value) || source.getDesc().equals(value)) {
return source.getCode();
}
}
return null;
}
private String buildStatusKey(String taskId) {
return "import:enterpriseBaseInfo:" + taskId;
}
private String buildFailuresKey(String taskId) {
return "import:enterpriseBaseInfo:" + taskId + ":failures";
}
}

View File

@@ -0,0 +1,182 @@
package com.ruoyi.info.collection.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.info.collection.domain.CcdiEnterpriseBaseInfo;
import com.ruoyi.info.collection.domain.dto.CcdiEnterpriseBaseInfoAddDTO;
import com.ruoyi.info.collection.domain.dto.CcdiEnterpriseBaseInfoEditDTO;
import com.ruoyi.info.collection.domain.dto.CcdiEnterpriseBaseInfoQueryDTO;
import com.ruoyi.info.collection.domain.excel.CcdiEnterpriseBaseInfoExcel;
import com.ruoyi.info.collection.domain.vo.CcdiEnterpriseBaseInfoVO;
import com.ruoyi.info.collection.enums.DataSource;
import com.ruoyi.info.collection.enums.EnterpriseRiskLevel;
import com.ruoyi.info.collection.enums.EnterpriseSource;
import com.ruoyi.info.collection.mapper.CcdiEnterpriseBaseInfoMapper;
import com.ruoyi.info.collection.service.ICcdiEnterpriseBaseInfoImportService;
import com.ruoyi.info.collection.service.ICcdiEnterpriseBaseInfoService;
import jakarta.annotation.Resource;
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.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
/**
* 实体库管理 Service 实现
*
* @author ruoyi
* @date 2026-04-17
*/
@Service
public class CcdiEnterpriseBaseInfoServiceImpl implements ICcdiEnterpriseBaseInfoService {
@Resource
private CcdiEnterpriseBaseInfoMapper enterpriseBaseInfoMapper;
@Resource
private ICcdiEnterpriseBaseInfoImportService enterpriseBaseInfoImportService;
@Resource
private RedisTemplate<String, Object> redisTemplate;
@Override
public Page<CcdiEnterpriseBaseInfoVO> selectEnterpriseBaseInfoPage(Page<CcdiEnterpriseBaseInfoVO> page,
CcdiEnterpriseBaseInfoQueryDTO queryDTO) {
return enterpriseBaseInfoMapper.selectEnterpriseBaseInfoPage(page, queryDTO);
}
@Override
public CcdiEnterpriseBaseInfoVO selectEnterpriseBaseInfoById(String socialCreditCode) {
CcdiEnterpriseBaseInfo entity = enterpriseBaseInfoMapper.selectById(socialCreditCode);
if (entity == null) {
return null;
}
CcdiEnterpriseBaseInfoVO vo = new CcdiEnterpriseBaseInfoVO();
BeanUtils.copyProperties(entity, vo);
return vo;
}
@Override
@Transactional
public int insertEnterpriseBaseInfo(CcdiEnterpriseBaseInfoAddDTO addDTO) {
if (enterpriseBaseInfoMapper.selectById(addDTO.getSocialCreditCode()) != null) {
throw new RuntimeException("该统一社会信用代码已存在");
}
validateEnumFields(addDTO.getStatus(), addDTO.getRiskLevel(), addDTO.getEntSource(), addDTO.getDataSource());
CcdiEnterpriseBaseInfo entity = new CcdiEnterpriseBaseInfo();
BeanUtils.copyProperties(addDTO, entity);
return enterpriseBaseInfoMapper.insert(entity);
}
@Override
@Transactional
public int updateEnterpriseBaseInfo(CcdiEnterpriseBaseInfoEditDTO editDTO) {
CcdiEnterpriseBaseInfo existing = enterpriseBaseInfoMapper.selectById(editDTO.getSocialCreditCode());
if (existing == null) {
throw new RuntimeException("实体库记录不存在");
}
validateEnumFields(editDTO.getStatus(), editDTO.getRiskLevel(), editDTO.getEntSource(), editDTO.getDataSource());
CcdiEnterpriseBaseInfo entity = new CcdiEnterpriseBaseInfo();
BeanUtils.copyProperties(editDTO, entity);
return enterpriseBaseInfoMapper.updateById(entity);
}
@Override
@Transactional
public int deleteEnterpriseBaseInfoByIds(String[] socialCreditCodes) {
if (socialCreditCodes == null || socialCreditCodes.length == 0) {
return 0;
}
return enterpriseBaseInfoMapper.deleteBatchIds(List.of(socialCreditCodes));
}
@Override
public List<CcdiEnterpriseBaseInfoExcel> selectEnterpriseBaseInfoListForExport(CcdiEnterpriseBaseInfoQueryDTO queryDTO) {
LambdaQueryWrapper<CcdiEnterpriseBaseInfo> wrapper = buildQueryWrapper(queryDTO);
return enterpriseBaseInfoMapper.selectList(wrapper).stream().map(entity -> {
CcdiEnterpriseBaseInfoExcel excel = new CcdiEnterpriseBaseInfoExcel();
BeanUtils.copyProperties(entity, excel);
return excel;
}).toList();
}
@Override
@Transactional
public String importEnterpriseBaseInfo(List<CcdiEnterpriseBaseInfoExcel> excelList) {
String taskId = UUID.randomUUID().toString();
String statusKey = "import:enterpriseBaseInfo:" + taskId;
Map<String, Object> statusData = new HashMap<>();
statusData.put("taskId", taskId);
statusData.put("status", "PROCESSING");
statusData.put("totalCount", excelList.size());
statusData.put("successCount", 0);
statusData.put("failureCount", 0);
statusData.put("progress", 0);
statusData.put("startTime", System.currentTimeMillis());
statusData.put("message", "正在处理...");
redisTemplate.opsForHash().putAll(statusKey, statusData);
redisTemplate.expire(statusKey, 7, TimeUnit.DAYS);
enterpriseBaseInfoImportService.importEnterpriseBaseInfoAsync(excelList, taskId, SecurityUtils.getUsername());
return taskId;
}
private LambdaQueryWrapper<CcdiEnterpriseBaseInfo> buildQueryWrapper(CcdiEnterpriseBaseInfoQueryDTO queryDTO) {
LambdaQueryWrapper<CcdiEnterpriseBaseInfo> wrapper = new LambdaQueryWrapper<>();
if (queryDTO == null) {
return wrapper.orderByDesc(CcdiEnterpriseBaseInfo::getCreateTime);
}
wrapper.like(StringUtils.isNotEmpty(queryDTO.getEnterpriseName()),
CcdiEnterpriseBaseInfo::getEnterpriseName, queryDTO.getEnterpriseName());
wrapper.eq(StringUtils.isNotEmpty(queryDTO.getSocialCreditCode()),
CcdiEnterpriseBaseInfo::getSocialCreditCode, queryDTO.getSocialCreditCode());
wrapper.eq(StringUtils.isNotEmpty(queryDTO.getEnterpriseType()),
CcdiEnterpriseBaseInfo::getEnterpriseType, queryDTO.getEnterpriseType());
wrapper.eq(StringUtils.isNotEmpty(queryDTO.getEnterpriseNature()),
CcdiEnterpriseBaseInfo::getEnterpriseNature, queryDTO.getEnterpriseNature());
wrapper.like(StringUtils.isNotEmpty(queryDTO.getIndustryClass()),
CcdiEnterpriseBaseInfo::getIndustryClass, queryDTO.getIndustryClass());
wrapper.eq(StringUtils.isNotEmpty(queryDTO.getStatus()),
CcdiEnterpriseBaseInfo::getStatus, queryDTO.getStatus());
wrapper.eq(StringUtils.isNotEmpty(queryDTO.getRiskLevel()),
CcdiEnterpriseBaseInfo::getRiskLevel, queryDTO.getRiskLevel());
wrapper.eq(StringUtils.isNotEmpty(queryDTO.getEntSource()),
CcdiEnterpriseBaseInfo::getEntSource, queryDTO.getEntSource());
return wrapper.orderByDesc(CcdiEnterpriseBaseInfo::getCreateTime);
}
private void validateEnumFields(String status, String riskLevel, String entSource, String dataSource) {
if (StringUtils.isEmpty(status)) {
throw new RuntimeException("经营状态不能为空");
}
if (!EnterpriseRiskLevel.contains(riskLevel)) {
throw new RuntimeException("风险等级不在允许范围内");
}
if (!EnterpriseSource.contains(entSource)) {
throw new RuntimeException("企业来源不在允许范围内");
}
if (!containsDataSource(dataSource)) {
throw new RuntimeException("数据来源不在允许范围内");
}
}
private boolean containsDataSource(String code) {
for (DataSource source : DataSource.values()) {
if (source.getCode().equals(code)) {
return true;
}
}
return false;
}
}

View File

@@ -4,6 +4,83 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.info.collection.mapper.CcdiEnterpriseBaseInfoMapper">
<resultMap id="CcdiEnterpriseBaseInfoVoResultMap" type="com.ruoyi.info.collection.domain.vo.CcdiEnterpriseBaseInfoVO">
<id property="socialCreditCode" column="social_credit_code"/>
<result property="enterpriseName" column="enterprise_name"/>
<result property="enterpriseType" column="enterprise_type"/>
<result property="enterpriseNature" column="enterprise_nature"/>
<result property="industryClass" column="industry_class"/>
<result property="industryName" column="industry_name"/>
<result property="establishDate" column="establish_date"/>
<result property="registerAddress" column="register_address"/>
<result property="legalRepresentative" column="legal_representative"/>
<result property="legalCertType" column="legal_cert_type"/>
<result property="legalCertNo" column="legal_cert_no"/>
<result property="shareholder1" column="shareholder1"/>
<result property="shareholder2" column="shareholder2"/>
<result property="shareholder3" column="shareholder3"/>
<result property="shareholder4" column="shareholder4"/>
<result property="shareholder5" column="shareholder5"/>
<result property="status" column="status"/>
<result property="riskLevel" column="risk_level"/>
<result property="entSource" column="ent_source"/>
<result property="dataSource" column="data_source"/>
<result property="createTime" column="create_time"/>
</resultMap>
<select id="selectEnterpriseBaseInfoPage" resultMap="CcdiEnterpriseBaseInfoVoResultMap">
SELECT
social_credit_code,
enterprise_name,
enterprise_type,
enterprise_nature,
industry_class,
industry_name,
establish_date,
register_address,
legal_representative,
legal_cert_type,
legal_cert_no,
shareholder1,
shareholder2,
shareholder3,
shareholder4,
shareholder5,
status,
risk_level,
ent_source,
data_source,
create_time
FROM ccdi_enterprise_base_info
<where>
<if test="queryDTO != null and queryDTO.enterpriseName != null and queryDTO.enterpriseName != ''">
AND enterprise_name LIKE CONCAT('%', #{queryDTO.enterpriseName}, '%')
</if>
<if test="queryDTO != null and queryDTO.socialCreditCode != null and queryDTO.socialCreditCode != ''">
AND social_credit_code = #{queryDTO.socialCreditCode}
</if>
<if test="queryDTO != null and queryDTO.enterpriseType != null and queryDTO.enterpriseType != ''">
AND enterprise_type = #{queryDTO.enterpriseType}
</if>
<if test="queryDTO != null and queryDTO.enterpriseNature != null and queryDTO.enterpriseNature != ''">
AND enterprise_nature = #{queryDTO.enterpriseNature}
</if>
<if test="queryDTO != null and queryDTO.industryClass != null and queryDTO.industryClass != ''">
AND industry_class LIKE CONCAT('%', #{queryDTO.industryClass}, '%')
</if>
<if test="queryDTO != null and queryDTO.status != null and queryDTO.status != ''">
AND status = #{queryDTO.status}
</if>
<if test="queryDTO != null and queryDTO.riskLevel != null and queryDTO.riskLevel != ''">
AND risk_level = #{queryDTO.riskLevel}
</if>
<if test="queryDTO != null and queryDTO.entSource != null and queryDTO.entSource != ''">
AND ent_source = #{queryDTO.entSource}
</if>
</where>
ORDER BY create_time DESC
</select>
<!-- 批量插入实体中介 -->
<insert id="insertBatch" parameterType="java.util.List">
INSERT INTO ccdi_enterprise_base_info (
@@ -21,7 +98,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#{item.legalRepresentative}, #{item.legalCertType}, #{item.legalCertNo},
#{item.shareholder1}, #{item.shareholder2}, #{item.shareholder3}, #{item.shareholder4}, #{item.shareholder5},
#{item.status}, #{item.riskLevel}, #{item.entSource}, #{item.dataSource},
#{item.createdBy}, #{item.updatedBy}, #{item.createTime}, #{item.updateTime}
#{item.createdBy}, #{item.updatedBy}, NOW(), NOW()
)
</foreach>
</insert>
@@ -43,7 +120,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#{item.legalRepresentative}, #{item.legalCertType}, #{item.legalCertNo},
#{item.shareholder1}, #{item.shareholder2}, #{item.shareholder3}, #{item.shareholder4}, #{item.shareholder5},
#{item.status}, #{item.riskLevel}, #{item.entSource}, #{item.dataSource},
#{item.createdBy}, #{item.updatedBy}, #{item.createTime}, #{item.updateTime}
#{item.createdBy}, #{item.updatedBy}, NOW(), NOW()
)
</foreach>
ON DUPLICATE KEY UPDATE
@@ -67,7 +144,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
ent_source = VALUES(ent_source),
data_source = VALUES(data_source),
updated_by = VALUES(updated_by),
update_time = VALUES(update_time)
update_time = NOW()
</insert>
<!-- 批量更新实体中介 -->
@@ -95,7 +172,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="item.entSource != null">ent_source = #{item.entSource},</if>
<if test="item.dataSource != null">data_source = #{item.dataSource},</if>
<if test="item.updatedBy != null">updated_by = #{item.updatedBy},</if>
update_time = #{item.updateTime}
update_time = NOW()
</set>
WHERE social_credit_code = #{item.socialCreditCode}
</foreach>

View File

@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.info.collection.mapper.CcdiIntermediaryEnterpriseRelationMapper">
<resultMap id="CcdiIntermediaryEnterpriseRelationVOResult"
type="com.ruoyi.info.collection.domain.vo.CcdiIntermediaryEnterpriseRelationVO">
<id property="id" column="id"/>
<result property="intermediaryBizId" column="intermediary_biz_id"/>
<result property="intermediaryName" column="intermediary_name"/>
<result property="intermediaryPersonId" column="intermediary_person_id"/>
<result property="socialCreditCode" column="social_credit_code"/>
<result property="enterpriseName" column="enterprise_name"/>
<result property="relationPersonPost" column="relation_person_post"/>
<result property="remark" column="remark"/>
<result property="createTime" column="create_time"/>
</resultMap>
<select id="selectByIntermediaryBizId" resultMap="CcdiIntermediaryEnterpriseRelationVOResult">
SELECT
rel.id,
rel.intermediary_biz_id,
parent.name AS intermediary_name,
parent.person_id AS intermediary_person_id,
rel.social_credit_code,
ent.enterprise_name,
rel.relation_person_post,
rel.remark,
rel.create_time
FROM ccdi_intermediary_enterprise_relation rel
INNER JOIN ccdi_biz_intermediary parent
ON rel.intermediary_biz_id = parent.biz_id
LEFT JOIN ccdi_enterprise_base_info ent
ON rel.social_credit_code = ent.social_credit_code
WHERE rel.intermediary_biz_id = #{bizId}
ORDER BY rel.create_time DESC
</select>
<select id="selectDetailById" resultMap="CcdiIntermediaryEnterpriseRelationVOResult">
SELECT
rel.id,
rel.intermediary_biz_id,
parent.name AS intermediary_name,
parent.person_id AS intermediary_person_id,
rel.social_credit_code,
ent.enterprise_name,
rel.relation_person_post,
rel.remark,
rel.create_time
FROM ccdi_intermediary_enterprise_relation rel
INNER JOIN ccdi_biz_intermediary parent
ON rel.intermediary_biz_id = parent.biz_id
LEFT JOIN ccdi_enterprise_base_info ent
ON rel.social_credit_code = ent.social_credit_code
WHERE rel.id = #{id}
</select>
<select id="existsByIntermediaryBizIdAndSocialCreditCode" resultType="boolean">
SELECT COUNT(1) > 0
FROM ccdi_intermediary_enterprise_relation
WHERE intermediary_biz_id = #{bizId}
AND social_credit_code = #{socialCreditCode}
</select>
</mapper>