feat(import): 添加Excel导入时超链接解析功能
- 在CreditCompany和CreditJudgmentDebtor实体中添加url字段 - 实现ExcelImportSupport工具类的超链接读取功能 - 支持通过表头名称定位列并提取超链接地址 - 在企业信息导入时自动解析原文件和匹配名称的超链接 - 在执行人信息导入时解析案号和被执行人名称的超链接 - 移除多余的import语句和调试输出代码 - 扩展ImportResult类以支持工作表索引信息
This commit is contained in:
@@ -11,10 +11,8 @@ import com.gxwebsoft.common.core.web.BatchParam;
|
|||||||
import com.gxwebsoft.common.core.web.PageResult;
|
import com.gxwebsoft.common.core.web.PageResult;
|
||||||
import com.gxwebsoft.common.system.entity.User;
|
import com.gxwebsoft.common.system.entity.User;
|
||||||
import com.gxwebsoft.credit.entity.CreditCompany;
|
import com.gxwebsoft.credit.entity.CreditCompany;
|
||||||
import com.gxwebsoft.credit.entity.CreditCompany;
|
|
||||||
import com.gxwebsoft.credit.param.CreditCompanyImportParam;
|
import com.gxwebsoft.credit.param.CreditCompanyImportParam;
|
||||||
import com.gxwebsoft.credit.param.CreditCompanyParam;
|
import com.gxwebsoft.credit.param.CreditCompanyParam;
|
||||||
import com.gxwebsoft.credit.param.CreditCompanyImportParam;
|
|
||||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
@@ -29,6 +27,7 @@ import javax.servlet.http.HttpServletResponse;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 企业控制器
|
* 企业控制器
|
||||||
@@ -161,11 +160,23 @@ public class CreditCompanyController extends BaseController {
|
|||||||
User loginUser = getLoginUser();
|
User loginUser = getLoginUser();
|
||||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||||
|
Map<String, String> urlByName = ExcelImportSupport.readHyperlinksByHeaderKey(file, 0, usedTitleRows, usedHeadRows, "原文件导入名称");
|
||||||
|
Map<String, String> urlByMatchName = ExcelImportSupport.readHyperlinksByHeaderKey(file, 0, usedTitleRows, usedHeadRows, "系统匹配企业名称");
|
||||||
|
|
||||||
for (int i = 0; i < list.size(); i++) {
|
for (int i = 0; i < list.size(); i++) {
|
||||||
CreditCompanyImportParam param = list.get(i);
|
CreditCompanyImportParam param = list.get(i);
|
||||||
try {
|
try {
|
||||||
CreditCompany item = convertImportParamToEntity(param);
|
CreditCompany item = convertImportParamToEntity(param);
|
||||||
|
String link = null;
|
||||||
|
if (item.getName() != null) {
|
||||||
|
link = urlByName.get(item.getName().trim());
|
||||||
|
}
|
||||||
|
if ((link == null || link.isEmpty()) && item.getMatchName() != null) {
|
||||||
|
link = urlByMatchName.get(item.getMatchName().trim());
|
||||||
|
}
|
||||||
|
if (link != null && !link.isEmpty()) {
|
||||||
|
item.setUrl(link);
|
||||||
|
}
|
||||||
|
|
||||||
// 设置默认值
|
// 设置默认值
|
||||||
if (item.getUserId() == null && currentUserId != null) {
|
if (item.getUserId() == null && currentUserId != null) {
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import java.nio.file.Files;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
import java.util.zip.ZipInputStream;
|
import java.util.zip.ZipInputStream;
|
||||||
|
|
||||||
@@ -267,16 +268,34 @@ public class CreditJudgmentDebtorController extends BaseController {
|
|||||||
List<CreditJudgmentDebtorImportParam> list = importResult.getData();
|
List<CreditJudgmentDebtorImportParam> list = importResult.getData();
|
||||||
int usedTitleRows = importResult.getTitleRows();
|
int usedTitleRows = importResult.getTitleRows();
|
||||||
int usedHeadRows = importResult.getHeadRows();
|
int usedHeadRows = importResult.getHeadRows();
|
||||||
|
int usedSheetIndex = importResult.getSheetIndex();
|
||||||
|
|
||||||
if (CollectionUtils.isEmpty(list)) {
|
if (CollectionUtils.isEmpty(list)) {
|
||||||
return new ImportOutcome(false, 0, errorMessages);
|
return new ImportOutcome(false, 0, errorMessages);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Map<String, String> urlByCaseNumber = ExcelImportSupport.readHyperlinksByHeaderKey(excelFile, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||||
|
Map<String, String> urlByName = ExcelImportSupport.readHyperlinksByHeaderKey(excelFile, usedSheetIndex, usedTitleRows, usedHeadRows, "被执行人名称");
|
||||||
|
Map<String, String> urlByName1 = ExcelImportSupport.readHyperlinksByHeaderKey(excelFile, usedSheetIndex, usedTitleRows, usedHeadRows, "被执行人");
|
||||||
|
|
||||||
String prefix = ImportHelper.isBlank(fileLabel) ? "" : "【" + fileLabel + "】";
|
String prefix = ImportHelper.isBlank(fileLabel) ? "" : "【" + fileLabel + "】";
|
||||||
for (int i = 0; i < list.size(); i++) {
|
for (int i = 0; i < list.size(); i++) {
|
||||||
CreditJudgmentDebtorImportParam param = list.get(i);
|
CreditJudgmentDebtorImportParam param = list.get(i);
|
||||||
try {
|
try {
|
||||||
CreditJudgmentDebtor item = convertImportParamToEntity(param);
|
CreditJudgmentDebtor item = convertImportParamToEntity(param);
|
||||||
|
String link = null;
|
||||||
|
if (!ImportHelper.isBlank(item.getCaseNumber())) {
|
||||||
|
link = urlByCaseNumber.get(item.getCaseNumber().trim());
|
||||||
|
}
|
||||||
|
if ((link == null || link.isEmpty()) && !ImportHelper.isBlank(item.getName())) {
|
||||||
|
link = urlByName.get(item.getName().trim());
|
||||||
|
}
|
||||||
|
if ((link == null || link.isEmpty()) && !ImportHelper.isBlank(item.getName1())) {
|
||||||
|
link = urlByName1.get(item.getName1().trim());
|
||||||
|
}
|
||||||
|
if (link != null && !link.isEmpty()) {
|
||||||
|
item.setUrl(link);
|
||||||
|
}
|
||||||
|
|
||||||
if (item.getUserId() == null && currentUserId != null) {
|
if (item.getUserId() == null && currentUserId != null) {
|
||||||
item.setUserId(currentUserId);
|
item.setUserId(currentUserId);
|
||||||
@@ -293,7 +312,6 @@ public class CreditJudgmentDebtorController extends BaseController {
|
|||||||
if (item.getDeleted() == null) {
|
if (item.getDeleted() == null) {
|
||||||
item.setDeleted(0);
|
item.setDeleted(0);
|
||||||
}
|
}
|
||||||
System.out.println("item = " + item);
|
|
||||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||||
errorMessages.add(prefix + "第" + excelRowNumber + "行:案号不能为空");
|
errorMessages.add(prefix + "第" + excelRowNumber + "行:案号不能为空");
|
||||||
|
|||||||
@@ -4,13 +4,22 @@ import cn.afterturn.easypoi.excel.ExcelExportUtil;
|
|||||||
import cn.afterturn.easypoi.excel.ExcelImportUtil;
|
import cn.afterturn.easypoi.excel.ExcelImportUtil;
|
||||||
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
||||||
import cn.afterturn.easypoi.excel.entity.ImportParams;
|
import cn.afterturn.easypoi.excel.entity.ImportParams;
|
||||||
|
import org.apache.poi.ss.usermodel.Cell;
|
||||||
|
import org.apache.poi.ss.usermodel.CellType;
|
||||||
|
import org.apache.poi.ss.usermodel.DataFormatter;
|
||||||
|
import org.apache.poi.ss.usermodel.Hyperlink;
|
||||||
|
import org.apache.poi.ss.usermodel.Row;
|
||||||
|
import org.apache.poi.ss.usermodel.Sheet;
|
||||||
import org.apache.poi.ss.usermodel.Workbook;
|
import org.apache.poi.ss.usermodel.Workbook;
|
||||||
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -22,11 +31,17 @@ public class ExcelImportSupport {
|
|||||||
private final List<T> data;
|
private final List<T> data;
|
||||||
private final int titleRows;
|
private final int titleRows;
|
||||||
private final int headRows;
|
private final int headRows;
|
||||||
|
private final int sheetIndex;
|
||||||
|
|
||||||
public ImportResult(List<T> data, int titleRows, int headRows) {
|
public ImportResult(List<T> data, int titleRows, int headRows) {
|
||||||
|
this(data, titleRows, headRows, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImportResult(List<T> data, int titleRows, int headRows, int sheetIndex) {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
this.titleRows = titleRows;
|
this.titleRows = titleRows;
|
||||||
this.headRows = headRows;
|
this.headRows = headRows;
|
||||||
|
this.sheetIndex = sheetIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<T> getData() {
|
public List<T> getData() {
|
||||||
@@ -40,6 +55,10 @@ public class ExcelImportSupport {
|
|||||||
public int getHeadRows() {
|
public int getHeadRows() {
|
||||||
return headRows;
|
return headRows;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getSheetIndex() {
|
||||||
|
return sheetIndex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> ImportResult<T> read(MultipartFile file, Class<T> clazz, Predicate<T> emptyRowPredicate) throws Exception {
|
public static <T> ImportResult<T> read(MultipartFile file, Class<T> clazz, Predicate<T> emptyRowPredicate) throws Exception {
|
||||||
@@ -103,7 +122,7 @@ public class ExcelImportSupport {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new ImportResult<>(list, usedTitleRows, usedHeadRows);
|
return new ImportResult<>(list, usedTitleRows, usedHeadRows, sheetIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -144,7 +163,7 @@ public class ExcelImportSupport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (bestList != null) {
|
if (bestList != null) {
|
||||||
return new ImportResult<>(bestList, bestTitleRows, bestHeadRows);
|
return new ImportResult<>(bestList, bestTitleRows, bestHeadRows, sheetIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return read(file, clazz, emptyRowPredicate, sheetIndex);
|
return read(file, clazz, emptyRowPredicate, sheetIndex);
|
||||||
@@ -173,6 +192,106 @@ public class ExcelImportSupport {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 读取指定列(由表头名定位)的超链接,返回:单元格显示值 -> 超链接地址。
|
||||||
|
*
|
||||||
|
* <p>适用于:导入对象没有 url 字段,但 Excel 把链接放在某个“名称/案号”等列的超链接里。</p>
|
||||||
|
*/
|
||||||
|
public static Map<String, String> readHyperlinksByHeaderKey(MultipartFile file, int sheetIndex, int titleRows, int headRows, String headerName) throws Exception {
|
||||||
|
if (file == null || headerName == null || headerName.trim().isEmpty()) {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
try (InputStream is = file.getInputStream(); Workbook workbook = WorkbookFactory.create(is)) {
|
||||||
|
if (workbook.getNumberOfSheets() <= sheetIndex) {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
Sheet sheet = workbook.getSheetAt(sheetIndex);
|
||||||
|
if (sheet == null) {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
int colIndex = findColumnIndexByHeader(sheet, titleRows, headRows, headerName);
|
||||||
|
if (colIndex < 0) {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, String> result = new HashMap<>();
|
||||||
|
DataFormatter formatter = new DataFormatter();
|
||||||
|
int dataStartRow = titleRows + headRows;
|
||||||
|
for (int r = dataStartRow; r <= sheet.getLastRowNum(); r++) {
|
||||||
|
Row row = sheet.getRow(r);
|
||||||
|
if (row == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Cell cell = row.getCell(colIndex);
|
||||||
|
if (cell == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String address = extractHyperlinkAddress(cell);
|
||||||
|
if (address == null || address.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String key = formatter.formatCellValue(cell);
|
||||||
|
if (key == null || key.trim().isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
result.put(key.trim(), address);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int findColumnIndexByHeader(Sheet sheet, int titleRows, int headRows, String headerName) {
|
||||||
|
int firstHeaderRow = Math.max(0, titleRows);
|
||||||
|
int lastHeaderRow = Math.max(0, titleRows + headRows - 1);
|
||||||
|
for (int r = firstHeaderRow; r <= lastHeaderRow; r++) {
|
||||||
|
Row row = sheet.getRow(r);
|
||||||
|
if (row == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (int c = row.getFirstCellNum(); c < row.getLastCellNum(); c++) {
|
||||||
|
Cell cell = row.getCell(c);
|
||||||
|
if (cell == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (cell.getCellType() == CellType.STRING) {
|
||||||
|
String value = cell.getStringCellValue();
|
||||||
|
if (headerName.equals(value != null ? value.trim() : null)) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DataFormatter formatter = new DataFormatter();
|
||||||
|
String value = formatter.formatCellValue(cell);
|
||||||
|
if (headerName.equals(value != null ? value.trim() : null)) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String extractHyperlinkAddress(Cell cell) {
|
||||||
|
Hyperlink hyperlink = cell.getHyperlink();
|
||||||
|
if (hyperlink != null && hyperlink.getAddress() != null && !hyperlink.getAddress().isEmpty()) {
|
||||||
|
return hyperlink.getAddress();
|
||||||
|
}
|
||||||
|
if (cell.getCellType() == CellType.FORMULA) {
|
||||||
|
String formula = cell.getCellFormula();
|
||||||
|
if (formula != null && formula.toUpperCase().startsWith("HYPERLINK(")) {
|
||||||
|
int firstQuote = formula.indexOf('\"');
|
||||||
|
if (firstQuote >= 0) {
|
||||||
|
int secondQuote = formula.indexOf('\"', firstQuote + 1);
|
||||||
|
if (secondQuote > firstQuote) {
|
||||||
|
return formula.substring(firstQuote + 1, secondQuote);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public static <T> Workbook buildTemplate(String title, String sheetName, Class<T> clazz, List<T> examples) {
|
public static <T> Workbook buildTemplate(String title, String sheetName, Class<T> clazz, List<T> examples) {
|
||||||
ExportParams exportParams = new ExportParams(title, sheetName);
|
ExportParams exportParams = new ExportParams(title, sheetName);
|
||||||
return ExcelExportUtil.exportExcel(exportParams, clazz, examples);
|
return ExcelExportUtil.exportExcel(exportParams, clazz, examples);
|
||||||
|
|||||||
@@ -36,6 +36,9 @@ public class CreditCompany implements Serializable {
|
|||||||
@Schema(description = "统一社会信用代码")
|
@Schema(description = "统一社会信用代码")
|
||||||
private String code;
|
private String code;
|
||||||
|
|
||||||
|
@Schema(description = "项目网址")
|
||||||
|
private String url;
|
||||||
|
|
||||||
@Schema(description = "类型")
|
@Schema(description = "类型")
|
||||||
private Integer type;
|
private Integer type;
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,9 @@ public class CreditJudgmentDebtor implements Serializable {
|
|||||||
@Schema(description = "证件号/组织机构代码")
|
@Schema(description = "证件号/组织机构代码")
|
||||||
private String code;
|
private String code;
|
||||||
|
|
||||||
|
@Schema(description = "项目网址")
|
||||||
|
private String url;
|
||||||
|
|
||||||
@Schema(description = "发生时间")
|
@Schema(description = "发生时间")
|
||||||
private String occurrenceTime;
|
private String occurrenceTime;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user