课程表部分字段类型修改

消息模块功能(用户收件箱,发件箱,已读/未读数据显示,消息逻辑删除,消息批量已读)
master
Alan 3 months ago
parent 2a42c9de00
commit 30a1d1f557
  1. 3
      src/main/java/com/teaching/backend/common/ErrorCode.java
  2. 79
      src/main/java/com/teaching/backend/controller/message/MessagesController.java
  3. 83
      src/main/java/com/teaching/backend/controller/message/UserInboxController.java
  4. 16
      src/main/java/com/teaching/backend/mapper/message/MessagesMapper.java
  5. 19
      src/main/java/com/teaching/backend/mapper/message/UserInboxMapper.java
  6. 14
      src/main/java/com/teaching/backend/model/dto/message/SysMessageDTO.java
  7. 56
      src/main/java/com/teaching/backend/model/entity/message/SysMessages.java
  8. 50
      src/main/java/com/teaching/backend/model/entity/message/UserInbox.java
  9. 6
      src/main/java/com/teaching/backend/model/query/CourseQuery.java
  10. 24
      src/main/java/com/teaching/backend/model/query/MessagesQuery.java
  11. 1
      src/main/java/com/teaching/backend/model/query/PageQuery.java
  12. 53
      src/main/java/com/teaching/backend/model/vo/message/SysMessageVO.java
  13. 36
      src/main/java/com/teaching/backend/model/vo/message/UserCheckMessageVO.java
  14. 21
      src/main/java/com/teaching/backend/model/vo/message/UserReadMessageTimeVO.java
  15. 14
      src/main/java/com/teaching/backend/service/impl/courses/CoursesServiceImpl.java
  16. 134
      src/main/java/com/teaching/backend/service/impl/message/MessagesServiceImpl.java
  17. 445
      src/main/java/com/teaching/backend/service/impl/message/UserInboxServiceImpl.java
  18. 27
      src/main/java/com/teaching/backend/service/message/IMessagesService.java
  19. 32
      src/main/java/com/teaching/backend/service/message/IUserInboxService.java
  20. 12
      src/main/resources/mapper/UserInboxMapper.xml

