天机学堂-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;
    }
}

测试

相关推荐
曹牧22 分钟前
文档格式:OFD
java
豆角焖肉1 小时前
Maven进阶与搭建私服
java·maven
大不点wow1 小时前
Java序列化与反序列化:让对象走出JVM
java·开发语言·jvm
止语Lab1 小时前
好的 DX 不等于少写代码——三种语言的摩擦力设计课
后端
吃饱了得干活1 小时前
别再手动解析 LLM 输出了!LangChain 四种结构化输出方案对比
后端·python·langchain
噢,我明白了1 小时前
Java中日期和字符串的处理
java·开发语言·日期
程序员天天困1 小时前
Arthas trace 命令怎么用?一行定位最慢那行代码
jvm·后端
Huiturn1 小时前
GPT 5.6 连续编码 10 小时,纯 Python 啃下 Word 二进制格式——doc2docx 实现拆解
后端
dkbnull1 小时前
Spring Boot请求处理组件对比详解
java·spring boot
jun_bai1 小时前
Orthanc服务器使用java上传dicom影像文件
java·运维·服务器