package com.rongyichuang.player.service; import com.rongyichuang.common.dto.PageResponse; 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; @Service public class PlayerApplicationService { @PersistenceContext private EntityManager em; /** * 查询活动报名信息 * 报名审核页面只显示海选阶段的数据,不包含复赛等后续阶段 * 当传入activityId时,查询该比赛下第一个阶段(sort_order=1)的报名项目 */ @SuppressWarnings("unchecked") public PageResponse listApplications(String name, Long activityId, Integer state, Integer page, Integer size) { 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 "; String limit = ""; if (page != null && size != null && page > 0 && size > 0) { int offset = (page - 1) * size; limit = "LIMIT " + size + " OFFSET " + offset + " "; } var q = em.createNativeQuery(baseSql + where + order + limit); if (name != null && !name.isEmpty()) { q.setParameter("name", name); } if (activityId != null) { q.setParameter("activityId", activityId); } if (state != null) { q.setParameter("state", state); } List rows = q.getResultList(); List list = new ArrayList<>(); for (Object[] r : rows) { ActivityPlayerApplicationResponse dto = new ActivityPlayerApplicationResponse(); dto.setId(r[0] != null ? Long.valueOf(r[0].toString()) : null); // activity_player_id dto.setPlayerName(r[1] != null ? r[1].toString() : ""); dto.setActivityName(r[2] != null ? r[2].toString() : ""); dto.setProjectName(r[3] != null ? r[3].toString() : ""); // project_name dto.setPhone(r[4] != null ? r[4].toString() : ""); dto.setApplyTime(r[5] != null ? r[5].toString() : ""); // 映射状态:使用 t_activity_player.state(0=未审核,1=审核通过,2=审核驳回) dto.setState(r[6] != null ? Integer.valueOf(r[6].toString()) : 0); // 映射评审统计数据 dto.setRatingCount(r[7] != null ? Integer.valueOf(r[7].toString()) : 0); dto.setAverageScore(r[8] != null ? Double.valueOf(r[8].toString()) : null); list.add(dto); } // 获取总数 String countSql = "SELECT COUNT(*) " + baseSql.substring(baseSql.indexOf("FROM")) + where; var countQuery = em.createNativeQuery(countSql); if (name != null && !name.isEmpty()) { countQuery.setParameter("name", name); } if (activityId != null) { countQuery.setParameter("activityId", activityId); } if (state != null) { countQuery.setParameter("state", state); } long total = ((Number) countQuery.getSingleResult()).longValue(); return new PageResponse<>(list, total, page != null ? page : 1, size != null ? size : 10); } /** * 导出活动报名信息为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 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的区别:不过滤复赛和决赛阶段 */ @SuppressWarnings("unchecked") public PageResponse listProjectReviewApplications(String name, Long activityId, Long regionId, Integer state, Integer page, Integer size) { String baseSql = "SELECT ap.id, CONCAT(p.name, '(', ap.project_name, ')') AS player_name, stage.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 " + "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; // 项目评审查询:直接根据阶段ID查询,且默认只查询审核通过的数据 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 "); } // 直接查询指定阶段ID的报名项目 whereClause.append("ap.stage_id = :activityId"); hasCondition = true; } if (regionId != null) { if (hasCondition) { whereClause.append(" AND "); } whereClause.append("ap.region_id = :regionId"); hasCondition = true; } // 默认只查询审核通过的数据 (state = 1) if (hasCondition) { whereClause.append(" AND "); } whereClause.append("ap.state = 1"); hasCondition = true; // 如果传入了state参数,则覆盖默认的state=1条件 if (state != null) { // 移除最后添加的 "ap.state = 1" 条件 String whereStr = whereClause.toString(); whereStr = whereStr.replace(" AND ap.state = 1", ""); whereClause = new StringBuilder(whereStr); if (hasCondition && !whereStr.isEmpty()) { whereClause.append(" AND "); } whereClause.append("ap.state = :state"); } String where = hasCondition ? "WHERE " + whereClause.toString() + " " : ""; String order = "ORDER BY ap.create_time DESC "; String limit = ""; if (page != null && size != null && page > 0 && size > 0) { int offset = (page - 1) * size; limit = "LIMIT " + size + " OFFSET " + offset + " "; } var q = em.createNativeQuery(baseSql + where + order + limit); if (name != null && !name.isEmpty()) { q.setParameter("name", name); } if (activityId != null) { q.setParameter("activityId", activityId); } if (regionId != null) { q.setParameter("regionId", regionId); } if (state != null) { q.setParameter("state", state); } List rows = q.getResultList(); List list = new ArrayList<>(); for (Object[] r : rows) { ActivityPlayerApplicationResponse dto = new ActivityPlayerApplicationResponse(); dto.setId(r[0] != null ? Long.valueOf(r[0].toString()) : null); // activity_player_id dto.setPlayerName(r[1] != null ? r[1].toString() : ""); dto.setActivityName(r[2] != null ? r[2].toString() : ""); dto.setProjectName(r[3] != null ? r[3].toString() : ""); // project_name dto.setPhone(r[4] != null ? r[4].toString() : ""); dto.setApplyTime(r[5] != null ? r[5].toString() : ""); // 映射状态:使用 t_activity_player.state(0=未审核,1=审核通过,2=审核驳回) dto.setState(r[6] != null ? Integer.valueOf(r[6].toString()) : 0); // 映射评审统计数据 dto.setRatingCount(r[7] != null ? Integer.valueOf(r[7].toString()) : 0); dto.setAverageScore(r[8] != null ? Double.valueOf(r[8].toString()) : null); list.add(dto); } // 创建分页响应 long totalElements = list.size(); return new PageResponse<>(list, totalElements, page, size); } }