@ -20,7 +20,8 @@ public enum ErrorCode {
CONTENT_NOT_EXIT(40008, "内容id不存在"),
KNOWS_EXIT(40009, "该项下面存在关联的知识点,请在删除关联的知识点后再来操作!"),
INVALID_ROLE(400010, "角色不存在"),
MESSAGE_NO_READ(400011, "消息未读,禁止删除!"),
MESSAGE_NO_EXIT(400012, "消息不存在!"),
NOT_LOGIN_ERROR(40100, "未登录"),
NO_AUTH_ERROR(40101, "无权限"),
NOT_FOUND_ERROR(40400, "请求数据不存在"),

@ -0,0 +1,79 @@
package com.teaching.backend.controller.message;
import com.teaching.backend.common.BaseResponse;
import com.teaching.backend.common.ResultUtils;
import com.teaching.backend.filter.ValidateParams;
import com.teaching.backend.model.dto.courses.PageDTO;
import com.teaching.backend.model.dto.message.SysMessageDTO;
import com.teaching.backend.model.entity.message.SysMessages;
import com.teaching.backend.model.query.CourseQuery;
import com.teaching.backend.model.query.MessagesQuery;
import com.teaching.backend.model.vo.courses.CoursesVO;
import com.teaching.backend.model.vo.message.SysMessageVO;
import com.teaching.backend.service.message.IMessagesService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.util.List;
/**
* <p>
* 前端控制器
* </p>
*
* @author zjh
* @since 2024-08-06
*/
@Api(tags = "系统消息管理接口")
@RestController
@RequestMapping("/messages")
public class MessagesController {
@Autowired
private IMessagesService messagesService;
@ApiOperation("发送消息")
@ValidateParams({"senderId","title","content","receiverId"}) // 需要校验的参数
@PostMapping("/addmessage")
public BaseResponse<String> sendMessage(@RequestBody SysMessageDTO sysMessageDTO){
String data = messagesService.sendMessageToUserInbox(sysMessageDTO);
return ResultUtils.success(data);
}
//TODO 功能待完善
@ApiOperation("删除发件箱的消息--批删--逻辑删除")
@ValidateParams({"messageIds"}) // 需要校验的参数
@DeleteMapping ("/deletesendmessage")
public BaseResponse<String> deleteMessages(@RequestParam List<Long> messageIds){
String data = messagesService.deleteSendMessagesByLogical(messageIds);
return ResultUtils.success(data);
}
@ApiOperation("根据id查询消息")
@ValidateParams({"id"}) // 需要校验的参数
@GetMapping ("/getmessage/{id}")
public BaseResponse<SysMessages> getMessageById(@PathVariable("id") Long id){
SysMessages data = messagesService.getById(id);
return ResultUtils.success(data);
}
/**
* 修改消息
* @param sysMessageDTO
* @return
*/
@ApiOperation("修改消息--仅限于未发送成功的消息(草稿功能)")
@PutMapping ("/modifymessage")
public BaseResponse<String> modifyMessage(@RequestBody SysMessageDTO sysMessageDTO){
boolean b = messagesService.updateById(sysMessageDTO);
return ResultUtils.success(b ? "修改成功" : "修改失败");
}
}

@ -0,0 +1,83 @@
package com.teaching.backend.controller.message;
import com.teaching.backend.common.BaseResponse;
import com.teaching.backend.common.ResultUtils;
import com.teaching.backend.filter.ValidateParams;
import com.teaching.backend.model.dto.courses.PageDTO;
import com.teaching.backend.model.query.MessagesQuery;
import com.teaching.backend.model.vo.message.SysMessageVO;
import com.teaching.backend.service.message.IUserInboxService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* <p>
* 前端控制器
* </p>
*
* @author zjh
* @since 2024-08-06
*/
@Api(tags = "用户信箱管理接口")
@RestController
@RequestMapping("/user-inbox")
public class UserInboxController {
@Autowired
private IUserInboxService userInboxService;
@ApiOperation("用户分页查看个人消息(收件箱)")
@ValidateParams({"userId","isDelete"}) // 需要校验的参数
@GetMapping("/page/receivemessages")
public BaseResponse<PageDTO<SysMessageVO>> getMessages(MessagesQuery messagesQuery){
PageDTO<SysMessageVO> messageList = userInboxService.queryReceiveMessages(messagesQuery);
return ResultUtils.success(messageList);
}
@ApiOperation("用户分页查看个人消息(发件箱)")
@ValidateParams({"userId","isDelete","isSend"})
@GetMapping("/page/sendmessages")
public BaseResponse<PageDTO<SysMessageVO>> getSendMessages(MessagesQuery messagesQuery){
PageDTO<SysMessageVO> messageList = userInboxService.querySendMessages(messagesQuery);
return ResultUtils.success(messageList);
}
//用户查看消息详情,如果是第一次查看,则会更新“已读状态”和“阅读时间”
@ApiOperation("查看消息详情")
@ValidateParams({"userId","messageId"}) // 需要校验的参数
@GetMapping("/getmessagedetails")
public BaseResponse<SysMessageVO> getMessageDetail(MessagesQuery messagesQuery){
SysMessageVO userCheckMessageVO = userInboxService.getMessageDetail(messagesQuery);
return ResultUtils.success(userCheckMessageVO);
}
@ApiOperation("获取已读/未读用户集合")
@ValidateParams({"userId", "messageId"})
@GetMapping("/message/readstatus")
public BaseResponse<SysMessageVO> getMessageReadStatus(@RequestParam Long userId, @RequestParam Long messageId) {
SysMessageVO messageVO = userInboxService.getReadStatus(userId, messageId);
return ResultUtils.success(messageVO);
}
@ApiOperation("一键已读")
@PutMapping ("/readmessagesbatch")
public BaseResponse<String> readMessagesBatch(@RequestParam List<Long> messageIds, @RequestParam Long userId){
String data = userInboxService.readMessagesBatch(messageIds,userId);
return ResultUtils.success(data);
}
@ApiOperation("删除收件箱的消息--批删--逻辑删除")
@ValidateParams({"messageIds","userId"}) // 需要校验的参数
@DeleteMapping ("/deletereceivemessage")
public BaseResponse<String> deleteReceiveMessages(@RequestParam List<Long> messageIds,@RequestParam Long userId){
String data = userInboxService.deleteReceiveMessagesByLogical(messageIds,userId);
return ResultUtils.success(data);
}
}

@ -0,0 +1,16 @@
package com.teaching.backend.mapper.message;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.teaching.backend.model.entity.message.SysMessages;
/**
* <p>
* Mapper 接口
* </p>
*
* @author zjh
* @since 2024-08-06
*/
public interface MessagesMapper extends BaseMapper<SysMessages> {
}

@ -0,0 +1,19 @@
package com.teaching.backend.mapper.message;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.teaching.backend.model.entity.message.UserInbox;
import java.util.List;
/**
* <p>
* Mapper 接口
* </p>
*
* @author zjh
* @since 2024-08-06
*/
public interface UserInboxMapper extends BaseMapper<UserInbox> {
boolean insertBatchInBox(List<UserInbox> userInboxes);
}

@ -0,0 +1,14 @@
package com.teaching.backend.model.dto.message;
import com.teaching.backend.model.entity.message.SysMessages;
import io.swagger.annotations.ApiModel;
import lombok.Data;
@Data
@ApiModel(description = "教师创建课程参数实体")
public class SysMessageDTO extends SysMessages {
/**
* 收件人id集合
*/
private String receiverId;
}

@ -0,0 +1,56 @@
package com.teaching.backend.model.entity.message;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.time.LocalDateTime;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* <p>
*
* </p>
*
* @author zjh
* @since 2024-08-06
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("sys_messages")
@ApiModel(value="SysMessages对象", description="")
public class SysMessages implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@ApiModelProperty(value = "发件人id")
private Long senderId;
@ApiModelProperty(value = "课程id")
private String courseId;
@ApiModelProperty(value = "消息标题")
private String title;
@ApiModelProperty(value = "消息内容")
private String content;
@ApiModelProperty(value = "发送时间")
private LocalDateTime sendTime;
@ApiModelProperty(value = "是否删除(逻辑删除)")
private Integer isDelete;
@ApiModelProperty(value = "是否发送(未发送的存草稿)")
private Boolean isSend;
}

