diff --git a/shoot-hand/ics-admin/src/main/java/com/ics/admin/controller/MeetingReservationIOController.java b/shoot-hand/ics-admin/src/main/java/com/ics/admin/controller/MeetingReservationIOController.java index de1deea..3d6bc9e 100644 --- a/shoot-hand/ics-admin/src/main/java/com/ics/admin/controller/MeetingReservationIOController.java +++ b/shoot-hand/ics-admin/src/main/java/com/ics/admin/controller/MeetingReservationIOController.java @@ -7,12 +7,21 @@ import com.ics.admin.vo.MeetingTotalVo; import com.ics.common.core.controller.BaseController; import com.ics.common.utils.DateUtils; import org.jxls.common.Context; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.wf.jwtp.annotation.RequiresPermissions; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; +import java.net.URLEncoder; +import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; @@ -29,6 +38,8 @@ import java.util.List; @RequestMapping("admin/mr/io") public class MeetingReservationIOController extends BaseController { + private static final Logger log = LoggerFactory.getLogger(MeetingReservationIOController.class); + @Autowired private IMeetingReservationIOService meetingReservationIOService; @@ -45,23 +56,162 @@ public class MeetingReservationIOController extends BaseController { * device,设备,模糊查询 * capacityNum,容纳人数,精确查询 * filterDate,预约日期查询,以预约开始时间为准;查询指定日期的所有预约。格式:2024-10-14。必填 + * 或者使用 startDate 和 endDate 指定日期范围 */ @RequiresPermissions(value = {"mr:manage:operator"}) @PostMapping("exportDayMR") - public void exportMR(MeetingRecordExportVo meetingRecordExportVo) { + public void exportMR(HttpServletResponse response, + @RequestParam(required = false) String filterDate, + @RequestParam(required = false) String startDate, + @RequestParam(required = false) String endDate, + @RequestParam(required = false) String userOrg, + @RequestParam(required = false) String title, + @RequestParam(required = false) String status) { + log.info("开始导出会议室预约记录,filterDate={}, startDate={}, endDate={}, userOrg={}, title={}, status={}", + filterDate, startDate, endDate, userOrg, title, status); + try { - Date day = DateUtils.dateTime(DateUtils.YYYY_MM_DD, meetingRecordExportVo.getFilterDate()); + MeetingRecordExportVo meetingRecordExportVo = new MeetingRecordExportVo(); + + // 设置查询参数 + meetingRecordExportVo.setFilterDate(filterDate); + meetingRecordExportVo.setUserOrg(userOrg); + meetingRecordExportVo.setTitle(title); + + // 添加额外的查询参数 + if (startDate != null && !startDate.isEmpty()) { + meetingRecordExportVo.setExt1(startDate); // 使用ext1临时存储startDate + } + + if (endDate != null && !endDate.isEmpty()) { + meetingRecordExportVo.setExt2(endDate); // 使用ext2临时存储endDate + } + + // 处理status参数,如果不为空,则转换为Integer + if (status != null && !status.isEmpty()) { + try { + meetingRecordExportVo.setStatus(Integer.parseInt(status)); + } catch (NumberFormatException e) { + log.error("状态参数格式错误: {}", status); + } + } + + // 确定日期 + String effectiveDate = filterDate; + if ((effectiveDate == null || effectiveDate.isEmpty()) && startDate != null && !startDate.isEmpty()) { + effectiveDate = startDate; + } + + // 检查是否有日期参数 + boolean hasDateParams = (filterDate != null && !filterDate.isEmpty()) || + (startDate != null && !startDate.isEmpty() && endDate != null && !endDate.isEmpty()); + + if (!hasDateParams) { + sendErrorResponse(response, "日期参数不能为空"); + return; + } + + Date day = null; + try { + if (filterDate != null && !filterDate.isEmpty()) { + log.info("解析单日期: {}", filterDate); + day = DateUtils.dateTime(DateUtils.YYYY_MM_DD, filterDate); + } else { + log.info("解析日期范围的第一天: {}", startDate); + day = DateUtils.dateTime(DateUtils.YYYY_MM_DD, startDate); + } + } catch (Exception e) { + log.error("日期解析错误: {}", e.getMessage(), e); + sendErrorResponse(response, "日期格式错误"); + return; + } + Calendar calendar = Calendar.getInstance(); calendar.setTime(day); int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK) - 1; - List list = meetingReservationIOService.getMeetingReservationList(meetingRecordExportVo); + + log.info("查询会议室预约记录列表"); + List list = null; + try { + list = meetingReservationIOService.getMeetingReservationList(meetingRecordExportVo); + } catch (Exception e) { + log.error("查询数据失败: {}", e.getMessage(), e); + sendErrorResponse(response, "查询数据失败: " + e.getMessage()); + return; + } + + if (list == null) { + list = new ArrayList<>(); + } + log.info("查询结果数量: {}", list.size()); + Context context = new Context(); - context.putVar("day", DateUtils.parseDateToStr("yyyy年MM月dd日", day)); - context.putVar("dayOfWeek", WEEK.charAt(dayOfWeek)); + // 根据日期参数设置不同的标题 + if (startDate != null && !startDate.isEmpty() && endDate != null && !endDate.isEmpty()) { + // 多天日期范围的情况 + String startDateStr = startDate.substring(5); // 提取MM-DD部分 + String endDateStr = endDate.substring(5); // 提取MM-DD部分 + String year = startDate.substring(0, 4); // 提取年份 + context.putVar("title", "会议中心" + year + "年" + startDateStr.replace("-", "月") + "日-" + endDateStr.replace("-", "月") + "日会情表"); + context.putVar("day", ""); // 不显示单日 + context.putVar("dayOfWeek", ""); // 不显示星期 + } else { + // 单日情况 + context.putVar("day", DateUtils.parseDateToStr("yyyy年MM月dd日", day)); + context.putVar("dayOfWeek", WEEK.charAt(dayOfWeek)); + } context.putVar("list", list); - new ExcelView("excel/会情表导出模版.xls", "会议中心会情表.xls", context); + + // 设置响应头,确保浏览器能够正确处理下载 + String filename = ""; + if (startDate != null && !startDate.isEmpty() && endDate != null && !endDate.isEmpty()) { + filename = URLEncoder.encode(startDate + "至" + endDate + "会议室预约记录.xls", "UTF-8"); + } else { + filename = URLEncoder.encode(effectiveDate + "会议室预约记录.xls", "UTF-8"); + } + + response.reset(); + response.setContentType("application/vnd.ms-excel;charset=UTF-8"); + response.setHeader("Content-Disposition", "attachment; filename=" + filename); + response.setHeader("Pragma", "no-cache"); + response.setHeader("Cache-Control", "no-cache"); + + log.info("开始生成Excel文件"); + try { + // 尝试不同的模板路径 + String[] templatePaths = { + "excel/会情表导出模版.xls", + "/excel/会情表导出模版.xls", + "会情表导出模版.xls" + }; + + boolean success = false; + Exception lastException = null; + + for (String path : templatePaths) { + try { + log.info("尝试使用模板路径: {}", path); + new ExcelView(path, response.getOutputStream(), context); + log.info("Excel文件生成成功"); + success = true; + break; + } catch (Exception e) { + lastException = e; + log.warn("使用模板 {} 失败: {}", path, e.getMessage()); + } + } + + if (!success) { + log.error("所有模板路径都失败", lastException); + sendErrorResponse(response, "导出失败:无法找到模板文件"); + } + } catch (Exception e) { + log.error("生成Excel文件失败: {}", e.getMessage(), e); + sendErrorResponse(response, "导出失败:" + e.getMessage()); + } } catch (Exception e) { - e.printStackTrace(); + log.error("导出会议室预约记录失败: {}", e.getMessage(), e); + sendErrorResponse(response, "导出失败:" + e.getMessage()); } } @@ -71,16 +221,114 @@ public class MeetingReservationIOController extends BaseController { */ @RequiresPermissions(value = {"mr:manage:operator"}) @PostMapping("exportMonthMR") - public void exportMonthMR(String month) { + public void exportMonthMR(HttpServletResponse response, @RequestParam(required = true) String month) { + log.info("开始导出月度汇总,month={}", month); + try { - Date mon = DateUtils.dateTime(DateUtils.YYYY_MM, month); - List list = meetingReservationIOService.total(month); + if (month == null || month.isEmpty()) { + sendErrorResponse(response, "月份参数不能为空"); + return; + } + + // 验证月份格式 + if (!month.matches("^\\d{4}-\\d{2}$")) { + sendErrorResponse(response, "月份格式错误,正确格式为:YYYY-MM"); + return; + } + + Date mon = null; + try { + mon = DateUtils.dateTime(DateUtils.YYYY_MM, month); + } catch (Exception e) { + log.error("月份解析错误: {}", e.getMessage(), e); + sendErrorResponse(response, "月份格式错误: " + month); + return; + } + + log.info("查询月度汇总数据,month={}", month); + List list = null; + try { + list = meetingReservationIOService.total(month); + log.info("查询SQL参数: {}", month); + } catch (Exception e) { + log.error("查询数据失败: {}", e.getMessage(), e); + sendErrorResponse(response, "查询数据失败: " + e.getMessage()); + return; + } + + if (list == null) { + list = new ArrayList<>(); + log.warn("查询结果为空,创建空列表"); + } + log.info("查询结果数量: {}", list.size()); + Context context = new Context(); context.putVar("month", DateUtils.parseDateToStr("yyyy年MM月", mon)); context.putVar("list", list); - new ExcelView("excel/会情汇总表导出模版.xls", "会议中心会情汇总表.xls", context); + + // 设置响应头,确保浏览器能够正确处理下载 + String filename = URLEncoder.encode(month + "月度会议汇总.xls", "UTF-8"); + response.reset(); + response.setContentType("application/vnd.ms-excel;charset=UTF-8"); + response.setHeader("Content-Disposition", "attachment; filename=" + filename); + response.setHeader("Pragma", "no-cache"); + response.setHeader("Cache-Control", "no-cache"); + + log.info("开始生成Excel文件"); + try { + // 尝试不同的模板路径 + String[] templatePaths = { + "excel/会情汇总表导出模版.xls", + "/excel/会情汇总表导出模版.xls", + "会情汇总表导出模版.xls", + "excel/会情汇总表导出模板.xls", + "/excel/会情汇总表导出模板.xls", + "会情汇总表导出模板.xls" + }; + + boolean success = false; + Exception lastException = null; + + for (String path : templatePaths) { + try { + log.info("尝试使用模板路径: {}", path); + new ExcelView(path, response.getOutputStream(), context); + log.info("Excel文件生成成功"); + success = true; + break; + } catch (Exception e) { + lastException = e; + log.warn("使用模板 {} 失败: {}", path, e.getMessage()); + } + } + + if (!success) { + log.error("所有模板路径都失败", lastException); + sendErrorResponse(response, "导出失败:无法找到模板文件,请检查模板文件是否存在"); + } + } catch (Exception e) { + log.error("生成Excel文件失败: {}", e.getMessage(), e); + sendErrorResponse(response, "导出失败:" + e.getMessage()); + } } catch (Exception e) { - e.printStackTrace(); + log.error("导出月度汇总失败: {}", e.getMessage(), e); + sendErrorResponse(response, "导出失败:" + e.getMessage()); + } + } + + /** + * 发送错误响应 + */ + private void sendErrorResponse(HttpServletResponse response, String message) { + try { + response.reset(); + response.setContentType("text/plain;charset=utf-8"); + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + PrintWriter writer = response.getWriter(); + writer.write(message); + writer.flush(); + } catch (IOException e) { + log.error("写入错误响应失败", e); } } } diff --git a/shoot-hand/ics-admin/src/main/java/com/ics/admin/service/impl/IMeetingReservationIOServiceImpl.java b/shoot-hand/ics-admin/src/main/java/com/ics/admin/service/impl/IMeetingReservationIOServiceImpl.java index c758ce3..7a572dd 100644 --- a/shoot-hand/ics-admin/src/main/java/com/ics/admin/service/impl/IMeetingReservationIOServiceImpl.java +++ b/shoot-hand/ics-admin/src/main/java/com/ics/admin/service/impl/IMeetingReservationIOServiceImpl.java @@ -4,9 +4,12 @@ import com.ics.admin.mapper.MeetingReservationIOMapper; import com.ics.admin.service.IMeetingReservationIOService; import com.ics.admin.vo.MeetingRecordExportVo; import com.ics.admin.vo.MeetingTotalVo; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.util.ArrayList; import java.util.List; /** @@ -19,28 +22,61 @@ import java.util.List; @Service public class IMeetingReservationIOServiceImpl implements IMeetingReservationIOService { + private static final Logger log = LoggerFactory.getLogger(IMeetingReservationIOServiceImpl.class); + @Autowired private MeetingReservationIOMapper meetingReservationIOMapper; @Override public List getMeetingReservationList(MeetingRecordExportVo meetingRecordExportVo) { + log.info("执行getMeetingReservationList查询,参数:filterDate={}", meetingRecordExportVo.getFilterDate()); return meetingReservationIOMapper.getMeetingReservationList(meetingRecordExportVo); } @Override public List total(String filterDate) { - List list = meetingReservationIOMapper.total(filterDate); - int cz = 0, pn = 0; - for (MeetingTotalVo meetingTotalVo : list) { - cz += meetingTotalVo.getCz(); - pn += meetingTotalVo.getPn(); + log.info("执行total查询,参数:filterDate={}", filterDate); + try { + if (filterDate == null || filterDate.isEmpty()) { + log.error("月份参数为空"); + throw new IllegalArgumentException("月份参数不能为空"); + } + + // 确保月份格式正确 + if (!filterDate.matches("^\\d{4}-\\d{2}$")) { + log.error("月份格式错误: {}", filterDate); + throw new IllegalArgumentException("月份格式错误,正确格式为:YYYY-MM"); + } + + log.info("开始查询数据库"); + List list = meetingReservationIOMapper.total(filterDate); + log.info("数据库查询完成"); + + if (list == null) { + log.warn("查询结果为null,返回空列表"); + return new ArrayList<>(); + } + + int cz = 0, pn = 0; + for (MeetingTotalVo meetingTotalVo : list) { + if (meetingTotalVo.getCz() != null) { + cz += meetingTotalVo.getCz(); + } + if (meetingTotalVo.getPn() != null) { + pn += meetingTotalVo.getPn(); + } + } + MeetingTotalVo m = new MeetingTotalVo(); + m.setName("合计"); + m.setCz(cz); + m.setPn(pn); + list.add(m); + log.info("查询结果处理完成,总记录数:{}", list.size()); + return list; + } catch (Exception e) { + log.error("执行total查询失败:{}", e.getMessage(), e); + throw e; } - MeetingTotalVo m = new MeetingTotalVo(); - m.setName("合计"); - m.setCz(cz); - m.setPn(pn); - list.add(m); - return list; } } diff --git a/shoot-hand/ics-admin/src/main/java/com/ics/admin/utils/ExcelView.java b/shoot-hand/ics-admin/src/main/java/com/ics/admin/utils/ExcelView.java index 6f2610a..b5bcede 100644 --- a/shoot-hand/ics-admin/src/main/java/com/ics/admin/utils/ExcelView.java +++ b/shoot-hand/ics-admin/src/main/java/com/ics/admin/utils/ExcelView.java @@ -57,6 +57,27 @@ public class ExcelView { throw new RuntimeException(e.getMessage(), e); } } + + /** + * 构造方法(使用指定的输出流) + * + * @param templatePath 模板路径 + * @param outputStream 输出流 + * @param context 数据上下文 + */ + public ExcelView(String templatePath, OutputStream outputStream, Context context) { + log.info("使用输出流构造方法,模板路径: {}", templatePath); + // 指定到resource目录 + ClassPathResource classPathResource = new ClassPathResource(templatePath); + try (InputStream inputStream = classPathResource.getInputStream()) { + JxlsHelper.getInstance().processTemplate(inputStream, outputStream, context); + outputStream.flush(); + // 注意:此处不关闭输出流,由调用者负责关闭 + } catch (IOException e) { + log.error("处理Excel模板失败: {}", e.getMessage(), e); + throw new RuntimeException("处理Excel模板失败: " + e.getMessage(), e); + } + } /** * 构造方法(保存到指定服务器路径) diff --git a/shoot-hand/ics-admin/src/main/resources/mapper/admin/MeetingReservationIOMapper.xml b/shoot-hand/ics-admin/src/main/resources/mapper/admin/MeetingReservationIOMapper.xml index 068d71d..bbf838d 100644 --- a/shoot-hand/ics-admin/src/main/resources/mapper/admin/MeetingReservationIOMapper.xml +++ b/shoot-hand/ics-admin/src/main/resources/mapper/admin/MeetingReservationIOMapper.xml @@ -8,23 +8,41 @@ \ No newline at end of file