src/main/java/com/linghu/config/MyBatisPlusConfig.java
@@ -1,18 +1,24 @@ package com.linghu.config; import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import org.mybatis.spring.annotation.MapperScan; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MyBatisPlusConfig { @MapperScan("com.linghu.mapper") public class MybatisPlusConfig { /** * 添加分页插件 */ @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); // 添加分页插件,这里可指定数据库类型(如 MySQL),也可默认 interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 如果配置多个插件, 切记分页最后添加 // 如果有多数据源可以不配具体类型, 否则都建议配上具体的 DbType return interceptor; } } src/main/java/com/linghu/controller/AuthController.java
@@ -63,15 +63,15 @@ return ResponseEntity.ok(decrypt); } // @GetMapping("/getToken") // @ApiOperation(value = "获取token") // public ResponseEntity<?> getToken(@RequestBody User user) { // // 创建用户对 // // // 创建JwtUtils对象,并生成JWT令牌 // OpenCryptUtil openCryptUtil = new OpenCryptUtil(); // String decrypt = openCryptUtil.encrypt(user); // // 返回JWT令牌 // return ResponseEntity.ok(decrypt); // } @GetMapping("/getToken") @ApiOperation(value = "获取token") public ResponseEntity<?> getToken( String user) { // 创建用户对 // 创建JwtUtils对象,并生成JWT令牌 OpenCryptUtil openCryptUtil = new OpenCryptUtil(); String decrypt = openCryptUtil.encrypt(user); // 返回JWT令牌 return ResponseEntity.ok(decrypt); } } src/main/java/com/linghu/controller/CollectController.java
@@ -47,6 +47,7 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; @RestController @RequestMapping("/collect") @@ -206,10 +207,11 @@ int maxConcurrentUsers = searchTaskRequest.getConfig() != null ? searchTaskRequest.getConfig().getMax_concurrent_users() : 3; List<List<UserDto>> userBatches = splitUsersIntoBatches(searchTaskRequest.getUsers(), maxConcurrentUsers); // 获取 keywordId Integer keywordId = searchTaskRequest.getKeyword_id(); //分割 List<List<UserDto>> userBatches = splitUsersIntoBatches(searchTaskRequest.getUsers(), maxConcurrentUsers,keywordId); return Flux.fromIterable(userBatches) .flatMap(batch -> { @@ -255,7 +257,15 @@ .then(); } private List<List<UserDto>> splitUsersIntoBatches(List<UserDto> users, int batchSize) { private List<List<UserDto>> splitUsersIntoBatches(List<UserDto> users, int batchSize,Integer keywordId) { Keyword keyword = keywordService.getById(keywordId); if (null==keyword.getNum()){ keyword.setNum(0); } keyword.setNum(keyword.getNum()+1); keywordService.updateById(keyword); List<List<UserDto>> batches = new ArrayList<>(); for (int i = 0; i < users.size(); i += batchSize) { batches.add(users.subList(i, Math.min(i + batchSize, users.size()))); @@ -485,7 +495,7 @@ // 3. 收集所有需要更新的问题和引用 List<Question> questionsToUpdate = new ArrayList<>(); List<Reference> allReferences = new ArrayList<>(); List<Reference> resultList = new ArrayList<>(); // 遍历结果 for (UserResult userResult : result.getResults()) { for (QuestionResult questionResult : userResult.getQuestions_results()) { @@ -511,17 +521,6 @@ questionsToUpdate.add(question); //如果查询结果不为空查询num Integer maxNumByKeywordId = referenceService.getMaxNumByKeywordId(keyword.getKeyword_id()); if (maxNumByKeywordId != null){ maxNumByKeywordId++; }else { maxNumByKeywordId = 1; } // 收集引用数据,处理空集合情况 Integer finalMaxNumByKeywordId = maxNumByKeywordId; List<Reference> references = Optional.ofNullable(questionResult.getReferences()) .orElse(Collections.emptyList()) @@ -532,30 +531,38 @@ reference.setTitle(ref.getTitle()); reference.setUrl(ref.getUrl()); reference.setDomain(ref.getDomain()); reference.setNum(finalMaxNumByKeywordId); reference.setNum(keyword.getNum()); reference.setTask_id(result.getTask_id()); reference.setKeyword_id(keyword.getKeyword_id()); //域名和平台id映射 reference.setCreate_time(LocalDateTime.now()); Platform platform = platformService.getPlatformByDomain(reference.getDomain()); // if (platform == null) { // throw new RuntimeException("未找到对应的平台: " + reference.getDomain()); // } if (platform != null){ if (platform == null) { //平台为空 创建平台 类型为“默认” Type type = typeService.getOne(new LambdaQueryWrapper<Type>().eq(Type::getType_name,"默认")); if (type == null) { Type newType = new Type(); newType.setType_name("默认"); typeService.save(newType); type = newType; } Platform platform1 = new Platform(); platform1.setDomain(reference.getDomain()); platform1.setPlatform_name(reference.getDomain()); platform1.setType_id(type.getType_id()); platformService.save(platform1); reference.setType_id(type.getType_id()); reference.setPlatform_id(platform1.getPlatform_id()); } else { reference.setPlatform_id(platform.getPlatform_id()); Type type = typeService.getById(platform.getType_id()); // if (type == null) { // throw new RuntimeException("未找到对应的类型: " + reference.getDomain()); // } if (type != null){ reference.setType_id(type.getType_id()); } } // 根据 domain 查询类型 return reference; }) .collect(Collectors.toList()); @@ -564,6 +571,53 @@ if (!references.isEmpty()) { allReferences.addAll(references); } //取数据库中当前关键词的当前轮次的当前问题id结果拿出来 List<Reference> dbList = referenceService.list(new LambdaQueryWrapper<Reference>().eq(Reference::getKeyword_id, keyword.getKeyword_id()) .eq(Reference::getNum, keyword.getNum()) .eq(Reference::getQuestion_id, question.getQuestion_id()) ); // 1. 合并两个列表 List<Reference> combinedList = new ArrayList<>(); combinedList.addAll(allReferences); combinedList.addAll(dbList); // 2. 创建复合键的Map,用于统计完全匹配的记录 Map<String, List<Reference>> compositeKeyMap = combinedList.stream() .collect(Collectors.groupingBy( ref -> ref.getTitle() + "|" + ref.getUrl() + "|" + ref.getDomain() )); // 3. 处理每组重复记录 compositeKeyMap.forEach((key, refGroup) -> { // 3.1 找出组内有ID的记录(优先从dbList中获取) Optional<Reference> existingRecord = refGroup.stream() .filter(ref -> ref.getReference_id() != null) .findFirst(); // 3.2 统计该组的重复次数(总数-1) int repetitionCount = refGroup.size() - 1; // 3.3 决定最终保留的记录 Reference recordToSave; if (existingRecord.isPresent()) { // 使用已有ID的记录并更新重复次数 recordToSave = existingRecord.get(); recordToSave.setRepetition_num( (recordToSave.getRepetition_num() == null ? 0 : recordToSave.getRepetition_num()) + repetitionCount ); } else { // 没有ID记录则取第一条并设置重复次数 recordToSave = refGroup.get(0); recordToSave.setRepetition_num(repetitionCount); } resultList.add(recordToSave); }); referenceService.saveOrUpdateBatch(resultList); } } catch (Exception e) { log.error(e.getMessage(), e); @@ -578,7 +632,7 @@ questionService.updateBatchById(questionsToUpdate); System.out.println("成功批量更新 " + questionsToUpdate.size() + " 个问题"); } referenceService.saveBatch(allReferences); // 5. 批量插入引用,使用流式分批处理 // if (!allReferences.isEmpty()) { // int batchSize = 1000; src/main/java/com/linghu/controller/KeywordController.java
@@ -75,14 +75,58 @@ @ApiOperation(value = "EChart图") public ResponseResult<KeywordStaticsListVO> statics(@RequestParam("id") Integer keywordId, @RequestParam(value = "questionId", required = false) Integer questionId) { // return keywordService.statics(keywordId, questionId); } @GetMapping("/getTime") @ApiOperation(value = "查看时间") public ResponseResult<GetTimeVO> getTime(@RequestParam("id") Integer keywordId,@RequestParam(value = "questionId", required = false) Integer questionId) { // GetTimeVO vo = new GetTimeVO(); Keyword keyword = keywordService.getById(keywordId); LambdaQueryWrapper<Reference> 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<Reference> list = referenceService.list(queryWrapper); if (null != list && !list.isEmpty()) { vo.setNow(list.get(0).getCreate_time()); } //首次 LambdaQueryWrapper<Reference> queryWrapper2 = new LambdaQueryWrapper<>(); queryWrapper2.eq(Reference::getKeyword_id, keywordId); if (questionId != null) { queryWrapper2.eq(Reference::getQuestion_id, questionId); } queryWrapper2.eq(Reference::getNum,1); List<Reference> 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<byte[]> exportStatics(@RequestBody ExportStaticsDTO exportStaticsDTO) { Keyword keyword = keywordMapper.selectById(exportStaticsDTO.getKeywordId()); List<KeywordStaticsVO> voList = keywordMapper.statics(exportStaticsDTO.getKeywordId(), exportStaticsDTO.getQuestionId(), keyword.getNum()); List<KeywordStaticsVO> 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(); @@ -112,14 +156,10 @@ keyword.getNum() , typeId); return ResponseResult.success(result); } if (isNow > 0 && keyword.getNum()>isNow){ List<PlatformProportionVO> result = keywordMapper.getResultByTypeId(keywordId, questionId, keyword.getNum() - isNow, typeId); }else { List<PlatformProportionVO> result = keywordMapper.getResultByTypeId(keywordId, questionId, 1, typeId); return ResponseResult.success(result); }else { return ResponseResult.success(new ArrayList<>()); } } @@ -131,8 +171,18 @@ @ApiOperation(value = "导出:根据类别查看") public ResponseEntity<byte[]> exportGetResultByTypeId(@RequestBody ExportGetResultDTO dto) { Keyword keyword = keywordService.getById(dto.getKeywordId()); List<PlatformProportionVO> result = keywordMapper.getResultByTypeId(dto.getKeywordId(), dto.getQuestionId(), keyword.getNum() - dto.getIsNow(), dto.getTypeId()); List<PlatformProportionVO> 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) @@ -160,15 +210,12 @@ List<ResultListVO> result = keywordMapper.getResultByPlatformId(keywordId, questionId, keyword.getNum(), platformId); return ResponseResult.success(result); } if (isNow > 0 && keyword.getNum()>isNow){ List<ResultListVO> result = keywordMapper.getResultByPlatformId(keywordId, questionId, keyword.getNum() - isNow, platformId); return ResponseResult.success(result); }else { return ResponseResult.success(new ArrayList<>()); List<ResultListVO> result = keywordMapper.getResultByPlatformId(keywordId, questionId, 1, platformId); return ResponseResult.success(result); } } /** @@ -178,8 +225,14 @@ @ApiOperation(value = "导出:根据平台查看") public ResponseEntity<byte[]> exportGetResultByPlatformId(@RequestBody ExportGetResultByPlatformIdDTO dto) { Keyword keyword = keywordService.getById(dto.getKeywordId()); List<ResultListVO> result = keywordMapper.getResultByPlatformId(dto.getKeywordId(), dto.getQuestionId(), keyword.getNum() - dto.getIsNow(), List<ResultListVO> 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) src/main/java/com/linghu/controller/QuestionController.java
@@ -25,6 +25,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; @RestController @@ -91,13 +92,11 @@ return question; }).collect(Collectors.toList()); boolean success = questionService.saveBatch(questionList); questionService.saveBatch(questionList); return ResponseResult.success(); if(success) { return ResponseResult.success(questionList); } return ResponseResult.error("更新提问词失败"); } // @PutMapping src/main/java/com/linghu/controller/SectionalizationController.java
@@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.linghu.model.common.ResponseResult; import com.linghu.model.entity.Sectionalization; import com.linghu.model.vo.SectionalizationUserVO; import com.linghu.service.SectionalizationService; import com.linghu.service.UserService; import io.swagger.annotations.Api; @@ -75,4 +76,14 @@ } /** * 列表和底下用户数据 */ @GetMapping("/sectionalizationUser") @ApiOperation(value = "获取分组列表和底下用户数据") public ResponseResult<List<SectionalizationUserVO>> sectionalizationUser() { List<SectionalizationUserVO> list = sectionalizationService.SectionalizationUser(); return ResponseResult.success(list); } } src/main/java/com/linghu/controller/UserController.java
@@ -5,11 +5,10 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.linghu.model.common.ResponseResult; import com.linghu.model.entity.Sectionalization; import com.linghu.model.entity.Type; import com.linghu.model.entity.User; import com.linghu.model.excel.KeywordExcel; import com.linghu.model.excel.UserExcel; import com.linghu.model.vo.UserPageVO; import com.linghu.service.SectionalizationService; import com.linghu.service.UserService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -17,12 +16,16 @@ 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.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @RestController @RequestMapping("/user") @@ -42,6 +45,7 @@ if (list != null && list.size() > 0) { return ResponseResult.error("该邮箱已存在"); } user.setStatus("正常"); userService.save(user); return ResponseResult.success(); @@ -52,8 +56,12 @@ * 修改用户 */ @PutMapping @ApiOperation(value = "添加") @ApiOperation(value = "修改") public ResponseResult edit(@RequestBody User user) { User user1 = userService.getById(user.getUser_id()); if (user1 == null) { return ResponseResult.error("该账户不存在"); } List<User> list = userService.list(new LambdaQueryWrapper<User>() .ne(User::getUser_id, user.getUser_id()) .eq(User::getUser_email, user.getUser_email())); @@ -80,22 +88,20 @@ * 分页查询 */ @GetMapping @ApiOperation(value = "删除") @ApiOperation(value = "分页") public ResponseResult<Page<UserPageVO>> page(@RequestParam(value = "pageSize", required = false, defaultValue = "10")Integer pageSize, @RequestParam(value = "pageNum", required = false,defaultValue = "1")Integer pageNum, @RequestParam(value = "sectionalization_id",required = false)Integer sectionalization_id, @RequestParam(value = "status" ,required = false)String status) { Page<UserPageVO> page = new Page<>(pageNum, pageSize); return ResponseResult.success( userService.getPage(page,sectionalization_id,status)); } /** * 下载模板 */ @PostMapping("/downloadTemplate") @GetMapping("/downloadTemplate") @ApiOperation("下载模板") public ResponseEntity<byte[]> downloadTemplate() throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); @@ -111,7 +117,102 @@ /** * 导入文件 */ // 导入文件 @Autowired private SectionalizationService sectionalizationService; @PostMapping("/importUserExcel") @ApiOperation("导入用户数据") public ResponseResult importUserExcel(@RequestParam("file") MultipartFile file) { //查找出用户列表 List<User> userList = userService.list(); //名称 Map<String, User> nameMap = userList.stream() .collect(Collectors.toMap( User::getUser_name, // Key映射 excel -> excel, // Value映射 (oldValue, newValue) -> oldValue // 键冲突处理(保留旧值) )); //查找出分组列表 List<Sectionalization> list = sectionalizationService.list(); //分组 Map<String, Sectionalization> sectionalizationMap = list.stream() .collect(Collectors.toMap( Sectionalization::getSectionalization_name, // Key映射 excel -> excel, // Value映射 (oldValue, newValue) -> oldValue // 键冲突处理(保留旧值) )); try { // 检查文件是否为空 if (file.isEmpty()) { return ResponseResult.error("上传文件不能为空"); } // 读取Excel数据 List<UserExcel> excelList = EasyExcel.read(file.getInputStream()) .head(UserExcel.class) .sheet() .doReadSync(); // 数据转换与验证 List<String> errorMessages = new ArrayList<>(); for (UserExcel excel : excelList) { // 检查必要字段 if (!StringUtils.hasText(excel.getUser_name())) { errorMessages.add("账户名不能为空"); continue; } if (!StringUtils.hasText(excel.getUser_email())) { errorMessages.add("邮箱不能为空"); continue; } if (!StringUtils.hasText(String.valueOf(excel.getPassword()))) { errorMessages.add("密码不能为空"); continue; } if (!StringUtils.hasText(excel.getSectionalization_name())) { errorMessages.add("分组不能为空"); continue; } if (nameMap.containsKey(excel.getUser_name())){ errorMessages.add("用户名称重复"); continue; } } // 处理错误 if (!errorMessages.isEmpty()) { return ResponseResult.error("数据验证失败: " + String.join("; ", errorMessages)); } // 开始添加 for (UserExcel excel : excelList) { User user = new User(); if (sectionalizationMap.containsKey(excel.getSectionalization_name())) { user.setSectionalization_id(sectionalizationMap.get(excel.getSectionalization_name()).getSectionalization_id()); }else { //新增 Sectionalization sectionalization = new Sectionalization(); sectionalization.setSectionalization_name(excel.getSectionalization_name()); sectionalizationService.save(sectionalization); user.setSectionalization_id(sectionalization.getSectionalization_id()); } user.setUser_email(excel.getUser_email()); user.setUser_name(excel.getUser_name()); user.setPassword(excel.getPassword()); user.setStatus("正常"); userService.save(user); } // 返回信息 return ResponseResult.success(); } catch (Exception e) { // 记录详细异常信息 return ResponseResult.error("文件解析失败:" + e.getMessage()); } } src/main/java/com/linghu/mapper/UserMapper.java
@@ -14,7 +14,7 @@ */ public interface UserMapper extends BaseMapper<User> { Page<UserPageVO> getPage(Page<UserPageVO> page, @Param("sectionalizationId") Integer sectionalizationId, @Param("status") String status); Page<UserPageVO> getPage(@Param("page") Page<UserPageVO> page, @Param("sectionalizationId") Integer sectionalizationId, @Param("status") String status); } src/main/java/com/linghu/model/dto/ExportGetResultDTO.java
@@ -9,6 +9,6 @@ private Integer keywordId; private Integer questionId; private Integer typeId; @ApiModelProperty("轮数 0:当前 1:前一轮") @ApiModelProperty("轮数 0:当前 1:首次") private Integer isNow; } src/main/java/com/linghu/model/dto/ExportStaticsDTO.java
@@ -9,4 +9,6 @@ private Integer keywordId; @ApiModelProperty("提问词id") private Integer questionId; @ApiModelProperty("是否首次 0-否 1- 是") private Integer isFirst; } src/main/java/com/linghu/model/entity/Sectionalization.java
@@ -1,5 +1,6 @@ package com.linghu.model.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; @@ -14,7 +15,7 @@ @TableField(exist = false) private static final long serialVersionUID = 1L; @TableId @TableId(type = IdType.AUTO) private Integer sectionalization_id; @NotEmpty(message = "用户名不能为空") src/main/java/com/linghu/model/entity/User.java
@@ -1,5 +1,6 @@ package com.linghu.model.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; @@ -9,6 +10,7 @@ import javax.validation.constraints.NotBlank; import javax.validation.constraints.Size; import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** @@ -21,7 +23,7 @@ /** * 用户id */ @TableId @TableId(type = IdType.AUTO) private Integer user_id; /** @@ -47,6 +49,7 @@ /** * 手机号 */ @ApiModelProperty(hidden = true) private Integer phone; /** src/main/java/com/linghu/model/vo/GetTimeVO.java
New file @@ -0,0 +1,21 @@ package com.linghu.model.vo; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.Api; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import sun.util.resources.LocaleData; import java.time.LocalDateTime; @Data public class GetTimeVO { @ApiModelProperty("本次采集时间") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime now; @ApiModelProperty("首次采集时间") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime first; } src/main/java/com/linghu/model/vo/KeywordStaticsListVO.java
@@ -5,6 +5,7 @@ import lombok.Data; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; @Data @@ -13,7 +14,7 @@ @ApiModelProperty("当前统计记录") private List<KeywordStaticsVO> nowRecord; @ApiModelProperty("统计记录-前一次") @ApiModelProperty("统计记录-首次") private List<KeywordStaticsVO> beforeRecord; } src/main/java/com/linghu/model/vo/KeywordStaticsVO.java
@@ -1,5 +1,6 @@ package com.linghu.model.vo; import com.alibaba.excel.annotation.ExcelIgnore; import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -10,6 +11,9 @@ @Data @ApiModel("关键词统计") public class KeywordStaticsVO { @ApiModelProperty("发布平台id") @ExcelIgnore private String platform_id; @ApiModelProperty("发布平台") @ExcelProperty("发布平台") private String platform_name; src/main/java/com/linghu/model/vo/SectionalizationUserVO.java
New file @@ -0,0 +1,18 @@ package com.linghu.model.vo; import com.linghu.model.entity.User; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.util.List; @Data public class SectionalizationUserVO { @ApiModelProperty("分组id") private Integer sectionalization_id; @ApiModelProperty("分组名称") private String sectionalization_name; @ApiModelProperty("用户VO") private List<User> sectionalization_users; } src/main/java/com/linghu/model/vo/UserPageVO.java
@@ -10,10 +10,10 @@ private Integer user_id; @ApiModelProperty("用户名") private Integer user_name; private String user_name; @ApiModelProperty("用户邮箱") private Integer user_email; private String user_email; @ApiModelProperty("密码") private String password; @@ -21,6 +21,8 @@ @ApiModelProperty("分组名称") private String sectionalization_name; @ApiModelProperty("分组名称") private Integer sectionalization_id; @ApiModelProperty("状态") private String status; src/main/java/com/linghu/service/SectionalizationService.java
@@ -5,6 +5,7 @@ import com.linghu.model.dto.OrderDto; import com.linghu.model.entity.Orders; import com.linghu.model.entity.Sectionalization; import com.linghu.model.vo.SectionalizationUserVO; import java.util.List; @@ -15,4 +16,5 @@ */ public interface SectionalizationService extends IService<Sectionalization> { List<SectionalizationUserVO> SectionalizationUser(); } src/main/java/com/linghu/service/impl/KeywordServiceImpl.java
@@ -41,7 +41,7 @@ List<KeywordStaticsVO> statics = this.getBaseMapper().statics(keywordId, questionId, keyword.getNum()); vo.setNowRecord(statics); if (keyword.getNum() > 1) { statics = this.getBaseMapper().statics(keywordId, questionId, keyword.getNum() - 1); statics = this.getBaseMapper().statics(keywordId, questionId, 1); vo.setBeforeRecord(statics); } return ResponseResult.success(vo); src/main/java/com/linghu/service/impl/SectionalizationServiceImpl.java
@@ -1,13 +1,21 @@ package com.linghu.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.linghu.mapper.SectionalizationMapper; import com.linghu.mapper.UserMapper; import com.linghu.model.entity.Sectionalization; import com.linghu.model.entity.User; import com.linghu.model.vo.SectionalizationUserVO; import com.linghu.service.SectionalizationService; import com.linghu.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** * @author xy @@ -18,6 +26,50 @@ public class SectionalizationServiceImpl extends ServiceImpl<SectionalizationMapper, Sectionalization> implements SectionalizationService { @Autowired private UserMapper userMapper; @Override public List<SectionalizationUserVO> SectionalizationUser() { // 1. 查询所有状态为"正常"的用户 List<User> userList = userMapper.selectList( new LambdaQueryWrapper<User>() .eq(User::getStatus, "正常") ); // 2. 提取所有分组ID并去重 List<Integer> sectionalizationIdList = userList.stream() .map(User::getSectionalization_id) .distinct() .collect(Collectors.toList()); // 3. 查询这些分组的基本信息 List<Sectionalization> sectionalizationList = this.baseMapper.selectList( new LambdaQueryWrapper<Sectionalization>() .in(Sectionalization::getSectionalization_id, sectionalizationIdList) ); // 4. 创建分组ID到分组名称的映射 Map<Integer, String> sectionalizationNameMap = sectionalizationList.stream() .collect(Collectors.toMap( Sectionalization::getSectionalization_id, Sectionalization::getSectionalization_name )); // 5. 按分组ID对用户进行分组 Map<Integer, List<User>> usersBySectionalization = userList.stream() .collect(Collectors.groupingBy(User::getSectionalization_id)); // 6. 构建最终返回结果 return sectionalizationIdList.stream() .map(id -> { SectionalizationUserVO vo = new SectionalizationUserVO(); vo.setSectionalization_id(id); vo.setSectionalization_name(sectionalizationNameMap.get(id)); vo.setSectionalization_users(usersBySectionalization.getOrDefault(id, Collections.emptyList())); return vo; }) .collect(Collectors.toList()); } } src/main/java/com/linghu/timeTask/ScheduledTasks.java
@@ -62,8 +62,9 @@ t.setStatus("completed"); return t; }); } else if (!"submit".equalsIgnoreCase(statusResponse.getStatus()) && !"running".equalsIgnoreCase(statusResponse.getStatus())) { } else if (!"submitted".equalsIgnoreCase(statusResponse.getStatus()) && !"running".equalsIgnoreCase(statusResponse.getStatus()) && !"Error".equalsIgnoreCase(statusResponse.getStatus())) { task.setStatus("false"); return Mono.just(task); } else { src/main/java/com/linghu/utils/OpenCryptUtil.java
@@ -32,7 +32,7 @@ /** * AES加密(假设 open-crypt 默认使用AES-CBC模式) */ public String encrypt(User user) { public String encrypt(String user) { try { // 调用 open-crypt 的加密方法(根据实际API调整) //user转为 json src/main/resources/mapper/UserMapper.xml
@@ -25,6 +25,7 @@ u.user_email, u.`password`, s.sectionalization_name, s.sectionalization_id, u.status FROM `user` u src/main/resources/mapper/keywordMapper.xml
@@ -19,6 +19,7 @@ </sql> <select id="statics" resultType="com.linghu.model.vo.KeywordStaticsVO"> SELECT p.platform_id, p.platform_name, SUM( r.repetition_num ) AS total_repetitions, ROUND(