@ -0,0 +1,50 @@
package com.teaching.backend.model.entity.message;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.time.LocalDateTime;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* <p>
*
* </p>
*
* @author zjh
* @since 2024-08-06
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("user_inbox")
@ApiModel(value="UserInbox对象", description="")
public class UserInbox implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@ApiModelProperty(value = "消息id")
private Long messageId;
@ApiModelProperty(value = "接收人id")
private Long receiverId;
@ApiModelProperty(value = "消息查看时间")
private LocalDateTime readTime;
@ApiModelProperty(value = "是否已读(0没有,1有)")
private Boolean isRead;
@ApiModelProperty(value = "是否删除(0没有,1有)")
private Boolean isDelete;
}

@ -25,11 +25,11 @@ public class CourseQuery extends PageQuery {
private String teacher;
@ApiModelProperty("课程类别")
private String category;
private Integer category;
@ApiModelProperty("课程性质")
private String nature;
private Integer nature;
@ApiModelProperty("课程考核类型")
private String assessmenttype;
private Integer assessmenttype;
}

@ -0,0 +1,24 @@
package com.teaching.backend.model.query;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
@ApiModel(description = "系统消息查询条件实体")
public class MessagesQuery extends PageQuery {
@ApiModelProperty(value = "用户的userId",required = true)
private Long userId;
@ApiModelProperty(value = "消息id")
private Long messageId;
@ApiModelProperty(value = "是否发送 false没有 true已发送")
private Boolean isSend;
@ApiModelProperty(value = "是否已读 false没有 true已读 可以作为消息筛选条件 用户不选这个就不用传")
private Boolean isRead;
@ApiModelProperty(value = "是否删除 0没有 1回收站 2回收站已删除(发件人不可见,收件人可见)")
private Integer isDelete;
}

@ -41,4 +41,5 @@ public class PageQuery {
public <T> Page<T> toMpPageDefaultSortByUpdateTime(){
return toMpPage(new OrderItem("update_time", false));
}
}

@ -0,0 +1,53 @@
package com.teaching.backend.model.vo.message;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
@Data
public class SysMessageVO {
@ApiModelProperty("id")
private Long id;
@ApiModelProperty("课程id")
private String courseId;
@ApiModelProperty("课程名称")
private String courseName;
@ApiModelProperty(value = "发件人id")
private Long senderId;
@ApiModelProperty(value = "发件人name")
private String senderName;
@ApiModelProperty(value = "消息标题")
private String title;
@ApiModelProperty(value = "消息内容")
private String content;
@ApiModelProperty(value = "发送时间")
private LocalDateTime sendTime;
@ApiModelProperty(value = "收信总人数")
private Long userNum;
@ApiModelProperty(value = "已读用户人数")
private Long readUserNum;
@ApiModelProperty(value = "收件用户信息集合")
private List<UserReadMessageTimeVO> receiveUsers;
@ApiModelProperty(value = "是否已读(0没有,1有)")
private Boolean isRead;
@ApiModelProperty(value = "已读用户集合")
private List<UserReadMessageTimeVO> readUsers;
@ApiModelProperty(value = "未读用户集合")
private List<UserReadMessageTimeVO> noReadUsers;
}

@ -0,0 +1,36 @@
package com.teaching.backend.model.vo.message;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class UserCheckMessageVO {
@ApiModelProperty("id")
private Long id;
@ApiModelProperty("课程id")
private String courseId;
@ApiModelProperty("课程名称")
private String courseName;
@ApiModelProperty(value = "发件人id")
private Long senderId;
@ApiModelProperty(value = "发件人name")
private String senderName;
@ApiModelProperty(value = "消息标题")
private String title;
@ApiModelProperty(value = "消息内容")
private String content;
@ApiModelProperty(value = "发送时间")
private LocalDateTime sendTime;
@ApiModelProperty(value = "是否已读(0没有,1有)")
private Boolean isRead;
}

@ -0,0 +1,21 @@
package com.teaching.backend.model.vo.message;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
@Data
public class UserReadMessageTimeVO {
@ApiModelProperty(value = "接收人id")
private Long id;
@ApiModelProperty(value = "接收人name")
private String receiverName;
@ApiModelProperty(value = "消息查看时间")
private LocalDateTime readTime;
}

