|
|
@@ -6,14 +6,34 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.poi.ss.usermodel.*;
|
|
|
+import org.apache.poi.ss.util.CellRangeAddress;
|
|
|
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
|
|
+import org.springframework.beans.BeanUtils;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
import org.springframework.util.StringUtils;
|
|
|
+import org.springframework.web.multipart.MultipartFile;
|
|
|
import shop.alien.entity.result.R;
|
|
|
import shop.alien.entity.store.LawFirm;
|
|
|
+import shop.alien.entity.store.excelVo.LawFirmExcelVo;
|
|
|
+import shop.alien.entity.store.excelVo.util.ExcelHeader;
|
|
|
import shop.alien.lawyer.service.LawFirmService;
|
|
|
import shop.alien.mapper.LawFirmMapper;
|
|
|
|
|
|
+import org.apache.poi.ss.usermodel.DateUtil;
|
|
|
+
|
|
|
+import javax.servlet.http.HttpServletResponse;
|
|
|
+import java.io.IOException;
|
|
|
+import java.io.InputStream;
|
|
|
+import java.io.OutputStream;
|
|
|
+import java.lang.reflect.Field;
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.net.URLEncoder;
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
/**
|
|
|
* 律所表 服务实现类
|
|
|
*
|
|
|
@@ -157,6 +177,689 @@ public class LawFirmServiceImpl extends ServiceImpl<LawFirmMapper, LawFirm> impl
|
|
|
}
|
|
|
return R.fail("注册失败,请稍后重试");
|
|
|
}
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public R<String> exportLawFirm(HttpServletResponse response) {
|
|
|
+ log.info("LawFirmServiceImpl.exportLawFirm");
|
|
|
+ try {
|
|
|
+ // 查询所有未删除的律所
|
|
|
+ LambdaQueryWrapper<LawFirm> queryWrapper = new LambdaQueryWrapper<>();
|
|
|
+ queryWrapper.eq(LawFirm::getDeleteFlag, 0);
|
|
|
+ queryWrapper.orderByDesc(LawFirm::getCreatedTime);
|
|
|
+ List<LawFirm> lawFirmList = this.list(queryWrapper);
|
|
|
+
|
|
|
+ if (lawFirmList.isEmpty()) {
|
|
|
+ return R.fail("暂无数据可导出");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 按律所名称分组
|
|
|
+ Map<String, List<LawFirm>> firmNameMap = lawFirmList.stream()
|
|
|
+ .collect(Collectors.groupingBy(LawFirm::getFirmName));
|
|
|
+
|
|
|
+ // 转换为ExcelVo,相同律所名称的每个账号一行
|
|
|
+ List<LawFirmExcelVo> excelVoList = new ArrayList<>();
|
|
|
+ int serialNumber = 0;
|
|
|
+ SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
|
|
|
+ SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
|
|
+
|
|
|
+ for (Map.Entry<String, List<LawFirm>> entry : firmNameMap.entrySet()) {
|
|
|
+ List<LawFirm> firms = entry.getValue();
|
|
|
+ // 合并所有账号
|
|
|
+ String allPaymentAccounts = firms.stream()
|
|
|
+ .map(LawFirm::getPaymentAccount)
|
|
|
+ .filter(Objects::nonNull)
|
|
|
+ .filter(acc -> !acc.trim().isEmpty())
|
|
|
+ .distinct()
|
|
|
+ .collect(Collectors.joining(","));
|
|
|
+
|
|
|
+ // 为每个账号创建一行(如果账号为空,至少创建一行)
|
|
|
+ if (firms.isEmpty()) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果账号为空或只有一个账号,创建一行
|
|
|
+ if (allPaymentAccounts.isEmpty() || !allPaymentAccounts.contains(",")) {
|
|
|
+ LawFirm firstFirm = firms.get(0);
|
|
|
+ LawFirmExcelVo excelVo = convertToExcelVo(firstFirm, ++serialNumber, dateFormat, dateTimeFormat);
|
|
|
+ excelVo.setPaymentAccount(allPaymentAccounts);
|
|
|
+ excelVoList.add(excelVo);
|
|
|
+ } else {
|
|
|
+ // 多个账号,每个账号一行
|
|
|
+ String[] accounts = allPaymentAccounts.split(",");
|
|
|
+ for (int i = 0; i < accounts.length; i++) {
|
|
|
+ LawFirm firstFirm = firms.get(0);
|
|
|
+ LawFirmExcelVo excelVo = convertToExcelVo(firstFirm, ++serialNumber, dateFormat, dateTimeFormat);
|
|
|
+ excelVo.setPaymentAccount(accounts[i].trim());
|
|
|
+ excelVoList.add(excelVo);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 生成Excel
|
|
|
+ generateExcelWithMerge(response, excelVoList, firmNameMap);
|
|
|
+
|
|
|
+ return R.success("导出成功");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("导出律所数据失败", e);
|
|
|
+ return R.fail("导出失败:" + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public R<String> importLawFirm(MultipartFile file) {
|
|
|
+ log.info("LawFirmServiceImpl.importLawFirm fileName={}", file.getOriginalFilename());
|
|
|
+ try {
|
|
|
+ if (file == null || file.isEmpty()) {
|
|
|
+ return R.fail("文件不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ String fileName = file.getOriginalFilename();
|
|
|
+ if (fileName == null || (!fileName.endsWith(".xlsx") && !fileName.endsWith(".xls"))) {
|
|
|
+ return R.fail("文件格式不正确,请上传Excel文件");
|
|
|
+ }
|
|
|
+
|
|
|
+ List<LawFirmExcelVo> excelVoList = new ArrayList<>();
|
|
|
+ List<String> errorMessages = new ArrayList<>();
|
|
|
+
|
|
|
+ // 使用POI读取Excel
|
|
|
+ try (InputStream inputStream = file.getInputStream();
|
|
|
+ Workbook workbook = new XSSFWorkbook(inputStream)) {
|
|
|
+ Sheet sheet = workbook.getSheetAt(0);
|
|
|
+
|
|
|
+ // 获取表头
|
|
|
+ Row headerRow = sheet.getRow(0);
|
|
|
+ if (headerRow == null) {
|
|
|
+ return R.fail("Excel文件格式不正确,缺少表头");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 构建字段映射(表头名称 -> 列索引)
|
|
|
+ Map<String, Integer> headerMap = new HashMap<>();
|
|
|
+ Field[] fields = LawFirmExcelVo.class.getDeclaredFields();
|
|
|
+ for (int i = 0; i < headerRow.getLastCellNum(); i++) {
|
|
|
+ Cell cell = headerRow.getCell(i);
|
|
|
+ if (cell != null) {
|
|
|
+ String headerName = cell.getStringCellValue().trim();
|
|
|
+ headerMap.put(headerName, i);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 读取数据行
|
|
|
+ for (int rowIndex = 1; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
|
|
|
+ Row row = sheet.getRow(rowIndex);
|
|
|
+ if (row == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查是否为空行
|
|
|
+ boolean isEmptyRow = true;
|
|
|
+ for (int i = 0; i < row.getLastCellNum(); i++) {
|
|
|
+ Cell cell = row.getCell(i);
|
|
|
+ if (cell != null && cell.getCellType() != CellType.BLANK) {
|
|
|
+ isEmptyRow = false;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (isEmptyRow) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ LawFirmExcelVo excelVo = new LawFirmExcelVo();
|
|
|
+
|
|
|
+ // 读取每个字段
|
|
|
+ for (Field field : fields) {
|
|
|
+ if (!field.isAnnotationPresent(ExcelHeader.class)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ ExcelHeader excelHeader = field.getAnnotation(ExcelHeader.class);
|
|
|
+ String headerName = excelHeader.value();
|
|
|
+ Integer colIndex = headerMap.get(headerName);
|
|
|
+ if (colIndex == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ Cell cell = row.getCell(colIndex);
|
|
|
+ if (cell == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ field.setAccessible(true);
|
|
|
+ try {
|
|
|
+ String cellValue = getCellValueAsString(cell);
|
|
|
+ if (cellValue != null && !cellValue.trim().isEmpty()) {
|
|
|
+ // 根据字段类型设置值
|
|
|
+ Class<?> fieldType = field.getType();
|
|
|
+ if (fieldType == String.class) {
|
|
|
+ field.set(excelVo, cellValue.trim());
|
|
|
+ } else if (fieldType == Integer.class) {
|
|
|
+ try {
|
|
|
+ field.set(excelVo, Integer.parseInt(cellValue.trim()));
|
|
|
+ } catch (NumberFormatException e) {
|
|
|
+ // 忽略
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("读取字段{}失败:{}", headerName, e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 校验数据
|
|
|
+ String errorMsg = validateExcelData(excelVo, rowIndex + 1);
|
|
|
+ if (errorMsg != null) {
|
|
|
+ errorMessages.add(errorMsg);
|
|
|
+ } else {
|
|
|
+ excelVoList.add(excelVo);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!errorMessages.isEmpty()) {
|
|
|
+ return R.fail("数据校验失败:\n" + String.join("\n", errorMessages));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (excelVoList.isEmpty()) {
|
|
|
+ return R.fail("Excel文件中没有有效数据");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 收集所有导入数据中的收款账号(用于检查重复)
|
|
|
+ Set<String> allImportAccounts = new HashSet<>();
|
|
|
+ Map<String, String> accountToFirmNameMap = new HashMap<>(); // 账号 -> 律所名称,用于错误提示
|
|
|
+
|
|
|
+ // 先收集所有账号,检查导入数据中的重复
|
|
|
+ for (LawFirmExcelVo excelVo : excelVoList) {
|
|
|
+ String paymentAccount = excelVo.getPaymentAccount();
|
|
|
+ if (StringUtils.hasText(paymentAccount)) {
|
|
|
+ // 账号可能包含多个,用逗号分隔
|
|
|
+ String[] accounts = paymentAccount.split(",");
|
|
|
+ for (String account : accounts) {
|
|
|
+ String trimmedAccount = account.trim();
|
|
|
+ if (!trimmedAccount.isEmpty()) {
|
|
|
+ if (allImportAccounts.contains(trimmedAccount)) {
|
|
|
+ // 发现重复账号
|
|
|
+ String existingFirmName = accountToFirmNameMap.get(trimmedAccount);
|
|
|
+ return R.fail(String.format("导入数据中存在重复的收款账号[%s],律所[%s]和律所[%s]使用了相同的账号,无法导入",
|
|
|
+ trimmedAccount, existingFirmName, excelVo.getFirmName()));
|
|
|
+ }
|
|
|
+ allImportAccounts.add(trimmedAccount);
|
|
|
+ accountToFirmNameMap.put(trimmedAccount, excelVo.getFirmName());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查数据库中是否已存在这些账号
|
|
|
+ if (!allImportAccounts.isEmpty()) {
|
|
|
+ // 查询数据库中所有已存在的收款账号
|
|
|
+ LambdaQueryWrapper<LawFirm> queryWrapper = new LambdaQueryWrapper<>();
|
|
|
+ queryWrapper.eq(LawFirm::getDeleteFlag, 0);
|
|
|
+ queryWrapper.isNotNull(LawFirm::getPaymentAccount);
|
|
|
+ queryWrapper.ne(LawFirm::getPaymentAccount, "");
|
|
|
+ List<LawFirm> existingLawFirms = this.list(queryWrapper);
|
|
|
+
|
|
|
+ // 收集数据库中所有已存在的账号
|
|
|
+ Set<String> existingAccounts = new HashSet<>();
|
|
|
+ for (LawFirm firm : existingLawFirms) {
|
|
|
+ String paymentAccount = firm.getPaymentAccount();
|
|
|
+ if (StringUtils.hasText(paymentAccount)) {
|
|
|
+ String[] accounts = paymentAccount.split(",");
|
|
|
+ for (String account : accounts) {
|
|
|
+ String trimmedAccount = account.trim();
|
|
|
+ if (!trimmedAccount.isEmpty()) {
|
|
|
+ existingAccounts.add(trimmedAccount);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查导入的账号是否已存在
|
|
|
+ Set<String> duplicateAccounts = new HashSet<>();
|
|
|
+ for (String importAccount : allImportAccounts) {
|
|
|
+ if (existingAccounts.contains(importAccount)) {
|
|
|
+ duplicateAccounts.add(importAccount);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!duplicateAccounts.isEmpty()) {
|
|
|
+ String duplicateAccountList = String.join("、", duplicateAccounts);
|
|
|
+ return R.fail(String.format("收款账号[%s]在数据库中已存在,无法导入。请检查并修改账号后重新导入", duplicateAccountList));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 按律所名称分组,合并账号
|
|
|
+ Map<String, List<LawFirmExcelVo>> firmNameMap = excelVoList.stream()
|
|
|
+ .collect(Collectors.groupingBy(LawFirmExcelVo::getFirmName));
|
|
|
+
|
|
|
+ int successCount = 0;
|
|
|
+ int failCount = 0;
|
|
|
+ List<String> importErrors = new ArrayList<>();
|
|
|
+
|
|
|
+ for (Map.Entry<String, List<LawFirmExcelVo>> entry : firmNameMap.entrySet()) {
|
|
|
+ String firmName = entry.getKey();
|
|
|
+ List<LawFirmExcelVo> voList = entry.getValue();
|
|
|
+
|
|
|
+ // 合并账号
|
|
|
+ String paymentAccounts = voList.stream()
|
|
|
+ .map(LawFirmExcelVo::getPaymentAccount)
|
|
|
+ .filter(Objects::nonNull)
|
|
|
+ .filter(acc -> !acc.trim().isEmpty())
|
|
|
+ .distinct()
|
|
|
+ .collect(Collectors.joining(","));
|
|
|
+
|
|
|
+ // 使用第一个数据作为主数据
|
|
|
+ LawFirmExcelVo firstVo = voList.get(0);
|
|
|
+ LawFirm lawFirm = convertToLawFirm(firstVo);
|
|
|
+ lawFirm.setPaymentAccount(paymentAccounts);
|
|
|
+
|
|
|
+ // 校验统一社会信用代码是否已存在
|
|
|
+// LambdaQueryWrapper<LawFirm> creditCodeWrapper = new LambdaQueryWrapper<>();
|
|
|
+// creditCodeWrapper.eq(LawFirm::getCreditCode, lawFirm.getCreditCode());
|
|
|
+// creditCodeWrapper.eq(LawFirm::getDeleteFlag, 0);
|
|
|
+// long creditCodeCount = this.count(creditCodeWrapper);
|
|
|
+// if (creditCodeCount > 0) {
|
|
|
+// importErrors.add("律所[" + firmName + "]的统一社会信用代码[" + lawFirm.getCreditCode() + "]已存在");
|
|
|
+// failCount++;
|
|
|
+// continue;
|
|
|
+// }
|
|
|
+
|
|
|
+ // 设置默认值
|
|
|
+ if (lawFirm.getStatus() == null) {
|
|
|
+ lawFirm.setStatus(1);
|
|
|
+ }
|
|
|
+// if (lawFirm.getCertificationStatus() == null) {
|
|
|
+// lawFirm.setCertificationStatus(0);
|
|
|
+// }
|
|
|
+ if (lawFirm.getDeleteFlag() == null) {
|
|
|
+ lawFirm.setDeleteFlag(0);
|
|
|
+ }
|
|
|
+// if (lawFirm.getIsRecommended() == null) {
|
|
|
+// lawFirm.setIsRecommended(0);
|
|
|
+// }
|
|
|
+// if (lawFirm.getLawyerCount() == null) {
|
|
|
+// lawFirm.setLawyerCount(0);
|
|
|
+// }
|
|
|
+// if (lawFirm.getPartnerCount() == null) {
|
|
|
+// lawFirm.setPartnerCount(0);
|
|
|
+// }
|
|
|
+// if (lawFirm.getPlatformCommissionRatio() == null) {
|
|
|
+// lawFirm.setPlatformCommissionRatio(new BigDecimal("3.00"));
|
|
|
+// }
|
|
|
+
|
|
|
+ // 保存
|
|
|
+ boolean result = this.save(lawFirm);
|
|
|
+ if (result) {
|
|
|
+ successCount++;
|
|
|
+ } else {
|
|
|
+ importErrors.add("律所[" + firmName + "]保存失败");
|
|
|
+ failCount++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ String resultMsg = String.format("导入完成:成功%d条,失败%d条", successCount, failCount);
|
|
|
+ if (!importErrors.isEmpty()) {
|
|
|
+ resultMsg += "\n失败详情:\n" + String.join("\n", importErrors);
|
|
|
+ }
|
|
|
+
|
|
|
+ return R.success(resultMsg);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("导入律所数据失败", e);
|
|
|
+ return R.fail("导入失败:" + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成带合并单元格的Excel
|
|
|
+ */
|
|
|
+ private void generateExcelWithMerge(HttpServletResponse response, List<LawFirmExcelVo> excelVoList,
|
|
|
+ Map<String, List<LawFirm>> firmNameMap) throws IOException {
|
|
|
+ XSSFWorkbook workbook = new XSSFWorkbook();
|
|
|
+ Sheet sheet = workbook.createSheet("律所列表");
|
|
|
+
|
|
|
+ // 获取字段
|
|
|
+ Field[] fields = LawFirmExcelVo.class.getDeclaredFields();
|
|
|
+ List<Field> excelFields = Arrays.stream(fields)
|
|
|
+ .filter(f -> f.isAnnotationPresent(ExcelHeader.class))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ // 创建表头样式
|
|
|
+ Font headerFont = workbook.createFont();
|
|
|
+ headerFont.setBold(true);
|
|
|
+ CellStyle headerCellStyle = workbook.createCellStyle();
|
|
|
+ headerCellStyle.setFont(headerFont);
|
|
|
+ headerCellStyle.setAlignment(HorizontalAlignment.CENTER);
|
|
|
+ headerCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
|
|
|
+
|
|
|
+ // 创建数据样式
|
|
|
+ CellStyle dataCellStyle = workbook.createCellStyle();
|
|
|
+ dataCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
|
|
|
+ dataCellStyle.setWrapText(true);
|
|
|
+
|
|
|
+ // 创建表头
|
|
|
+ Row headerRow = sheet.createRow(0);
|
|
|
+ for (int i = 0; i < excelFields.size(); i++) {
|
|
|
+ Field field = excelFields.get(i);
|
|
|
+ ExcelHeader excelHeader = field.getAnnotation(ExcelHeader.class);
|
|
|
+ Cell cell = headerRow.createCell(i);
|
|
|
+ cell.setCellValue(excelHeader.value());
|
|
|
+ cell.setCellStyle(headerCellStyle);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 填充数据
|
|
|
+ int rowNum = 1;
|
|
|
+ Map<String, Integer> firmNameRowMap = new HashMap<>(); // 记录每个律所名称的第一行
|
|
|
+ Map<String, Integer> firmNameCountMap = new HashMap<>(); // 记录每个律所名称的行数
|
|
|
+
|
|
|
+ for (LawFirmExcelVo excelVo : excelVoList) {
|
|
|
+ Row row = sheet.createRow(rowNum);
|
|
|
+ String firmName = excelVo.getFirmName();
|
|
|
+
|
|
|
+ if (!firmNameRowMap.containsKey(firmName)) {
|
|
|
+ firmNameRowMap.put(firmName, rowNum);
|
|
|
+ // 计算该律所名称有多少行
|
|
|
+ long count = excelVoList.stream()
|
|
|
+ .filter(vo -> firmName.equals(vo.getFirmName()))
|
|
|
+ .count();
|
|
|
+ firmNameCountMap.put(firmName, (int) count);
|
|
|
+ }
|
|
|
+
|
|
|
+ for (int i = 0; i < excelFields.size(); i++) {
|
|
|
+ Field field = excelFields.get(i);
|
|
|
+ field.setAccessible(true);
|
|
|
+ Cell cell = row.createCell(i);
|
|
|
+ cell.setCellStyle(dataCellStyle);
|
|
|
+ try {
|
|
|
+ Object value = field.get(excelVo);
|
|
|
+ if (value != null) {
|
|
|
+ cell.setCellValue(value.toString());
|
|
|
+ }
|
|
|
+ } catch (IllegalAccessException e) {
|
|
|
+ log.error("获取字段值失败", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ rowNum++;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 合并相同律所名称的单元格(除了账号列)
|
|
|
+ int firmNameColIndex = -1;
|
|
|
+ int paymentAccountColIndex = -1;
|
|
|
+ for (int i = 0; i < excelFields.size(); i++) {
|
|
|
+ Field field = excelFields.get(i);
|
|
|
+ ExcelHeader excelHeader = field.getAnnotation(ExcelHeader.class);
|
|
|
+ if ("律所名称".equals(excelHeader.value())) {
|
|
|
+ firmNameColIndex = i;
|
|
|
+ } else if ("律师事务所收款账号".equals(excelHeader.value())) {
|
|
|
+ paymentAccountColIndex = i;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 合并律所名称列
|
|
|
+ if (firmNameColIndex >= 0) {
|
|
|
+ for (Map.Entry<String, Integer> entry : firmNameRowMap.entrySet()) {
|
|
|
+ String firmName = entry.getKey();
|
|
|
+ int firstRow = entry.getValue();
|
|
|
+ int rowCount = firmNameCountMap.get(firmName);
|
|
|
+ if (rowCount > 1) {
|
|
|
+ sheet.addMergedRegion(new CellRangeAddress(firstRow, firstRow + rowCount - 1, firmNameColIndex, firmNameColIndex));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 合并其他列(除了账号列)
|
|
|
+ for (int i = 0; i < excelFields.size(); i++) {
|
|
|
+ if (i == firmNameColIndex || i == paymentAccountColIndex) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ for (Map.Entry<String, Integer> entry : firmNameRowMap.entrySet()) {
|
|
|
+ String firmName = entry.getKey();
|
|
|
+ int firstRow = entry.getValue();
|
|
|
+ int rowCount = firmNameCountMap.get(firmName);
|
|
|
+ if (rowCount > 1) {
|
|
|
+ sheet.addMergedRegion(new CellRangeAddress(firstRow, firstRow + rowCount - 1, i, i));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置列宽
|
|
|
+ for (int i = 0; i < excelFields.size(); i++) {
|
|
|
+ sheet.setColumnWidth(i, 20 * 256);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置响应头
|
|
|
+ response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
|
|
+ response.setCharacterEncoding("utf-8");
|
|
|
+ String fileName = URLEncoder.encode("律所列表", "UTF-8").replaceAll("\\+", "%20");
|
|
|
+ response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
|
|
|
+
|
|
|
+ // 输出
|
|
|
+ OutputStream outputStream = response.getOutputStream();
|
|
|
+ workbook.write(outputStream);
|
|
|
+ workbook.close();
|
|
|
+ outputStream.close();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 转换为ExcelVo
|
|
|
+ */
|
|
|
+ private LawFirmExcelVo convertToExcelVo(LawFirm lawFirm, int serialNumber,
|
|
|
+ SimpleDateFormat dateFormat, SimpleDateFormat dateTimeFormat) {
|
|
|
+ LawFirmExcelVo excelVo = new LawFirmExcelVo();
|
|
|
+ BeanUtils.copyProperties(lawFirm, excelVo);
|
|
|
+ excelVo.setSerialNumber(serialNumber);
|
|
|
+
|
|
|
+ // 格式化日期
|
|
|
+ if (lawFirm.getEstablishmentDate() != null) {
|
|
|
+ excelVo.setEstablishmentDate(dateFormat.format(lawFirm.getEstablishmentDate()));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 格式化类型
|
|
|
+ if (lawFirm.getFirmType() != null) {
|
|
|
+ switch (lawFirm.getFirmType()) {
|
|
|
+ case 1:
|
|
|
+ excelVo.setFirmType("合伙制");
|
|
|
+ break;
|
|
|
+ case 2:
|
|
|
+ excelVo.setFirmType("个人制");
|
|
|
+ break;
|
|
|
+ case 3:
|
|
|
+ excelVo.setFirmType("国资制");
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 格式化规模
|
|
|
+ if (lawFirm.getFirmScale() != null) {
|
|
|
+ switch (lawFirm.getFirmScale()) {
|
|
|
+ case 1:
|
|
|
+ excelVo.setFirmScale("小型(1-10人)");
|
|
|
+ break;
|
|
|
+ case 2:
|
|
|
+ excelVo.setFirmScale("中型(11-50人)");
|
|
|
+ break;
|
|
|
+ case 3:
|
|
|
+ excelVo.setFirmScale("大型(51-200人)");
|
|
|
+ break;
|
|
|
+ case 4:
|
|
|
+ excelVo.setFirmScale("超大型(200人以上)");
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 格式化状态
|
|
|
+ if (lawFirm.getStatus() != null) {
|
|
|
+ excelVo.setStatus(lawFirm.getStatus() == 1 ? "启用" : "禁用");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 格式化认证状态
|
|
|
+ if (lawFirm.getCertificationStatus() != null) {
|
|
|
+ switch (lawFirm.getCertificationStatus()) {
|
|
|
+ case 0:
|
|
|
+ excelVo.setCertificationStatus("未认证");
|
|
|
+ break;
|
|
|
+ case 1:
|
|
|
+ excelVo.setCertificationStatus("认证中");
|
|
|
+ break;
|
|
|
+ case 2:
|
|
|
+ excelVo.setCertificationStatus("已认证");
|
|
|
+ break;
|
|
|
+ case 3:
|
|
|
+ excelVo.setCertificationStatus("认证失败");
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 格式化佣金比例
|
|
|
+ if (lawFirm.getPlatformCommissionRatio() != null) {
|
|
|
+ excelVo.setPlatformCommissionRatio(lawFirm.getPlatformCommissionRatio().toString() + "%");
|
|
|
+ }
|
|
|
+
|
|
|
+ return excelVo;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 校验Excel数据
|
|
|
+ */
|
|
|
+ private String validateExcelData(LawFirmExcelVo excelVo, int rowIndex) {
|
|
|
+ if (!StringUtils.hasText(excelVo.getFirmName())) {
|
|
|
+ return "第" + rowIndex + "行:律所名称不能为空";
|
|
|
+ }
|
|
|
+// if (!StringUtils.hasText(excelVo.getCreditCode())) {
|
|
|
+// return "第" + rowIndex + "行:统一社会信用代码不能为空";
|
|
|
+// }
|
|
|
+// if (!StringUtils.hasText(excelVo.getPhone())) {
|
|
|
+// return "第" + rowIndex + "行:联系电话不能为空";
|
|
|
+// }
|
|
|
+ if (!StringUtils.hasText(excelVo.getDirectorName())) {
|
|
|
+ return "第" + rowIndex + "行:负责人姓名不能为空";
|
|
|
+ }
|
|
|
+// if (!StringUtils.hasText(excelVo.getDirectorPhone())) {
|
|
|
+// return "第" + rowIndex + "行:负责人电话不能为空";
|
|
|
+// }
|
|
|
+
|
|
|
+ // 校验邮箱格式
|
|
|
+// if (StringUtils.hasText(excelVo.getEmail())) {
|
|
|
+// if (!excelVo.getEmail().matches("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$")) {
|
|
|
+// return "第" + rowIndex + "行:邮箱格式不正确";
|
|
|
+// }
|
|
|
+// }
|
|
|
+// if (StringUtils.hasText(excelVo.getDirectorEmail())) {
|
|
|
+// if (!excelVo.getDirectorEmail().matches("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$")) {
|
|
|
+// return "第" + rowIndex + "行:负责人邮箱格式不正确";
|
|
|
+// }
|
|
|
+// }
|
|
|
+
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 转换为LawFirm实体
|
|
|
+ */
|
|
|
+ private LawFirm convertToLawFirm(LawFirmExcelVo excelVo) {
|
|
|
+ LawFirm lawFirm = new LawFirm();
|
|
|
+ BeanUtils.copyProperties(excelVo, lawFirm);
|
|
|
+
|
|
|
+ // 解析类型
|
|
|
+ if (StringUtils.hasText(excelVo.getFirmType())) {
|
|
|
+ switch (excelVo.getFirmType()) {
|
|
|
+ case "合伙制":
|
|
|
+ lawFirm.setFirmType(1);
|
|
|
+ break;
|
|
|
+ case "个人制":
|
|
|
+ lawFirm.setFirmType(2);
|
|
|
+ break;
|
|
|
+ case "国资制":
|
|
|
+ lawFirm.setFirmType(3);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 解析规模
|
|
|
+ if (StringUtils.hasText(excelVo.getFirmScale())) {
|
|
|
+ if (excelVo.getFirmScale().contains("小型")) {
|
|
|
+ lawFirm.setFirmScale(1);
|
|
|
+ } else if (excelVo.getFirmScale().contains("中型")) {
|
|
|
+ lawFirm.setFirmScale(2);
|
|
|
+ } else if (excelVo.getFirmScale().contains("大型") && !excelVo.getFirmScale().contains("超大型")) {
|
|
|
+ lawFirm.setFirmScale(3);
|
|
|
+ } else if (excelVo.getFirmScale().contains("超大型")) {
|
|
|
+ lawFirm.setFirmScale(4);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 解析状态
|
|
|
+ if (StringUtils.hasText(excelVo.getStatus())) {
|
|
|
+ lawFirm.setStatus("启用".equals(excelVo.getStatus()) ? 1 : 0);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 解析认证状态
|
|
|
+ if (StringUtils.hasText(excelVo.getCertificationStatus())) {
|
|
|
+ switch (excelVo.getCertificationStatus()) {
|
|
|
+ case "未认证":
|
|
|
+ lawFirm.setCertificationStatus(0);
|
|
|
+ break;
|
|
|
+ case "认证中":
|
|
|
+ lawFirm.setCertificationStatus(1);
|
|
|
+ break;
|
|
|
+ case "已认证":
|
|
|
+ lawFirm.setCertificationStatus(2);
|
|
|
+ break;
|
|
|
+ case "认证失败":
|
|
|
+ lawFirm.setCertificationStatus(3);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 解析日期
|
|
|
+ if (StringUtils.hasText(excelVo.getEstablishmentDate())) {
|
|
|
+ try {
|
|
|
+ SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
|
|
|
+ lawFirm.setEstablishmentDate(dateFormat.parse(excelVo.getEstablishmentDate()));
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("解析成立日期失败:{}", excelVo.getEstablishmentDate());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 解析佣金比例
|
|
|
+ if (StringUtils.hasText(excelVo.getPlatformCommissionRatio())) {
|
|
|
+ try {
|
|
|
+ String ratio = excelVo.getPlatformCommissionRatio().replace("%", "").trim();
|
|
|
+ lawFirm.setPlatformCommissionRatio(new BigDecimal(ratio));
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("解析佣金比例失败:{}", excelVo.getPlatformCommissionRatio());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return lawFirm;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取单元格值作为字符串
|
|
|
+ */
|
|
|
+ private String getCellValueAsString(Cell cell) {
|
|
|
+ if (cell == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ switch (cell.getCellType()) {
|
|
|
+ case STRING:
|
|
|
+ return cell.getStringCellValue();
|
|
|
+ case NUMERIC:
|
|
|
+ if (DateUtil.isCellDateFormatted(cell)) {
|
|
|
+ return new SimpleDateFormat("yyyy-MM-dd").format(cell.getDateCellValue());
|
|
|
+ } else {
|
|
|
+ double numericValue = cell.getNumericCellValue();
|
|
|
+ // 如果是整数,返回整数格式
|
|
|
+ if (numericValue == (long) numericValue) {
|
|
|
+ return String.valueOf((long) numericValue);
|
|
|
+ } else {
|
|
|
+ return String.valueOf(numericValue);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ case BOOLEAN:
|
|
|
+ return String.valueOf(cell.getBooleanCellValue());
|
|
|
+ case FORMULA:
|
|
|
+ return cell.getCellFormula();
|
|
|
+ default:
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
|