| | |
| | | import com.rongyichuang.player.dto.response.ActivityPlayerApplicationResponse; |
| | | import jakarta.persistence.EntityManager; |
| | | import jakarta.persistence.PersistenceContext; |
| | | import org.apache.poi.ss.usermodel.*; |
| | | import org.apache.poi.xssf.usermodel.XSSFWorkbook; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.io.ByteArrayOutputStream; |
| | | import java.io.IOException; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | |
| | | } |
| | | |
| | | /** |
| | | * 导出活动报名信息为Excel |
| | | */ |
| | | @SuppressWarnings("unchecked") |
| | | public byte[] exportApplicationsToExcel(String name, Long activityId, Integer state) throws IOException { |
| | | String baseSql = |
| | | "SELECT ap.id, p.name AS player_name, parent.name AS activity_name, ap.project_name AS project_name, u.phone AS phone, ap.create_time AS apply_time, ap.state AS state, " + |
| | | "COALESCE(rating_stats.rating_count, 0) AS rating_count, rating_stats.average_score " + |
| | | "FROM t_activity_player ap " + |
| | | "JOIN t_player p ON p.id = ap.player_id " + |
| | | "JOIN t_user u ON u.id = p.user_id " + |
| | | "JOIN t_activity stage ON stage.id = ap.stage_id " + |
| | | "JOIN t_activity parent ON parent.id = stage.pid " + |
| | | "LEFT JOIN (" + |
| | | " SELECT activity_player_id, COUNT(*) AS rating_count, AVG(total_score) AS average_score " + |
| | | " FROM t_activity_player_rating " + |
| | | " WHERE state = 1 " + |
| | | " GROUP BY activity_player_id" + |
| | | ") rating_stats ON rating_stats.activity_player_id = ap.id "; |
| | | |
| | | StringBuilder whereClause = new StringBuilder(); |
| | | boolean hasCondition = false; |
| | | |
| | | // 默认只显示第一阶段的数据(基于sort_order=1),避免硬编码阶段名称 |
| | | whereClause.append("stage.sort_order = 1"); |
| | | hasCondition = true; |
| | | |
| | | if (name != null && !name.isEmpty()) { |
| | | if (hasCondition) { |
| | | whereClause.append(" AND "); |
| | | } |
| | | whereClause.append("p.name LIKE CONCAT('%', :name, '%')"); |
| | | hasCondition = true; |
| | | } |
| | | |
| | | if (activityId != null) { |
| | | if (hasCondition) { |
| | | whereClause.append(" AND "); |
| | | } |
| | | // 查询指定主比赛的第一阶段报名项目:activity_id=主比赛ID, stage_id=第一阶段ID |
| | | whereClause.append("ap.activity_id = :activityId AND ap.stage_id = stage.id AND stage.pid = :activityId AND stage.sort_order = 1"); |
| | | hasCondition = true; |
| | | } |
| | | |
| | | if (state != null) { |
| | | if (hasCondition) { |
| | | whereClause.append(" AND "); |
| | | } |
| | | whereClause.append("ap.state = :state"); |
| | | hasCondition = true; |
| | | } |
| | | |
| | | String where = hasCondition ? "WHERE " + whereClause.toString() + " " : ""; |
| | | String order = "ORDER BY ap.create_time DESC "; |
| | | |
| | | var q = em.createNativeQuery(baseSql + where + order); |
| | | if (name != null && !name.isEmpty()) { |
| | | q.setParameter("name", name); |
| | | } |
| | | if (activityId != null) { |
| | | q.setParameter("activityId", activityId); |
| | | } |
| | | |
| | | if (state != null) { |
| | | q.setParameter("state", state); |
| | | } |
| | | List<Object[]> rows = q.getResultList(); |
| | | |
| | | // 创建Excel工作簿 |
| | | Workbook workbook = new XSSFWorkbook(); |
| | | Sheet sheet = workbook.createSheet("报名人员"); |
| | | |
| | | // 创建标题行 |
| | | Row headerRow = sheet.createRow(0); |
| | | String[] headers = {"ID", "学员名称", "比赛名称", "项目名称", "联系电话", "申请时间", "状态", "评分次数", "平均分"}; |
| | | for (int i = 0; i < headers.length; i++) { |
| | | Cell cell = headerRow.createCell(i); |
| | | cell.setCellValue(headers[i]); |
| | | |
| | | // 设置标题样式 |
| | | CellStyle headerStyle = workbook.createCellStyle(); |
| | | Font font = workbook.createFont(); |
| | | font.setBold(true); |
| | | headerStyle.setFont(font); |
| | | cell.setCellStyle(headerStyle); |
| | | } |
| | | |
| | | // 填充数据 |
| | | int rowNum = 1; |
| | | for (Object[] r : rows) { |
| | | Row row = sheet.createRow(rowNum++); |
| | | row.createCell(0).setCellValue(r[0] != null ? r[0].toString() : ""); |
| | | row.createCell(1).setCellValue(r[1] != null ? r[1].toString() : ""); |
| | | row.createCell(2).setCellValue(r[2] != null ? r[2].toString() : ""); |
| | | row.createCell(3).setCellValue(r[3] != null ? r[3].toString() : ""); |
| | | row.createCell(4).setCellValue(r[4] != null ? r[4].toString() : ""); |
| | | row.createCell(5).setCellValue(r[5] != null ? r[5].toString() : ""); |
| | | |
| | | // 状态转换 |
| | | String stateText = "未知"; |
| | | if (r[6] != null) { |
| | | int stateValue = Integer.parseInt(r[6].toString()); |
| | | switch (stateValue) { |
| | | case 0: stateText = "未审核"; break; |
| | | case 1: stateText = "审核通过"; break; |
| | | case 2: stateText = "审核驳回"; break; |
| | | default: stateText = "未知"; |
| | | } |
| | | } |
| | | row.createCell(6).setCellValue(stateText); |
| | | |
| | | row.createCell(7).setCellValue(r[7] != null ? r[7].toString() : "0"); |
| | | row.createCell(8).setCellValue(r[8] != null ? r[8].toString() : ""); |
| | | } |
| | | |
| | | // 自动调整列宽 |
| | | for (int i = 0; i < headers.length; i++) { |
| | | sheet.autoSizeColumn(i); |
| | | } |
| | | |
| | | // 将工作簿写入字节数组 |
| | | ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); |
| | | workbook.write(outputStream); |
| | | workbook.close(); |
| | | outputStream.close(); |
| | | |
| | | return outputStream.toByteArray(); |
| | | } |
| | | |
| | | /** |
| | | * 项目评审专用查询,包含所有阶段数据(包括复赛、决赛) |
| | | * 与listApplications的区别:不过滤复赛和决赛阶段 |
| | | */ |