@ -195,10 +195,10 @@ public class CoursesServiceImpl extends ServiceImpl<CoursesMapper, Courses> impl
Page<Courses> p = lambdaQuery()
.like(courseQuery.getName() != null, Courses::getName, courseQuery.getName())
.apply("FIND_IN_SET({0}, teacher)", courseQuery.getUserId())
.eq(StringUtils.hasText(courseQuery.getCategory()), Courses::getCategory, courseQuery.getCategory())
// .eq(courseQuery.getCategory() != null && !courseQuery.getCategory().isEmpty(), Courses::getCategory, courseQuery.getCategory())
.eq(courseQuery.getNature() != null && !courseQuery.getNature().isEmpty(), Courses::getNature, courseQuery.getNature())
.eq(courseQuery.getAssessmenttype() != null &&!courseQuery.getAssessmenttype().isEmpty(), Courses::getAssessmenttype, courseQuery.getAssessmenttype())
// .eq(StringUtils.hasText(courseQuery.getCategory()), Courses::getCategory, courseQuery.getCategory())
.eq(courseQuery.getCategory() != null, Courses::getCategory, courseQuery.getCategory())
.eq(courseQuery.getNature() != null, Courses::getNature, courseQuery.getNature())
.eq(courseQuery.getAssessmenttype() != null, Courses::getAssessmenttype, courseQuery.getAssessmenttype())
.select(Courses::getId,Courses::getTeacher,Courses::getImg,Courses::getName,Courses::getCredit,Courses::getClasshours)
.page(page);
return PageDTO.of(p,CoursesVO.class);
@ -222,9 +222,9 @@ public class CoursesServiceImpl extends ServiceImpl<CoursesMapper, Courses> impl
Page<Courses> page = courseQuery.toMpPageDefaultSortByCreateTime();
Page<Courses> p = lambdaQuery()
.like(courseQuery.getName() != null && !courseQuery.getName().isEmpty(), Courses::getName, courseQuery.getName())
.eq(courseQuery.getCategory() != null && !courseQuery.getCategory().isEmpty(), Courses::getCategory, courseQuery.getCategory())
.eq(courseQuery.getNature() != null && !courseQuery.getNature().isEmpty(), Courses::getNature, courseQuery.getNature())
.eq(courseQuery.getAssessmenttype() != null &&!courseQuery.getAssessmenttype().isEmpty(), Courses::getAssessmenttype, courseQuery.getAssessmenttype())
.eq(courseQuery.getCategory() != null, Courses::getCategory, courseQuery.getCategory())
.eq(courseQuery.getNature() != null, Courses::getNature, courseQuery.getNature())
.eq(courseQuery.getAssessmenttype() != null, Courses::getAssessmenttype, courseQuery.getAssessmenttype())
.apply(courseQuery.getTeacher() != null && !courseQuery.getTeacher().isEmpty(), "FIND_IN_SET({0}, teacher)", courseQuery.getTeacher())
.select(Courses::getId,Courses::getTeacher,Courses::getImg,Courses::getName,Courses::getCredit,Courses::getClasshours)
.page(page);

@ -0,0 +1,134 @@
package com.teaching.backend.service.impl.message;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.teaching.backend.common.ErrorCode;
import com.teaching.backend.exception.BusinessException;
import com.teaching.backend.mapper.message.MessagesMapper;
import com.teaching.backend.mapper.message.UserInboxMapper;
import com.teaching.backend.model.dto.message.SysMessageDTO;
import com.teaching.backend.model.entity.message.SysMessages;
import com.teaching.backend.model.entity.message.UserInbox;
import com.teaching.backend.service.message.IMessagesService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
/**
* <p>
* 服务实现类
* </p>
*
* @author zjh
* @since 2024-08-06
*/
@Service
@Slf4j
public class MessagesServiceImpl extends ServiceImpl<MessagesMapper, SysMessages> implements IMessagesService {
@Autowired
private UserInboxMapper userInboxMapper;
@Override
@Transactional
public String sendMessageToUserInbox(SysMessageDTO sysMessageDTO) {
// 1.数据非空校验(已完成)
// 2.消息ID检查,如果存在,说明是草稿箱编辑过的消息,否则生成新的ID
Long messageId = Optional.ofNullable(sysMessageDTO.getId())
.orElseGet(() -> System.currentTimeMillis() + ThreadLocalRandom.current().nextLong(1000));
// 3.解析传过来的receiverId
List<Long> receiverIds = Arrays.stream(sysMessageDTO.getReceiverId().split(","))
.map(Long::valueOf)
.collect(Collectors.toList());
// 4.数据写入收件箱
List<UserInbox> userInboxes = receiverIds.stream()
.map(receiverId -> {
UserInbox userInbox = new UserInbox();
userInbox.setMessageId(messageId);
userInbox.setReceiverId(receiverId);
return userInbox;
})
.collect(Collectors.toList());
// 执行批量插入操作,并判断是否成功
boolean inboxInsertSuccess = userInboxMapper.insertBatchInBox(userInboxes);
if (!inboxInsertSuccess) {
throw new BusinessException(ErrorCode.OPERATION_ERROR,"收件箱数据插入失败!");
}
// 5.更新或保存消息数据
SysMessages sysMessages = new SysMessages();
BeanUtils.copyProperties(sysMessageDTO, sysMessages);
sysMessages.setId(messageId);
sysMessages.setSendTime(LocalDateTime.now());
sysMessages.setIsSend(true);
boolean messageSaveSuccess = updateById(sysMessages);
if (!messageSaveSuccess) {
throw new BusinessException(ErrorCode.OPERATION_ERROR,"消息保存失败!");
}
return "消息发送成功!";
}
/**
* 发件箱的删除
*
* @param messageIds 消息ID列表
* @return 删除结果
*/
@Override
@Transactional
public String deleteSendMessagesByLogical(List<Long> messageIds) {
for (Long messageId : messageIds) {
// 1.查询消息体
SysMessages message = query().getBaseMapper().selectById(messageId);
if (message == null) {
log.error("消息未找到,消息id:{}", messageId);
continue;
}
// 2.根据消息状态处理删除逻辑
switch (message.getIsDelete()) {
case 0: // 未删除状态
if (Boolean.FALSE.equals(message.getIsSend())) {
// 未发送,物理删除
if (query().getBaseMapper().deleteById(messageId) < 1) {
log.error("删除失败,消息id:{}", messageId);
}
} else {
// 已发送,标记为回收站
updateMessageDeleteStatus(message, 1);
}
break;
case 1: // 回收站状态
// 标记为彻底删除
updateMessageDeleteStatus(message, 2);
break;
default:
log.warn("未知删除状态,消息id:{}", messageId);
break;
}
}
return "删除成功";
}
private void updateMessageDeleteStatus(SysMessages message, int deleteStatus) {
message.setIsDelete(deleteStatus);
if (query().getBaseMapper().updateById(message) < 1) {
log.error("删除失败,消息id:{}", message.getId());
}
}
}

