天机学堂-day5(互动问答)

目录


文章目录


前言

本文章使用的是《天机学堂》开源的资料,并从创建虚拟机开始部署《天机学堂项目》,避免还要下载资料中的20GB虚拟机 ,只需要下载镜像以及其他基础资料即可,请大家放心食用 (https://blog.csdn.net/weixin_68576312/article/details/154407558?spm=1011.2415.3001.5331)

上一篇:《天机学堂-day4(高并发优化方案)》


一、接口介绍

这一节课主要就是根据业务需求写接口,所需要完成的接口如下:

分类 编号 接口简述
互动问题相关接口 1 新增互动问题
2 修改互动问题
3 分页查询问题(用户端)
4 根据id查询问题详情(用户端)
5 删除我的问题
6 分页查询问题(管理端)
7 根据id查询问题详情(管理端)
8 隐藏或显示指定问题(管理端)
回答及评论相关接口 1 新增回答或评论
2 分页查询回答或评论列表
3 根据id查询回答或评论(管理端)
4 隐藏或显示指定回答或评论(管理端)

二、互动问题相关接口

1 新增互动问题

代码实现

learning 中的 InteractionQuestionController

java 复制代码
@RestController
@RequestMapping("/questions")
@RequiredArgsConstructor
public class InteractionQuestionController {

    private final IInteractionQuestionService questionService;

    @PostMapping
    @ApiOperation("添加问题")
    public void addQuestion(@Valid @RequestBody QuestionFormDTO dto) {
        questionService.saveQuestion(dto);
    }
}

业务逻辑实现 learning 中的 InteractionQuestionServiceImpl

java 复制代码
/**
 * @author chyb
 * @description 针对表【interaction_question(互动提问的问题表)】的数据库操作Service实现
 * @createDate 2025-12-07 15:41:10
 */
@RequiredArgsConstructor
@Service
public class InteractionQuestionServiceImpl extends ServiceImpl<InteractionQuestionMapper, InteractionQuestion> implements InteractionQuestionService {
    private final UserClient userClient;

    @Override
    public void saveQuestion(QuestionFormDTO questionDTO) {
        /*获取当前用户*/
        Long user = UserContext.getUser();
        /*创建实体类*/
        InteractionQuestion interactionQuestion = BeanUtils.copyBean(questionDTO, InteractionQuestion.class);
        interactionQuestion.setUserId(user);
        /*保存*/
        save(interactionQuestion);
    }
}

		

测试


2 修改互动问题

代码实现

learning 中的 InteractionQuestionController

java 复制代码
@RestController
@RequestMapping("/questions")
@RequiredArgsConstructor
public class InteractionQuestionController {

    private final IInteractionQuestionService questionService;

	@PostMapping("{id}")
    @ApiOperation("修改问题")
    public void updateQuestion(@Valid @RequestBody QuestionFormDTO dto, @PathVariable("id") Long id) {
        questionService.updateQuestion(dto,id);
    }
}

learning 中的 InteractionQuestionServiceImpl

java 复制代码
@RequiredArgsConstructor
@Service
public class InteractionQuestionServiceImpl extends ServiceImpl<InteractionQuestionMapper, InteractionQuestion> implements InteractionQuestionService {
    private final UserClient userClient;
//     dto: ⬇
//        "title":  "JDK哪里下载",  // 问题标题
//        "description": "找不到网站啊老师", // 问题描述
//        "anonymity": false, // 是否匿名
//     id: 问题id
    @Override
    public void updateQuestion(QuestionFormDTO dto, Long id) {
        /*获取问题信息*/
        InteractionQuestion question = getById(id);
        if (question == null) throw new BadRequestException("没有此问题");
        /*获取当前登录用户,用来避免其他用户修改此用户的问题信息*/
        Long user = UserContext.getUser();
        if (user != question.getUserId()) throw new BadRequestException("你不可以修改其他人的问题信息");
        /*复制修改后的内容*/
        InteractionQuestion questionDto = BeanUtils.toBean(dto, InteractionQuestion.class);
        /*避免修改的id不存在或者修改到其他的id上*/
        questionDto.setId(question.getId());
        /*修改内容*/
        updateById(questionDto);
    }
}

测试


3 分页查询问题(用户端)

代码实现

learning 中的 InteractionQuestionController

java 复制代码
@RestController
@RequestMapping("/questions")
@RequiredArgsConstructor
public class InteractionQuestionController {

    private final IInteractionQuestionService questionService;

    @GetMapping("page")
    @ApiOperation("分页查询")
    public PageDTO<QuestionVO> pageGet(QuestionPageQuery query) {
        return questionService.getPage(query);
    }
}

learning 中的 InteractionQuestionServiceImpl

java 复制代码
@RequiredArgsConstructor
@Service
public class InteractionQuestionServiceImpl extends ServiceImpl<InteractionQuestionMapper, InteractionQuestion> implements InteractionQuestionService {
    private final InteractionReplyMapper replyMapper;
    private final UserClient userClient;

    @Override
    public PageDTO<QuestionVO> getPage(QuestionPageQuery query) {
        Long courseId = query.getCourseId();
        Long sectionId = query.getSectionId();
        /*参数校验:课程id和小节id不能同时为空,一般业务查询评论都是在某个课程或小节下查看,不太课程全部查询出来*/
        if (courseId == null && sectionId == null) {
            throw new BadRequestException("课程id和小节id不能同时为空");
        }

        /*分页查询,根据query过滤courseId,sectionId,以及userId、hidden(是否被隐藏)。
            同时将问题详细字段:description,给排除因为这个字段在这个即可下是用不到的,查出来只会浪费性能。*/
        Page<InteractionQuestion> description = lambdaQuery()
                /*这个是根据java实体类属性名,进行判断的例如:userName*/
                .select(InteractionQuestion.class, info -> !info.getProperty().equals("description"))
                /*这个字段是根据数据库字段名,进行判断的例如:user_name*/
                //.select(i -> !i.getColumn().equals("description"))
                /*没有被隐藏的用户*/
                .eq(InteractionQuestion::getHidden, false)
                .eq(query.getOnlyMine() == null || query.getOnlyMine(), InteractionQuestion::getUserId, UserContext.getUser())
                .eq(courseId != null, InteractionQuestion::getCourseId, courseId)
                .eq(sectionId != null, InteractionQuestion::getSectionId, sectionId)
                .page(query.toMpPageDefaultSortByCreateTimeDesc());
        List<InteractionQuestion> records = description.getRecords();
        /*为空返回*/
        if (CollUtils.isEmpty(records)) return PageDTO.empty(description);

        HashSet<Long> userIds = new HashSet<>();
        HashSet<Long> answerIds = new HashSet<>();
        /*查询用户id*/
        for (InteractionQuestion record : records) {
            if (!record.getAnonymity()) {
                userIds.add(record.getUserId());
            }
            answerIds.add(record.getLatestAnswerId());
        }

        /*根据回答ids去查询回复用户的昵称,注意该用户是否设置匿名*/
        answerIds.remove(null);
        HashMap<Long, InteractionReply> replyMap = new HashMap<>(answerIds.size());
        if (CollUtils.isNotEmpty(answerIds)) {
            List<InteractionReply> interactionReplies = replyMapper.selectBatchIds(answerIds);
//            replyMap = interactionReplies.stream()
//                    .filter(reply -> !reply.getAnonymity())
//                    .collect(Collectors
//                            .toMap(InteractionReply::getId, u -> u,
//                                    /*
//                                    要想直接转换为hashMap,这里必须做一个若是key值相同,
//                                    v值取谁的设定【(v1,v2)->v1】,
//                                    Map工厂:告诉"Stream流"请用HashMap填装接口。
//                                    */
//                                    (v1, v2) -> v1, HashMap::new));
            /*所以这里使用普通的forEach即可,没必要使用stream流这样反倒:性能下降了、代码也并不是很简洁了*/
            interactionReplies.forEach(c -> {
                if (!c.getAnonymity()) {
                    replyMap.put(c.getUserId(), c);
                    /*这里因为vo封装类中在没有匿名的前提下,需要显示该用户的name,
                    而InteractionReply里面是没有该字段,所以这里只需要将该用户的id添加到userIds后续在通过userClient去获取即可*/
                    userIds.add(c.getUserId());
                }
            });

        }
        /*获取非匿名的用户基础信息*/
        userIds.remove(null);
        HashMap<Long, UserDTO> userMap = new HashMap<>(userIds.size());
        if (CollUtils.isNotEmpty(userIds)) {
            List<UserDTO> userDTOS = userClient.queryUserByIds(userIds);
            userDTOS.forEach(c -> userMap.put(c.getId(), c));
//            HashMap<Long, UserDTO> collect = userDTOS.stream()
//                    .collect(Collectors
//                            .toMap(UserDTO::getId, u -> u,
//                                    (v1, v2) -> v1,
//                                    () -> new HashMap<>(userIds.size())));
        }

        /*封装vo*/
        ArrayList<QuestionVO> voArrayList = new ArrayList<>(records.size());
        for (InteractionQuestion record : records) {
            QuestionVO questionVO = BeanUtils.copyBean(record, QuestionVO.class);
            questionVO.setUserId(null);
            voArrayList.add(questionVO);

            /*获取非匿名回复用户的基础信息*/
            InteractionReply replyTemp = replyMap.get(record.getLatestAnswerId());
            if (replyTemp != null && !replyTemp.getAnonymity()) {
                UserDTO userDTO = userMap.get(replyTemp.getTargetUserId());
                questionVO.setLatestReplyUser(userDTO.getName());
            }
            /*获取非匿名问题用户的基础信息*/
            if (!record.getAnonymity()) {
                UserDTO userTemp = userMap.get(record.getUserId());
                if (userTemp != null) {
                    questionVO.setUserName(userTemp.getName());
                    questionVO.setUserIcon(userTemp.getIcon());
                }
            }

        }
        return PageDTO.of(description, voArrayList);
    }

}

测试

4 根据id查询问题详情(用户端)

代码实现

learning 中的 InteractionQuestionController

java 复制代码
@RestController
@RequestMapping("/questions")
@RequiredArgsConstructor
public class InteractionQuestionController {

    private final IInteractionQuestionService questionService;

    @GetMapping("{id}")
    @ApiOperation("根据id查询信息")
    public QuestionVO selectById(@PathVariable("id") Long id) {
        return questionService.selectById(id);
    }
}

learning 中的 InteractionQuestionServiceImpl

java 复制代码
@RequiredArgsConstructor
@Service
public class InteractionQuestionServiceImpl extends ServiceImpl<InteractionQuestionMapper, InteractionQuestion> implements InteractionQuestionService {
    private final UserClient userClient;

    @Override
    public QuestionVO selectById(Long id) {
        InteractionQuestion question = getById(id);
        UserDTO user = null;
        if (!question.getAnonymity()) {
            user = userClient.queryUserById(question.getUserId());
        }
        QuestionVO questionVO = BeanUtils.copyBean(question, QuestionVO.class);
        if (user != null) {
            questionVO.setUserName(user.getName());
            questionVO.setUserIcon(user.getIcon());
        }
        return questionVO;
    }

}

测试

5 删除我的问题

代码实现

learning 中的 InteractionQuestionController

java 复制代码
@RestController
@RequestMapping("/questions")
@RequiredArgsConstructor
public class InteractionQuestionController {

    private final IInteractionQuestionService questionService;

	@DeleteMapping("{id}")
    @ApiOperation("删除")
    public void DeleteQuestion(@PathVariable("id") Long id) {
        questionService.DelQuestion(id);
    }
}

learning 中的 InteractionQuestionServiceImpl

java 复制代码
@RequiredArgsConstructor
@Service
public class InteractionQuestionServiceImpl extends ServiceImpl<InteractionQuestionMapper, InteractionQuestion> implements InteractionQuestionService {
    private final UserClient userClient;
    @Override
    public void DelQuestion(Long id) {
        //查询问题是否存在
        InteractionQuestion byId = getById(id);
        if (byId == null) throw new BadRequestException("该问题不存在");
        //判断是否是当前用户提问的
        Long user = UserContext.getUser();
        //如果不是则报错
        if (byId.getUserId() != user) throw new BadRequestException("你不可以删除其他人的问题信息");
        //如果是则删除问题
        removeById(id);
        //然后删除问题下的回答及评论
        replyMapper.delete(
                new LambdaQueryWrapper<InteractionReply>()
                        .eq(InteractionReply::getQuestionId, id)
        );
    }
}

测试

测试是否可以删除其他人的问题


测试是否可以完成删除成功


6 分页查询问题(管理端)

代码实现

learning 中的 InteractionQuestionAdminController

java 复制代码
@RestController
@RequestMapping("/admin/questions")
@RequiredArgsConstructor
@Api(tags = "互动问题管理")
public class InteractionQuestionAdminController {
    private final InteractionQuestionService questionService;

    @GetMapping("page")
    @ApiOperation("分页查询管理端")
    public PageDTO<QuestionAdminVO> pageGet(QuestionAdminPageQuery query) {
        return questionService.getPageAdmin(query);
    }
}

learning 中的 InteractionQuestionServiceImpl

java 复制代码
@RequiredArgsConstructor
@Service
public class InteractionQuestionServiceImpl extends ServiceImpl<InteractionQuestionMapper, InteractionQuestion> implements InteractionQuestionService {
    private final UserClient userClient;
    private final SearchClient searchClient;
    private final CourseClient courseClient;
    private final CatalogueClient catalogueClient;
    private final CategoryCache categoryCache;

    @Override
    public PageDTO<QuestionAdminVO> getPageAdmin(QuestionAdminPageQuery query) {
        /*获取该课程id*/
        List<Long> coursesIds = null;
        if (StringUtils.isNotEmpty(query.getCourseName())) {
            coursesIds = searchClient.queryCoursesIdByName(query.getCourseName());
            if (CollUtils.isEmpty(coursesIds)) return PageDTO.empty(0L, 0L);
        }
        /*分页查询*/
        Integer status = query.getStatus();
        LocalDateTime beginTime = query.getBeginTime();
        LocalDateTime endTime = query.getEndTime();
        Page<InteractionQuestion> page = lambdaQuery()
                .in(coursesIds != null, InteractionQuestion::getCourseId, coursesIds)
                .eq(status != null, InteractionQuestion::getStatus, status)
                .gt(beginTime != null, InteractionQuestion::getCreateTime, beginTime)
                .lt(endTime != null, InteractionQuestion::getCreateTime, endTime)
                .page(query.toMpPageDefaultSortByCreateTimeDesc());

        List<InteractionQuestion> records = page.getRecords();
        if (CollUtils.isEmpty(records)) {
            return PageDTO.empty(page);
        }
        /*根据id查询:用户、课程、章节、分类,id集合*/
        Set<Long> userIds = new HashSet<>();
        Set<Long> cIds = new HashSet<>();
        /*章节id*/
        Set<Long> cataIds = new HashSet<>();

        for (InteractionQuestion record : records) {
            userIds.add(record.getUserId());
            cIds.add(record.getCourseId());
            cataIds.add(record.getChapterId());
            cataIds.add(record.getSectionId());
        }

        /*user数据map集合*/
        HashMap<Long, UserDTO> userMap = new HashMap<>(userIds.size());
        List<UserDTO> userDTOS = userClient.queryUserByIds(userIds);
        if (CollUtils.isNotEmpty(userDTOS)) {
//            /*方法一*/
//            userMap = userDTOS.stream()
//                    .collect(Collectors.toMap(UserDTO::getId, c -> c, (v1, v2) -> v1, HashMap::new));
            /*方法二*/
            for (UserDTO userDTO : userDTOS) {
                userMap.put(userDTO.getId(), userDTO);
            }
        }
        /*课程数据Map集合*/
        List<CourseSimpleInfoDTO> infoList = courseClient.getSimpleInfoList(cIds);
        HashMap<Long, CourseSimpleInfoDTO> courseMap = new HashMap<>(cIds.size());
        if (CollUtils.isNotEmpty(cIds)) {
            for (CourseSimpleInfoDTO infoDTO : infoList) {
                courseMap.put(infoDTO.getId(), infoDTO);
            }
        }
        /*章节数据map集合*/
        List<CataSimpleInfoDTO> cataInfos = catalogueClient.batchQueryCatalogue(cataIds);
        HashMap<Long, String> cataMap = new HashMap<>(cataIds.size());
        if (CollUtils.isNotEmpty(cataInfos)) {
            for (CataSimpleInfoDTO cataInfo : cataInfos) {
                cataMap.put(cataInfo.getId(), cataInfo.getName());
            }
        }


        /*封装vo*/
        ArrayList<QuestionAdminVO> vos = new ArrayList<>(records.size());
        for (InteractionQuestion record : records) {
            QuestionAdminVO vo = BeanUtils.copyBean(record, QuestionAdminVO.class);
            vos.add(vo);
            /*用户*/
            UserDTO userDTO = userMap.get(record.getUserId());
            if (userDTO != null) {
                vo.setUserIcon(userDTO.getIcon());
                vo.setUserName(userDTO.getUsername());
            }
            /*课程,课程分类*/
            CourseSimpleInfoDTO infoDTO = courseMap.get(record.getCourseId());
            if (infoDTO != null) {
                vo.setCourseName(infoDTO.getName());
                List<Long> categoryIds = infoDTO.getCategoryIds();
                String categoryNames = categoryCache.getCategoryNames(categoryIds);
                vo.setCategoryName(categoryNames);
            }
            /*章节、小节名*/
            vo.setSectionName(cataMap.get(record.getSectionId()));
            vo.setChapterName(cataMap.get(record.getChapterId()));
        }
        return PageDTO.of(page, vos);
    }

}

测试

7 根据id查询问题详情(管理端)

代码实现

learning 中的 InteractionQuestionAdminController

java 复制代码
@RestController
@RequestMapping("/admin/questions")
@RequiredArgsConstructor
@Api(tags = "互动问题管理")
public class InteractionQuestionAdminController {
    private final InteractionQuestionService questionService;

    @GetMapping("{id}")
    @ApiOperation("根据id查询问题详情")
    public QuestionAdminVO getInfoById(@PathVariable("id") Long id) {
        return questionService.getInfoById(id);
    }
}

learning 中的 InteractionQuestionAdminController

java 复制代码
@RequiredArgsConstructor
@Service
public class InteractionQuestionServiceImpl extends ServiceImpl<InteractionQuestionMapper, InteractionQuestion>
        implements InteractionQuestionService {
    private final UserClient userClient;
    private final CourseClient courseClient;
    private final CatalogueClient catalogueClient;
    private final CategoryCache categoryCache;

    @Override
    public QuestionAdminVO getInfoById(Long id) {
        /*1. 根据id查询问题数据*/
        InteractionQuestion q = getById(id);
        if (q == null) throw new BadRequestException("当前问题不存在");
        /*2. 封装*/
        QuestionAdminVO vo = BeanUtils.copyBean(q, QuestionAdminVO.class);
        /*3. 查询基础数据*/
        /*3.1 课程*/
        CourseFullInfoDTO cInfo = courseClient.getCourseInfoById(q.getCourseId(), false, false);

        if (cInfo != null) {
            /*3.1.2 课程名称*/
            vo.setCourseName(cInfo.getName());
            /*3.1.2 课程分类*/
            String categoryNames = categoryCache.getCategoryNames(cInfo.getCategoryIds());
            vo.setCategoryName(categoryNames);
            /*3.1.2 教师名称*/
            List<Long> teacherIds = cInfo.getTeacherIds();
            if (CollUtils.isNotEmpty(teacherIds)) {
                List<UserDTO> userDTOS = userClient.queryUserByIds(teacherIds);
                if (CollUtils.isNotEmpty(userDTOS)) {
                    vo.setTeacherName(userDTOS.stream()
                            .map(UserDTO::getName).collect(Collectors.joining("/")));
                }
            }
        }
        /*3.2 问题用户*/
        UserDTO userDTO = userClient.queryUserById(q.getUserId());
        if (userDTO != null) {
            vo.setUserName(userDTO.getName());
            vo.setUserIcon(userDTO.getIcon());
        }
        /*3.2 章节*/
        List<CataSimpleInfoDTO> cataInfos = catalogueClient.batchQueryCatalogue(List.of(q.getChapterId(), q.getSectionId()));
        Map<Long, String> cataMap = new HashMap<>();
        if (CollUtils.isNotEmpty(cataInfos)) {
            cataMap = cataInfos.stream()
                    .collect(Collectors.toMap(CataSimpleInfoDTO::getId, CataSimpleInfoDTO::getName));
        }
        vo.setSectionName(cataMap.getOrDefault(q.getSectionId(), ""));
        vo.setChapterName(cataMap.getOrDefault(q.getChapterId(), ""));
        /*修改问题的状态*/
        lambdaUpdate()
                .eq(InteractionQuestion::getId, id)
                .set(InteractionQuestion::getStatus, QuestionStatus.CHECKED)
                .update();
        /*返回*/
        return vo;
    }


}

测试


8 隐藏或显示指定问题(管理端)

代码实现

learning 中的 InteractionQuestionAdminController

java 复制代码
@RestController
@RequestMapping("/admin/questions")
@RequiredArgsConstructor
@Api(tags = "互动问题管理")
public class InteractionQuestionAdminController {
    private final InteractionQuestionService questionService;

    @PutMapping("/{id}/hidden/{hidden}")
    @ApiOperation("管理端:显示或隐藏评论|回答")
    public void hiddenReply(@PathVariable("id") Long id, @PathVariable("hidden") Boolean hidden) {
        questionService.hiddenReply(id,hidden);
    }
}

learning 中的 InteractionQuestionAdminController

java 复制代码
@RequiredArgsConstructor
@Service
public class InteractionQuestionServiceImpl extends ServiceImpl<InteractionQuestionMapper, InteractionQuestion>
        implements InteractionQuestionService {
    /**
     * 管理端:显示或隐藏问题
     *
     * @param id
     * @param hidden
     */
    @Override
    public void hiddenReply(Long id, Boolean hidden) {
        /*获取评论*/
        InteractionQuestion question = getById(id);
        if (ObjectUtils.isEmpty(question)) throw new BadRequestException("该数据不存在");
        lambdaUpdate().eq(InteractionQuestion::getId, id)
                .set(InteractionQuestion::getHidden, hidden)
                .update();
    }
}

测试


这里按道理来说显示的状态应该是隐藏,但是这里显示的是显示状态,应该是前端的问题,但是在操作、网络请求这里显示的都是隐藏的状态

三、回答及评论相关接口

1 新增回答或评论

代码实现

learning 中的 InteractionReplyController

java 复制代码
@RestController
@RequestMapping("/replies")
@Api(tags = "评论相关的接口")
@RequiredArgsConstructor
public class InteractionReplyController {
    private final InteractionReplyService replyService;

    @PostMapping
    @ApiOperation("新增评论或回答")
    public void addReply(@RequestBody ReplyDTO replyDTO) {
        replyService.addReply(replyDTO);
    }
}

learning 中的 InteractionReplyController

java 复制代码
/**
 * @author chyb
 * @description 针对表【interaction_reply(互动问题的回答或评论)】的数据库操作Service实现
 * @createDate 2025-12-07 15:41:10
 */
@Service
@RequiredArgsConstructor
public class InteractionReplyServiceImpl extends ServiceImpl<InteractionReplyMapper, InteractionReply>
        implements InteractionReplyService {
    private final InteractionQuestionService questionService;
    private final UserClient userClient;


    @Override
    @Transactional
    public void addReply(ReplyDTO dto) {
        /*注意这里的UserId为当前用户id*/
        Long user = UserContext.getUser();
        /*1. 写入回答或评论*/
        InteractionReply reply = BeanUtils.toBean(dto, InteractionReply.class);
        reply.setUserId(user);
        save(reply);
        /*2. 判断是回答还是评论*/
        if (dto.getAnswerId() == null) {
            /*1.1 回答:*/
            /*更新问题表中的:回答次数、最近的回答id*/
            questionService.lambdaUpdate()
                    .eq(InteractionQuestion::getId, dto.getQuestionId())
                    .set(InteractionQuestion::getLatestAnswerId, reply.getId())
                    .setSql("answer_times = answer_times+1")
                    /*判断是否是学生提交,
                        是:修改问题表中的查看状态为;未查看*/
                    .set(dto.getIsStudent(), InteractionQuestion::getStatus, QuestionStatus.UN_CHECK)
                    .update();
        } else {
            /*1.2 评论:*/
            /*更新回答下评论的次数*/
            lambdaUpdate()
                    .eq(InteractionReply::getId, dto.getAnswerId())
                    .setSql("reply_times = reply_times+1")
                    .update();
        }
    }
}

测试


这里要先编写完下面的分页查询的接口才可以查询

2 分页查询回答或评论列表

代码实现

learning 中的 InteractionReplyController

java 复制代码
@RestController
@RequestMapping("/replies")
@Api(tags = "评论相关的接口")
@RequiredArgsConstructor
public class InteractionReplyController {
    private final InteractionReplyService replyService;

    @GetMapping("/page")
    @ApiOperation("分页查询评论")
    public PageDTO<ReplyVO> getPage(ReplyPageQuery query) {
        return replyService.getPage(query, false);
    }
}

learning 中的 InteractionReplyController

java 复制代码
/**
 * @author chyb
 * @description 针对表【interaction_reply(互动问题的回答或评论)】的数据库操作Service实现
 * @createDate 2025-12-07 15:41:10
 */
@Service
@RequiredArgsConstructor
public class InteractionReplyServiceImpl extends ServiceImpl<InteractionReplyMapper, InteractionReply>
        implements InteractionReplyService {
    private final InteractionQuestionService questionService;
    private final UserClient userClient;

    /**
     * @param query
     * @param forAdmin 是否是管理端
     * @return
     */
    @Override
    public PageDTO<ReplyVO> getPage(ReplyPageQuery query, boolean forAdmin) {
        /*判断query两个id是否符合规则*/
        Long questionId = query.getQuestionId();
        Long answerId = query.getAnswerId();
        if (questionId != null && answerId != null) {
            throw new BadRequestException("问题id和回答id不可以都为空");
        }
        /*标记是否为问题*/
        boolean isQuestion = questionId != null;
        /*分页查询*/
        Page<InteractionReply> page = lambdaQuery()
                /*若是问题则做判断*/
                .eq(isQuestion, InteractionReply::getQuestionId, questionId)
                /*
                若是回答,注意这里并不能直接根据isQuestion,然后是否eq
                而是:若isQuestion=true;查询所有的回答(AnswerId=0)
                     若isQuestion=false;查询所有的回答(AnswerId=answerId)*/
                .eq(InteractionReply::getAnswerId, isQuestion ? 0L : answerId)
                /*判断隐藏,不是管理员的才需要判断*/
                .eq(!forAdmin, InteractionReply::getHidden, false)
                .page(query.toMpPage(
                        /*默认为点赞数量排序*/
                        new OrderItem(Constant.DATA_FIELD_NAME_LIKED_TIME, false),
                        /*若是点赞数量相同,根据创建时间排序*/
                        new OrderItem(Constant.DATA_FIELD_NAME_CREATE_TIME, true)
                ));
        /*若是为空直接返回空分页数据列表*/
        List<InteractionReply> records = page.getRecords();
        if (CollUtils.isEmpty(records)) {
            return PageDTO.empty(0L, 0L);
        }

        /*数据处理,需要查询:提问者信息、回复目标信息、当前用户是否点赞*/
        HashSet<Long> userIds = new HashSet<>();        //回答者
        HashSet<Long> answerIds = new HashSet<>();      //回答字段id
        HashSet<Long> targetReplyId = new HashSet<>();  //目标回复id
        // 获取提问者id 、回复的目标id、当前回答或评论id(统计点赞信息)
        for (InteractionReply record : records) {
            /*判断是否匿名,如果是管理员除外*/
            if (!record.getAnonymity() || forAdmin) {
                /*回答者Id*/
                userIds.add(record.getUserId());
            }
            answerIds.add(record.getAnswerId());
            targetReplyId.add(record.getTargetReplyId());
        }
        /*目标id数据处理*/
        //查询目标回复,如果目标回复不是匿名,则需要查询出目标回复的用户信息
        targetReplyId.remove(null);
        if (!targetReplyId.isEmpty()) {
            List<InteractionReply> list = listByIds(targetReplyId);
            for (InteractionReply reply : list) {
                if (!reply.getAnonymity() || forAdmin) {
                    userIds.add(reply.getUserId());
                }
            }
        }
        /*查询用户*/
        Map<Long, UserDTO> userDTOMap = new HashMap<>();
        userIds.remove(null);
        if (!userIds.isEmpty()) {
            List<UserDTO> userDTOS = userClient.queryUserByIds(userIds);
            userDTOMap = userDTOS.stream().collect(Collectors.toMap(UserDTO::getId, v -> v));
        }
        /*查询用户点赞状态*/
        //TODO Set<Long> bizLiked = remarkClient.isBizLiked(answerIds);
        /*处理VO*/
        ArrayList<ReplyVO> replyVOS = new ArrayList<>(records.size());
        for (InteractionReply record : records) {
            /*基本属性拷贝*/
            ReplyVO reply = BeanUtils.toBean(record, ReplyVO.class);
            replyVOS.add(reply);
            /*回复人信息*/
            if (!record.getAnonymity() || forAdmin) {
                UserDTO userDTO = userDTOMap.get(record.getUserId());
                if (userDTO != null) {
                    reply.setUserName(userDTO.getName());
                    reply.setUserIcon(userDTO.getIcon());
                    reply.setUserType(userDTO.getType());
                }
            }
            /*如果存在评论的目标,则需要设置目标用户信息*/
            if (record.getTargetReplyId() != null) {
                UserDTO userDTO = userDTOMap.get(record.getTargetUserId());
                if (userDTO != null) {
                    reply.setTargetUserName(userDTO.getName());
                }
            }
            /*点赞状态*/
            //TODO v.setLiked(bizLiked.contains(r.getId()));
        }
        return new PageDTO<>(page.getTotal(), page.getPages(), replyVOS);
    }

}

测试

3 根据id查询回答或评论(管理端)

代码实现

learning 中的 InteractionReplyAdminController

java 复制代码
@RestController
@RequestMapping("/admin/replies")
@Api(tags = "管理端评论相关的接口")
@RequiredArgsConstructor
public class InteractionReplyAdminController {
    private final InteractionReplyService replyService;

    @PutMapping("/{id}")
    @ApiOperation("管理端:根据id查询评论详情")
    public ReplyVO queryReplyVoByIdAdmin(@ApiParam(value = "评论", example = "1") @PathVariable("id") Long id) {
        return replyService.queryReplyVoByIdAdmin(id);
    }
}

learning 中的 InteractionReplyServiceImpl

java 复制代码
@Service
@RequiredArgsConstructor
public class InteractionReplyServiceImpl extends ServiceImpl<InteractionReplyMapper, InteractionReply>
        implements InteractionReplyService {
    private final InteractionQuestionService questionService;
    private final UserClient userClient;

    
    /**
     * 根据id查询回答或评论详情-管理端
     * @param id 互动回答或评论id
     * @return 互动回答或评论详情-管理端
     */
    @Override
    public ReplyVO queryReplyVoByIdAdmin(Long id) {
        // 1.根据id查询
        InteractionReply r = getById(id);
        if (r==null) throw new BadRequestException("数据不存在");
        // 2.数据处理,需要查询用户信息、评论目标信息、当前用户是否点赞
        Set<Long> userIds = new HashSet<>();
        // 2.1.获取用户 id
        userIds.add(r.getUserId());
        // 2.2.查询评论目标,如果评论目标不是匿名,则需要查询出目标回复的用户id
        if (r.getTargetReplyId() != null && r.getTargetReplyId() != 0) {
            InteractionReply target = getById(r.getTargetReplyId());
            if (!target.getAnonymity()) {
                userIds.add(target.getUserId());
            }
        }
        // 2.3.查询用户详细
        Map<Long, UserDTO> userMap = new HashMap<>(userIds.size());
        if (userIds.size() > 0) {
            List<UserDTO> users = userClient.queryUserByIds(userIds);
            userMap = users.stream().collect(Collectors.toMap(UserDTO::getId, u -> u));
        }
        // 2.4.查询用户点赞状态
        //TODO Set<Long> bizLiked = remarkClient.isBizLiked(CollUtils.singletonList(id));

        // 3.处理VO
        // 3.1.拷贝基础属性
        ReplyVO v = BeanUtils.toBean(r, ReplyVO.class);
        // 3.2.回复人信息
        UserDTO userDTO = userMap.get(r.getUserId());
        if (userDTO != null) {
            v.setUserIcon(userDTO.getIcon());
            v.setUserName(userDTO.getName());
            v.setUserType(userDTO.getType());
        }
        // 3.3.目标用户
        UserDTO targetUser = userMap.get(r.getTargetUserId());
        if (targetUser != null) {
            v.setTargetUserName(targetUser.getName());
        }
        // 3.4.点赞状态
        //TODO v.setLiked(bizLiked.contains(id));
        return v;
    }
    
}

测试


4 隐藏或显示指定回答或评论(管理端)

代码实现

learning 中的 InteractionReplyAdminController

java 复制代码
@RestController
@RequestMapping("/admin/replies")
@Api(tags = "管理端评论相关的接口")
@RequiredArgsConstructor
public class InteractionReplyAdminController {
    private final InteractionReplyService replyService;

    @PutMapping("/{id}/hidden/{hidden}")
    @ApiOperation("管理端:显示或隐藏评论|回答")
    public void hiddenReply(@PathVariable("id") Long id, @PathVariable("hidden") Boolean hidden) {
        replyService.hiddenReply(id,hidden);
    }
}

learning 中的 InteractionReplyServiceImpl

java 复制代码
@Service
@RequiredArgsConstructor
public class InteractionReplyServiceImpl extends ServiceImpl<InteractionReplyMapper, InteractionReply>
        implements InteractionReplyService {
    private final InteractionQuestionService questionService;
    private final UserClient userClient;

    /**
     * 根据id查询回答或评论详情-管理端
     * @param id 互动回答或评论id
     * @return 互动回答或评论详情-管理端
     */
    @Override
    public ReplyVO queryReplyVoByIdAdmin(Long id) {
        // 1.根据id查询
        InteractionReply r = getById(id);
        if (r==null) throw new BadRequestException("数据不存在");
        // 2.数据处理,需要查询用户信息、评论目标信息、当前用户是否点赞
        Set<Long> userIds = new HashSet<>();
        // 2.1.获取用户 id
        userIds.add(r.getUserId());
        // 2.2.查询评论目标,如果评论目标不是匿名,则需要查询出目标回复的用户id
        if (r.getTargetReplyId() != null && r.getTargetReplyId() != 0) {
            InteractionReply target = getById(r.getTargetReplyId());
            if (!target.getAnonymity()) {
                userIds.add(target.getUserId());
            }
        }
        // 2.3.查询用户详细
        Map<Long, UserDTO> userMap = new HashMap<>(userIds.size());
        if (userIds.size() > 0) {
            List<UserDTO> users = userClient.queryUserByIds(userIds);
            userMap = users.stream().collect(Collectors.toMap(UserDTO::getId, u -> u));
        }
        // 2.4.查询用户点赞状态
        //TODO Set<Long> bizLiked = remarkClient.isBizLiked(CollUtils.singletonList(id));

        // 3.处理VO
        // 3.1.拷贝基础属性
        ReplyVO v = BeanUtils.toBean(r, ReplyVO.class);
        // 3.2.回复人信息
        UserDTO userDTO = userMap.get(r.getUserId());
        if (userDTO != null) {
            v.setUserIcon(userDTO.getIcon());
            v.setUserName(userDTO.getName());
            v.setUserType(userDTO.getType());
        }
        // 3.3.目标用户
        UserDTO targetUser = userMap.get(r.getTargetUserId());
        if (targetUser != null) {
            v.setTargetUserName(targetUser.getName());
        }
        // 3.4.点赞状态
        //TODO v.setLiked(bizLiked.contains(id));
        return v;
    }
}

测试

相关推荐
BingoGo2 小时前
再推荐 10 个低调但非常实用的 PHP 包
后端·php
北友舰长3 小时前
基于Springboot+thymeleaf图书管理系统的设计与实现【Java毕业设计·安装调试·代码讲解】
java·spring boot·mysql·课程设计·图书管理·b/s·图书
KD6 小时前
设计模式——责任链模式实战,优雅处理Kafka消息
后端·设计模式·kafka
陈文锦丫10 小时前
MQ的学习
java·开发语言
乌暮10 小时前
JavaEE初阶---线程安全问题
java·java-ee
爱笑的眼睛1110 小时前
GraphQL:从数据查询到应用架构的范式演进
java·人工智能·python·ai
Seven9711 小时前
剑指offer-52、正则表达式匹配
java
代码or搬砖11 小时前
RBAC(权限认证)小例子
java·数据库·spring boot
青蛙大侠公主11 小时前
Thread及其相关类
java·开发语言