修复导入模板格式和必填标记

This commit is contained in:
wkc
2026-05-07 00:01:27 +08:00
parent 5980ed0790
commit 402a0c3e2f
22 changed files with 458 additions and 51 deletions

View File

@@ -2,6 +2,7 @@ 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.TextFormat;
import lombok.Data;
import java.io.Serial;
@@ -25,6 +26,7 @@ public class CcdiAccountInfoExcel implements Serializable {
@ExcelProperty(value = "证件号*", index = 1)
@ColumnWidth(24)
@TextFormat
private String ownerId;
@ExcelProperty(value = "账户姓名*", index = 2)
@@ -33,6 +35,7 @@ public class CcdiAccountInfoExcel implements Serializable {
@ExcelProperty(value = "账户号码*", index = 3)
@ColumnWidth(28)
@TextFormat
private String accountNo;
@ExcelProperty(value = "账户类型*", index = 4)
@@ -49,6 +52,7 @@ public class CcdiAccountInfoExcel implements Serializable {
@ExcelProperty(value = "银行代码", index = 7)
@ColumnWidth(16)
@TextFormat
private String bankCode;
@ExcelProperty(value = "币种", index = 8)

View File

@@ -26,14 +26,14 @@ public class CcdiBaseStaffAssetInfoExcel implements Serializable {
/** 员工身份证号 */
@ExcelProperty(value = "员工身份证号*", index = 0)
@ColumnWidth(22)
@ColumnWidth(24)
@Required
@TextFormat
private String personId;
/** 资产大类 */
@ExcelProperty(value = "资产大类*", index = 1)
@ColumnWidth(16)
@ColumnWidth(18)
@Required
private String assetMainType;
@@ -51,39 +51,39 @@ public class CcdiBaseStaffAssetInfoExcel implements Serializable {
/** 产权占比 */
@ExcelProperty(value = "产权占比", index = 4)
@ColumnWidth(12)
@ColumnWidth(14)
private BigDecimal ownershipRatio;
/** 购买/评估日期 */
@ExcelProperty(value = "购买/评估日期", index = 5)
@ColumnWidth(16)
@ColumnWidth(20)
private Date purchaseEvalDate;
/** 资产原值 */
@ExcelProperty(value = "资产原值", index = 6)
@ColumnWidth(16)
@ColumnWidth(18)
private BigDecimal originalValue;
/** 当前估值 */
@ExcelProperty(value = "当前估值*", index = 7)
@ColumnWidth(16)
@ColumnWidth(18)
@Required
private BigDecimal currentValue;
/** 估值截止日期 */
@ExcelProperty(value = "估值截止日期", index = 8)
@ColumnWidth(16)
@ColumnWidth(20)
private Date valuationDate;
/** 资产状态 */
@ExcelProperty(value = "资产状态*", index = 9)
@ColumnWidth(14)
@ColumnWidth(16)
@DictDropdown(dictType = "ccdi_asset_status")
@Required
private String assetStatus;
/** 备注 */
@ExcelProperty(value = "备注", index = 10)
@ColumnWidth(28)
@ColumnWidth(32)
private String remarks;
}

View File

@@ -4,6 +4,7 @@ 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 com.ruoyi.common.annotation.TextFormat;
import lombok.Data;
import java.io.Serial;
@@ -25,54 +26,56 @@ public class CcdiBaseStaffExcel implements Serializable {
/** 姓名 */
@ExcelProperty(value = "姓名", index = 0)
@ColumnWidth(15)
@ColumnWidth(16)
@Required
private String name;
/** 员工ID */
@ExcelProperty(value = "员工ID", index = 1)
@ColumnWidth(15)
@ColumnWidth(18)
@Required
private Long staffId;
/** 所属部门ID */
@ExcelProperty(value = "所属部门ID", index = 2)
@ColumnWidth(15)
@ColumnWidth(20)
@Required
private Long deptId;
/** 身份证号 */
@ExcelProperty(value = "身份证号", index = 3)
@ColumnWidth(20)
@ColumnWidth(24)
@Required
@TextFormat
private String idCard;
/** 电话 */
@ExcelProperty(value = "电话", index = 4)
@ColumnWidth(15)
@ColumnWidth(18)
@Required
@TextFormat
private String phone;
/** 年收入 */
@ExcelProperty(value = "年收入(元/年)", index = 5)
@ColumnWidth(18)
@ColumnWidth(20)
private BigDecimal annualIncome;
/** 入职时间 */
@ExcelProperty(value = "入职时间", index = 6)
@ColumnWidth(15)
@ColumnWidth(18)
private Date hireDate;
/** 是否党员 */
@ExcelProperty(value = "是否党员", index = 7)
@ColumnWidth(12)
@ColumnWidth(16)
@DictDropdown(dictType = "ccdi_yes_no_flag")
@Required
private Integer partyMember;
/** 状态 */
@ExcelProperty(value = "状态", index = 8)
@ColumnWidth(10)
@ColumnWidth(14)
@DictDropdown(dictType = "ccdi_employee_status")
@Required
private String status;

View File

@@ -3,6 +3,7 @@ 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.Required;
import com.ruoyi.common.annotation.TextFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@@ -26,6 +27,7 @@ public class CcdiCustEnterpriseRelationExcel implements Serializable {
@ExcelProperty(value = "身份证号", index = 0)
@ColumnWidth(20)
@Required
@TextFormat
@Schema(description = "身份证号")
private String personId;
@@ -33,6 +35,7 @@ public class CcdiCustEnterpriseRelationExcel implements Serializable {
@ExcelProperty(value = "统一社会信用代码", index = 1)
@ColumnWidth(25)
@Required
@TextFormat
@Schema(description = "统一社会信用代码")
private String socialCreditCode;

View File

@@ -4,6 +4,7 @@ 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 com.ruoyi.common.annotation.TextFormat;
import lombok.Data;
import java.io.Serial;
@@ -26,6 +27,7 @@ public class CcdiCustFmyRelationExcel implements Serializable {
@ExcelProperty(value = "信贷客户身份证号*", index = 0)
@ColumnWidth(20)
@Required
@TextFormat
private String personId;
/** 关系类型 */
@@ -63,16 +65,19 @@ public class CcdiCustFmyRelationExcel implements Serializable {
@ExcelProperty(value = "关系人证件号码*", index = 6)
@ColumnWidth(20)
@Required
@TextFormat
private String relationCertNo;
/** 手机号码1 */
@ExcelProperty(value = "手机号码1", index = 7)
@ColumnWidth(15)
@TextFormat
private String mobilePhone1;
/** 手机号码2 */
@ExcelProperty(value = "手机号码2", index = 8)
@ColumnWidth(15)
@TextFormat
private String mobilePhone2;
/** 微信名称1 */

View File

@@ -3,6 +3,7 @@ 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 com.ruoyi.common.annotation.TextFormat;
import lombok.Data;
import java.io.Serial;
@@ -23,6 +24,7 @@ public class CcdiEnterpriseBaseInfoExcel implements Serializable {
@ExcelProperty(value = "统一社会信用代码*", index = 0)
@ColumnWidth(24)
@TextFormat
private String socialCreditCode;
@ExcelProperty(value = "企业名称*", index = 1)
@@ -66,6 +68,7 @@ public class CcdiEnterpriseBaseInfoExcel implements Serializable {
@ExcelProperty(value = "法定代表人证件号码", index = 10)
@ColumnWidth(24)
@TextFormat
private String legalCertNo;
@ExcelProperty(value = "股东1", index = 11)

View File

@@ -3,6 +3,7 @@ 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.Required;
import com.ruoyi.common.annotation.TextFormat;
import lombok.Data;
import java.io.Serial;
@@ -21,12 +22,14 @@ public class CcdiIntermediaryEnterpriseRelationExcel implements Serializable {
@ExcelProperty(value = "中介本人证件号码", index = 0)
@ColumnWidth(24)
@Required
@TextFormat
private String ownerPersonId;
/** 统一社会信用代码 */
@ExcelProperty(value = "统一社会信用代码", index = 1)
@ColumnWidth(24)
@Required
@TextFormat
private String socialCreditCode;
/** 关联职务 */

View File

@@ -3,6 +3,7 @@ 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 com.ruoyi.common.annotation.TextFormat;
import lombok.Data;
import java.io.Serial;
@@ -29,6 +30,7 @@ public class CcdiIntermediaryEntityExcel implements Serializable {
/** 统一社会信用代码 */
@ExcelProperty(value = "统一社会信用代码*", index = 1)
@ColumnWidth(20)
@TextFormat
private String socialCreditCode;
/** 主体类型 */
@@ -77,6 +79,7 @@ public class CcdiIntermediaryEntityExcel implements Serializable {
/** 法定代表人证件号码 */
@ExcelProperty(value = "法定代表人证件号码", index = 10)
@ColumnWidth(20)
@TextFormat
private String legalCertNo;
/** 股东1 */

View File

@@ -3,6 +3,7 @@ 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 com.ruoyi.common.annotation.TextFormat;
import lombok.Data;
import java.io.Serial;
@@ -52,11 +53,13 @@ public class CcdiIntermediaryPersonExcel implements Serializable {
/** 证件号码 */
@ExcelProperty(value = "证件号码*", index = 5)
@ColumnWidth(20)
@TextFormat
private String personId;
/** 手机号码 */
@ExcelProperty(value = "手机号码", index = 6)
@ColumnWidth(15)
@TextFormat
private String mobile;
/** 微信号 */
@@ -77,6 +80,7 @@ public class CcdiIntermediaryPersonExcel implements Serializable {
/** 企业统一信用码 */
@ExcelProperty(value = "企业统一信用码", index = 10)
@ColumnWidth(20)
@TextFormat
private String socialCreditCode;
/** 职位 */
@@ -87,6 +91,7 @@ public class CcdiIntermediaryPersonExcel implements Serializable {
/** 关联中介本人证件号码 */
@ExcelProperty(value = "关联中介本人证件号码", index = 12)
@ColumnWidth(24)
@TextFormat
private String relatedNumId;
/** 备注 */

View File

@@ -3,6 +3,7 @@ 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.Required;
import com.ruoyi.common.annotation.TextFormat;
import lombok.Data;
import java.io.Serial;
@@ -26,6 +27,7 @@ public class CcdiPurchaseTransactionExcel implements Serializable {
@ExcelProperty(value = "采购事项ID", index = 0)
@ColumnWidth(20)
@Required
@TextFormat
private String purchaseId;
/** 采购类别 */
@@ -138,6 +140,7 @@ public class CcdiPurchaseTransactionExcel implements Serializable {
@ExcelProperty(value = "申请人工号", index = 21)
@ColumnWidth(15)
@Required
@TextFormat
private String applicantId;
/** 申请人姓名 */
@@ -155,6 +158,7 @@ public class CcdiPurchaseTransactionExcel implements Serializable {
/** 采购负责人工号 */
@ExcelProperty(value = "采购负责人工号", index = 24)
@ColumnWidth(15)
@TextFormat
private String purchaseLeaderId;
/** 采购负责人姓名 */

View File

@@ -4,6 +4,7 @@ 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 com.ruoyi.common.annotation.TextFormat;
import lombok.Data;
import java.io.Serial;
@@ -21,6 +22,7 @@ public class CcdiPurchaseTransactionSupplierExcel implements Serializable {
@ExcelProperty(value = "采购事项ID", index = 0)
@ColumnWidth(20)
@Required
@TextFormat
private String purchaseId;
@ExcelProperty(value = "供应商名称", index = 1)
@@ -30,6 +32,7 @@ public class CcdiPurchaseTransactionSupplierExcel implements Serializable {
@ExcelProperty(value = "供应商统一信用代码", index = 2)
@ColumnWidth(25)
@TextFormat
private String supplierUscc;
@ExcelProperty(value = "供应商联系人", index = 3)
@@ -38,10 +41,12 @@ public class CcdiPurchaseTransactionSupplierExcel implements Serializable {
@ExcelProperty(value = "供应商联系电话", index = 4)
@ColumnWidth(18)
@TextFormat
private String contactPhone;
@ExcelProperty(value = "供应商银行账户", index = 5)
@ColumnWidth(20)
@TextFormat
private String supplierBankAccount;
@ExcelProperty(value = "是否中标", index = 6)

View File

@@ -3,6 +3,7 @@ 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.Required;
import com.ruoyi.common.annotation.TextFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@@ -26,6 +27,7 @@ public class CcdiStaffEnterpriseRelationExcel implements Serializable {
@ExcelProperty(value = "亲属身份证号", index = 0)
@ColumnWidth(20)
@Required
@TextFormat
@Schema(description = "亲属身份证号")
private String personId;
@@ -33,6 +35,7 @@ public class CcdiStaffEnterpriseRelationExcel implements Serializable {
@ExcelProperty(value = "统一社会信用代码", index = 1)
@ColumnWidth(25)
@Required
@TextFormat
@Schema(description = "统一社会信用代码")
private String socialCreditCode;

View File

@@ -28,6 +28,7 @@ public class CcdiStaffFmyRelationExcel implements Serializable {
@ExcelProperty(value = "员工身份证号*", index = 0)
@ColumnWidth(20)
@Required
@TextFormat
private String personId;
/** 关系类型 */
@@ -71,11 +72,13 @@ public class CcdiStaffFmyRelationExcel implements Serializable {
/** 手机号码1 */
@ExcelProperty(value = "手机号码1", index = 7)
@ColumnWidth(15)
@TextFormat
private String mobilePhone1;
/** 手机号码2 */
@ExcelProperty(value = "手机号码2", index = 8)
@ColumnWidth(15)
@TextFormat
private String mobilePhone2;
/** 家庭成员年收入 */

View File

@@ -4,6 +4,7 @@ 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 com.ruoyi.common.annotation.TextFormat;
import lombok.Data;
import java.io.Serial;
@@ -25,6 +26,7 @@ public class CcdiStaffRecruitmentExcel implements Serializable {
@ExcelProperty(value = "招聘记录编号", index = 0)
@ColumnWidth(20)
@Required
@TextFormat
private String recruitId;
/** 招聘项目名称 */
@@ -80,6 +82,7 @@ public class CcdiStaffRecruitmentExcel implements Serializable {
@ExcelProperty(value = "证件号码", index = 9)
@ColumnWidth(20)
@Required
@TextFormat
private String candId;
/** 应聘人员毕业年月 */
@@ -108,6 +111,7 @@ public class CcdiStaffRecruitmentExcel implements Serializable {
/** 面试官1工号 */
@ExcelProperty(value = "面试官1工号", index = 14)
@ColumnWidth(15)
@TextFormat
private String interviewerId1;
/** 面试官2姓名 */
@@ -118,5 +122,6 @@ public class CcdiStaffRecruitmentExcel implements Serializable {
/** 面试官2工号 */
@ExcelProperty(value = "面试官2工号", index = 16)
@ColumnWidth(15)
@TextFormat
private String interviewerId2;
}

View File

@@ -3,6 +3,7 @@ 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.Required;
import com.ruoyi.common.annotation.TextFormat;
import lombok.Data;
import java.io.Serial;
@@ -24,6 +25,7 @@ public class CcdiStaffRecruitmentWorkExcel implements Serializable {
@ExcelProperty(value = "招聘记录编号", index = 0)
@ColumnWidth(20)
@Required
@TextFormat
private String recruitId;
/** 候选人姓名 */

View File

@@ -1,15 +1,28 @@
package com.ruoyi.info.collection.handler;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import com.ruoyi.common.annotation.Required;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.usermodel.Workbook;
import java.lang.reflect.Field;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* EasyExcel必填字段标注处理器
@@ -18,13 +31,18 @@ import java.util.*;
* @author ruoyi
*/
@Slf4j
public class RequiredFieldWriteHandler implements SheetWriteHandler {
public class RequiredFieldWriteHandler implements CellWriteHandler {
/**
* 实体类Class对象
*/
private final Class<?> modelClass;
/**
* 必填字段列索引集合
*/
private final Set<Integer> requiredColumns;
/**
* 构造函数
*
@@ -32,39 +50,30 @@ public class RequiredFieldWriteHandler implements SheetWriteHandler {
*/
public RequiredFieldWriteHandler(Class<?> modelClass) {
this.modelClass = modelClass;
this.requiredColumns = parseRequiredFields();
}
@Override
public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
// 获取工作表
Sheet sheet = writeSheetHolder.getSheet();
// 获取表头行第1行索引为0
Row headerRow = sheet.getRow(0);
if (headerRow == null) {
log.warn("表头行不存在,跳过必填字段标注");
public void afterCellDispose(WriteSheetHolder writeSheetHolder,
WriteTableHolder writeTableHolder,
List<WriteCellData<?>> cellDataList,
Cell cell,
Head head,
Integer relativeRowIndex,
Boolean isHead) {
if (!Boolean.TRUE.equals(isHead) || cell == null || !requiredColumns.contains(cell.getColumnIndex())) {
return;
}
// 创建红色字体样式
Workbook workbook = writeWorkbookHolder.getWorkbook();
Workbook workbook = cell.getSheet().getWorkbook();
CellStyle redStyle = createRedFontStyle(workbook);
// 解析实体类中的必填字段
Set<Integer> requiredColumns = parseRequiredFields();
// 为必填字段的表头添加红色星号
for (Integer columnIndex : requiredColumns) {
Cell cell = headerRow.getCell(columnIndex);
if (cell != null) {
String originalValue = cell.getStringCellValue();
// 添加红色星号
cell.setCellValue(originalValue + "*");
// 应用红色样式到星号
cell.setCellStyle(redStyle);
log.info("为列[{}]的表头添加必填标记(*)", columnIndex);
}
String originalValue = cell.getStringCellValue();
if (originalValue != null && !originalValue.endsWith("*")) {
cell.setCellValue(originalValue + "*");
}
cell.setCellStyle(redStyle);
log.info("为列[{}]的表头添加必填标记(*)", cell.getColumnIndex());
}
/**

View File

@@ -158,6 +158,7 @@ public class EasyExcelUtil {
templateWriter(response, clazz)
.sheet(sheetName)
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
.registerWriteHandler(new TextFormatWriteHandler(clazz))
.doWrite(List.of());
} catch (IOException e) {
throw new RuntimeException("下载导入模板失败", e);
@@ -180,7 +181,8 @@ public class EasyExcelUtil {
setResponseHeader(response, sheetName + "模板");
var writerBuilder = templateWriter(response, clazz)
.sheet(sheetName)
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy());
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
.registerWriteHandler(new TextFormatWriteHandler(clazz));
// 注册所有自定义处理器
for (WriteHandler handler : handlers) {
writerBuilder.registerWriteHandler(handler);
@@ -288,7 +290,6 @@ public class EasyExcelUtil {
private static <T> WriteSheet buildTemplateSheet(int sheetNo, Class<T> clazz, String sheetName) {
return EasyExcel.writerSheet(sheetNo, sheetName)
.head(clazz)
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
.registerWriteHandler(new DictDropdownWriteHandler(clazz))
.registerWriteHandler(new TextFormatWriteHandler(clazz))
.registerWriteHandler(new RequiredFieldWriteHandler(clazz))

View File

@@ -2,12 +2,22 @@ package com.ruoyi.info.collection.utils;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.info.collection.domain.excel.CcdiBaseStaffExcel;
import com.ruoyi.info.collection.domain.excel.CcdiAccountInfoExcel;
import com.ruoyi.info.collection.domain.excel.CcdiAssetInfoExcel;
import com.ruoyi.info.collection.domain.excel.CcdiBaseStaffAssetInfoExcel;
import com.ruoyi.info.collection.domain.excel.CcdiBaseStaffExcel;
import com.ruoyi.info.collection.domain.excel.CcdiCustEnterpriseRelationExcel;
import com.ruoyi.info.collection.domain.excel.CcdiCustFmyRelationExcel;
import com.ruoyi.info.collection.domain.excel.CcdiEnterpriseBaseInfoExcel;
import com.ruoyi.info.collection.domain.excel.CcdiIntermediaryEnterpriseRelationExcel;
import com.ruoyi.info.collection.domain.excel.CcdiIntermediaryEntityExcel;
import com.ruoyi.info.collection.domain.excel.CcdiIntermediaryPersonExcel;
import com.ruoyi.info.collection.domain.excel.CcdiPurchaseTransactionExcel;
import com.ruoyi.info.collection.domain.excel.CcdiPurchaseTransactionSupplierExcel;
import com.ruoyi.info.collection.domain.excel.CcdiStaffEnterpriseRelationExcel;
import com.ruoyi.info.collection.domain.excel.CcdiStaffFmyRelationExcel;
import com.ruoyi.info.collection.domain.excel.CcdiStaffRecruitmentExcel;
import com.ruoyi.info.collection.domain.excel.CcdiStaffRecruitmentWorkExcel;
import com.ruoyi.info.collection.domain.excel.CcdiStaffFmyRelationExcel;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.Row;
@@ -99,6 +109,63 @@ class EasyExcelUtilTemplateTest {
try (Workbook workbook = WorkbookFactory.create(new ByteArrayInputStream(response.getContentAsByteArray()))) {
Sheet sheet = workbook.getSheetAt(0);
assertTrue(hasValidationOnColumn(sheet, 7), "是否党员列应包含下拉校验");
assertHeaderValue(sheet, 0, "姓名*");
assertHeaderValue(sheet, 1, "员工ID*");
assertHeaderValue(sheet, 2, "所属部门ID*");
assertHeaderValue(sheet, 3, "身份证号*");
assertHeaderValue(sheet, 4, "电话*");
assertHeaderValue(sheet, 7, "是否党员*");
assertHeaderValue(sheet, 8, "状态*");
assertTextColumn(sheet, 3);
assertTextColumn(sheet, 4);
}
}
@Test
void importTemplateWithDictDropdown_shouldKeepBaseStaffDualSheetColumnWidths() throws Exception {
MockHttpServletResponse response = new MockHttpServletResponse();
try (MockedStatic<DictUtils> mocked = mockStatic(DictUtils.class)) {
mocked.when(() -> DictUtils.getDictCache("ccdi_employee_status"))
.thenReturn(List.of(
buildDictData("在职", "0"),
buildDictData("离职", "1")
));
mocked.when(() -> DictUtils.getDictCache("ccdi_yes_no_flag"))
.thenReturn(List.of(
buildDictData("", "1"),
buildDictData("", "0")
));
mocked.when(() -> DictUtils.getDictCache("ccdi_asset_status"))
.thenReturn(List.of(
buildDictData("正常"),
buildDictData("冻结"),
buildDictData("处置中")
));
EasyExcelUtil.importTemplateWithDictDropdown(
response,
CcdiBaseStaffExcel.class,
"员工信息",
CcdiBaseStaffAssetInfoExcel.class,
"员工资产信息",
"员工信息维护导入模板"
);
}
try (Workbook workbook = WorkbookFactory.create(new ByteArrayInputStream(response.getContentAsByteArray()))) {
Sheet staffSheet = workbook.getSheet("员工信息");
Sheet assetSheet = workbook.getSheet("员工资产信息");
assertNotNull(staffSheet);
assertNotNull(assetSheet);
assertColumnWidthsAtLeast(staffSheet, new int[] {16, 18, 20, 24, 18, 20, 18, 16, 14});
assertColumnWidthsAtLeast(assetSheet, new int[] {24, 18, 18, 24, 14, 20, 18, 18, 20, 16, 32});
assertHeaderValue(staffSheet, 0, "姓名*");
assertHeaderValue(staffSheet, 8, "状态*");
assertHeaderValue(assetSheet, 0, "员工身份证号*");
assertHeaderValue(assetSheet, 1, "资产大类*");
assertHeaderValue(assetSheet, 10, "备注");
}
}
@@ -155,12 +222,119 @@ class EasyExcelUtilTemplateTest {
}
}
@Test
void infoImportTemplates_shouldFormatIdentifierAndContactColumnsAsText() throws Exception {
try (MockedStatic<DictUtils> mocked = mockStatic(DictUtils.class)) {
mockCommonDicts(mocked);
assertPlainTemplateTextColumns(CcdiAccountInfoExcel.class, "账户库管理", 1, 3, 7);
assertSingleTemplateTextColumns(CcdiAssetInfoExcel.class, "亲属资产信息", 0);
assertSingleTemplateTextColumns(CcdiBaseStaffAssetInfoExcel.class, "员工资产信息", 0);
assertDualTemplateTextColumns(
CcdiBaseStaffExcel.class,
"员工信息",
new int[] {3, 4},
CcdiBaseStaffAssetInfoExcel.class,
"员工资产信息",
new int[] {0},
"员工信息维护导入模板"
);
assertSingleTemplateTextColumns(CcdiCustEnterpriseRelationExcel.class, "信贷客户实体关联信息", 0, 1);
assertSingleTemplateTextColumns(CcdiCustFmyRelationExcel.class, "信贷客户家庭关系", 0, 6, 7, 8);
assertSingleTemplateTextColumns(CcdiEnterpriseBaseInfoExcel.class, "实体库管理", 0, 10);
assertSingleTemplateTextColumns(CcdiIntermediaryPersonExcel.class, "个人中介信息", 5, 6, 10, 12);
assertSingleTemplateTextColumns(CcdiIntermediaryEntityExcel.class, "实体中介信息", 1, 10);
assertSingleTemplateTextColumns(CcdiIntermediaryEnterpriseRelationExcel.class, "中介实体关联关系信息", 0, 1);
assertDualTemplateTextColumns(
CcdiPurchaseTransactionExcel.class,
"招投标主信息",
new int[] {0, 21, 24},
CcdiPurchaseTransactionSupplierExcel.class,
"供应商信息",
new int[] {0, 2, 4, 5},
"招投标信息维护导入模板"
);
assertSingleTemplateTextColumns(CcdiStaffEnterpriseRelationExcel.class, "员工亲属实体关联", 0, 1);
assertSingleTemplateTextColumns(CcdiStaffFmyRelationExcel.class, "员工亲属关系信息", 0, 6, 7, 8);
assertDualTemplateTextColumns(
CcdiStaffRecruitmentExcel.class,
"招聘信息",
new int[] {0, 9, 14, 16},
CcdiStaffRecruitmentWorkExcel.class,
"历史工作经历",
new int[] {0},
"招聘信息管理导入模板"
);
}
}
private void assertTextColumn(Sheet sheet, int columnIndex) {
CellStyle style = sheet.getColumnStyle(columnIndex);
assertNotNull(style, "文本列应设置默认样式");
assertEquals("@", style.getDataFormatString(), "证件号列应使用文本格式");
}
private void assertHeaderValue(Sheet sheet, int columnIndex, String expectedValue) {
assertEquals(expectedValue, sheet.getRow(0).getCell(columnIndex).getStringCellValue());
}
private void assertTextColumns(Sheet sheet, int... columnIndexes) {
for (int columnIndex : columnIndexes) {
assertTextColumn(sheet, columnIndex);
}
}
private void assertPlainTemplateTextColumns(Class<?> clazz, String sheetName, int... columnIndexes) throws Exception {
MockHttpServletResponse response = new MockHttpServletResponse();
EasyExcelUtil.importTemplateExcel(response, clazz, sheetName);
try (Workbook workbook = WorkbookFactory.create(new ByteArrayInputStream(response.getContentAsByteArray()))) {
assertTextColumns(workbook.getSheetAt(0), columnIndexes);
}
}
private void assertSingleTemplateTextColumns(Class<?> clazz, String sheetName, int... columnIndexes) throws Exception {
MockHttpServletResponse response = new MockHttpServletResponse();
EasyExcelUtil.importTemplateWithDictDropdown(response, clazz, sheetName);
try (Workbook workbook = WorkbookFactory.create(new ByteArrayInputStream(response.getContentAsByteArray()))) {
assertTextColumns(workbook.getSheetAt(0), columnIndexes);
}
}
private <T1, T2> void assertDualTemplateTextColumns(Class<T1> firstClazz,
String firstSheetName,
int[] firstColumnIndexes,
Class<T2> secondClazz,
String secondSheetName,
int[] secondColumnIndexes,
String fileName) throws Exception {
MockHttpServletResponse response = new MockHttpServletResponse();
EasyExcelUtil.importTemplateWithDictDropdown(
response,
firstClazz,
firstSheetName,
secondClazz,
secondSheetName,
fileName
);
try (Workbook workbook = WorkbookFactory.create(new ByteArrayInputStream(response.getContentAsByteArray()))) {
assertTextColumns(workbook.getSheet(firstSheetName), firstColumnIndexes);
assertTextColumns(workbook.getSheet(secondSheetName), secondColumnIndexes);
}
}
private void assertColumnWidthsAtLeast(Sheet sheet, int[] expectedWidths) {
for (int columnIndex = 0; columnIndex < expectedWidths.length; columnIndex++) {
int currentColumnIndex = columnIndex;
int expectedWidth = expectedWidths[currentColumnIndex];
int expected = expectedWidth * 256;
assertTrue(sheet.getColumnWidth(currentColumnIndex) >= expected,
() -> sheet.getSheetName() + "" + (currentColumnIndex + 1) + "列宽度应不小于" + expectedWidth);
}
}
private boolean hasValidationOnColumn(Sheet sheet, int columnIndex) {
for (DataValidation validation : sheet.getDataValidations()) {
for (CellRangeAddress address : validation.getRegions().getCellRangeAddresses()) {
@@ -172,6 +346,31 @@ class EasyExcelUtilTemplateTest {
return false;
}
private void mockCommonDicts(MockedStatic<DictUtils> mocked) {
mocked.when(() -> DictUtils.getDictCache("ccdi_asset_status"))
.thenReturn(List.of(buildDictData("正常")));
mocked.when(() -> DictUtils.getDictCache("ccdi_employee_status"))
.thenReturn(List.of(buildDictData("在职", "1")));
mocked.when(() -> DictUtils.getDictCache("ccdi_yes_no_flag"))
.thenReturn(List.of(buildDictData("", "1")));
mocked.when(() -> DictUtils.getDictCache("ccdi_relation_type"))
.thenReturn(List.of(buildDictData("配偶")));
mocked.when(() -> DictUtils.getDictCache("ccdi_indiv_gender"))
.thenReturn(List.of(buildDictData("")));
mocked.when(() -> DictUtils.getDictCache("ccdi_certificate_type"))
.thenReturn(List.of(buildDictData("居民身份证")));
mocked.when(() -> DictUtils.getDictCache("ccdi_entity_type"))
.thenReturn(List.of(buildDictData("有限责任公司")));
mocked.when(() -> DictUtils.getDictCache("ccdi_enterprise_nature"))
.thenReturn(List.of(buildDictData("民营企业")));
mocked.when(() -> DictUtils.getDictCache("ccdi_person_type"))
.thenReturn(List.of(buildDictData("中介")));
mocked.when(() -> DictUtils.getDictCache("ccdi_person_sub_type"))
.thenReturn(List.of(buildDictData("本人")));
mocked.when(() -> DictUtils.getDictCache("ccdi_admit_status"))
.thenReturn(List.of(buildDictData("录用")));
}
private SysDictData buildDictData(String label) {
return buildDictData(label, label);
}