@ -0,0 +1,445 @@
package com.teaching.backend.service.impl.message;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.teaching.backend.common.ErrorCode;
import com.teaching.backend.exception.BusinessException;
import com.teaching.backend.mapper.courses.CoursesMapper;
import com.teaching.backend.mapper.message.UserInboxMapper;
import com.teaching.backend.mapper.umsAdmin.UmsStudentMapper;
import com.teaching.backend.mapper.umsAdmin.UmsTeacherMapper;
import com.teaching.backend.model.dto.courses.PageDTO;
import com.teaching.backend.model.entity.courses.Courses;
import com.teaching.backend.model.entity.message.SysMessages;
import com.teaching.backend.model.entity.message.UserInbox;
import com.teaching.backend.model.entity.umsAdmin.UmsStudent;
import com.teaching.backend.model.entity.umsAdmin.UmsTeacher;
import com.teaching.backend.model.query.MessagesQuery;
import com.teaching.backend.model.vo.message.SysMessageVO;
import com.teaching.backend.model.vo.message.UserReadMessageTimeVO;
import com.teaching.backend.service.message.IMessagesService;
import com.teaching.backend.service.message.IUserInboxService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* <p>
* 服务实现类
* </p>
*
* @author zjh
* @since 2024-08-06
*/
@Service
@Slf4j
public class UserInboxServiceImpl extends ServiceImpl<UserInboxMapper, UserInbox> implements IUserInboxService {
@Autowired
private UmsTeacherMapper umsTeacherMapper;
@Autowired
private UmsStudentMapper umsStudentMapper;
@Autowired
private CoursesMapper coursesMapper;
@Autowired
private IMessagesService messagesService;
@Autowired
private UserInboxMapper userInboxMapper;
//TODO 不需要特别指定“已读”或者是“未读”
@Override
public PageDTO<SysMessageVO> queryReceiveMessages(MessagesQuery messagesQuery) {
// 先按用户的id找到其的消息列表 默认看未删除的,(是否读 作为筛选条件后传进去)
LambdaQueryWrapper<UserInbox> userInboxQueryWrapper = new LambdaQueryWrapper<>();
userInboxQueryWrapper
.eq(UserInbox::getReceiverId, messagesQuery.getUserId())
.eq(messagesQuery.getIsRead() != null,UserInbox::getIsRead,messagesQuery.getIsRead())
.eq(UserInbox::getIsDelete, messagesQuery.getIsDelete());
List<UserInbox> userInboxes = userInboxMapper.selectList(userInboxQueryWrapper);
if (userInboxes.isEmpty()){
throw new BusinessException(ErrorCode.MESSAGE_NO_EXIT);
}
Map<Long, Boolean> messageReadStatusMap = userInboxes.stream()
.collect(Collectors.toMap(UserInbox::getMessageId, UserInbox::getIsRead));
List<Long> messageIds = new ArrayList<>(messageReadStatusMap.keySet());
Page<SysMessages> page = messagesQuery.toMpPage("send_time", false);
// 根据条件查询SysMessages表
Page<SysMessages> p = messagesService.page(page,
new LambdaQueryWrapper<SysMessages>()
.in(SysMessages::getId,messageIds)
.select(SysMessages::getId,SysMessages::getCourseId,SysMessages::getTitle,SysMessages::getSenderId,SysMessages::getSendTime)
);
// 将Page<SysMessages>转换为PageDTO<SysMessageVO>
PageDTO<SysMessageVO> messages = PageDTO.of(p, SysMessageVO.class);
// PageDTO<SysMessageVO> messages = PageDTO.of(p, message -> {
// SysMessageVO vo = new SysMessageVO();
// BeanUtil.copyProperties(message, vo, CopyOptions.create().setIgnoreProperties(SysMessageVO::getContent));
// return vo;
// });
// 获取PageDTO中的SysMessageVO列表
List<SysMessageVO> messagesList = messages.getList();
// 填充附加数据
for (SysMessageVO messageVO : messagesList) {
//获取发件人信息
UmsTeacher umsTeacher = umsTeacherMapper.selectOne(
new LambdaQueryWrapper<UmsTeacher>()
.eq(UmsTeacher::getUserId, messageVO.getSenderId()));
//没有这个教师那说明就是学生
if (umsTeacher == null) {
messageVO.setSenderName(umsStudentMapper.selectOne(
new LambdaQueryWrapper<UmsStudent>()
.eq(UmsStudent::getUserId, messageVO.getSenderId())
).getName());
} else {
messageVO.setSenderName(umsTeacher.getName());
}
Courses course = coursesMapper.selectOne(new LambdaQueryWrapper<Courses>()
.eq(Courses::getId, messageVO.getCourseId()));
if (course != null) {
messageVO.setCourseName(course.getName());
}
// 设置isRead字段
Boolean isRead = messageReadStatusMap.get(messageVO.getId());
messageVO.setIsRead(isRead != null ? isRead : false);
}
// 设置消息列表并返回
messages.setList(messagesList);
return messages;
}
@Override
public PageDTO<SysMessageVO> querySendMessages(MessagesQuery messagesQuery) {
// 初始化一个按发送时间降序排序的Page对象
Page<SysMessages> page = messagesQuery.toMpPage("send_time", false);
// 根据条件查询SysMessages表
Page<SysMessages> p = messagesService.page(page,
new LambdaQueryWrapper<SysMessages>()
.eq(SysMessages::getSenderId, messagesQuery.getUserId())
.eq(SysMessages::getIsSend, messagesQuery.getIsSend())
.eq(SysMessages::getIsDelete, messagesQuery.getIsDelete())
.select(SysMessages::getId,SysMessages::getCourseId,SysMessages::getTitle,SysMessages::getSendTime));
// 将Page<SysMessages>转换为PageDTO<SysMessageVO>
// PageDTO<SysMessageVO> messages = PageDTO.of(p, sysMessages -> {
// SysMessageVO vo = new SysMessageVO();
// BeanUtil.copyProperties(sysMessages, vo, CopyOptions.create().setIgnoreProperties(SysMessageVO::getSenderId));
// return vo;
// });
PageDTO<SysMessageVO> messages = PageDTO.of(p, SysMessageVO.class);
// 获取PageDTO中的SysMessageVO列表
List<SysMessageVO> messagesList = messages.getList();
if (messagesList.isEmpty()) {
throw new BusinessException(ErrorCode.MESSAGE_NO_EXIT);
}
// 遍历每个消息以填充附加数据
for (SysMessageVO sysMessageVO : messagesList) {
// 设置课程名称
if (!StringUtils.isEmpty(sysMessageVO.getCourseId())) {
Courses courses = coursesMapper.selectById(sysMessageVO.getCourseId());
if (courses != null) {
sysMessageVO.setCourseName(courses.getName());
}
}
// 查询UserInbox以获取当前消息的所有收件人数量
Long totalReceiverCount = userInboxMapper.selectCount(
new LambdaQueryWrapper<UserInbox>()
.eq(UserInbox::getMessageId, sysMessageVO.getId())
);
sysMessageVO.setUserNum(totalReceiverCount); // 设置收信总人数
// 查询前5个UserInbox以获取当前消息的收件人列表
List<UserInbox> userInboxes = userInboxMapper.selectList(
new LambdaQueryWrapper<UserInbox>()
.eq(UserInbox::getMessageId, sysMessageVO.getId())
.select(UserInbox::getReceiverId, UserInbox::getIsRead)
.last("LIMIT 5")
);
// 设置收件用户集合
List<UserReadMessageTimeVO> receiveUsers = userInboxes.stream().map(userInbox -> {
UserReadMessageTimeVO vo = new UserReadMessageTimeVO();
vo.setId(userInbox.getReceiverId());
UmsStudent umsStudent = umsStudentMapper.selectOne(
new LambdaQueryWrapper<UmsStudent>()
.eq(UmsStudent::getUserId, userInbox.getReceiverId()));
if (umsStudent == null) {
vo.setReceiverName(umsTeacherMapper.selectOne(
new LambdaQueryWrapper<UmsTeacher>()
.eq(UmsTeacher::getUserId, userInbox.getReceiverId())
).getName());
} else {
vo.setReceiverName(umsStudent.getName());
}
return vo;
}).collect(Collectors.toList());
sysMessageVO.setReceiveUsers(receiveUsers); // 设置收件人信息
// 计算已读用户人数
long readUserCount = userInboxes.stream()
.filter(UserInbox::getIsRead)
.count();
sysMessageVO.setReadUserNum(readUserCount);
}
// 更新PageDTO中的消息列表并返回
messages.setList(messagesList);
return messages;
}
@Override
public SysMessageVO getMessageDetail(MessagesQuery messagesQuery) {
SysMessages sysMessage = messagesService.getById(messagesQuery.getMessageId());
SysMessageVO sysMessageVO = new SysMessageVO();
// BeanUtil.copyProperties(sysMessage, sysMessageVO);
sysMessageVO.setId(messagesQuery.getMessageId());
sysMessageVO.setContent(sysMessage.getContent());
// 设置课程名称 列表已查 前端自己去拿
// if (!StringUtils.isEmpty(sysMessage.getCourseId())) {
// Courses courses = coursesMapper.selectById(sysMessage.getCourseId());
// if (courses != null) {
// sysMessageVO.setCourseName(courses.getName());
// }
// }
sysMessageVO.setSenderId(messagesQuery.getUserId());
// 获取发件人信息
UmsTeacher umsTeacher = umsTeacherMapper.selectOne(
new LambdaQueryWrapper<UmsTeacher>()
.eq(UmsTeacher::getUserId, sysMessage.getSenderId()));
if (umsTeacher == null) {
sysMessageVO.setSenderName(umsStudentMapper.selectOne(
new LambdaQueryWrapper<UmsStudent>()
.eq(UmsStudent::getUserId, sysMessage.getSenderId())
).getName());
} else {
sysMessageVO.setSenderName(umsTeacher.getName());
}
// 根据当前用户是发件人还是收件人决定查询的内容
if (sysMessage.getSenderId().equals(messagesQuery.getUserId())) {
// 发件人查看详情,查询所有收件人信息
List<UserInbox> userInboxes = userInboxMapper.selectList(
new LambdaQueryWrapper<UserInbox>()
.eq(UserInbox::getMessageId, messagesQuery.getMessageId())
);
List<UserReadMessageTimeVO> receiveUsers = userInboxes.stream().map(userInbox -> {
UserReadMessageTimeVO vo = new UserReadMessageTimeVO();
vo.setId(userInbox.getReceiverId());
UmsStudent umsStudent = umsStudentMapper.selectOne(
new LambdaQueryWrapper<UmsStudent>()
.eq(UmsStudent::getUserId, userInbox.getReceiverId()));
if (umsStudent == null) {
vo.setReceiverName(umsTeacherMapper.selectOne(
new LambdaQueryWrapper<UmsTeacher>()
.eq(UmsTeacher::getUserId, userInbox.getReceiverId())
).getName());
} else {
vo.setReceiverName(umsStudent.getName());
}
vo.setReadTime(userInbox.getReadTime());
return vo;
}).collect(Collectors.toList());
sysMessageVO.setReceiveUsers(receiveUsers);
} else {
// 收件人查看详情,无需再次查询收件人信息,前端可复用列表中已查询到的部分数据
UserInbox userInbox = userInboxMapper.selectOne(
new LambdaQueryWrapper<UserInbox>()
.eq(UserInbox::getMessageId, messagesQuery.getMessageId())
.eq(UserInbox::getReceiverId, messagesQuery.getUserId())
);
if (userInbox != null) {
if (userInbox.getReadTime() == null) {
userInbox.setReadTime(LocalDateTime.now());
}
if (!userInbox.getIsRead()) {
userInbox.setIsRead(true);
}
sysMessageVO.setIsRead(userInbox.getIsRead());
userInboxMapper.updateById(userInbox);
}
}
return sysMessageVO;
}
/**
* 收件箱消息删除逻辑删除
*
* @param messageIds 消息ID列表
* @param userId 用户ID
* @return 删除结果
*/
@Override
@Transactional
public String deleteReceiveMessagesByLogical(List<Long> messageIds, Long userId) {
for (Long messageId : messageIds) {
UserInbox userInbox = getUserInboxByMessageIdAndUserId(messageId, userId);
if (userInbox == null) {
log.error("未找到收件箱消息,消息id:{},用户id:{}", messageId, userId);
continue;
}
if (!userInbox.getIsRead()) {
log.error("此消息未读:{}", messageId);
throw new BusinessException(ErrorCode.MESSAGE_NO_READ);
}
if (!userInbox.getIsDelete()) {
userInbox.setIsDelete(true);
userInboxMapper.updateById(userInbox);
} else {
userInboxMapper.deleteById(userInbox);
}
}
return "删除成功!";
}
/**
* 一键已读
*
* @param messageIds 消息ID列表
* @param userId 用户ID
* @return 操作结果
*/
@Override
@Transactional
public String readMessagesBatch(List<Long> messageIds, Long userId) {
for (Long messageId : messageIds) {
UserInbox userInbox = getUserInboxByMessageIdAndUserId(messageId, userId);
if (userInbox == null) {
log.error("未找到收件箱消息,消息id:{},用户id:{}", messageId, userId);
continue;
}
if (!userInbox.getIsRead()) {
userInbox.setIsRead(true);
userInbox.setReadTime(LocalDateTime.now());
userInboxMapper.updateById(userInbox);
}
}
return "操作成功!";
}
private UserInbox getUserInboxByMessageIdAndUserId(Long messageId, Long userId) {
return userInboxMapper.selectOne(new LambdaQueryWrapper<UserInbox>()
.eq(UserInbox::getMessageId, messageId)
.eq(UserInbox::getReceiverId, userId));
}
/**
*
* @param userId
* @param messageId
* @return
*/
@Override
public SysMessageVO getReadStatus(Long userId, Long messageId) {
// 验证当前用户是否是消息的发件人
SysMessages sysMessages = messagesService.getById(messageId);
if (sysMessages == null || !sysMessages.getSenderId().equals(userId)) {
throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "您没有权限查看此消息的已读/未读用户信息。");
}
SysMessageVO sysMessageVO = new SysMessageVO();
sysMessageVO.setId(messageId);
// 查询 UserInbox 以获取当前消息的收件人列表
List<UserInbox> userInboxes = userInboxMapper.selectList(
new LambdaQueryWrapper<UserInbox>()
.eq(UserInbox::getMessageId, messageId)
.select(UserInbox::getReceiverId, UserInbox::getIsRead, UserInbox::getReadTime)
);
List<Long> receiverIds = userInboxes.stream().map(UserInbox::getReceiverId).collect(Collectors.toList());
sysMessageVO.setUserNum((long) receiverIds.size()); // 设置收信总人数
// 提取已读消息的 UserInbox 并按阅读时间降序排序
List<UserInbox> readUserInboxes = userInboxes.stream()
.filter(UserInbox::getIsRead)
.sorted(Comparator.comparing(UserInbox::getReadTime, Comparator.nullsLast(Comparator.reverseOrder())))
.collect(Collectors.toList());
// 设置已读学生人数
sysMessageVO.setReadUserNum((long) readUserInboxes.size());
// 创建已读用户的 UserReadMessageTimeVO 列表
List<UserReadMessageTimeVO> readStudents = readUserInboxes.stream()
.map(userInbox -> {
UserReadMessageTimeVO vo = new UserReadMessageTimeVO();
vo.setId(userInbox.getReceiverId());
UmsStudent umsStudent = umsStudentMapper.selectOne(
new LambdaQueryWrapper<UmsStudent>()
.eq(UmsStudent::getUserId, userInbox.getReceiverId()));
if (umsStudent == null) {
vo.setReceiverName(umsTeacherMapper.selectOne(
new LambdaQueryWrapper<UmsTeacher>()
.eq(UmsTeacher::getUserId, userInbox.getReceiverId())
).getName());
} else {
vo.setReceiverName(umsStudent.getName());
}
vo.setReadTime(userInbox.getReadTime());
return vo;
})
.collect(Collectors.toList());
// 创建未读用户的 UserReadMessageTimeVO 列表
List<UserReadMessageTimeVO> noReadStudents = receiverIds.stream()
.filter(id -> readUserInboxes.stream().noneMatch(ri -> ri.getReceiverId().equals(id)))
.map(id -> {
UserReadMessageTimeVO vo = new UserReadMessageTimeVO();
vo.setId(id);
UmsStudent umsStudent = umsStudentMapper.selectOne(
new LambdaQueryWrapper<UmsStudent>()
.eq(UmsStudent::getUserId, id));
if (umsStudent == null) {
vo.setReceiverName(umsTeacherMapper.selectOne(
new LambdaQueryWrapper<UmsTeacher>()
.eq(UmsTeacher::getUserId, id)
).getName());
} else {
vo.setReceiverName(umsStudent.getName());
}
return vo;
})
.collect(Collectors.toList());
// 设置已读和未读学生集合
sysMessageVO.setReadUsers(readStudents);
sysMessageVO.setNoReadUsers(noReadStudents);
return sysMessageVO;
}
}

