|
@@ -2,9 +2,17 @@ package org.jeecg.modules.system.app.service.impl;
|
|
|
|
|
|
import cn.hutool.core.collection.CollUtil;
|
|
|
import cn.hutool.core.util.ObjectUtil;
|
|
|
+import com.alibaba.fastjson2.JSONArray;
|
|
|
+import com.alibaba.fastjson2.JSONObject;
|
|
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
+import org.apache.poi.ss.usermodel.*;
|
|
|
+import org.apache.poi.ss.usermodel.Font;
|
|
|
+import org.apache.poi.util.IOUtils;
|
|
|
+import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
|
|
|
+import org.apache.poi.xssf.usermodel.XSSFPicture;
|
|
|
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
|
|
import org.apache.shiro.SecurityUtils;
|
|
|
import org.jeecg.common.constant.CommonConstant;
|
|
|
import org.jeecg.common.exception.JeecgBootException;
|
|
@@ -16,24 +24,32 @@ import org.jeecg.modules.app.vo.ScanCodeQueryOrderVO;
|
|
|
import org.jeecg.modules.quartz.vo.JobClassNoticeVo;
|
|
|
import org.jeecg.modules.quartz.vo.JobReservationSiteVo;
|
|
|
import org.jeecg.modules.system.app.dto.AppOrderDTO;
|
|
|
+import org.jeecg.modules.system.app.dto.ExportConditionDTO;
|
|
|
import org.jeecg.modules.system.app.dto.IsinUserInfoDTO;
|
|
|
import org.jeecg.modules.system.app.dto.VerificationRecordDTO;
|
|
|
import org.jeecg.modules.system.app.entity.*;
|
|
|
import org.jeecg.modules.system.app.form.AppOrderPageForm;
|
|
|
import org.jeecg.modules.system.app.mapper.*;
|
|
|
import org.jeecg.modules.system.app.service.IAppOrderService;
|
|
|
-import org.jeecg.modules.system.app.vo.AppIsinVO;
|
|
|
-import org.jeecg.modules.system.app.vo.AppOrderInfoVO;
|
|
|
-import org.jeecg.modules.system.app.vo.OrderPageVO;
|
|
|
+import org.jeecg.modules.system.app.vo.*;
|
|
|
import org.jeecg.modules.system.entity.SysUser;
|
|
|
import org.jeecg.modules.system.mapper.SysUserMapper;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
|
import javax.annotation.Resource;
|
|
|
+import javax.imageio.ImageIO;
|
|
|
+import javax.imageio.ImageReader;
|
|
|
+import javax.imageio.stream.ImageInputStream;
|
|
|
+import java.awt.*;
|
|
|
+import java.awt.image.BufferedImage;
|
|
|
+import java.io.*;
|
|
|
+import java.net.HttpURLConnection;
|
|
|
+import java.net.URL;
|
|
|
import java.time.LocalDate;
|
|
|
import java.time.LocalTime;
|
|
|
import java.util.*;
|
|
|
+import java.util.List;
|
|
|
import java.util.function.Function;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
@@ -83,6 +99,8 @@ public class AppOrderServiceImpl extends ServiceImpl<AppOrderMapper, AppOrder> i
|
|
|
private AppCoursesMapper appCoursesMapper;
|
|
|
@Resource
|
|
|
private AppCoursesPriceRulesMapper appCoursesPriceRulesMapper;
|
|
|
+ @Resource
|
|
|
+ private AppCategoryMapper appCategoryMapper;
|
|
|
|
|
|
|
|
|
@Override
|
|
@@ -355,4 +373,357 @@ public class AppOrderServiceImpl extends ServiceImpl<AppOrderMapper, AppOrder> i
|
|
|
return jobReservationSiteVosTwe;
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ public List<ExportConditionVO> exportConditionByName(String name) {
|
|
|
+ List<AppGame> appGames = null;
|
|
|
+ if(null != name && !name.isEmpty()){
|
|
|
+ appGames = appGameMapper.selectList(Wrappers.<AppGame>lambdaQuery().like(AppGame::getName, name).eq(AppGame::getDelFlag, 0));
|
|
|
+ }else {
|
|
|
+ appGames = appGameMapper.selectList(Wrappers.<AppGame>lambdaQuery().eq(AppGame::getDelFlag, 0));
|
|
|
+ }
|
|
|
+ List<ExportConditionVO> collect = appGames.stream()
|
|
|
+ .map(game -> {
|
|
|
+ ExportConditionVO vo = new ExportConditionVO();
|
|
|
+ vo.setId(game.getId());
|
|
|
+ vo.setName(game.getName());
|
|
|
+ return vo;
|
|
|
+ })
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ collect.add(new ExportConditionVO().setId("ALL").setName("全部"));
|
|
|
+ return collect;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<ExportConditionVO> exportConditionByProjectName(String projectName, String gameId) {
|
|
|
+ List<ExportConditionVO> collect = new ArrayList<>();
|
|
|
+ collect.add(new ExportConditionVO().setId("ALL").setName("全部"));
|
|
|
+ if(null != projectName && !projectName.isEmpty()){
|
|
|
+ AppCategory appCategory = appCategoryMapper.selectOne(Wrappers.<AppCategory>lambdaQuery().like(AppCategory::getName, projectName)
|
|
|
+ .eq(AppCategory::getDelFlag, 0)
|
|
|
+ .eq(AppCategory::getStatus, 0).last("limit 1"));
|
|
|
+ List<AppGamePriceRules> appGamePriceRules = appGamePriceRulesMapper.selectList(Wrappers.<AppGamePriceRules>lambdaQuery()
|
|
|
+ .eq(AppGamePriceRules::getGameId, gameId)
|
|
|
+ .eq(AppGamePriceRules::getCategoryId, appCategory.getId()));
|
|
|
+ collect = appGamePriceRules.stream()
|
|
|
+ .map(priceRules -> {
|
|
|
+ ExportConditionVO vo = new ExportConditionVO();
|
|
|
+ vo.setId(priceRules.getId());
|
|
|
+ vo.setName((priceRules.getType() == 0 ? "个人-": "团队-") + appCategoryMapper.selectById(priceRules.getCategoryId()).getName());
|
|
|
+ return vo;
|
|
|
+ })
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ }else {
|
|
|
+ List<AppGamePriceRules> appGamePriceRules = appGamePriceRulesMapper.selectList(Wrappers.<AppGamePriceRules>lambdaQuery()
|
|
|
+ .eq(AppGamePriceRules::getGameId, gameId));
|
|
|
+ collect = appGamePriceRules.stream()
|
|
|
+ .map(priceRules -> {
|
|
|
+ ExportConditionVO vo = new ExportConditionVO();
|
|
|
+ vo.setId(priceRules.getId());
|
|
|
+ vo.setName((priceRules.getType() == 0 ? "个人-": "团队-") + appCategoryMapper.selectById(priceRules.getCategoryId()).getName());
|
|
|
+ return vo;
|
|
|
+ })
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ collect.add(new ExportConditionVO().setId("ALL").setName("全部"));
|
|
|
+ }
|
|
|
+ return collect;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public File exportCondition(ExportConditionDTO exportConditionDTO) throws IOException {
|
|
|
+ List<ExportConditionOutVO> exportConditionOutVO = appGameMapper.exportCondition(exportConditionDTO);
|
|
|
+ List<Map<String, Object>> list = new ArrayList<>();
|
|
|
+ int index = 1;
|
|
|
+ for (ExportConditionOutVO outVO : exportConditionOutVO){
|
|
|
+ String gameCertification = outVO.getGameCertification();
|
|
|
+
|
|
|
+ // 使用 FastJSON 解析 gameCertification 字段
|
|
|
+ JSONObject certificationJson = JSONObject.parseObject(gameCertification);
|
|
|
+
|
|
|
+ Map<String, Object> map = new HashMap<>();
|
|
|
+ map.put("序号", index);
|
|
|
+ map.put("赛事名称", outVO.getName());
|
|
|
+ map.put("个人/团队赛", outVO.getType());
|
|
|
+ map.put("报名项目", outVO.getProjectName());
|
|
|
+
|
|
|
+ // 提取 teamName 放到 队名
|
|
|
+ String teamName = certificationJson.getString("teamName");
|
|
|
+ map.put("队名", teamName != null ? teamName : "");
|
|
|
+
|
|
|
+ // 提取 teamEmblemImg 放到 队徽
|
|
|
+ String teamEmblemImg = certificationJson.getString("teamEmblemImg");
|
|
|
+ map.put("队徽", teamEmblemImg != null ? teamEmblemImg : "");
|
|
|
+
|
|
|
+ // 提取 certificationDTOS 放到 社保证明
|
|
|
+ JSONArray certificationDTOS = certificationJson.getJSONArray("certificationDTOS");
|
|
|
+ if (certificationDTOS != null && !certificationDTOS.isEmpty()) {
|
|
|
+ StringBuilder certificationBuilder = new StringBuilder();
|
|
|
+ for (int i = 0; i < certificationDTOS.size(); i++) {
|
|
|
+ JSONObject cert = certificationDTOS.getJSONObject(i);
|
|
|
+ String name = cert.getString("name");
|
|
|
+ String certificationImg = cert.getString("certificationImg");
|
|
|
+ certificationBuilder.append(name).append(": ").append(certificationImg).append(";");
|
|
|
+ }
|
|
|
+ map.put("社保证明", certificationBuilder.toString());
|
|
|
+ } else {
|
|
|
+ map.put("社保证明", "");
|
|
|
+ }
|
|
|
+
|
|
|
+ map.put("报名人员", outVO.getUserName());
|
|
|
+ map.put("联系电话", outVO.getUserPhone());
|
|
|
+ list.add(map);
|
|
|
+ index++;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 生成 Excel 文件
|
|
|
+ return generateExcel(list);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 优化后的 generateExcel 方法
|
|
|
+ private File generateExcel(List<Map<String, Object>> dataList) throws IOException {
|
|
|
+ // 创建工作簿和工作表
|
|
|
+ Workbook workbook = new XSSFWorkbook();
|
|
|
+ Sheet sheet = workbook.createSheet("报名信息");
|
|
|
+
|
|
|
+ // 设置列宽
|
|
|
+ sheet.setColumnWidth(0, 3000); // 序号
|
|
|
+ sheet.setColumnWidth(1, 8000); // 赛事名称
|
|
|
+ sheet.setColumnWidth(2, 6000); // 个人/团队赛
|
|
|
+ sheet.setColumnWidth(3, 6000); // 报名项目
|
|
|
+ sheet.setColumnWidth(4, 6000); // 队名
|
|
|
+ sheet.setColumnWidth(5, 6000); // 队徽
|
|
|
+ sheet.setColumnWidth(6, 12000); // 社保证明
|
|
|
+ sheet.setColumnWidth(7, 4000); // 报名人员
|
|
|
+ sheet.setColumnWidth(8, 4000); // 联系电话
|
|
|
+
|
|
|
+ // 创建标题样式
|
|
|
+ CellStyle headerStyle = createHeaderStyle(workbook);
|
|
|
+
|
|
|
+ // 创建内容样式
|
|
|
+ CellStyle contentStyle = createContentStyle(workbook);
|
|
|
+
|
|
|
+ // 写入表头
|
|
|
+ Row headerRow = sheet.createRow(0);
|
|
|
+ String[] headers = {"序号", "赛事名称", "个人/团队赛", "报名项目", "队名", "队徽", "社保证明", "报名人员", "联系电话"};
|
|
|
+ for (int i = 0; i < headers.length; i++) {
|
|
|
+ Cell cell = headerRow.createCell(i);
|
|
|
+ cell.setCellValue(headers[i]);
|
|
|
+ cell.setCellStyle(headerStyle);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 写入数据
|
|
|
+ for (int i = 0; i < dataList.size(); i++) {
|
|
|
+ Map<String, Object> rowMap = dataList.get(i);
|
|
|
+ Row dataRow = sheet.createRow(i + 1);
|
|
|
+ // 设置行高,为图片留出空间
|
|
|
+ dataRow.setHeightInPoints(80);
|
|
|
+
|
|
|
+ // 序号
|
|
|
+ Cell cell0 = dataRow.createCell(0);
|
|
|
+ cell0.setCellValue((Integer) rowMap.get("序号"));
|
|
|
+ cell0.setCellStyle(contentStyle);
|
|
|
+
|
|
|
+ // 赛事名称
|
|
|
+ Cell cell1 = dataRow.createCell(1);
|
|
|
+ cell1.setCellValue((String) rowMap.get("赛事名称"));
|
|
|
+ cell1.setCellStyle(contentStyle);
|
|
|
+
|
|
|
+ // 个人/团队赛
|
|
|
+ Cell cell2 = dataRow.createCell(2);
|
|
|
+ cell2.setCellValue((int) rowMap.get("个人/团队赛") == 3 ? "个人" : "团队");
|
|
|
+ cell2.setCellStyle(contentStyle);
|
|
|
+
|
|
|
+ // 报名项目
|
|
|
+ Cell cell3 = dataRow.createCell(3);
|
|
|
+ cell3.setCellValue((String) rowMap.get("报名项目"));
|
|
|
+ cell3.setCellStyle(contentStyle);
|
|
|
+
|
|
|
+ // 队名
|
|
|
+ Cell cell4 = dataRow.createCell(4);
|
|
|
+ cell4.setCellValue((String) rowMap.get("队名"));
|
|
|
+ cell4.setCellStyle(contentStyle);
|
|
|
+
|
|
|
+ // 队徽:插入图片(嵌入单元格)
|
|
|
+ String teamEmblemImg = (String) rowMap.get("队徽");
|
|
|
+ Cell cell5 = dataRow.createCell(5);
|
|
|
+ cell5.setCellStyle(contentStyle);
|
|
|
+ if (teamEmblemImg != null && !teamEmblemImg.isEmpty()) {
|
|
|
+ insertImageToCell(workbook, sheet, teamEmblemImg, 5, i + 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 社保证明:多个图片,放在同一单元格内,按行排列
|
|
|
+ String certificationStr = (String) rowMap.get("社保证明");
|
|
|
+ Cell cell6 = dataRow.createCell(6);
|
|
|
+ cell6.setCellStyle(contentStyle);
|
|
|
+
|
|
|
+ if (certificationStr != null && !certificationStr.isEmpty()) {
|
|
|
+ List<String> allImageUrls = extractImageUrls(certificationStr);
|
|
|
+ if (!allImageUrls.isEmpty()) {
|
|
|
+ insertMultipleImagesToCell(workbook, sheet, allImageUrls, 6, i + 1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 报名人员
|
|
|
+ Cell cell7 = dataRow.createCell(7);
|
|
|
+ cell7.setCellValue((String) rowMap.get("报名人员"));
|
|
|
+ cell7.setCellStyle(contentStyle);
|
|
|
+
|
|
|
+ // 联系电话
|
|
|
+ Cell cell8 = dataRow.createCell(8);
|
|
|
+ cell8.setCellValue((String) rowMap.get("联系电话"));
|
|
|
+ cell8.setCellStyle(contentStyle);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 输出文件
|
|
|
+ File file = File.createTempFile("export_condition_", ".xlsx");
|
|
|
+ try (FileOutputStream fos = new FileOutputStream(file)) {
|
|
|
+ workbook.write(fos);
|
|
|
+ }
|
|
|
+ workbook.close();
|
|
|
+ return file;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 创建表头样式
|
|
|
+ private CellStyle createHeaderStyle(Workbook workbook) {
|
|
|
+ CellStyle headerStyle = workbook.createCellStyle();
|
|
|
+ Font headerFont = workbook.createFont();
|
|
|
+ headerFont.setBold(true);
|
|
|
+ headerStyle.setFont(headerFont);
|
|
|
+ headerStyle.setAlignment(HorizontalAlignment.CENTER);
|
|
|
+ headerStyle.setVerticalAlignment(VerticalAlignment.CENTER);
|
|
|
+ headerStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
|
|
|
+ headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
|
|
+ headerStyle.setBorderTop(BorderStyle.THIN);
|
|
|
+ headerStyle.setBorderBottom(BorderStyle.THIN);
|
|
|
+ headerStyle.setBorderLeft(BorderStyle.THIN);
|
|
|
+ headerStyle.setBorderRight(BorderStyle.THIN);
|
|
|
+ return headerStyle;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 创建内容样式
|
|
|
+ private CellStyle createContentStyle(Workbook workbook) {
|
|
|
+ CellStyle contentStyle = workbook.createCellStyle();
|
|
|
+ contentStyle.setAlignment(HorizontalAlignment.CENTER);
|
|
|
+ contentStyle.setVerticalAlignment(VerticalAlignment.CENTER);
|
|
|
+ contentStyle.setBorderTop(BorderStyle.THIN);
|
|
|
+ contentStyle.setBorderBottom(BorderStyle.THIN);
|
|
|
+ contentStyle.setBorderLeft(BorderStyle.THIN);
|
|
|
+ contentStyle.setBorderRight(BorderStyle.THIN);
|
|
|
+ return contentStyle;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 提取图片URL
|
|
|
+ private List<String> extractImageUrls(String certificationStr) {
|
|
|
+ List<String> allImageUrls = new ArrayList<>();
|
|
|
+ String[] certLines = certificationStr.split(";");
|
|
|
+
|
|
|
+ for (String line : certLines) {
|
|
|
+ line = line.trim();
|
|
|
+ if (line.contains(":")) {
|
|
|
+ String[] parts = line.split(": ", 2);
|
|
|
+ if (parts.length > 1) {
|
|
|
+ String imgUrls = parts[1];
|
|
|
+ String[] urls = imgUrls.split(",");
|
|
|
+ for (String url : urls) {
|
|
|
+ String trimmedUrl = url.trim();
|
|
|
+ if (!trimmedUrl.isEmpty()) {
|
|
|
+ allImageUrls.add(trimmedUrl);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return allImageUrls;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 在单元格中插入单张图片
|
|
|
+ private void insertImageToCell(Workbook workbook, Sheet sheet, String imageUrl, int column, int row) {
|
|
|
+ byte[] imageBytes = downloadImage(imageUrl);
|
|
|
+ if (imageBytes != null) {
|
|
|
+ int pictureIdx = workbook.addPicture(imageBytes, Workbook.PICTURE_TYPE_PNG);
|
|
|
+ Drawing<?> drawing = sheet.createDrawingPatriarch();
|
|
|
+ CreationHelper helper = workbook.getCreationHelper();
|
|
|
+ ClientAnchor anchor = helper.createClientAnchor();
|
|
|
+
|
|
|
+ // 设置图片锚点
|
|
|
+ anchor.setCol1(column);
|
|
|
+ anchor.setCol2(column + 1);
|
|
|
+ anchor.setRow1(row);
|
|
|
+ anchor.setRow2(row + 1);
|
|
|
+ anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);
|
|
|
+
|
|
|
+ drawing.createPicture(anchor, pictureIdx);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 在单元格中插入多张图片
|
|
|
+ private void insertMultipleImagesToCell(Workbook workbook, Sheet sheet, List<String> imageUrls, int column, int row) {
|
|
|
+ Drawing<?> drawing = sheet.createDrawingPatriarch();
|
|
|
+ CreationHelper helper = workbook.getCreationHelper();
|
|
|
+
|
|
|
+ // 图片排列参数
|
|
|
+ int maxPerRow = 4; // 每行最多3张图片
|
|
|
+ int imageWidth = 800000; // 图片宽度
|
|
|
+ int imageHeight = 800000; // 图片高度
|
|
|
+ int horizontalSpacing = 15000; // 水平间距
|
|
|
+ int verticalSpacing = 15000; // 垂直间距
|
|
|
+
|
|
|
+ for (int i = 0; i < imageUrls.size(); i++) {
|
|
|
+ String imageUrl = imageUrls.get(i);
|
|
|
+ byte[] imageBytes = downloadImage(imageUrl);
|
|
|
+
|
|
|
+ if (imageBytes != null) {
|
|
|
+ int pictureIdx = workbook.addPicture(imageBytes, Workbook.PICTURE_TYPE_PNG);
|
|
|
+
|
|
|
+ // 计算当前图片在网格中的位置
|
|
|
+ int rowIndex = i / maxPerRow;
|
|
|
+ int colIndex = i % maxPerRow;
|
|
|
+
|
|
|
+ ClientAnchor anchor = helper.createClientAnchor();
|
|
|
+
|
|
|
+ // 设置图片在单元格内的相对位置
|
|
|
+ anchor.setCol1(column);
|
|
|
+ anchor.setCol2(column);
|
|
|
+ anchor.setRow1(row);
|
|
|
+ anchor.setRow2(row);
|
|
|
+
|
|
|
+ // 计算图片的精确位置
|
|
|
+ int dx1 = colIndex * (imageWidth + horizontalSpacing) + 20000;
|
|
|
+ int dy1 = rowIndex * (imageHeight + verticalSpacing) + 20000;
|
|
|
+ int dx2 = dx1 + imageWidth;
|
|
|
+ int dy2 = dy1 + imageHeight;
|
|
|
+
|
|
|
+ anchor.setDx1(dx1);
|
|
|
+ anchor.setDy1(dy1);
|
|
|
+ anchor.setDx2(dx2);
|
|
|
+ anchor.setDy2(dy2);
|
|
|
+
|
|
|
+ drawing.createPicture(anchor, pictureIdx);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 下载图片字节流
|
|
|
+ private byte[] downloadImage(String imageUrl) {
|
|
|
+ try {
|
|
|
+ URL url = new URL(imageUrl);
|
|
|
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
|
|
+ conn.setRequestMethod("GET");
|
|
|
+ conn.setConnectTimeout(5000);
|
|
|
+ conn.setReadTimeout(5000);
|
|
|
+ InputStream is = conn.getInputStream();
|
|
|
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
|
|
+ byte[] buffer = new byte[1024];
|
|
|
+ int len;
|
|
|
+ while ((len = is.read(buffer)) > 0) {
|
|
|
+ bos.write(buffer, 0, len);
|
|
|
+ }
|
|
|
+ is.close();
|
|
|
+ return bos.toByteArray();
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
}
|