pom.xml
@@ -55,23 +55,7 @@ <artifactId>easyexcel</artifactId> <version>3.3.2</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-api</artifactId> <version>0.12.5</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-impl</artifactId> <version>0.12.5</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-jackson</artifactId> <!-- 或 jjwt-gson --> <version>0.12.5</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> src/main/java/com/linghu/config/FinalStatus.java
@@ -4,19 +4,34 @@ @Getter public enum FinalStatus { //成功 SUCCESS("success"), //没有结果 NO_RESULTS("no_results"), //繁忙 BUSYNESS("busyness"), //已取消 CANCELLED("cancelled"), //已完成 COMPLETED("completed"), CANCELED("canceled"), //报错 ERROR("ERROR"), //已提交 SUBMITTED("submitted"), //待处理 PENDING("pending"), //网络错误 FALSE("false"), //不存在 NONENTITY("nonentity"), //未提交 NOTSUBMITTED("notSubmitted"), //执行中 RUNNING("running"), //失败 FAILED("failed"); private final String value; FinalStatus(String value) { src/main/java/com/linghu/config/GlobalExceptionHandler.java
New file @@ -0,0 +1,45 @@ package com.linghu.config; import com.linghu.model.common.ResponseResult; import org.springframework.validation.BindingResult; import org.springframework.validation.FieldError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import javax.validation.ConstraintViolation; import javax.validation.ConstraintViolationException; import java.util.HashMap; import java.util.Map; import java.util.Set; // 全局异常处理器,作用于所有 @RestController 注解的控制器 @RestControllerAdvice public class GlobalExceptionHandler { // 处理 @RequestBody 参数校验失败的异常(如 DTO 中的校验) @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseResult handleMethodArgumentNotValid(MethodArgumentNotValidException e) { Map<String, String> errors = new HashMap<>(); // 获取所有校验失败的字段和消息 BindingResult bindingResult = e.getBindingResult(); for (FieldError fieldError : e.getBindingResult().getFieldErrors()) { // 字段名 -> 错误消息(如 "keyword: 关键词不能为空") errors.put(fieldError.getField(), fieldError.getDefaultMessage()); } // 返回自定义的错误响应(根据你的 ResponseResult 结构调整) return ResponseResult.error("参数校验失败"+ errors); } // 处理 @RequestParam/@PathVariable 参数校验失败的异常 @ExceptionHandler(ConstraintViolationException.class) public ResponseResult<Map<String, String>> handleConstraintViolation(ConstraintViolationException e) { Map<String, String> errors = new HashMap<>(); for (ConstraintViolation<?> violation : e.getConstraintViolations()) { String field = violation.getPropertyPath().toString(); String simplifiedField = field.substring(field.lastIndexOf('.') + 1); errors.put(simplifiedField, violation.getMessage()); } return ResponseResult.error("参数校验失败"+ errors); } } src/main/java/com/linghu/controller/AuthController.java
@@ -32,7 +32,7 @@ } @GetMapping("/getToken") @ApiOperation(value = "获取token") public ResponseEntity<?> getToken( String user) { public ResponseEntity<?> getToken(@RequestParam(value = "user" ) String user) { // 创建JwtUtils对象,并生成JWT令牌 OpenCryptUtil openCryptUtil = new OpenCryptUtil(); String decrypt = openCryptUtil.encrypt(user); src/main/java/com/linghu/controller/CollectController.java
@@ -42,13 +42,13 @@ @ApiOperation(value = "查询任务状态") @GetMapping("/status") public Mono<TaskStatusResponse> getTaskStatus(String taskId) { public Mono<TaskStatusResponse> getTaskStatus(@RequestParam(value = "taskId" )String taskId) { return collectionService.getError(taskId); } @PostMapping("/cancel/{keywordId}") @ApiOperation(value = "取消任务") public Mono<ResponseResult<TaskCancelResponse>> cancelTask(@PathVariable Integer keywordId) { public Mono<ResponseResult<TaskCancelResponse>> cancelTask(@PathVariable Integer keywordId) { return collectionService.getResponseResult(keywordId); } src/main/java/com/linghu/controller/KeywordController.java
@@ -1,6 +1,7 @@ package com.linghu.controller; import com.alibaba.excel.EasyExcel; import com.linghu.config.FinalStatus; import com.linghu.listener.KeywordExcelListener; import com.linghu.model.common.ResponseResult; import com.linghu.model.dto.ExportFeedDTO; @@ -10,6 +11,7 @@ import com.linghu.model.dto.ExportStaticsDTO; import com.linghu.model.entity.*; import com.linghu.model.excel.*; import com.linghu.model.validator.UpdateGroup; import com.linghu.model.vo.*; import com.linghu.model.vo.KeywordStaticsListVO; import com.linghu.model.vo.PlatformProportionVO; @@ -24,6 +26,7 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -66,7 +69,7 @@ @PostMapping(value = "/exportStatics") @ApiOperation(value = "EChart图导出") public ResponseEntity<byte[]> exportStatics(@RequestBody ExportStaticsDTO exportStaticsDTO) { public ResponseEntity<byte[]> exportStatics(@Valid @RequestBody ExportStaticsDTO exportStaticsDTO) { return keywordService.exportEChart(exportStaticsDTO); } @@ -92,7 +95,7 @@ */ @PostMapping(value = "/exportGetResultByTypeId") @ApiOperation(value = "导出:根据类别查看") public ResponseEntity<byte[]> exportGetResultByTypeId(@RequestBody ExportGetResultDTO dto) { public ResponseEntity<byte[]> exportGetResultByTypeId(@Valid @RequestBody ExportGetResultDTO dto) { return keywordService.exportResult(dto); } @@ -190,8 +193,8 @@ */ @PostMapping("/updateKeyword") @ApiOperation(value = "修改关键词") public ResponseResult<String> updateKeyword(@RequestBody Keyword keyword) { if("submitted".equals(keyword.getStatus())){ public ResponseResult<String> updateKeyword(@Validated(UpdateGroup.class) @RequestBody Keyword keyword) { if(FinalStatus.SUBMITTED.getValue().equals(keyword.getStatus())){ return ResponseResult.error("关键词已开始采集不允许修改!"); } keywordService.updateById(keyword); @@ -205,7 +208,7 @@ @ApiOperation(value = "删除关键词") public ResponseResult<String> deleteKeyword(@RequestParam("keywordId") Integer keywordId) { Keyword keyword = keywordService.getById(keywordId); if("submitted".equals(keyword.getStatus())){ if(FinalStatus.SUBMITTED.getValue().equals(keyword.getStatus())){ return ResponseResult.error("关键词已开始采集或不允许删除!"); } keywordService.removeById(keywordId); src/main/java/com/linghu/controller/PlatformController.java
@@ -18,6 +18,8 @@ import com.linghu.model.excel.PlatformExcel; import com.linghu.model.excel.UserExcel; import com.linghu.model.page.CustomPage; import com.linghu.model.validator.CreateGroup; import com.linghu.model.validator.UpdateGroup; import com.linghu.service.PlatformService; import com.linghu.service.TypeService; @@ -35,6 +37,7 @@ import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.util.StringUtils; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -60,14 +63,14 @@ @PostMapping @ApiOperation(value = "添加平台") public ResponseResult<Platform> add(@RequestBody Platform platform) { public ResponseResult<Platform> add( @Validated(CreateGroup.class) @RequestBody Platform platform) { return platformService.addPlatform(platform); } @DeleteMapping("/{platformId}") @ApiOperation(value = "删除平台") public ResponseResult<Void> delete(@PathVariable Integer platformId) { public ResponseResult<Void> delete( @PathVariable Integer platformId) { return platformService.deleteByPlatFormId(platformId); } @@ -75,7 +78,7 @@ @PutMapping @ApiOperation(value = "更新平台") public ResponseResult<Void> update(@RequestBody Platform platform) { public ResponseResult<Void> update(@Validated(UpdateGroup.class) @RequestBody Platform platform) { return platformService.updatePlatform(platform); } src/main/java/com/linghu/controller/QuestionController.java
@@ -14,6 +14,8 @@ import com.linghu.model.entity.Reference; import com.linghu.model.excel.KeywordExcel; import com.linghu.model.excel.QuestionExcel; import com.linghu.model.validator.CreateGroup; import com.linghu.model.validator.UpdateGroup; import com.linghu.service.KeywordService; import com.linghu.service.QuestionService; import io.swagger.annotations.Api; @@ -23,10 +25,12 @@ import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.validation.Valid; import javax.validation.constraints.NotEmpty; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.*; @@ -44,7 +48,7 @@ @PostMapping @ApiOperation(value = "添加提问词") public ResponseResult<List<Question>> add(@Valid @RequestBody KeywordDto keywordDto) { public ResponseResult<List<Question>> add(@Validated(CreateGroup.class) @RequestBody KeywordDto keywordDto) { return questionService.addQuestion(keywordDto); } @@ -52,27 +56,27 @@ @PutMapping @ApiOperation(value = "修改提问词") public ResponseResult<List<Question>> update(@RequestBody KeywordDto keywordDto) { public ResponseResult<List<Question>> update(@Validated(UpdateGroup.class) @RequestBody KeywordDto keywordDto) { return questionService.updateQuestion(keywordDto); } @PutMapping("/update") @ApiOperation(value = "修改单个提问词") public ResponseResult<Void> update(@RequestBody Question questions) { public ResponseResult<Void> update(@Validated(UpdateGroup.class) @RequestBody Question questions) { return questionService.updateKeyWord(questions); } @DeleteMapping("/batch") @ApiOperation(value = "批量删除提问词") public ResponseResult<Void> batchDelete(@RequestBody List<Integer> questionIds) { public ResponseResult<Void> batchDelete( @RequestBody List<Integer> questionIds) { return questionService.batchDeleteQuestion(questionIds); } @GetMapping("/list") @ApiOperation("根据关键词查询提问词列表") public ResponseResult<List<Question>> list(Integer keyword_id) { public ResponseResult<List<Question>> list(@RequestParam("keyword_id") Integer keyword_id) { return questionService.getQuestionListByKeywordId(keyword_id); } @@ -81,7 +85,7 @@ @GetMapping("/notNullList") @ApiOperation("根据关键词查询提问词列表") public ResponseResult<List<Question>> notNullList(Integer keyword_id) { public ResponseResult<List<Question>> notNullList(@RequestParam("keyword_id") Integer keyword_id) { return questionService.notNullQuestionList(keyword_id); } src/main/java/com/linghu/controller/SectionalizationController.java
@@ -3,14 +3,17 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.linghu.model.common.ResponseResult; import com.linghu.model.entity.Sectionalization; import com.linghu.model.validator.UpdateGroup; import com.linghu.model.vo.SectionalizationUserVO; import com.linghu.service.SectionalizationService; import com.linghu.service.UserService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.util.List; @RestController @@ -27,7 +30,7 @@ @PostMapping @ApiOperation(value = "添加") public ResponseResult add(@RequestBody Sectionalization sectionalization) { public ResponseResult add(@Valid @RequestBody Sectionalization sectionalization) { return sectionalizationService.addSectionalization(sectionalization); } @@ -36,7 +39,7 @@ */ @PutMapping @ApiOperation(value = "修改") public ResponseResult edit(@RequestBody Sectionalization sectionalization) { public ResponseResult edit(@Validated(UpdateGroup.class) @RequestBody Sectionalization sectionalization) { return sectionalizationService.edit(sectionalization); } src/main/java/com/linghu/controller/TypeController.java
@@ -8,13 +8,17 @@ import com.linghu.model.entity.Keyword; import com.linghu.model.entity.Reference; import com.linghu.model.entity.Type; import com.linghu.model.validator.CreateGroup; import com.linghu.model.validator.UpdateGroup; import com.linghu.service.KeywordService; import com.linghu.service.TypeService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -31,7 +35,7 @@ @PostMapping @ApiOperation(value = "添加类型") public ResponseResult<Type> add(@RequestBody Type type) { public ResponseResult<Type> add(@Validated( CreateGroup.class) @RequestBody Type type) { return typeService.addType(type); } @@ -39,7 +43,7 @@ @PostMapping("/batch") @ApiOperation(value = "批量添加类型") public ResponseResult<Void> batchAdd(@RequestBody List<Type> types) { public ResponseResult<Void> batchAdd(@Validated(CreateGroup.class) @Valid @RequestBody List<Type> types) { boolean success = typeService.saveBatch(types); if (success) { return ResponseResult.success(); @@ -56,14 +60,14 @@ @PutMapping @ApiOperation(value = "更新类型") public ResponseResult<Void> update(@RequestBody Type type) { public ResponseResult<Void> update(@Validated(UpdateGroup.class) @RequestBody Type type) { typeService.updateById(type); return ResponseResult.success(); } @PutMapping("/batch") @ApiOperation(value = "批量更新类型") public ResponseResult<Void> batchUpdate(@RequestBody List<Type> types) { public ResponseResult<Void> batchUpdate(@Validated(UpdateGroup.class) @RequestBody List<Type> types) { boolean success = typeService.updateBatchById(types); if (success) { return ResponseResult.success(); src/main/java/com/linghu/controller/UserController.java
@@ -35,6 +35,7 @@ import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.validation.Valid; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.time.LocalDateTime; @@ -55,7 +56,7 @@ @PostMapping @ApiOperation(value = "添加") public ResponseResult add(@RequestBody User user) { public ResponseResult add(@Valid @RequestBody User user) { return userService.addUser(user); } @@ -65,7 +66,7 @@ */ @PutMapping @ApiOperation(value = "修改") public ResponseResult edit(@RequestBody User user) { public ResponseResult edit(@Valid @RequestBody User user) { return userService.editUser(user); } src/main/java/com/linghu/model/dto/KeywordDto.java
@@ -1,5 +1,6 @@ package com.linghu.model.dto; import com.linghu.model.validator.CreateGroup; import lombok.Data; import lombok.EqualsAndHashCode; @@ -7,7 +8,9 @@ import com.linghu.model.entity.Keyword; import com.linghu.model.entity.Question; import org.springframework.validation.annotation.Validated; import javax.validation.Valid; import javax.validation.constraints.NotEmpty; @EqualsAndHashCode(callSuper = true) @@ -16,9 +19,10 @@ /** * 提问词列表,用换行符分隔 */ @NotEmpty(message = "提问词不能为空") @NotEmpty(message = "提问词不能为空",groups = CreateGroup.class) private String questions; @Valid private List<Question> questionList; private List<String> taskIdList; } src/main/java/com/linghu/model/entity/Keyword.java
@@ -5,7 +5,11 @@ import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import java.io.Serializable; import com.linghu.model.validator.UpdateGroup; import lombok.Data; import javax.validation.constraints.NotNull; /** * @@ -18,6 +22,7 @@ * 关键词 */ @TableId(type = IdType.AUTO) @NotNull(message = "id 不能为空", groups = UpdateGroup.class) private Integer keyword_id; /** src/main/java/com/linghu/model/entity/Platform.java
@@ -8,9 +8,13 @@ import java.time.LocalDateTime; import java.util.Date; import com.linghu.model.validator.CreateGroup; import com.linghu.model.validator.UpdateGroup; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import com.fasterxml.jackson.annotation.JsonFormat; import javax.validation.constraints.NotNull; /** * @@ -24,24 +28,28 @@ */ @TableId(type = IdType.AUTO) @ApiModelProperty("平台id") @NotNull(message = "id 不能为空", groups = UpdateGroup.class) private Integer platform_id; /** * 类型id */ @ApiModelProperty("类型id") @NotNull(message = "类型id 不能为空", groups = CreateGroup.class) private Integer type_id; /** * 平台名称 */ @ApiModelProperty("平台名称") @NotNull(message = "平台名称不能为空", groups = CreateGroup.class) private String platform_name; /** * 平台域名 */ @ApiModelProperty("平台域名") @NotNull(message = "平台域名不能为空", groups = CreateGroup.class) private String domain; /** @@ -67,7 +75,7 @@ /** * */ @ApiModelProperty("创建者") @ApiModelProperty("修改者") private String update_by; @TableField(exist = false) src/main/java/com/linghu/model/entity/Question.java
@@ -6,9 +6,13 @@ import com.baomidou.mybatisplus.annotation.TableName; import java.io.Serializable; import java.time.LocalDateTime; import java.util.Date; import com.linghu.model.validator.CreateGroup; import com.linghu.model.validator.UpdateGroup; import lombok.Data; import com.fasterxml.jackson.annotation.JsonFormat; import javax.validation.constraints.NotNull; /** * @@ -21,6 +25,7 @@ * 提问词id */ @TableId(type = IdType.AUTO) @NotNull(message = "id不能为空",groups = UpdateGroup.class) private Integer question_id; /** src/main/java/com/linghu/model/entity/Sectionalization.java
@@ -4,10 +4,12 @@ import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.linghu.model.validator.UpdateGroup; import lombok.Data; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; @Data @TableName(value = "sectionalization") @@ -16,9 +18,10 @@ @TableField(exist = false) private static final long serialVersionUID = 1L; @TableId(type = IdType.AUTO) @NotNull(message = "分组id不能为空", groups = UpdateGroup.class) private Integer sectionalization_id; @NotEmpty(message = "用户名不能为空") @NotEmpty(message = "分组名不能为空") private String sectionalization_name; src/main/java/com/linghu/model/entity/Type.java
@@ -5,7 +5,12 @@ import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import java.io.Serializable; import com.linghu.model.validator.CreateGroup; import com.linghu.model.validator.UpdateGroup; import lombok.Data; import javax.validation.constraints.NotNull; /** * @@ -18,11 +23,13 @@ * 类型 */ @TableId(type = IdType.AUTO) @NotNull(message = "类型ID不能为空", groups = {UpdateGroup.class}) private Integer type_id; /** * 名字 */ @NotNull(message = "类型不能为空", groups = {CreateGroup.class, UpdateGroup.class}) private String type_name; src/main/java/com/linghu/model/validator/CreateGroup.java
New file @@ -0,0 +1,3 @@ package com.linghu.model.validator; public interface CreateGroup {} src/main/java/com/linghu/model/validator/QueryGroup.java
New file @@ -0,0 +1,3 @@ package com.linghu.model.validator; public interface QueryGroup {} src/main/java/com/linghu/model/validator/UpdateGroup.java
New file @@ -0,0 +1,3 @@ package com.linghu.model.validator; public interface UpdateGroup {} src/main/java/com/linghu/service/impl/CollectionServiceImpl.java
@@ -30,7 +30,6 @@ import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentMap; import java.util.stream.Collectors; @Slf4j @Service public class CollectionServiceImpl implements CollectionService { @@ -181,7 +180,7 @@ return Flux.fromIterable(tasksToCancelRemotely) .flatMap(task -> { // 创建状态更新和远程取消的组合操作 Mono<Void> updateStatus = updateTaskStatus(task.getTask_id(), "cancelled"); Mono<Void> updateStatus = updateTaskStatus(task.getTask_id(), FinalStatus.CANCELLED.getValue()); Mono<ResponseResult<?>> cancelOp = cancelRemoteTask(task.getTask_id()) .onErrorResume(e -> { log.error("取消任务 {} 失败: {}", task.getTask_id(), e.getMessage()); @@ -347,7 +346,7 @@ // 如果任务状态是"submitted"或"running",继续轮询 if (!FinalStatus.COMPLETED.getValue().equalsIgnoreCase(statusResponse.getStatus()) && !FinalStatus.FAILED.getValue().equalsIgnoreCase(statusResponse.getStatus()) && !FinalStatus.CANCELED.getValue().equalsIgnoreCase(statusResponse.getStatus()) && !FinalStatus.CANCELLED.getValue().equalsIgnoreCase(statusResponse.getStatus()) && !(FinalStatus.ERROR.getValue().equalsIgnoreCase(statusResponse.getStatus()) && statusResponse.getMessage().contains("Task not found")) ) { return Mono.delay(Duration.ofSeconds(5)) // 延迟 5 秒后再次查询 @@ -453,12 +452,12 @@ if (keywordTasks.size() > 0) { KeywordTask keywordTask = keywordTasks.get(0); keywordTask.setTask_id(taskResponse.getTask_id()); keywordTask.setStatus("pending"); keywordTask.setStatus(FinalStatus.PENDING.getValue()); keywordTaskService.updateById(keywordTask); } //将提问词列表的状态转为pending for (String questionName : batchRequest.getQuestions()) { questionService.update(new LambdaUpdateWrapper<Question>().eq(Question::getKeyword_id, keyword.getKeyword_id()).eq(Question::getQuestion,questionName).set(Question::getStatus, "pending")); questionService.update(new LambdaUpdateWrapper<Question>().eq(Question::getKeyword_id, keyword.getKeyword_id()).eq(Question::getQuestion,questionName).set(Question::getStatus, FinalStatus.PENDING.getValue())); } //所有关键词都在采集中或者已完成或者错误设置订单进入采集状态 @@ -497,7 +496,7 @@ new LambdaQueryWrapper<KeywordTask>() .eq(KeywordTask::getKeyword_id, keywordId) .isNotNull(KeywordTask::getTask_id) .eq(KeywordTask::getStatus, "pending") .eq(KeywordTask::getStatus, FinalStatus.PENDING.getValue()) ); } @@ -524,7 +523,7 @@ List<KeywordTask> keywordTasks = keywordTaskService.list(keywordTaskWrapper); // 更新关键词状态 keyword.setStatus("completed"); keyword.setStatus(FinalStatus.COMPLETED.getValue()); keywordService.updateById(keyword); //更新提问词状态为取消 @@ -588,7 +587,7 @@ private Mono<ResponseResult<?>> cancelRemoteTask(String taskId) { // 使用Collections.singletonMap或手动创建Map Map<String, Object> requestBody = new HashMap<>(); requestBody.put("status", "pending"); requestBody.put("status", FinalStatus.PENDING.getValue()); return webClient.post() .uri(baseUrl + "/api/v1/tasks/" + taskId + "/cancel") @@ -762,7 +761,6 @@ .allMatch(task -> FinalStatus.COMPLETED.getValue().equals(task.getStatus()) || FinalStatus.FALSE.getValue().equals(task.getStatus()) || FinalStatus.CANCELLED.getValue().equals(task.getStatus()) || FinalStatus.CANCELED.getValue().equals(task.getStatus()) || FinalStatus.NONENTITY.getValue().equals(task.getStatus())); if (allCompletedOrFailed) { @@ -908,7 +906,9 @@ List<Reference> validRefGroup = refGroup.stream() .filter(Objects::nonNull) .collect(Collectors.toList()); if (validRefGroup.isEmpty()) return; if (validRefGroup.isEmpty()){ return; } Optional<Reference> existingRef = validRefGroup.stream() .filter(ref -> ref.getReference_id() != null) @@ -983,7 +983,7 @@ // 批量更新问题状态 List<Question> questionsToUpdate = new ArrayList<>(); questions.forEach(question -> { List<QuestionResultList> results = questionResultsMap.getOrDefault(question.getQuestion(), io.jsonwebtoken.lang.Collections.emptyList()); List<QuestionResultList> results = questionResultsMap.getOrDefault(question.getQuestion(), Collections.emptyList()); FinalStatus finalStatus = determineFinalStatus(results); // 使用枚举进行switch判断 src/main/java/com/linghu/service/impl/KeywordServiceImpl.java
@@ -8,6 +8,7 @@ import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.linghu.config.FinalStatus; import com.linghu.mapper.ReferenceMapper; import com.linghu.model.common.ResponseResult; import com.linghu.model.dto.ExportFeedDTO; @@ -75,7 +76,7 @@ if (keyword == null) { return ResponseResult.error("关键词不存在"); } if (!"completed".equals(keyword.getStatus())) { if (!FinalStatus.COMPLETED.getValue().equals(keyword.getStatus())) { return ResponseResult.success(); } List<KeywordStaticsVO> statics = this.getBaseMapper().statics(keywordId, questionId, keyword.getNum()); @@ -97,7 +98,7 @@ if (keyword == null) { return ResponseResult.error("关键词不存在"); } if (!"completed".equals(keyword.getStatus())) { if (!FinalStatus.COMPLETED.getValue().equals(keyword.getStatus())) { return ResponseResult.error("关键词采集未完成"); } List<PlatformProportionVO> result = this.getBaseMapper().getResultByTypeId(keywordId, questionId, @@ -113,7 +114,7 @@ if (keyword == null) { return ResponseResult.error("关键词不存在"); } if (!"completed".equals(keyword.getStatus())) { if (!FinalStatus.COMPLETED.getValue().equals(keyword.getStatus())) { return ResponseResult.error("关键词采集未完成"); } src/main/java/com/linghu/service/impl/OrderServiceImpl.java
@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.linghu.config.FinalStatus; import com.linghu.model.common.ResponseResult; import com.linghu.model.dto.KeywordDto; import com.linghu.model.dto.OrderDto; @@ -63,7 +64,7 @@ Keyword keyword = new Keyword(); keyword.setOrder_id(order_id); keyword.setKeyword_name(keywordName.trim()); keyword.setStatus("notSubmitted"); keyword.setStatus(FinalStatus.NOTSUBMITTED.getValue()); // keyword.setNum(1); // 默认采集轮数为1 keywordService.save(keyword); } @@ -87,10 +88,10 @@ return false; } // 删除旧关键词(当状态为1时允许修改关键词) // 删除旧关键词(当状态为未提交时允许修改关键词) keywordService.lambdaUpdate() .eq(Keyword::getOrder_id, orderDto.getOrder_id()) .eq(Keyword::getStatus, "notSubmitted") .eq(Keyword::getStatus, FinalStatus.NOTSUBMITTED.getValue()) .remove(); // 保存新关键词 @@ -101,7 +102,7 @@ Keyword keyword = new Keyword(); keyword.setOrder_id(orderDto.getOrder_id()); keyword.setKeyword_name(keywordName.trim()); keyword.setStatus("notSubmitted"); keyword.setStatus(FinalStatus.NOTSUBMITTED.getValue()); keywordService.save(keyword); } } src/main/java/com/linghu/service/impl/QuestionServiceImpl.java
@@ -3,6 +3,7 @@ import com.alibaba.excel.EasyExcel; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.linghu.config.FinalStatus; import com.linghu.listener.QuestionExcelListener; import com.linghu.mapper.KeywordMapper; import com.linghu.mapper.ReferenceMapper; @@ -20,6 +21,7 @@ import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import org.springframework.web.multipart.MultipartFile; import java.io.ByteArrayOutputStream; @@ -52,7 +54,7 @@ Question question = new Question(); question.setKeyword_id(keywordDto.getKeyword_id()); question.setQuestion(q.trim()); question.setStatus("pending"); question.setStatus(FinalStatus.PENDING.getValue()); return question; }).collect(Collectors.toList()); @@ -69,7 +71,7 @@ LambdaQueryWrapper<Question> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(Question::getQuestion_id, questions.getQuestion_id()); Question keyword = this.getOne(queryWrapper); if ("submitted".equals(keyword.getStatus()) ) { if (FinalStatus.SUBMITTED.getValue().equals(keyword.getStatus()) ) { return ResponseResult.error("该关键词在采集中"); } @@ -82,6 +84,10 @@ @Override public ResponseResult<Void> batchDeleteQuestion(List<Integer> questionIds) { // 新增判断:如果集合为空,直接返回错误 if (CollectionUtils.isEmpty(questionIds)) { return ResponseResult.error("删除失败,至少选择一个提问词"); } // 2. 批量查询所有提问词 List<Question> questions = this.listByIds(questionIds); // 3. 校验所有提问词关联的关键词是否处于采集中 @@ -92,7 +98,7 @@ return ResponseResult.error("提问词关联的关键词不存在,ID:" + question.getKeyword_id()); } // 核心校验:若有任何关键词在采集中,禁止删除 if ("submitted".equals(keyword.getStatus())) { if (FinalStatus.PENDING.getValue().equals(keyword.getStatus())) { return ResponseResult.error("该关键词在采集中,无法删除"); } } @@ -146,7 +152,7 @@ @Override public ResponseResult<List<Question>> updateQuestion(KeywordDto keywordDto) { if ("submitted".equals(keywordDto.getStatus()) ) { if (FinalStatus.SUBMITTED.getValue().equals(keywordDto.getStatus()) ) { return ResponseResult.error("该关键词在采集中"); } this.updateBatchById(keywordDto.getQuestionList()); src/main/java/com/linghu/service/impl/TypeServiceImpl.java
@@ -50,6 +50,9 @@ @Override public ResponseResult<Void> batchDeleteTypes(List<Integer> typeIds) { if (typeIds.isEmpty()) { return ResponseResult.error("请选择要删除的类型"); } List<Type> types = typeIds.stream().map(id -> { Type type = new Type(); type.setType_id(id); src/main/java/com/linghu/timeTask/ScheduledTasks.java
@@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.linghu.config.FinalStatus; import com.linghu.controller.CollectController; import com.linghu.model.dto.TaskResultResponse; import com.linghu.model.dto.TaskStatusResponse; @@ -158,7 +159,7 @@ try { // 查询所有状态为pending的任务 LambdaQueryWrapper<KeywordTask> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(KeywordTask::getStatus, "pending"); queryWrapper.eq(KeywordTask::getStatus, FinalStatus.PENDING.getValue()); List<KeywordTask> tasks = keywordTaskService.list(queryWrapper); log.info("查询到 {} 个待处理任务", tasks.size()); @@ -173,7 +174,7 @@ boolean updatedCount = keywordTaskService.update( new LambdaUpdateWrapper<KeywordTask>() .in(KeywordTask::getId, taskIds) // 限定为查询到的任务 .eq(KeywordTask::getStatus, "pending") // 确保状态未被其他进程修改 .eq(KeywordTask::getStatus, FinalStatus.PENDING.getValue()) // 确保状态未被其他进程修改 .set(KeywordTask::getStatus, "processing") ); log.info("成功标记 {} 个任务为processing(查询到{}个)", updatedCount, tasks.size()); @@ -201,29 +202,29 @@ private Mono<KeywordTask> processTaskStatus(KeywordTask task) { return collectController.getTaskStatus(task.getTask_id()) .flatMap(statusResponse -> { if ("completed".equalsIgnoreCase(statusResponse.getStatus())) { if (FinalStatus.COMPLETED.getValue().equalsIgnoreCase(statusResponse.getStatus())) { log.info("任务 {} 已完成,获取结果", task.getTask_id()); return collectController.getTaskResult(task.getTask_id()) .doOnSuccess(result -> log.info("获取任务 {} 结果成功", task.getTask_id())) .thenReturn(task) .map(t -> { t.setStatus("completed"); t.setStatus(FinalStatus.COMPLETED.getValue()); return t; }); } else if (!"submitted".equalsIgnoreCase(statusResponse.getStatus()) && !"running".equalsIgnoreCase(statusResponse.getStatus()) && !"Error".equalsIgnoreCase(statusResponse.getStatus())) { task.setStatus("false"); } else if (!FinalStatus.SUBMITTED.getValue().equalsIgnoreCase(statusResponse.getStatus()) && !FinalStatus.RUNNING.getValue().equalsIgnoreCase(statusResponse.getStatus()) && !FinalStatus.ERROR.getValue().equalsIgnoreCase(statusResponse.getStatus())) { task.setStatus(FinalStatus.FALSE.getValue()); // 新增:处理status为false时的关键词状态更新 return updateKeywordStatusWhenTaskFinished(task) .then(Mono.just(task)); }else if ( "running".equalsIgnoreCase(statusResponse.getStatus())) { }else if ( FinalStatus.RUNNING.getValue().equalsIgnoreCase(statusResponse.getStatus())) { // 改回 pending,进行下一轮查询 task.setStatus("pending"); task.setStatus(FinalStatus.PENDING.getValue()); //更新每个提问词的状态 return updateQuestionStatus(task, statusResponse); // 抽取为独立方法 }else if("ERROR".equalsIgnoreCase(statusResponse.getStatus())&&statusResponse.getMessage().contains("Task not found")){ task.setStatus("nonentity"); }else if(FinalStatus.ERROR.getValue().equalsIgnoreCase(statusResponse.getStatus())&&statusResponse.getMessage().contains("Task not found")){ task.setStatus(FinalStatus.NONENTITY.getValue()); // 更新关键词状态 return updateKeywordStatusWhenTaskFinished(task) .then(Mono.just(task)); @@ -243,7 +244,7 @@ }) .onErrorResume(e -> { log.error("处理任务 {} 状态时发生错误: {}", task.getTask_id(), e.getMessage()); task.setStatus("error"); task.setStatus(FinalStatus.ERROR.getValue()); // 将updateById的结果包装成Mono return Mono.fromSupplier(() -> keywordTaskService.updateById(task)) @@ -287,16 +288,15 @@ }).flatMap(keywordTasks -> { // 检查所有关联任务是否都已完成(包括各种结束状态) boolean allCompleted = keywordTasks.stream().allMatch(t -> "completed".equals(t.getStatus()) || "false".equals(t.getStatus()) || "cancelled".equals(t.getStatus()) || "canceled".equals(t.getStatus()) || "nonentity".equals(t.getStatus()) FinalStatus.COMPLETED.getValue().equals(t.getStatus()) || FinalStatus.FALSE.getValue().equals(t.getStatus()) || FinalStatus.CANCELLED.getValue().equals(t.getStatus()) || FinalStatus.NONENTITY.getValue().equals(t.getStatus()) ); if (allCompleted) { Keyword keyword = keywordService.getById(task.getKeyword_id()); keyword.setStatus("completed"); keyword.setStatus(FinalStatus.COMPLETED.getValue()); // return Mono.fromSupplier(() -> keywordService.updateById(keyword)) .then(); // 转换为Mono<Void> src/main/java/com/linghu/utils/JwtUtils.java
File was deleted