@ -0,0 +1,27 @@
package com.teaching.backend.service.message;
import com.baomidou.mybatisplus.extension.service.IService;
import com.teaching.backend.model.dto.courses.PageDTO;
import com.teaching.backend.model.dto.message.SysMessageDTO;
import com.teaching.backend.model.entity.message.SysMessages;
import com.teaching.backend.model.entity.message.UserInbox;
import com.teaching.backend.model.query.MessagesQuery;
import com.teaching.backend.model.vo.message.SysMessageVO;
import java.util.List;
/**
* <p>
* 服务类
* </p>
*
* @author zjh
* @since 2024-08-06
*/
public interface IMessagesService extends IService<SysMessages> {
String sendMessageToUserInbox(SysMessageDTO sysMessageDTO);
String deleteSendMessagesByLogical(List<Long> messageIds);
}

@ -0,0 +1,32 @@
package com.teaching.backend.service.message;
import com.baomidou.mybatisplus.extension.service.IService;
import com.teaching.backend.model.dto.courses.PageDTO;
import com.teaching.backend.model.entity.message.UserInbox;
import com.teaching.backend.model.query.MessagesQuery;
import com.teaching.backend.model.vo.message.SysMessageVO;
import java.util.List;
/**
* <p>
* 服务类
* </p>
*
* @author zjh
* @since 2024-08-06
*/
public interface IUserInboxService extends IService<UserInbox> {
PageDTO<SysMessageVO> queryReceiveMessages(MessagesQuery messagesQuery);
SysMessageVO getMessageDetail(MessagesQuery messagesQuery);
PageDTO<SysMessageVO> querySendMessages(MessagesQuery messagesQuery);
String readMessagesBatch(List<Long> messageIds, Long userId);
String deleteReceiveMessagesByLogical(List<Long> messageIds, Long userId);
SysMessageVO getReadStatus(Long userId, Long messageId);
}

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.teaching.backend.mapper.message.UserInboxMapper">
<insert id="insertBatchInBox" parameterType="java.util.List">
INSERT INTO user_inbox (message_id, receiver_id)
VALUES
<foreach collection="list" item="item" index="index" separator=",">
(#{item.messageId}, #{item.receiverId})
</foreach>
</insert>
</mapper>
Loading…
Cancel
Save