package cc.evil.logtest1.controller.logger; import cc.evil.logtest1.exception.ClientException; import cc.evil.logtest1.exception.EvilBaseException; import cc.evil.logtest1.exception.EvilErrorCode; import cc.evil.logtest1.exception.InternalServerException; import cc.evil.logtest1.model.dto.EmailListDTO; import cc.evil.logtest1.model.vo.LogFileNameList; import cc.evil.logtest1.service.log.LogFileService; import lombok.RequiredArgsConstructor; import jakarta.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; import java.io.IOException; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; import java.util.List; /** * 实现日志的基本功能: * - 获取日志文件列表, 支持按日期范围过滤; * - 获取日志文件的尾部内容, 支持指定行数; * - 下载日志文件, 支持批量下载并打包成zip; * - 添加和删除发送邮箱; */ @RestController @RequestMapping("/api/logs") @RequiredArgsConstructor public class LogsController { // service private final LogFileService logFileService; /** * 日志日期格式 */ @Value("${logs.file.date_format:yyyy-MM-dd}") private final String dateFormat = "yyyy-MM-dd"; private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(dateFormat); @GetMapping("/files") public LogFileNameList getLogsFiles(@RequestParam(value = "startDate", required = false) String startDate, @RequestParam(value = "endDate", required = false) String endDate) { LocalDate start = null, end = null; try { if (startDate != null && !startDate.isBlank()) start = LocalDate.parse(startDate.trim(), formatter); if (endDate != null && !endDate.isBlank()) end = LocalDate.parse(endDate.trim(), formatter); if (start != null && end != null && start.isAfter(end)) throw new EvilBaseException(EvilErrorCode.TIME_LOGICAL_ERROR); if (end != null && end.isAfter(LocalDate.now())) endDate = LocalDate.now().format(formatter); return logFileService.getLogFiles(start, end); } catch (EvilBaseException ebe) { throw ebe; } catch (DateTimeParseException e) { throw new ClientException(EvilErrorCode.BAD_REQUEST, "日期解析错误"); } catch (Exception e) { throw new InternalServerException(EvilErrorCode.UNEXPECTED_ERROR); } } @GetMapping("/tail") public List getFileTail(@RequestParam(value = "lines", defaultValue = "200") int lines) { lines = Math.min(lines, 500); try { return logFileService.fileTail(lines); } catch (EvilBaseException ebe) { throw ebe; } catch (Exception e) { throw new InternalServerException(EvilErrorCode.UNEXPECTED_ERROR); } } @PostMapping("/download") public void downloadLogs(@RequestBody LogFileNameList logFileNameList, HttpServletResponse response) { if (logFileNameList == null || logFileNameList.getLogFilesByDate() == null || logFileNameList.getLogFilesByDate().isEmpty()) { throw new ClientException(EvilErrorCode.BAD_REQUEST, "下载文件列表不能为空"); } try { String downloadFileName = "logs-" + LocalDate.now().format(formatter) + ".zip"; response.setContentType("application/zip"); response.setHeader("Content-Disposition", "attachment; filename=\"" + downloadFileName + "\""); logFileService.writeLogsToZip(logFileNameList, response.getOutputStream()); response.flushBuffer(); } catch (EvilBaseException ebe) { throw ebe; } catch (IOException e) { throw new InternalServerException(EvilErrorCode.SERVER_FILE_IO_ERROR, "下载日志压缩包失败"); } catch (Exception e) { throw new InternalServerException(EvilErrorCode.UNEXPECTED_ERROR); } } @PostMapping("/email") public void addEmail(@RequestBody EmailListDTO email) { try { logFileService.addEmails(email.getEmails()); } catch (EvilBaseException ebe) { throw ebe; } catch (Exception e) { throw new InternalServerException(EvilErrorCode.UNEXPECTED_ERROR); } } @DeleteMapping("/email") public void delEmail(@RequestBody EmailListDTO email) { try { for (var emails : email.getEmails()) { logFileService.removeEmail(emails); } } catch (EvilBaseException ebe) { throw ebe; } catch (Exception e) { throw new InternalServerException(EvilErrorCode.UNEXPECTED_ERROR); } } }