From 0d9d77ea9e2616489be34e990f130baff0ccbd85 Mon Sep 17 00:00:00 2001 From: cst61 Date: Fri, 15 May 2026 13:43:20 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AF=BC=E5=87=BA=E8=AF=84=E4=BC=B0=E7=94=B3?= =?UTF-8?q?=E8=AF=B7=E8=A1=A8=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../LbAssessmentApplyController.java | 15 ++ .../rj/service/ILbAssessmentApplyService.java | 6 + .../impl/LbAssessmentApplyServiceImpl.java | 232 ++++++++++++++++-- 3 files changed, 226 insertions(+), 27 deletions(-) diff --git a/src/main/java/com/rj/controller/LbAssessmentApplyController.java b/src/main/java/com/rj/controller/LbAssessmentApplyController.java index 9cef0eb..19d8581 100644 --- a/src/main/java/com/rj/controller/LbAssessmentApplyController.java +++ b/src/main/java/com/rj/controller/LbAssessmentApplyController.java @@ -6,6 +6,7 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.Valid; import jakarta.validation.constraints.NotBlank; import lombok.Data; @@ -107,4 +108,18 @@ public class LbAssessmentApplyController { return ResponseEntity.internalServerError().body(result); } + @GetMapping("/export") + @Operation(summary = "导出申请评估Excel", description = "按租户ID与申请日期时间范围导出申请评估列表") + public void export( + @Parameter(description = "租户ID", required = true) @RequestParam String tenantId, + @Parameter(description = "申请开始时间,格式:yyyy-MM-dd HH:mm:ss", required = true) + @RequestParam String applicationDatetimeStart, + @Parameter(description = "申请结束时间,格式:yyyy-MM-dd HH:mm:ss", required = true) + @RequestParam String applicationDatetimeEnd, + HttpServletResponse response) { + lbAssessmentApplyService.exportExcel( + tenantId, applicationDatetimeStart, applicationDatetimeEnd, response + ); + } + } diff --git a/src/main/java/com/rj/service/ILbAssessmentApplyService.java b/src/main/java/com/rj/service/ILbAssessmentApplyService.java index 7204812..08cb594 100644 --- a/src/main/java/com/rj/service/ILbAssessmentApplyService.java +++ b/src/main/java/com/rj/service/ILbAssessmentApplyService.java @@ -2,6 +2,7 @@ package com.rj.service; import com.baomidou.mybatisplus.extension.service.IService; import com.rj.entity.LbAssessmentApply; +import jakarta.servlet.http.HttpServletResponse; import java.util.Map; @@ -29,4 +30,9 @@ public interface ILbAssessmentApplyService extends IService { */ Map parseFromAssessmentTextByLlm(String assessmentText, String tenantId); + void exportExcel(String tenantId, + String applicationDatetimeStart, + String applicationDatetimeEnd, + HttpServletResponse response); + } diff --git a/src/main/java/com/rj/service/impl/LbAssessmentApplyServiceImpl.java b/src/main/java/com/rj/service/impl/LbAssessmentApplyServiceImpl.java index 91f6e63..ab52b6d 100644 --- a/src/main/java/com/rj/service/impl/LbAssessmentApplyServiceImpl.java +++ b/src/main/java/com/rj/service/impl/LbAssessmentApplyServiceImpl.java @@ -14,14 +14,26 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.rj.entity.LbAssessmentApply; import com.rj.mapper.LbAssessmentApplyMapper; import com.rj.service.ILbAssessmentApplyService; +import jakarta.servlet.ServletOutputStream; +import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.xssf.usermodel.XSSFCellStyle; +import org.apache.poi.xssf.usermodel.XSSFColor; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpHeaders; import org.springframework.stereotype.Service; +import java.awt.Color; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.UUID; @@ -250,33 +262,10 @@ public class LbAssessmentApplyServiceImpl size = 10; } - LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); - if (tenantId != null && !tenantId.trim().isEmpty()) { - queryWrapper.eq(LbAssessmentApply::getTenantId, tenantId.trim()); - } - if (applicantName != null && !applicantName.trim().isEmpty()) { - queryWrapper.like(LbAssessmentApply::getApplicantName, applicantName.trim()); - } - if (applicantPhone != null && !applicantPhone.trim().isEmpty()) { - queryWrapper.like(LbAssessmentApply::getApplicantPhone, applicantPhone.trim()); - } - if (colleagueName != null && !colleagueName.trim().isEmpty()) { - queryWrapper.like(LbAssessmentApply::getColleagueName, colleagueName.trim()); - } - if (teamLeaderName != null && !teamLeaderName.trim().isEmpty()) { - queryWrapper.like(LbAssessmentApply::getTeamLeaderName, teamLeaderName.trim()); - } - if (assessmentTeacherName != null && !assessmentTeacherName.trim().isEmpty()) { - queryWrapper.like(LbAssessmentApply::getAssessmentTeacherName, assessmentTeacherName.trim()); - } - if (moderatorName != null && !moderatorName.trim().isEmpty()) { - queryWrapper.like(LbAssessmentApply::getModeratorName, moderatorName.trim()); - } - if (meetingNumber != null && !meetingNumber.trim().isEmpty()) { - queryWrapper.like(LbAssessmentApply::getMeetingNumber, meetingNumber.trim()); - } - queryWrapper.orderByDesc(LbAssessmentApply::getUpdatedAt) - .orderByDesc(LbAssessmentApply::getCreatedAt); + LambdaQueryWrapper queryWrapper = buildQueryWrapper( + tenantId, applicantName, applicantPhone, colleagueName, teamLeaderName, + assessmentTeacherName, moderatorName, meetingNumber + ); Page page = this.page(new Page<>(current, size), queryWrapper); result.put("success", true); @@ -294,4 +283,193 @@ public class LbAssessmentApplyServiceImpl return result; } } + + @Override + public void exportExcel(String tenantId, + String applicationDatetimeStart, + String applicationDatetimeEnd, + HttpServletResponse response) { + try { + if (tenantId == null || tenantId.trim().isEmpty()) { + response.sendError(HttpServletResponse.SC_BAD_REQUEST, "tenantId不能为空"); + return; + } + if (applicationDatetimeStart == null || applicationDatetimeStart.trim().isEmpty()) { + response.sendError(HttpServletResponse.SC_BAD_REQUEST, "applicationDatetimeStart不能为空"); + return; + } + if (applicationDatetimeEnd == null || applicationDatetimeEnd.trim().isEmpty()) { + response.sendError(HttpServletResponse.SC_BAD_REQUEST, "applicationDatetimeEnd不能为空"); + return; + } + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + LocalDateTime start; + LocalDateTime end; + try { + start = LocalDateTime.parse(applicationDatetimeStart.trim(), formatter); + } catch (Exception e) { + response.sendError(HttpServletResponse.SC_BAD_REQUEST, "申请开始时间格式错误,请使用 yyyy-MM-dd HH:mm:ss"); + return; + } + try { + end = LocalDateTime.parse(applicationDatetimeEnd.trim(), formatter); + } catch (Exception e) { + response.sendError(HttpServletResponse.SC_BAD_REQUEST, "申请结束时间格式错误,请使用 yyyy-MM-dd HH:mm:ss"); + return; + } + if (start.isAfter(end)) { + response.sendError(HttpServletResponse.SC_BAD_REQUEST, "申请开始时间不能晚于结束时间"); + return; + } + + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(LbAssessmentApply::getTenantId, tenantId.trim()) + .ge(LbAssessmentApply::getApplicationDatetime, start) + .le(LbAssessmentApply::getApplicationDatetime, end) + .orderByDesc(LbAssessmentApply::getApplicationDatetime); + List rows = this.list(queryWrapper); + + try (Workbook workbook = new XSSFWorkbook()) { + Sheet sheet = workbook.createSheet("申请评估"); + + CellStyle headerStyle = workbook.createCellStyle(); + Font headerFont = workbook.createFont(); + headerFont.setBold(true); + headerStyle.setFont(headerFont); + headerStyle.setAlignment(HorizontalAlignment.CENTER); + headerStyle.setVerticalAlignment(VerticalAlignment.CENTER); + headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); + ((XSSFCellStyle) headerStyle).setFillForegroundColor(new XSSFColor(new Color(255, 217, 102), null)); + headerStyle.setBorderTop(BorderStyle.THIN); + headerStyle.setBorderBottom(BorderStyle.THIN); + headerStyle.setBorderLeft(BorderStyle.THIN); + headerStyle.setBorderRight(BorderStyle.THIN); + + CellStyle dataStyle = workbook.createCellStyle(); + dataStyle.setAlignment(HorizontalAlignment.CENTER); + dataStyle.setVerticalAlignment(VerticalAlignment.CENTER); + dataStyle.setBorderTop(BorderStyle.THIN); + dataStyle.setBorderBottom(BorderStyle.THIN); + dataStyle.setBorderLeft(BorderStyle.THIN); + dataStyle.setBorderRight(BorderStyle.THIN); + + String[] headers = { + "序号", "申请人", "电话", "同事", "电话", "团队长", "全收益团队长", + "整理确定时间", "安排评估老师", "安排主持人", "会议号" + }; + + Row headerRow = sheet.createRow(0); + headerRow.setHeightInPoints(22); + for (int i = 0; i < headers.length; i++) { + createCell(headerRow, i, headers[i], headerStyle); + } + + int rowIndex = 1; + for (LbAssessmentApply item : rows) { + Row row = sheet.createRow(rowIndex); + row.setHeightInPoints(20); + createCell(row, 0, String.valueOf(rowIndex), dataStyle); + createCell(row, 1, nullToEmpty(item.getApplicantName()), dataStyle); + createCell(row, 2, nullToEmpty(item.getApplicantPhone()), dataStyle); + createCell(row, 3, nullToEmpty(item.getColleagueName()), dataStyle); + createCell(row, 4, nullToEmpty(item.getColleaguePhone()), dataStyle); + createCell(row, 5, nullToEmpty(item.getTeamLeaderName()), dataStyle); + createCell(row, 6, "", dataStyle); + createCell(row, 7, formatApplicationDatetime(item.getApplicationDatetime()), dataStyle); + createCell(row, 8, nullToEmpty(item.getAssessmentTeacherName()), dataStyle); + createCell(row, 9, nullToEmpty(item.getModeratorName()), dataStyle); + createCell(row, 10, nullToEmpty(item.getMeetingNumber()), dataStyle); + rowIndex++; + } + + for (int i = 0; i < headers.length; i++) { + sheet.autoSizeColumn(i); + int width = sheet.getColumnWidth(i); + sheet.setColumnWidth(i, Math.min(255 * 256, (int) (width * 1.2))); + } + + String filename = "申请评估_" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + ".xlsx"; + String encoded = URLEncoder.encode(filename, StandardCharsets.UTF_8).replaceAll("\\+", "%20"); + + response.setCharacterEncoding(StandardCharsets.UTF_8.name()); + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + encoded); + + try (ServletOutputStream os = response.getOutputStream()) { + workbook.write(os); + os.flush(); + } + } + } catch (Exception e) { + log.error("申请评估导出异常", e); + try { + response.reset(); + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + response.setCharacterEncoding(StandardCharsets.UTF_8.name()); + response.setContentType("text/plain;charset=UTF-8"); + response.getWriter().write("导出异常:" + e.getMessage()); + } catch (Exception ignored) { + // ignore + } + } + } + + private LambdaQueryWrapper buildQueryWrapper(String tenantId, + String applicantName, + String applicantPhone, + String colleagueName, + String teamLeaderName, + String assessmentTeacherName, + String moderatorName, + String meetingNumber) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + if (tenantId != null && !tenantId.trim().isEmpty()) { + queryWrapper.eq(LbAssessmentApply::getTenantId, tenantId.trim()); + } + if (applicantName != null && !applicantName.trim().isEmpty()) { + queryWrapper.like(LbAssessmentApply::getApplicantName, applicantName.trim()); + } + if (applicantPhone != null && !applicantPhone.trim().isEmpty()) { + queryWrapper.like(LbAssessmentApply::getApplicantPhone, applicantPhone.trim()); + } + if (colleagueName != null && !colleagueName.trim().isEmpty()) { + queryWrapper.like(LbAssessmentApply::getColleagueName, colleagueName.trim()); + } + if (teamLeaderName != null && !teamLeaderName.trim().isEmpty()) { + queryWrapper.like(LbAssessmentApply::getTeamLeaderName, teamLeaderName.trim()); + } + if (assessmentTeacherName != null && !assessmentTeacherName.trim().isEmpty()) { + queryWrapper.like(LbAssessmentApply::getAssessmentTeacherName, assessmentTeacherName.trim()); + } + if (moderatorName != null && !moderatorName.trim().isEmpty()) { + queryWrapper.like(LbAssessmentApply::getModeratorName, moderatorName.trim()); + } + if (meetingNumber != null && !meetingNumber.trim().isEmpty()) { + queryWrapper.like(LbAssessmentApply::getMeetingNumber, meetingNumber.trim()); + } + queryWrapper.orderByDesc(LbAssessmentApply::getUpdatedAt) + .orderByDesc(LbAssessmentApply::getCreatedAt); + return queryWrapper; + } + + private static String nullToEmpty(String value) { + return value == null ? "" : value; + } + + private static String formatApplicationDatetime(LocalDateTime datetime) { + if (datetime == null) { + return ""; + } + if (datetime.getMinute() == 0 && datetime.getSecond() == 0) { + return datetime.getMonthValue() + "." + datetime.getDayOfMonth() + "日" + datetime.getHour() + "点"; + } + return datetime.format(DateTimeFormatter.ofPattern("M月d日 H:mm")); + } + + private static void createCell(Row row, int col, String text, CellStyle style) { + Cell cell = row.createCell(col); + cell.setCellValue(text); + cell.setCellStyle(style); + } }