parent
2a42c9de00
commit
30a1d1f557
20 changed files with 1114 additions and 11 deletions
@ -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; |
||||
|
||||
|
||||
} |
@ -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; |
||||
|
||||
|
||||
} |
@ -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; |
||||
|
||||
} |
@ -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…
Reference in new issue