Showing
3 changed files
with
121 additions
and
11 deletions
xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/customer/CustomerCreditController.java
| 1 | 1 | package com.lframework.xingyun.sc.controller.customer; |
| 2 | 2 | |
| 3 | +import com.alibaba.excel.EasyExcel; | |
| 4 | +import com.alibaba.excel.ExcelWriter; | |
| 5 | +import com.alibaba.excel.write.metadata.WriteSheet; | |
| 3 | 6 | import com.lframework.starter.bpm.dto.FlowTaskDto; |
| 4 | 7 | import com.lframework.starter.bpm.mappers.FlowTaskWrapperMapper; |
| 5 | 8 | import com.lframework.starter.bpm.vo.flow.task.QueryTodoTaskListVo; |
| ... | ... | @@ -24,6 +27,7 @@ import com.lframework.starter.web.core.components.resp.InvokeResult; |
| 24 | 27 | import javax.annotation.Resource; |
| 25 | 28 | import javax.servlet.http.HttpServletResponse; |
| 26 | 29 | import javax.validation.constraints.NotBlank; |
| 30 | +import com.lframework.xingyun.sc.excel.customerCredit.AutoColumnWidthHandler; | |
| 27 | 31 | import com.lframework.xingyun.sc.excel.customerCredit.CustomerCreditImportListener; |
| 28 | 32 | import com.lframework.xingyun.sc.excel.customerCredit.CustomerCreditImportModel; |
| 29 | 33 | import com.lframework.xingyun.sc.service.contract.ContractDistributorStandardService; |
| ... | ... | @@ -51,6 +55,7 @@ import javax.validation.Valid; |
| 51 | 55 | import javax.validation.constraints.NotNull; |
| 52 | 56 | import java.io.*; |
| 53 | 57 | import java.net.URLEncoder; |
| 58 | +import java.nio.charset.StandardCharsets; | |
| 54 | 59 | import java.time.LocalDate; |
| 55 | 60 | import java.time.LocalDateTime; |
| 56 | 61 | import java.time.format.DateTimeFormatter; |
| ... | ... | @@ -293,8 +298,47 @@ public class CustomerCreditController extends DefaultBaseController { |
| 293 | 298 | @ApiOperation("下载导入模板") |
| 294 | 299 | @HasPermission({"customer-credit-manage:customer-credit-plan:import"}) |
| 295 | 300 | @GetMapping("/import/template") |
| 296 | - public void downloadImportTemplate() { | |
| 297 | - ExcelUtil.exportXls("客户资信导入模板", CustomerCreditImportModel.class); | |
| 301 | + public void downloadImportTemplate(HttpServletResponse response) throws IOException { | |
| 302 | + String fileName = "客户资信导入模板.xlsx"; | |
| 303 | + | |
| 304 | + //设置响应头 | |
| 305 | + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); | |
| 306 | + | |
| 307 | + String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString()).replace("+", "%20"); | |
| 308 | + String contentDisposition = "attachment; filename=\"" + encodedFileName + "\"; filename*=UTF-8''" + encodedFileName; | |
| 309 | + response.setHeader("Content-Disposition", contentDisposition); | |
| 310 | + | |
| 311 | + | |
| 312 | + List<List<String>> noteRows = Arrays.asList( | |
| 313 | + Collections.singletonList("【重要填写说明】"), | |
| 314 | + Collections.singletonList("1. 带*是必填项"), | |
| 315 | + Collections.singletonList("2. 办事处要是全称:例如 北方办事处"), | |
| 316 | + Collections.singletonList("3. 区域要是全称:例如 山东区域"), | |
| 317 | + Collections.singletonList("4. 企业类型只能是:经销商、终端"), | |
| 318 | + Collections.singletonList("5. 注册资本格式:100 或 100万元"), | |
| 319 | + Collections.singletonList("6. 登记日期、注册时间格式:2025年3月21日 或 2025-03-21 或 2025/3/21"), | |
| 320 | + Collections.singletonList("7. 年龄格式:正整数,不要带单位 例如 25"), | |
| 321 | + Collections.singletonList("8. 性别格式:男 或 女"), | |
| 322 | + Collections.singletonList("9. 员工人数格式:正整数,不要带单位 例如 25"), | |
| 323 | + Collections.singletonList("10. 建议客户分类格式:只能为:AAA、AA、A、BBB、BB、B、C、D") | |
| 324 | + ); | |
| 325 | + | |
| 326 | + try (OutputStream out = response.getOutputStream()) { | |
| 327 | + ExcelWriter excelWriter = EasyExcel.write(out).build(); | |
| 328 | + | |
| 329 | + // ✅ 注册自定义 handler,仅用于数据 sheet | |
| 330 | + WriteSheet dataSheet = EasyExcel.writerSheet("客户资信导入") | |
| 331 | + .head(CustomerCreditImportModel.class) | |
| 332 | + .registerWriteHandler(new AutoColumnWidthHandler()) | |
| 333 | + .build(); | |
| 334 | + excelWriter.write(Collections.emptyList(), dataSheet); | |
| 335 | + | |
| 336 | + // “填写说明” sheet 不需要样式,不注册 handler | |
| 337 | + WriteSheet noteSheet = EasyExcel.writerSheet("填写说明").build(); | |
| 338 | + excelWriter.write(noteRows, noteSheet); | |
| 339 | + | |
| 340 | + excelWriter.finish(); | |
| 341 | + } | |
| 298 | 342 | } |
| 299 | 343 | |
| 300 | 344 | @ApiOperation("导入") | ... | ... |
xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/customerCredit/AutoColumnWidthHandler.java
0 → 100644
| 1 | +package com.lframework.xingyun.sc.excel.customerCredit; | |
| 2 | + | |
| 3 | +import com.alibaba.excel.metadata.CellData; | |
| 4 | +import com.alibaba.excel.metadata.Head; | |
| 5 | +import com.alibaba.excel.write.handler.CellWriteHandler; | |
| 6 | +import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; | |
| 7 | +import com.alibaba.excel.write.metadata.holder.WriteTableHolder; | |
| 8 | + | |
| 9 | + | |
| 10 | +import org.apache.poi.ss.usermodel.Cell; | |
| 11 | +import org.apache.poi.ss.usermodel.Sheet; | |
| 12 | + | |
| 13 | +import java.util.List; | |
| 14 | + | |
| 15 | +/** | |
| 16 | + * 仅用于在导出 Excel 模板时自动调整表头列宽 | |
| 17 | + */ | |
| 18 | +public class AutoColumnWidthHandler implements CellWriteHandler { | |
| 19 | + | |
| 20 | + @Override | |
| 21 | + public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, | |
| 22 | + org.apache.poi.ss.usermodel.Row row, Head head, Integer columnIndex, | |
| 23 | + Integer relativeRowIndex, Boolean isHead) { | |
| 24 | + // 不处理 | |
| 25 | + } | |
| 26 | + | |
| 27 | + @Override | |
| 28 | + public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, | |
| 29 | + Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { | |
| 30 | + // 不处理 | |
| 31 | + } | |
| 32 | + | |
| 33 | + @Override | |
| 34 | + public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { | |
| 35 | + | |
| 36 | + } | |
| 37 | + | |
| 38 | + @Override | |
| 39 | + public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { | |
| 40 | + if (Boolean.TRUE.equals(isHead) && head != null && head.getHeadNameList() != null) { | |
| 41 | + String headName = head.getHeadNameList().get(0).replaceAll("[\\n\\r\\t]", "").trim(); | |
| 42 | + Sheet sheet = cell.getSheet(); | |
| 43 | + int columnIndex = cell.getColumnIndex(); | |
| 44 | + | |
| 45 | + int width = calculateColumnWidth(headName); | |
| 46 | + // 限制最大宽度(例如最多 50 个字符),避免过宽 | |
| 47 | + sheet.setColumnWidth(columnIndex, Math.min(width * 256, 50 * 256)); | |
| 48 | + } | |
| 49 | + | |
| 50 | + } | |
| 51 | + | |
| 52 | + private int calculateColumnWidth(String text) { | |
| 53 | + int width = 0; | |
| 54 | + for (char c : text.toCharArray()) { | |
| 55 | + if (Character.isWhitespace(c)) { | |
| 56 | + width += 1; | |
| 57 | + } else if (c >= '\u4e00' && c <= '\u9fff') { // 中文 | |
| 58 | + width += 2; | |
| 59 | + } else { | |
| 60 | + width += 1; | |
| 61 | + } | |
| 62 | + } | |
| 63 | + // 增加额外宽度(防止拥挤) | |
| 64 | + return (int) Math.max(width * 2, 12); // 乘以1.5,并最小12 | |
| 65 | + } | |
| 66 | +} | ... | ... |
| ... | ... | @@ -27,14 +27,14 @@ public class CustomerCreditImportModel implements ExcelModel { |
| 27 | 27 | * 编号 |
| 28 | 28 | */ |
| 29 | 29 | @ExcelRequired |
| 30 | - @ExcelProperty("编号") | |
| 30 | + @ExcelProperty("*编号") | |
| 31 | 31 | private String code; |
| 32 | 32 | |
| 33 | 33 | /** |
| 34 | 34 | * 办事处 |
| 35 | 35 | */ |
| 36 | 36 | @ExcelRequired |
| 37 | - @ExcelProperty("办事处") | |
| 37 | + @ExcelProperty("*办事处") | |
| 38 | 38 | private String deptName; |
| 39 | 39 | |
| 40 | 40 | /** |
| ... | ... | @@ -47,7 +47,7 @@ public class CustomerCreditImportModel implements ExcelModel { |
| 47 | 47 | * 区域 |
| 48 | 48 | */ |
| 49 | 49 | @ExcelRequired |
| 50 | - @ExcelProperty("区域") | |
| 50 | + @ExcelProperty("*区域") | |
| 51 | 51 | private String regionName; |
| 52 | 52 | |
| 53 | 53 | /** |
| ... | ... | @@ -60,14 +60,14 @@ public class CustomerCreditImportModel implements ExcelModel { |
| 60 | 60 | * 简写名称 |
| 61 | 61 | */ |
| 62 | 62 | @ExcelRequired |
| 63 | - @ExcelProperty("简写名称") | |
| 63 | + @ExcelProperty("*简写名称") | |
| 64 | 64 | private String customerShortName; |
| 65 | 65 | |
| 66 | 66 | /** |
| 67 | 67 | * 登记日期 |
| 68 | 68 | */ |
| 69 | 69 | @ExcelRequired |
| 70 | - @ExcelProperty("登记日期") | |
| 70 | + @ExcelProperty("*登记日期") | |
| 71 | 71 | private String registerDateStr; |
| 72 | 72 | |
| 73 | 73 | /** |
| ... | ... | @@ -80,7 +80,7 @@ public class CustomerCreditImportModel implements ExcelModel { |
| 80 | 80 | * 公司名称 |
| 81 | 81 | */ |
| 82 | 82 | @ExcelRequired |
| 83 | - @ExcelProperty("公司名称") | |
| 83 | + @ExcelProperty("*公司名称") | |
| 84 | 84 | private String name; |
| 85 | 85 | |
| 86 | 86 | /** |
| ... | ... | @@ -93,7 +93,7 @@ public class CustomerCreditImportModel implements ExcelModel { |
| 93 | 93 | * 企业类型 |
| 94 | 94 | */ |
| 95 | 95 | @ExcelRequired |
| 96 | - @ExcelProperty("企业类型") | |
| 96 | + @ExcelProperty("*企业类型") | |
| 97 | 97 | private String enterpriseType; |
| 98 | 98 | |
| 99 | 99 | /** |
| ... | ... | @@ -414,7 +414,7 @@ public class CustomerCreditImportModel implements ExcelModel { |
| 414 | 414 | * 结算期限 |
| 415 | 415 | */ |
| 416 | 416 | @ExcelRequired |
| 417 | - @ExcelProperty("结算期限") | |
| 417 | + @ExcelProperty("*结算期限") | |
| 418 | 418 | private String settlementPeriod; |
| 419 | 419 | |
| 420 | 420 | /** |
| ... | ... | @@ -433,7 +433,7 @@ public class CustomerCreditImportModel implements ExcelModel { |
| 433 | 433 | * 授信额度 |
| 434 | 434 | */ |
| 435 | 435 | @ExcelRequired |
| 436 | - @ExcelProperty("授信额度") | |
| 436 | + @ExcelProperty("*授信额度") | |
| 437 | 437 | private String creditLimit; |
| 438 | 438 | |
| 439 | 439 | /** | ... | ... |