feat(import): 实现Excel导入时链接地址自动提取功能

- 修改CreditAdministrativeLicense相关类将"许可类型"字段描述改为"许可类别"
- 在多个实体类(CreditBreachOfTrust、CreditCompetitor、CreditCourtAnnouncement等)中新增url字段用于存储链接地址
- 重构CreditCompany实体类调整字段顺序和位置
- 在各个控制器中实现Excel导入时链接地址的自动提取和填充逻辑
- 新增readKeyValueByHeaders方法支持从指定列读取键值对数据
- 新增readUrlByKey方法支持从超链接或独立列提取URL地址
- 优化Excel导入流程增加链接地址批量处理功能
- 修复EasyPOI无法读取单元格超链接地址的问题
This commit is contained in:
2026-01-19 14:23:48 +08:00
parent 071c44679a
commit 12fc77b35c
27 changed files with 310 additions and 35 deletions

View File

@@ -24,6 +24,7 @@ import java.io.IOException;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 失信被执行人控制器
@@ -146,6 +147,7 @@ public class CreditBreachOfTrustController extends BaseController {
List<CreditBreachOfTrustImportParam> list = importResult.getData();
int usedTitleRows = importResult.getTitleRows();
int usedHeadRows = importResult.getHeadRows();
int usedSheetIndex = importResult.getSheetIndex();
if (CollectionUtils.isEmpty(list)) {
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
@@ -154,6 +156,7 @@ public class CreditBreachOfTrustController extends BaseController {
User loginUser = getLoginUser();
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
final int chunkSize = 500;
final int mpBatchSize = 500;
@@ -164,6 +167,12 @@ public class CreditBreachOfTrustController extends BaseController {
CreditBreachOfTrustImportParam param = list.get(i);
try {
CreditBreachOfTrust item = convertImportParamToEntity(param);
if (!ImportHelper.isBlank(item.getCaseNumber())) {
String link = urlByCaseNumber.get(item.getCaseNumber().trim());
if (!ImportHelper.isBlank(link)) {
item.setUrl(link.trim());
}
}
if (item.getCompanyId() == null && companyId != null) {
item.setCompanyId(companyId);

View File

@@ -23,6 +23,7 @@ import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 竞争对手控制器
@@ -150,6 +151,7 @@ public class CreditCompetitorController extends BaseController {
List<CreditCompetitorImportParam> list = importResult.getData();
int usedTitleRows = importResult.getTitleRows();
int usedHeadRows = importResult.getHeadRows();
int usedSheetIndex = importResult.getSheetIndex();
if (CollectionUtils.isEmpty(list)) {
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
@@ -158,6 +160,7 @@ public class CreditCompetitorController extends BaseController {
User loginUser = getLoginUser();
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
Map<String, String> urlByCompanyName = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "企业名称");
final int chunkSize = 500;
final int mpBatchSize = 500;
@@ -168,6 +171,12 @@ public class CreditCompetitorController extends BaseController {
CreditCompetitorImportParam param = list.get(i);
try {
CreditCompetitor item = convertImportParamToEntity(param);
if (!ImportHelper.isBlank(item.getCompanyName())) {
String link = urlByCompanyName.get(item.getCompanyName().trim());
if (!ImportHelper.isBlank(link)) {
item.setUrl(link.trim());
}
}
if (item.getCompanyId() == null && companyId != null) {
item.setCompanyId(companyId);

View File

@@ -23,6 +23,7 @@ import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 法院公告司法大数据控制器
@@ -149,6 +150,7 @@ public class CreditCourtAnnouncementController extends BaseController {
List<CreditCourtAnnouncementImportParam> list = importResult.getData();
int usedTitleRows = importResult.getTitleRows();
int usedHeadRows = importResult.getHeadRows();
int usedSheetIndex = importResult.getSheetIndex();
if (CollectionUtils.isEmpty(list)) {
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
@@ -157,6 +159,7 @@ public class CreditCourtAnnouncementController extends BaseController {
User loginUser = getLoginUser();
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
final int chunkSize = 500;
final int mpBatchSize = 500;
@@ -167,6 +170,12 @@ public class CreditCourtAnnouncementController extends BaseController {
CreditCourtAnnouncementImportParam param = list.get(i);
try {
CreditCourtAnnouncement item = convertImportParamToEntity(param);
if (!ImportHelper.isBlank(item.getCaseNumber())) {
String link = urlByCaseNumber.get(item.getCaseNumber().trim());
if (!ImportHelper.isBlank(link)) {
item.setUrl(link.trim());
}
}
if (item.getCompanyId() == null && companyId != null) {
item.setCompanyId(companyId);

View File

@@ -23,6 +23,7 @@ import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 开庭公告司法大数据控制器
@@ -149,6 +150,7 @@ public class CreditCourtSessionController extends BaseController {
List<CreditCourtSessionImportParam> list = importResult.getData();
int usedTitleRows = importResult.getTitleRows();
int usedHeadRows = importResult.getHeadRows();
int usedSheetIndex = importResult.getSheetIndex();
if (CollectionUtils.isEmpty(list)) {
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
@@ -157,6 +159,7 @@ public class CreditCourtSessionController extends BaseController {
User loginUser = getLoginUser();
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
final int chunkSize = 500;
final int mpBatchSize = 500;
@@ -167,6 +170,12 @@ public class CreditCourtSessionController extends BaseController {
CreditCourtSessionImportParam param = list.get(i);
try {
CreditCourtSession item = convertImportParamToEntity(param);
if (!ImportHelper.isBlank(item.getCaseNumber())) {
String link = urlByCaseNumber.get(item.getCaseNumber().trim());
if (!ImportHelper.isBlank(link)) {
item.setUrl(link.trim());
}
}
if (item.getCompanyId() == null && companyId != null) {
item.setCompanyId(companyId);

View File

@@ -24,6 +24,7 @@ import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 客户控制器
@@ -146,6 +147,7 @@ public class CreditCustomerController extends BaseController {
List<CreditCustomerImportParam> list = importResult.getData();
int usedTitleRows = importResult.getTitleRows();
int usedHeadRows = importResult.getHeadRows();
int usedSheetIndex = importResult.getSheetIndex();
if (CollectionUtils.isEmpty(list)) {
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
@@ -154,6 +156,7 @@ public class CreditCustomerController extends BaseController {
User loginUser = getLoginUser();
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
Map<String, String> urlByName = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "客户");
final int chunkSize = 500;
final int mpBatchSize = 500;
@@ -165,6 +168,12 @@ public class CreditCustomerController extends BaseController {
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
try {
CreditCustomer item = convertImportParamToEntity(param);
if (!ImportHelper.isBlank(item.getName())) {
String link = urlByName.get(item.getName().trim());
if (!ImportHelper.isBlank(link)) {
item.setUrl(link.trim());
}
}
if (item.getCompanyId() == null && companyId != null) {
item.setCompanyId(companyId);

View File

@@ -23,6 +23,7 @@ import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 对外投资控制器
@@ -150,6 +151,7 @@ public class CreditExternalController extends BaseController {
List<CreditExternalImportParam> list = importResult.getData();
int usedTitleRows = importResult.getTitleRows();
int usedHeadRows = importResult.getHeadRows();
int usedSheetIndex = importResult.getSheetIndex();
if (CollectionUtils.isEmpty(list)) {
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
@@ -158,6 +160,7 @@ public class CreditExternalController extends BaseController {
User loginUser = getLoginUser();
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
Map<String, String> urlByName = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "被投资企业名称");
final int chunkSize = 500;
final int mpBatchSize = 500;
@@ -168,6 +171,12 @@ public class CreditExternalController extends BaseController {
CreditExternalImportParam param = list.get(i);
try {
CreditExternal item = convertImportParamToEntity(param);
if (!ImportHelper.isBlank(item.getName())) {
String link = urlByName.get(item.getName().trim());
if (!ImportHelper.isBlank(link)) {
item.setUrl(link.trim());
}
}
if (item.getCompanyId() == null && companyId != null) {
item.setCompanyId(companyId);

View File

@@ -23,6 +23,7 @@ import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 终本案件控制器
@@ -151,6 +152,7 @@ public class CreditFinalVersionController extends BaseController {
List<CreditFinalVersionImportParam> list = importResult.getData();
int usedTitleRows = importResult.getTitleRows();
int usedHeadRows = importResult.getHeadRows();
int usedSheetIndex = importResult.getSheetIndex();
if (CollectionUtils.isEmpty(list)) {
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
@@ -159,6 +161,7 @@ public class CreditFinalVersionController extends BaseController {
User loginUser = getLoginUser();
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
final int chunkSize = 500;
final int mpBatchSize = 500;
@@ -169,6 +172,12 @@ public class CreditFinalVersionController extends BaseController {
CreditFinalVersionImportParam param = list.get(i);
try {
CreditFinalVersion item = convertImportParamToEntity(param);
if (!ImportHelper.isBlank(item.getCaseNumber())) {
String link = urlByCaseNumber.get(item.getCaseNumber().trim());
if (!ImportHelper.isBlank(link)) {
item.setUrl(link.trim());
}
}
if (item.getCompanyId() == null && companyId != null) {
item.setCompanyId(companyId);

View File

@@ -160,9 +160,25 @@ public class CreditGqdjController extends BaseController {
User loginUser = getLoginUser();
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
// easypoi 默认不会读取单元格超链接地址url 通常挂在“号”列的超链接中,需要额外读取回填。
// easypoi 默认不会读取单元格超链接地址url 通常挂在“执行通知文书号”列的超链接中,需要额外读取回填。
String caseNumberHeader = "执行通知文书号";
Map<String, String> urlByCaseNumber = ExcelImportSupport.readHyperlinksByHeaderKey(
file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
file, usedSheetIndex, usedTitleRows, usedHeadRows, caseNumberHeader);
// 有些源文件会单独提供“url/网址/链接”等列(可能是纯文本也可能是超链接)
Map<String, String> urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
file, usedSheetIndex, usedTitleRows, usedHeadRows, caseNumberHeader, "url");
if (urlByCaseNumberFromUrlCol.isEmpty()) {
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
file, usedSheetIndex, usedTitleRows, usedHeadRows, caseNumberHeader, "URL");
}
if (urlByCaseNumberFromUrlCol.isEmpty()) {
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
file, usedSheetIndex, usedTitleRows, usedHeadRows, caseNumberHeader, "网址");
}
if (urlByCaseNumberFromUrlCol.isEmpty()) {
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
file, usedSheetIndex, usedTitleRows, usedHeadRows, caseNumberHeader, "链接");
}
final int chunkSize = 500;
final int mpBatchSize = 500;
@@ -174,7 +190,11 @@ public class CreditGqdjController extends BaseController {
try {
CreditGqdj item = convertImportParamToEntity(param);
if (!ImportHelper.isBlank(item.getCaseNumber())) {
String link = urlByCaseNumber.get(item.getCaseNumber().trim());
String key = item.getCaseNumber().trim();
String link = urlByCaseNumber.get(key);
if (ImportHelper.isBlank(link)) {
link = urlByCaseNumberFromUrlCol.get(key);
}
if (link != null && !link.isEmpty()) {
item.setUrl(link);
}

View File

@@ -23,6 +23,7 @@ import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 裁判文书司法大数据控制器
@@ -149,6 +150,7 @@ public class CreditJudicialDocumentController extends BaseController {
List<CreditJudicialDocumentImportParam> list = importResult.getData();
int usedTitleRows = importResult.getTitleRows();
int usedHeadRows = importResult.getHeadRows();
int usedSheetIndex = importResult.getSheetIndex();
if (CollectionUtils.isEmpty(list)) {
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
@@ -157,6 +159,8 @@ public class CreditJudicialDocumentController extends BaseController {
User loginUser = getLoginUser();
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
Map<String, String> urlByTitle = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "文书标题");
final int chunkSize = 500;
final int mpBatchSize = 500;
@@ -167,6 +171,16 @@ public class CreditJudicialDocumentController extends BaseController {
CreditJudicialDocumentImportParam param = list.get(i);
try {
CreditJudicialDocument item = convertImportParamToEntity(param);
String link = null;
if (!ImportHelper.isBlank(item.getCaseNumber())) {
link = urlByCaseNumber.get(item.getCaseNumber().trim());
}
if (ImportHelper.isBlank(link) && !ImportHelper.isBlank(item.getTitle())) {
link = urlByTitle.get(item.getTitle().trim());
}
if (!ImportHelper.isBlank(link)) {
item.setUrl(link.trim());
}
if (item.getCompanyId() == null && companyId != null) {
item.setCompanyId(companyId);

View File

@@ -27,6 +27,7 @@ import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 司法案件控制器
@@ -163,6 +164,20 @@ public class CreditJudiciaryController extends BaseController {
User loginUser = getLoginUser();
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
// easypoi 默认不会读取单元格超链接地址url 可能挂在“案号/案件名称”等列的超链接中,需要额外读取回填。
Map<String, String> urlByCode = ExcelImportSupport.readHyperlinksByHeaderKey(file, 0, usedTitleRows, usedHeadRows, "案号");
Map<String, String> urlByName = ExcelImportSupport.readHyperlinksByHeaderKey(file, 0, usedTitleRows, usedHeadRows, "案件名称");
// 有些源文件会单独提供“url/网址/链接”等列(可能是纯文本也可能是超链接)
Map<String, String> urlByCodeFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(file, 0, usedTitleRows, usedHeadRows, "案号", "url");
if (urlByCodeFromUrlCol.isEmpty()) {
urlByCodeFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(file, 0, usedTitleRows, usedHeadRows, "案号", "URL");
}
if (urlByCodeFromUrlCol.isEmpty()) {
urlByCodeFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(file, 0, usedTitleRows, usedHeadRows, "案号", "网址");
}
if (urlByCodeFromUrlCol.isEmpty()) {
urlByCodeFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(file, 0, usedTitleRows, usedHeadRows, "案号", "链接");
}
final int chunkSize = 500;
final int mpBatchSize = 500;
@@ -173,6 +188,21 @@ public class CreditJudiciaryController extends BaseController {
CreditJudiciaryImportParam param = list.get(i);
try {
CreditJudiciary item = convertImportParamToEntity(param);
if (!isBlank(item.getCode())) {
String key = item.getCode().trim();
String link = urlByCode.get(key);
if (isBlank(link)) {
link = urlByCodeFromUrlCol.get(key);
}
if (!isBlank(link)) {
item.setUrl(link.trim());
}
} else if (!isBlank(item.getName())) {
String link = urlByName.get(item.getName().trim());
if (!isBlank(link)) {
item.setUrl(link.trim());
}
}
if (item.getCompanyId() == null && companyId != null) {
item.setCompanyId(companyId);
}

View File

@@ -160,9 +160,7 @@ public class CreditMediationController extends BaseController {
User loginUser = getLoginUser();
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
// URL 通常以超链接形式存在于“案号”列里
Map<String, String> urlByCaseNumber = ExcelImportSupport.readHyperlinksByHeaderKey(
file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
final int chunkSize = 500;
final int mpBatchSize = 500;
@@ -175,8 +173,8 @@ public class CreditMediationController extends BaseController {
CreditMediation item = convertImportParamToEntity(param);
if (!ImportHelper.isBlank(item.getCaseNumber())) {
String link = urlByCaseNumber.get(item.getCaseNumber().trim());
if (link != null && !link.isEmpty()) {
item.setUrl(link);
if (!ImportHelper.isBlank(link)) {
item.setUrl(link.trim());
}
}

View File

@@ -23,6 +23,7 @@ import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 供应商控制器
@@ -150,6 +151,7 @@ public class CreditSupplierController extends BaseController {
List<CreditSupplierImportParam> list = importResult.getData();
int usedTitleRows = importResult.getTitleRows();
int usedHeadRows = importResult.getHeadRows();
int usedSheetIndex = importResult.getSheetIndex();
if (CollectionUtils.isEmpty(list)) {
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
@@ -158,6 +160,7 @@ public class CreditSupplierController extends BaseController {
User loginUser = getLoginUser();
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
Map<String, String> urlBySupplier = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "供应商");
final int chunkSize = 500;
final int mpBatchSize = 500;
@@ -168,6 +171,12 @@ public class CreditSupplierController extends BaseController {
CreditSupplierImportParam param = list.get(i);
try {
CreditSupplier item = convertImportParamToEntity(param);
if (!ImportHelper.isBlank(item.getSupplier())) {
String link = urlBySupplier.get(item.getSupplier().trim());
if (!ImportHelper.isBlank(link)) {
item.setUrl(link.trim());
}
}
if (item.getCompanyId() == null && companyId != null) {
item.setCompanyId(companyId);

View File

@@ -23,6 +23,7 @@ import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 限制高消费控制器
@@ -150,6 +151,7 @@ public class CreditXgxfController extends BaseController {
List<CreditXgxfImportParam> list = importResult.getData();
int usedTitleRows = importResult.getTitleRows();
int usedHeadRows = importResult.getHeadRows();
int usedSheetIndex = importResult.getSheetIndex();
if (CollectionUtils.isEmpty(list)) {
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
@@ -158,6 +160,8 @@ public class CreditXgxfController extends BaseController {
User loginUser = getLoginUser();
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
// easypoi 默认不会读取单元格超链接地址url 可能挂在“案号”等列的超链接中,或单独提供 url/网址/链接 列。
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
final int chunkSize = 500;
final int mpBatchSize = 500;
@@ -168,6 +172,12 @@ public class CreditXgxfController extends BaseController {
CreditXgxfImportParam param = list.get(i);
try {
CreditXgxf item = convertImportParamToEntity(param);
if (!ImportHelper.isBlank(item.getCaseNumber())) {
String link = urlByCaseNumber.get(item.getCaseNumber().trim());
if (!ImportHelper.isBlank(link)) {
item.setUrl(link.trim());
}
}
if (item.getCompanyId() == null && companyId != null) {
item.setCompanyId(companyId);

View File

@@ -287,6 +287,109 @@ public class ExcelImportSupport {
}
}
/**
* 读取两列(由表头名定位)的文本/超链接返回key列显示值 -> value列优先超链接地址其次单元格文本
*
* <p>适用于Excel 把 url 放在单独一列(可能是纯文本,也可能是超链接)。</p>
*/
public static Map<String, String> readKeyValueByHeaders(MultipartFile file,
int sheetIndex,
int titleRows,
int headRows,
String keyHeaderName,
String valueHeaderName) throws Exception {
if (file == null
|| keyHeaderName == null || keyHeaderName.trim().isEmpty()
|| valueHeaderName == null || valueHeaderName.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 keyCol = findColumnIndexByHeader(sheet, titleRows, headRows, keyHeaderName);
int valCol = findColumnIndexByHeader(sheet, titleRows, headRows, valueHeaderName);
if (keyCol < 0 || valCol < 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 keyCell = row.getCell(keyCol);
if (keyCell == null) {
continue;
}
String key = formatter.formatCellValue(keyCell);
if (key == null || key.trim().isEmpty()) {
continue;
}
Cell valCell = row.getCell(valCol);
if (valCell == null) {
continue;
}
String value = extractHyperlinkAddress(valCell);
if (value == null || value.trim().isEmpty()) {
value = formatter.formatCellValue(valCell);
}
if (value == null || value.trim().isEmpty()) {
continue;
}
result.put(key.trim(), value.trim());
}
return result;
}
}
/**
* 读取“key列 -> url”的映射
* - 优先读取 key 列自身的超链接url 常挂在名称/案号等列的超链接里)
* - 如果源文件提供独立的 url/URL/网址/链接/链接地址 等列,则读取该列(支持文本或超链接)
*/
public static Map<String, String> readUrlByKey(MultipartFile file,
int sheetIndex,
int titleRows,
int headRows,
String keyHeaderName) throws Exception {
if (file == null || keyHeaderName == null || keyHeaderName.trim().isEmpty()) {
return Collections.emptyMap();
}
Map<String, String> result = new HashMap<>();
// 1) url 挂在 key 列超链接里(最常见)
Map<String, String> fromKeyHyperlinks = readHyperlinksByHeaderKey(file, sheetIndex, titleRows, headRows, keyHeaderName);
if (!fromKeyHyperlinks.isEmpty()) {
result.putAll(fromKeyHyperlinks);
}
// 2) url 作为单独一列(多种表头命名)
String[] urlHeaders = new String[]{"url", "URL", "网址", "链接", "链接地址"};
for (String urlHeader : urlHeaders) {
Map<String, String> fromUrlCol = readKeyValueByHeaders(file, sheetIndex, titleRows, headRows, keyHeaderName, urlHeader);
if (fromUrlCol.isEmpty()) {
continue;
}
for (Map.Entry<String, String> entry : fromUrlCol.entrySet()) {
// 不覆盖已从 key 超链接读取到的地址
result.putIfAbsent(entry.getKey(), entry.getValue());
}
}
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);

View File

@@ -37,7 +37,7 @@ public class CreditAdministrativeLicense implements Serializable {
@Schema(description = "许可状态")
private String statusText;
@Schema(description = "许可类")
@Schema(description = "许可类")
private String type;
@Schema(description = "链接")

View File

@@ -33,6 +33,9 @@ public class CreditBreachOfTrust implements Serializable {
@Schema(description = "案号")
private String caseNumber;
@Schema(description = "链接地址")
private String url;
@Schema(description = "失信被执行人")
private String plaintiffAppellant;

View File

@@ -33,18 +33,6 @@ public class CreditCompany implements Serializable {
@Schema(description = "系统匹配企业名称")
private String matchName;
@Schema(description = "统一社会信用代码")
private String code;
@Schema(description = "项目网址")
private String url;
@Schema(description = "类型")
private Integer type;
@Schema(description = "上级id, 0是顶级")
private Integer parentId;
@Schema(description = "登记状态")
private String registrationStatus;
@@ -60,9 +48,21 @@ public class CreditCompany implements Serializable {
@Schema(description = "成立日期")
private String establishDate;
@Schema(description = "统一社会信用代码")
private String code;
@Schema(description = "企业地址")
private String address;
@Schema(description = "所属省份")
private String province;
@Schema(description = "所属城市")
private String city;
@Schema(description = "所属区县")
private String region;
@Schema(description = "电话")
private String tel;
@@ -75,18 +75,6 @@ public class CreditCompany implements Serializable {
@Schema(description = "更多邮箱")
private String moreEmail;
@Schema(description = "所在国家")
private String country;
@Schema(description = "所属省份")
private String province;
@Schema(description = "所属城市")
private String city;
@Schema(description = "所属区县")
private String region;
@Schema(description = "企业(机构)类型")
private String institutionType;
@@ -180,6 +168,19 @@ public class CreditCompany implements Serializable {
@Schema(description = "是否小微企业")
private String smallEnterprise;
@Schema(description = "项目网址")
private String url;
@Schema(description = "类型")
private Integer type;
@Schema(description = "上级id, 0是顶级")
private Integer parentId;
@Schema(description = "所在国家")
private String country;
@Schema(description = "备注")
private String comments;

View File

@@ -33,6 +33,9 @@ public class CreditCompetitor implements Serializable {
@Schema(description = "企业名称")
private String companyName;
@Schema(description = "链接地址")
private String url;
@Schema(description = "法定代表人")
private String legalRepresentative;

View File

@@ -49,6 +49,9 @@ public class CreditCourtAnnouncement implements Serializable {
@Schema(description = "案号")
private String caseNumber;
@Schema(description = "链接地址")
private String url;
@Schema(description = "案由")
private String causeOfAction;

View File

@@ -33,6 +33,9 @@ public class CreditCustomer implements Serializable {
@Schema(description = "客户")
private String name;
@Schema(description = "链接地址")
private String url;
@Schema(description = "状态")
private String statusTxt;

View File

@@ -33,6 +33,9 @@ public class CreditFinalVersion implements Serializable {
@Schema(description = "案号")
private String caseNumber;
@Schema(description = "链接地址")
private String url;
@Schema(description = "被执行人")
private String appellee;

View File

@@ -36,6 +36,9 @@ public class CreditJudicialDocument implements Serializable {
@Schema(description = "案号")
private String caseNumber;
@Schema(description = "链接地址")
private String url;
@Schema(description = "案由")
private String causeOfAction;

View File

@@ -34,6 +34,9 @@ public class CreditJudiciary implements Serializable {
@Schema(description = "案号")
private String code;
@Schema(description = "详情链接")
private String url;
@Schema(description = "类型, 0普通用户, 1招投标")
private Integer type;

View File

@@ -33,6 +33,9 @@ public class CreditSupplier implements Serializable {
@Schema(description = "供应商")
private String supplier;
@Schema(description = "链接地址")
private String url;
@Schema(description = "状态")
private String statusTxt;

View File

@@ -33,6 +33,9 @@ public class CreditXgxf implements Serializable {
@Schema(description = "案号")
private String caseNumber;
@Schema(description = "链接地址")
private String url;
@Schema(description = "限消令对象")
private String dataType;

View File

@@ -21,7 +21,7 @@ public class CreditAdministrativeLicenseImportParam implements Serializable {
@Excel(name = "许可状态")
private String statusText;
@Excel(name = "许可类")
@Excel(name = "许可类")
private String type;
@Excel(name = "有效期自")

View File

@@ -34,7 +34,7 @@ public class CreditAdministrativeLicenseParam extends BaseParam {
@Schema(description = "许可状态")
private String statusText;
@Schema(description = "许可类")
@Schema(description = "许可类")
private String type;
@Schema(description = "链接")