package com.ai.da.controller; import com.ai.da.common.response.Response; import com.ai.da.model.dto.*; import com.ai.da.model.dto.ContestantDTO; import com.ai.da.model.vo.CheckOTPVO; import com.ai.da.model.vo.ContestantCountVO; import com.ai.da.service.GlobalAwardService; import com.ai.da.service.upload.UploadService; import com.ai.da.service.upload.UploadTask; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.util.Map; @RestController @RequestMapping("/api/global-award") @Api(tags = "全球奖项API", description = "全球奖项大赛管理和文件上传") public class GlobalAwardController { @Resource private GlobalAwardService globalAwardService; @Resource private UploadService uploadService; // @PostMapping("/uploads/pdf") // public Response uploadPdf(@RequestParam("file") MultipartFile file, // @RequestParam(value = "email", required = false) String email) throws Exception { // return Response.success(globalAwardService.uploadPdf(file, email)); // } // // @PostMapping("/uploads/video") // public Response uploadVideo(@RequestParam("file") MultipartFile file, // @RequestParam(value = "email", required = false) String email) throws Exception { // return Response.success(globalAwardService.uploadVideo(file, email)); // } // ===== 新增分片上传接口 ===== // ===== PDF分片上传接口 ===== /** 初始化PDF上传任务 */ @PostMapping("/uploads/pdf/init") @ApiOperation(value = "初始化PDF上传", notes = "创建新的PDF上传任务并返回上传参数") public Response initPdfUpload(@ApiParam(value = "PDF上传初始化请求", required = true) @RequestBody UploadInitRequest request) { UploadTask uploadTask = uploadService.initPdfUpload(request); return Response.success(UploadInitResponse.builder() .uploadId(uploadTask.getUploadId()) .chunkSize(uploadTask.getChunkSize()) .totalChunks(uploadTask.getTotalChunks()) .expiresAt(uploadTask.getExpiresAt()) .build()); } /** 上传PDF分片 */ @PostMapping("/uploads/pdf/chunk") @ApiOperation(value = "上传PDF分片", notes = "上传PDF文件的单个分片") public Response uploadPdfChunk( @ApiParam(value = "PDF文件分片", required = true) @RequestParam("chunk") MultipartFile chunk, @ApiParam(value = "上传任务ID", required = true) @RequestParam("uploadId") String uploadId, @ApiParam(value = "分片索引(从0开始)", required = true) @RequestParam("chunkIndex") int chunkIndex, @ApiParam(value = "分片总数", required = true) @RequestParam("totalChunks") int totalChunks) { UploadChunkResponse uploadChunkResponse = uploadService.uploadPdfChunk(uploadId, chunk, chunkIndex, totalChunks); return Response.success(uploadChunkResponse); } /** 完成PDF上传 */ @PostMapping("/uploads/pdf/complete") @ApiOperation(value = "完成PDF上传", notes = "完成PDF上传并合并所有分片") public Response completePdfUpload(@ApiParam(value = "PDF上传完成请求", required = true) @RequestBody UploadCompleteRequest request) { UploadCompleteResponse uploadCompleteResponse = uploadService.completePdfUpload( request.getUploadId(), request.getFileName(), request.getTotalSize(), request.getEmail(), request.getSecureToken()); return Response.success(uploadCompleteResponse); } /** 查询PDF上传状态 */ @GetMapping("/uploads/pdf/status/{uploadId}") @ApiOperation(value = "查询PDF上传状态", notes = "获取PDF上传任务的当前状态") public Response getPdfUploadStatus(@ApiParam(value = "上传任务ID", required = true) @PathVariable String uploadId) { UploadStatusResponse pdfUploadStatus = uploadService.getPdfUploadStatus(uploadId); return Response.success(pdfUploadStatus); } // ===== 视频分片上传接口 ===== /** 初始化视频上传任务 */ @PostMapping("/uploads/video/init") @ApiOperation(value = "初始化视频上传", notes = "创建新的视频上传任务并返回上传参数") public Response initVideoUpload(@ApiParam(value = "视频上传初始化请求", required = true) @RequestBody UploadInitRequest request) { UploadTask uploadTask = uploadService.initVideoUpload(request); return Response.success(UploadInitResponse.builder() .uploadId(uploadTask.getUploadId()) .chunkSize(uploadTask.getChunkSize()) .totalChunks(uploadTask.getTotalChunks()) .expiresAt(uploadTask.getExpiresAt()) .build()); } /** 上传视频分片 */ @PostMapping("/uploads/video/chunk") @ApiOperation(value = "上传视频分片", notes = "上传视频文件的单个分片") public Response uploadVideoChunk( @ApiParam(value = "视频文件分片", required = true) @RequestParam("chunk") MultipartFile chunk, @ApiParam(value = "上传任务ID", required = true) @RequestParam("uploadId") String uploadId, @ApiParam(value = "分片索引(从0开始)", required = true) @RequestParam("chunkIndex") int chunkIndex, @ApiParam(value = "分片总数", required = true) @RequestParam("totalChunks") int totalChunks) { UploadChunkResponse uploadChunkResponse = uploadService.uploadVideoChunk(uploadId, chunk, chunkIndex, totalChunks); return Response.success(uploadChunkResponse); } /** 完成视频上传 */ @PostMapping("/uploads/video/complete") @ApiOperation(value = "完成视频上传", notes = "完成视频上传并合并所有分片") public Response completeVideoUpload(@ApiParam(value = "视频上传完成请求", required = true) @RequestBody UploadCompleteRequest request) { UploadCompleteResponse uploadCompleteResponse = uploadService.completeVideoUpload( request.getUploadId(), request.getFileName(), request.getTotalSize(), request.getEmail(), request.getSecureToken()); return Response.success(uploadCompleteResponse); } /** 查询视频上传状态 */ @GetMapping("/uploads/video/status/{uploadId}") @ApiOperation(value = "查询视频上传状态", notes = "获取视频上传任务的当前状态") public Response getVideoUploadStatus(@ApiParam(value = "上传任务ID", required = true) @PathVariable String uploadId) { UploadStatusResponse videoUploadStatus = uploadService.getVideoUploadStatus(uploadId); return Response.success(videoUploadStatus); } @PostMapping("/contestants/save") @ApiOperation(value = "保存参赛者信息", notes = "保存或更新参赛者信息及已上传的文件") public Response> submit(@ApiParam(value = "参赛者信息", required = true) @RequestBody ContestantDTO request) { return Response.success(globalAwardService.saveContestant(request)); } @GetMapping("/contestants/{id}") @ApiOperation(value = "根据id查询参赛者", notes = "根据id获取参赛者信息") public Response getContestantByID(@ApiParam(value = "参赛者id", required = true) @PathVariable("id") String id) { ContestantDTO dto = globalAwardService.getContestantByID(id); return Response.success(dto); } @GetMapping("/checkEmail") public Response checkEmail(@RequestParam("email") String email) { globalAwardService.checkEmail(email); return Response.success(); } @GetMapping("/checkCode") public Response checkCode(@RequestParam("email") String email, @RequestParam("code") String code) { return Response.success(globalAwardService.checkCode(email, code)); } @GetMapping("/contestants/export") @ApiOperation(value = "导出参赛者列表为Excel", notes = "导出所有参赛者信息为xlsx并触发下载") public void exportContestants(HttpServletResponse response) throws Exception { byte[] data = globalAwardService.exportContestants(); response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setHeader("Content-Disposition", "attachment; filename=\"contestants.xlsx\""); response.setContentLength(data.length); response.getOutputStream().write(data); response.getOutputStream().flush(); } @PostMapping("/contestants/export/files") @ApiOperation(value = "导出参赛者文件为ZIP", notes = "根据参赛者编号范围导出PDF、视频和信息文件为ZIP,直接响应给浏览器") public void exportContestantFiles(@ApiParam(value = "参赛者文件导出请求", required = true) @RequestBody ContestantExportRequest request, HttpServletResponse response) throws Exception { byte[] zipData = globalAwardService.exportContestantFilesAsZip(request.getMinContestantNumber(), request.getMaxContestantNumber()); if (zipData.length == 0) { response.setStatus(HttpServletResponse.SC_NOT_FOUND); response.getWriter().write("No contestants found in the specified range."); return; } response.setContentType("application/zip"); response.setHeader("Content-Disposition", "attachment; filename=\"contestants.zip\""); response.setContentLength(zipData.length); response.getOutputStream().write(zipData); response.getOutputStream().flush(); } @GetMapping("/contestants/count") @ApiOperation(value = "查询参赛者总数", notes = "查询数据库中参赛者的总数量和最大参赛者编号") public Response getContestantCount() { return Response.success(globalAwardService.getContestantCount()); } }