package com.linghu.controller; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.linghu.listener.KeywordExcelListener; import com.linghu.mapper.KeywordMapper; import com.linghu.mapper.ReferenceMapper; import com.linghu.model.common.ResponseResult; import com.linghu.model.dto.ExportFeedDTO; import com.linghu.model.dto.ExportGetResultByPlatformIdDTO; import com.linghu.model.dto.ExportGetResultDTO; import com.linghu.model.dto.ExportStaticsDTO; import com.linghu.model.entity.Keyword; import com.linghu.model.entity.Platform; import com.linghu.model.entity.Reference; import com.linghu.model.entity.Type; import com.linghu.model.excel.FeedExportExcel; import com.linghu.model.excel.PlatformExcel; import com.linghu.model.excel.ReferenceExcel; import com.linghu.model.vo.*; import com.linghu.model.excel.KeywordExcel; import com.linghu.model.excel.PlatformExcel; import com.linghu.model.vo.KeywordStaticsListVO; import com.linghu.model.vo.KeywordStaticsVO; import com.linghu.model.vo.PlatformProportionVO; import com.linghu.model.vo.ResultListVO; import com.linghu.service.KeywordService; import com.linghu.service.ReferenceService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.util.StringUtils; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; import javax.xml.bind.ValidationException; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.time.LocalDateTime; import java.io.IOException; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @RestController @RequestMapping("/keyword") @Api(value = "采集详情相关接口", tags = "订单列表-采集列表-采集详情") public class KeywordController { @Autowired private KeywordService keywordService; @Autowired private KeywordMapper keywordMapper; @Autowired private ReferenceService referenceService; @Autowired private ReferenceMapper referenceMapper; /** * 关键词统计 EChart图 */ @GetMapping("/statics") @ApiOperation(value = "EChart图") public ResponseResult statics(@RequestParam("id") Integer keywordId, @RequestParam(value = "questionId", required = false) Integer questionId) { // return keywordService.statics(keywordId, questionId); } @GetMapping("/getTime") @ApiOperation(value = "查看时间") public ResponseResult getTime(@RequestParam("id") Integer keywordId,@RequestParam(value = "questionId", required = false) Integer questionId) { // GetTimeVO vo = new GetTimeVO(); Keyword keyword = keywordService.getById(keywordId); LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(Reference::getKeyword_id, keywordId); if (questionId != null) { queryWrapper.eq(Reference::getQuestion_id, questionId); } queryWrapper.eq(Reference::getNum,keyword.getNum()); List list = referenceService.list(queryWrapper); if (null != list && !list.isEmpty()) { vo.setNow(list.get(0).getCreate_time()); } //首次 LambdaQueryWrapper queryWrapper2 = new LambdaQueryWrapper<>(); queryWrapper2.eq(Reference::getKeyword_id, keywordId); if (questionId != null) { queryWrapper2.eq(Reference::getQuestion_id, questionId); } queryWrapper2.eq(Reference::getNum,1); List list2 = referenceService.list(queryWrapper2); if (null != list2 && !list2.isEmpty()) { vo.setFirst(list2.get(0).getCreate_time()); } return ResponseResult.success(vo); } @PostMapping(value = "/exportStatics") @ApiOperation(value = "EChart图导出") public ResponseEntity exportStatics(@RequestBody ExportStaticsDTO exportStaticsDTO) { Keyword keyword = keywordMapper.selectById(exportStaticsDTO.getKeywordId()); List voList=new ArrayList<>(); if (exportStaticsDTO.getIsFirst()==0){ voList = keywordMapper.statics(exportStaticsDTO.getKeywordId(), exportStaticsDTO.getQuestionId(), keyword.getNum()); }else { voList = keywordMapper.statics(exportStaticsDTO.getKeywordId(), exportStaticsDTO.getQuestionId(), 1); } // 3. 导出Excel ByteArrayOutputStream out = new ByteArrayOutputStream(); EasyExcel.write(out, KeywordStaticsVO.class) .sheet("引用数据") .doWrite(voList); // 4. 构建响应 return ResponseEntity.ok() .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=references_export.xlsx") .contentType(MediaType.APPLICATION_OCTET_STREAM) .body(out.toByteArray()); } /** * 根据类别查看 */ @GetMapping("/getResultByTypeId") @ApiOperation(value = "根据类别查看") public ResponseResult > getResultByTypeId(@RequestParam("keywordId") Integer keywordId, @RequestParam(value = "questionId", required = false) Integer questionId, @RequestParam(value = "typeId", required = false) Integer typeId, @RequestParam(value = "isNow") Integer isNow) { Keyword keyword = keywordService.getById(keywordId); if (isNow == 0) { List result = keywordMapper.getResultByTypeId(keywordId, questionId, keyword.getNum() , typeId); return ResponseResult.success(result); }else { List result = keywordMapper.getResultByTypeId(keywordId, questionId, 1, typeId); return ResponseResult.success(result); } } /** * 导出:根据类别查看 */ @PostMapping(value = "/exportGetResultByTypeId") @ApiOperation(value = "导出:根据类别查看") public ResponseEntity exportGetResultByTypeId(@RequestBody ExportGetResultDTO dto) { Keyword keyword = keywordService.getById(dto.getKeywordId()); List result =new ArrayList<>(); if (dto.getIsNow()==0){ result = keywordMapper.getResultByTypeId(dto.getKeywordId(), dto.getQuestionId(), keyword.getNum() , dto.getTypeId()); }else { result = keywordMapper.getResultByTypeId(dto.getKeywordId(), dto.getQuestionId(), 1 , dto.getTypeId()); } // 3. 导出Excel ByteArrayOutputStream out = new ByteArrayOutputStream(); EasyExcel.write(out, PlatformProportionVO.class) .sheet("引用数据") .doWrite(result); // 4. 构建响应 return ResponseEntity.ok() .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=references_export.xlsx") .contentType(MediaType.APPLICATION_OCTET_STREAM) .body(out.toByteArray()); } /** * 根据平台查看 */ @PostMapping("/getResultByPlatformId") @ApiOperation(value = "根据平台查看") public ResponseResult> getResultByPlatformId(@RequestParam("keywordId") Integer keywordId, @RequestParam(value = "questionId", required = false) Integer questionId, @RequestParam(value = "platformId", required = false) Integer platformId, @RequestParam(value = "isNow") Integer isNow) { Keyword keyword = keywordService.getById(keywordId); if (isNow == 0) { List result = keywordMapper.getResultByPlatformId(keywordId, questionId, keyword.getNum(), platformId); return ResponseResult.success(result); } else { List result = keywordMapper.getResultByPlatformId(keywordId, questionId, 1, platformId); return ResponseResult.success(result); } } /** * 根据平台查看 0-当前轮 1-代表前1轮 2-代表前2轮 */ @PostMapping("/exportGetResultByPlatformId") @ApiOperation(value = "导出:根据平台查看") public ResponseEntity exportGetResultByPlatformId(@RequestBody ExportGetResultByPlatformIdDTO dto) { Keyword keyword = keywordService.getById(dto.getKeywordId()); List result=new ArrayList<>(); if (dto.getIsNow()==0){ result = keywordMapper.getResultByPlatformId(dto.getKeywordId(), dto.getQuestionId(), keyword.getNum(), dto.getPlatformId()); }else { result = keywordMapper.getResultByPlatformId(dto.getKeywordId(), dto.getQuestionId(), 1, dto.getPlatformId()); } // 3. 导出Excel ByteArrayOutputStream out = new ByteArrayOutputStream(); EasyExcel.write(out, ResultListVO.class) .sheet("引用数据") .doWrite(result); // 4. 构建响应 return ResponseEntity.ok() .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=references_export.xlsx") .contentType(MediaType.APPLICATION_OCTET_STREAM) .body(out.toByteArray()); } /** * 查看详情 */ @GetMapping("/getResultById") @ApiOperation(value = "查看") public ResponseResult getResultById(@RequestParam("referenceId") Integer referenceId) { Reference reference = referenceService.getById(referenceId); if (reference == null) { return ResponseResult.error("该结果不存在"); } return ResponseResult.success(reference); } /** * 下载模版 */ @GetMapping("/download") @ApiOperation("下载投喂模板") public ResponseEntity downTemplate() throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); EasyExcel.write(out, ReferenceExcel.class).sheet("投喂模板").doWrite(new ArrayList<>()); return ResponseEntity.ok() .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=platform_template.xlsx") .contentType(MediaType.APPLICATION_OCTET_STREAM) .body(out.toByteArray()); } /** * 投喂 */ @PostMapping("/importFeed/{keywordId}") @ApiOperation("投喂") public ResponseResult> importTemplate(@PathVariable("keywordId") Integer keywordId,@RequestParam("file") MultipartFile file) { Keyword keyword = keywordService.getById(keywordId); //查找出最近一次的结果 List references = referenceMapper.importTemplateList(keywordId,keyword.getNum()); //平台名称 Map nameMap = references.stream() .collect(Collectors.toMap( FeedExportExcel::getPlatform_name, // Key映射 excel -> excel, // Value映射 (oldValue, newValue) -> oldValue // 键冲突处理(保留旧值) )); //URL Map urlMap = references.stream() .collect(Collectors.toMap( FeedExportExcel::getUrl, // Key映射 excel -> excel, // Value映射 (oldValue, newValue) -> oldValue // 键冲突处理(保留旧值) )); //title Map titleMap = references.stream() .collect(Collectors.toMap( FeedExportExcel::getTitle, // Key映射 excel -> excel, // Value映射 (oldValue, newValue) -> oldValue // 键冲突处理(保留旧值) )); //time Map timeMap = references.stream() .collect(Collectors.toMap( FeedExportExcel::getCreate_time, // Key映射 excel -> excel, // Value映射 (oldValue, newValue) -> oldValue // 键冲突处理(保留旧值) )); try { // 检查文件是否为空 if (file.isEmpty()) { return ResponseResult.error("上传文件不能为空"); } // 读取Excel数据 List excelList = EasyExcel.read(file.getInputStream()) .head(ReferenceExcel.class) .sheet() .doReadSync(); // 数据转换与验证 List errorMessages = new ArrayList<>(); List result = new ArrayList<>(); for (ReferenceExcel excel : excelList) { // 检查必要字段 if (!StringUtils.hasText(excel.getPlatform_name())) { errorMessages.add("平台名称不能为空"); continue; } if (!StringUtils.hasText(excel.getTitle())) { errorMessages.add("标题不能为空"); continue; } if (!StringUtils.hasText(String.valueOf(excel.getCreate_time()))) { errorMessages.add("发布时间不能为空"); continue; } if (!StringUtils.hasText(excel.getUrl())) { errorMessages.add("发布网址不能为空"); continue; } DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); LocalDateTime dateTime = LocalDateTime.parse(excel.getCreate_time(), formatter); excel.setCreateTimeAsDateTime(dateTime); FeedExportExcel feedExportExcel = getFeedExportExcel(excel, nameMap, urlMap, titleMap, timeMap); result.add(feedExportExcel); } // 处理错误 if (!errorMessages.isEmpty()) { return ResponseResult.error("数据验证失败: " + String.join("; ", errorMessages)); } // 返回信息 return ResponseResult.success(result); }catch (DateTimeParseException e) { return ResponseResult.error("文件解析失败:发布时间格式输入错误"); } catch (Exception e) { // 记录详细异常信息 return ResponseResult.error("文件解析失败:" + e.getMessage()); } } private FeedExportExcel getFeedExportExcel(ReferenceExcel excel, Map nameMap, Map urlMap, Map titleMap, Map timeMap) { FeedExportExcel vo=new FeedExportExcel(); vo.setPlatform_name(excel.getPlatform_name()); vo.setTitle(excel.getTitle()); vo.setCreate_time(excel.getCreateTimeAsDateTime()); vo.setUrl(excel.getUrl()); vo.setInclusionStatus("未收录"); vo.setPlatformIs(0); vo.setTitleIs(0); vo.setUrlIs(0); vo.setCreateIs(0); //平台名称 if (nameMap.containsKey(excel.getPlatform_name())) { vo.setPlatformIs(1); if (urlMap.containsKey(excel.getUrl())) { vo.setUrlIs(1); } if (titleMap.containsKey(excel.getTitle())) { vo.setTitleIs(1); } if (timeMap.containsKey(excel.getCreateTimeAsDateTime())) { vo.setCreateIs(1); } return vo; } //网站链接 if (urlMap.containsKey(excel.getUrl())) { vo.setUrlIs(1); if (titleMap.containsKey(excel.getTitle())) { vo.setTitleIs(1); } if (timeMap.containsKey(excel.getCreateTimeAsDateTime())) { vo.setCreateIs(1); } return vo; } //标题 if (titleMap.containsKey(excel.getTitle())) { vo.setTitleIs(1); if (timeMap.containsKey(excel.getCreateTimeAsDateTime())) { vo.setCreateIs(1); } } //时间 if (timeMap.containsKey(excel.getCreateTimeAsDateTime())) { vo.setCreateIs(1); return vo; } return vo; } /** * 导出投喂结果 */ @PostMapping("/exportFeed") @ApiOperation(value = "导出投喂结果") public ResponseEntity exportGetResultByPlatformId(@RequestBody ExportFeedDTO dto) { // 3. 导出Excel ByteArrayOutputStream out = new ByteArrayOutputStream(); EasyExcel.write(out, FeedExportExcel.class) .sheet("导出投喂结果") .doWrite(dto.getExcels()); // 4. 构建响应 return ResponseEntity.ok() .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=references_export.xlsx") .contentType(MediaType.APPLICATION_OCTET_STREAM) .body(out.toByteArray()); } /** * 批量新增关键词 */ @PostMapping("/batchAdd") @ApiOperation(value = "批量新增关键词") public ResponseResult batchAdd(String keywords, String order_id) { Boolean saveKeywords = keywordService.saveKeywords(keywords, order_id); if (saveKeywords) { return ResponseResult.success("新增成功"); } else { return ResponseResult.error("新增失败"); } } /** * 根据订单ID查询关键词 */ @GetMapping("/getKeywordsByOrderId") @ApiOperation(value = "根据订单ID查询关键词") public ResponseResult> getKeywordsByOrderId(@RequestParam("orderId") String orderId) { List keywords = keywordService.getKeywordsByOrderId(orderId); return ResponseResult.success(keywords); } /** * 修改关键词 */ @PostMapping("/updateKeyword") @ApiOperation(value = "修改关键词") public ResponseResult updateKeyword(@RequestBody Keyword keyword) { if(!"notSubmitted".equals(keyword.getStatus())){ return ResponseResult.error("关键词已开始采集或采集完成不允许修改!"); } keywordService.updateById(keyword); return ResponseResult.success("修改成功"); } /** * 删除关键词 */ @DeleteMapping("/deleteKeyword") @ApiOperation(value = "删除关键词") public ResponseResult deleteKeyword(@RequestParam("keywordId") Integer keywordId) { Keyword keyword = keywordService.getById(keywordId); if(!"notSubmitted".equals(keyword.getStatus())){ return ResponseResult.error("关键词已开始采集或采集完成不允许删除!"); } keywordService.removeById(keywordId); return ResponseResult.success("删除成功"); } // 下载模板 @PostMapping("/downloadTemplate") @ApiOperation("下载关键词导入模板") public ResponseEntity downloadTemplate() throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); EasyExcel.write(out, KeywordExcel.class).sheet("关键词模板").doWrite(new ArrayList<>()); return ResponseEntity.ok() .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=keyword_template.xlsx") .contentType(MediaType.APPLICATION_OCTET_STREAM) .body(out.toByteArray()); } // 导入文件 @PostMapping("/import") @ApiOperation("导入关键词数据") public ResponseResult importPlatforms(@RequestParam("file") MultipartFile file) { try { if (file.isEmpty()) { return ResponseResult.error("上传文件不能为空"); } // 创建数据监听器 KeywordExcelListener listener = new KeywordExcelListener(); EasyExcel.read(file.getInputStream(), KeywordExcel.class, listener) .sheet() .doRead(); // 获取并合并关键词 String mergedKeywords = String.join("\n", listener.getMergedKeywords()); return ResponseResult.success(mergedKeywords); } catch (IOException e) { return ResponseResult.error("文件读取失败:" + e.getMessage()); } catch (Exception e) { return ResponseResult.error("导入失败:" + e.getMessage()); } } //根据关键词id查询任务id }