新增:群聊发送

This commit is contained in:
安浩浩 2024-03-16 15:43:42 +08:00
parent f694825435
commit 9cee1b3ceb
32 changed files with 1322 additions and 70 deletions

View File

@ -17,4 +17,10 @@ public interface ErrorCodeConstants {
// ========== 消息 (1-040-300-000) ==========
ErrorCode MESSAGE_NOT_EXISTS = new ErrorCode(1_040_300_000, "消息不存在");
// ========== (1-040-400-000) ==========
ErrorCode GROUP_NOT_EXISTS = new ErrorCode(1_040_400_000, "群不存在");
// ========== 群成员 (1-040-500-000) ==========
ErrorCode GROUP_MEMBER_NOT_EXISTS = new ErrorCode(1_040_500_000, "群成员不存在");
}

View File

@ -0,0 +1,94 @@
package cn.iocoder.yudao.module.im.controller.admin.group;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.validation.*;
import jakarta.servlet.http.*;
import java.util.*;
import java.io.IOException;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*;
import cn.iocoder.yudao.module.im.controller.admin.group.vo.*;
import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupDO;
import cn.iocoder.yudao.module.im.service.group.ImGroupService;
@Tag(name = "管理后台 - 群")
@RestController
@RequestMapping("/im/group")
@Validated
public class ImGroupController {
@Resource
private ImGroupService imGroupService;
@PostMapping("/create")
@Operation(summary = "创建群")
@PreAuthorize("@ss.hasPermission('im:group:create')")
public CommonResult<Long> createGroup(@Valid @RequestBody ImGroupSaveReqVO createReqVO) {
return success(imGroupService.createGroup(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新群")
@PreAuthorize("@ss.hasPermission('im:group:update')")
public CommonResult<Boolean> updateGroup(@Valid @RequestBody ImGroupSaveReqVO updateReqVO) {
imGroupService.updateGroup(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除群")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('im:group:delete')")
public CommonResult<Boolean> deleteGroup(@RequestParam("id") Long id) {
imGroupService.deleteGroup(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得群")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('im:group:query')")
public CommonResult<ImGroupRespVO> getGroup(@RequestParam("id") Long id) {
ImGroupDO group = imGroupService.getGroup(id);
return success(BeanUtils.toBean(group, ImGroupRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "获得群分页")
@PreAuthorize("@ss.hasPermission('im:group:query')")
public CommonResult<PageResult<ImGroupRespVO>> getGroupPage(@Valid ImGroupPageReqVO pageReqVO) {
PageResult<ImGroupDO> pageResult = imGroupService.getGroupPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, ImGroupRespVO.class));
}
@GetMapping("/export-excel")
@Operation(summary = "导出群 Excel")
@PreAuthorize("@ss.hasPermission('im:group:export')")
@OperateLog(type = EXPORT)
public void exportGroupExcel(@Valid ImGroupPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<ImGroupDO> list = imGroupService.getGroupPage(pageReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "群.xls", "数据", ImGroupRespVO.class,
BeanUtils.toBean(list, ImGroupRespVO.class));
}
}

View File

@ -0,0 +1,39 @@
package cn.iocoder.yudao.module.im.controller.admin.group.vo;
import lombok.*;
import io.swagger.v3.oas.annotations.media.Schema;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 群分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ImGroupPageReqVO extends PageParam {
@Schema(description = "群名字", example = "芋艿")
private String groupName;
@Schema(description = "群主id", example = "31460")
private Long ownerId;
@Schema(description = "群头像")
private String headImage;
@Schema(description = "群头像缩略图")
private String headImageThumb;
@Schema(description = "群公告")
private String notice;
@Schema(description = "群备注", example = "你说的对")
private String remark;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@ -0,0 +1,46 @@
package cn.iocoder.yudao.module.im.controller.admin.group.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.time.LocalDateTime;
import com.alibaba.excel.annotation.*;
@Schema(description = "管理后台 - 群 Response VO")
@Data
@ExcelIgnoreUnannotated
public class ImGroupRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1003")
@ExcelProperty("编号")
private Long id;
@Schema(description = "群名字", example = "芋艿")
@ExcelProperty("群名字")
private String groupName;
@Schema(description = "群主id", requiredMode = Schema.RequiredMode.REQUIRED, example = "31460")
@ExcelProperty("群主id")
private Long ownerId;
@Schema(description = "群头像")
@ExcelProperty("群头像")
private String headImage;
@Schema(description = "群头像缩略图")
@ExcelProperty("群头像缩略图")
private String headImageThumb;
@Schema(description = "群公告")
@ExcelProperty("群公告")
private String notice;
@Schema(description = "群备注", example = "你说的对")
@ExcelProperty("群备注")
private String remark;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间")
private LocalDateTime createTime;
}

View File

@ -0,0 +1,33 @@
package cn.iocoder.yudao.module.im.controller.admin.group.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import jakarta.validation.constraints.*;
@Schema(description = "管理后台 - 群新增/修改 Request VO")
@Data
public class ImGroupSaveReqVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1003")
private Long id;
@Schema(description = "群名字", example = "芋艿")
private String groupName;
@Schema(description = "群主id", requiredMode = Schema.RequiredMode.REQUIRED, example = "31460")
@NotNull(message = "群主id不能为空")
private Long ownerId;
@Schema(description = "群头像")
private String headImage;
@Schema(description = "群头像缩略图")
private String headImageThumb;
@Schema(description = "群公告")
private String notice;
@Schema(description = "群备注", example = "你说的对")
private String remark;
}

View File

@ -0,0 +1,93 @@
package cn.iocoder.yudao.module.im.controller.admin.groupmember;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.module.im.controller.admin.groupmember.vo.ImGroupMemberPageReqVO;
import cn.iocoder.yudao.module.im.controller.admin.groupmember.vo.ImGroupMemberRespVO;
import cn.iocoder.yudao.module.im.controller.admin.groupmember.vo.ImGroupMemberSaveReqVO;
import cn.iocoder.yudao.module.im.dal.dataobject.groupmember.GroupMemberDO;
import cn.iocoder.yudao.module.im.service.groupmember.ImGroupMemberService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
@Tag(name = "管理后台 - 群成员")
@RestController
@RequestMapping("/im/group-member")
@Validated
public class ImGroupMemberController {
@Resource
private ImGroupMemberService imGroupMemberService;
@PostMapping("/create")
@Operation(summary = "创建群成员")
@PreAuthorize("@ss.hasPermission('im:group-member:create')")
public CommonResult<Long> createGroupMember(@Valid @RequestBody ImGroupMemberSaveReqVO createReqVO) {
return success(imGroupMemberService.createGroupMember(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新群成员")
@PreAuthorize("@ss.hasPermission('im:group-member:update')")
public CommonResult<Boolean> updateGroupMember(@Valid @RequestBody ImGroupMemberSaveReqVO updateReqVO) {
imGroupMemberService.updateGroupMember(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除群成员")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('im:group-member:delete')")
public CommonResult<Boolean> deleteGroupMember(@RequestParam("id") Long id) {
imGroupMemberService.deleteGroupMember(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得群成员")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('im:group-member:query')")
public CommonResult<ImGroupMemberRespVO> getGroupMember(@RequestParam("id") Long id) {
GroupMemberDO groupMember = imGroupMemberService.getGroupMember(id);
return success(BeanUtils.toBean(groupMember, ImGroupMemberRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "获得群成员分页")
@PreAuthorize("@ss.hasPermission('im:group-member:query')")
public CommonResult<PageResult<ImGroupMemberRespVO>> getGroupMemberPage(@Valid ImGroupMemberPageReqVO pageReqVO) {
PageResult<GroupMemberDO> pageResult = imGroupMemberService.getGroupMemberPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, ImGroupMemberRespVO.class));
}
@GetMapping("/export-excel")
@Operation(summary = "导出群成员 Excel")
@PreAuthorize("@ss.hasPermission('im:group-member:export')")
@OperateLog(type = EXPORT)
public void exportGroupMemberExcel(@Valid ImGroupMemberPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<GroupMemberDO> list = imGroupMemberService.getGroupMemberPage(pageReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "群成员.xls", "数据", ImGroupMemberRespVO.class,
BeanUtils.toBean(list, ImGroupMemberRespVO.class));
}
}

View File

@ -0,0 +1,42 @@
package cn.iocoder.yudao.module.im.controller.admin.groupmember.vo;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 群成员分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ImGroupMemberPageReqVO extends PageParam {
@Schema(description = "群 id", example = "13279")
private Long groupId;
@Schema(description = "用户id", example = "21730")
private Long userId;
@Schema(description = "昵称", example = "芋艿")
private String nickname;
@Schema(description = "头像")
private String avatar;
@Schema(description = "组内显示名称", example = "芋艿")
private String aliasName;
@Schema(description = "备注", example = "你说的对")
private String remark;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@ -0,0 +1,47 @@
package cn.iocoder.yudao.module.im.controller.admin.groupmember.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 群成员 Response VO")
@Data
@ExcelIgnoreUnannotated
public class ImGroupMemberRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17071")
@ExcelProperty("编号")
private Long id;
@Schema(description = "群 id", example = "13279")
@ExcelProperty("群 id")
private Long groupId;
@Schema(description = "用户id", requiredMode = Schema.RequiredMode.REQUIRED, example = "21730")
@ExcelProperty("用户id")
private Long userId;
@Schema(description = "昵称", example = "芋艿")
@ExcelProperty("昵称")
private String nickname;
@Schema(description = "头像")
@ExcelProperty("头像")
private String avatar;
@Schema(description = "组内显示名称", example = "芋艿")
@ExcelProperty("组内显示名称")
private String aliasName;
@Schema(description = "备注", example = "你说的对")
@ExcelProperty("备注")
private String remark;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间")
private LocalDateTime createTime;
}

View File

@ -0,0 +1,33 @@
package cn.iocoder.yudao.module.im.controller.admin.groupmember.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Schema(description = "管理后台 - 群成员新增/修改 Request VO")
@Data
public class ImGroupMemberSaveReqVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17071")
private Long id;
@Schema(description = "群 id", example = "13279")
private Long groupId;
@Schema(description = "用户id", requiredMode = Schema.RequiredMode.REQUIRED, example = "21730")
@NotNull(message = "用户id不能为空")
private Long userId;
@Schema(description = "昵称", example = "芋艿")
private String nickname;
@Schema(description = "头像")
private String avatar;
@Schema(description = "组内显示名称", example = "芋艿")
private String aliasName;
@Schema(description = "备注", example = "你说的对")
private String remark;
}

View File

@ -0,0 +1,52 @@
package cn.iocoder.yudao.module.im.dal.dataobject.group;
import lombok.*;
import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
/**
* DO
*
* @author 芋道源码
*/
@TableName("im_group")
@KeySequence("im_group_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ImGroupDO extends BaseDO {
/**
* 编号
*/
@TableId
private Long id;
/**
* 群名字
*/
private String groupName;
/**
* 群主id
*/
private Long ownerId;
/**
* 群头像
*/
private String headImage;
/**
* 群头像缩略图
*/
private String headImageThumb;
/**
* 群公告
*/
private String notice;
/**
* 群备注
*/
private String remark;
}

View File

@ -0,0 +1,55 @@
package cn.iocoder.yudao.module.im.dal.dataobject.groupmember;
import lombok.*;
import java.util.*;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
/**
* 群成员 DO
*
* @author 芋道源码
*/
@TableName("im_group_member")
@KeySequence("im_group_member_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class GroupMemberDO extends BaseDO {
/**
* 编号
*/
@TableId
private Long id;
/**
* id
*/
private Long groupId;
/**
* 用户id
*/
private Long userId;
/**
* 昵称
*/
private String nickname;
/**
* 头像
*/
private String avatar;
/**
* 组内显示名称
*/
private String aliasName;
/**
* 备注
*/
private String remark;
}

View File

@ -7,13 +7,15 @@ import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversatio
import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ImConversationDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.Optional;
/**
* 会话 Mapper
*
* @author 芋道源码
*/
@Mapper
public interface ConversationMapper extends BaseMapperX<ImConversationDO> {
public interface ImConversationMapper extends BaseMapperX<ImConversationDO> {
default PageResult<ImConversationDO> selectPage(ImConversationPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<ImConversationDO>()
@ -27,4 +29,7 @@ public interface ConversationMapper extends BaseMapperX<ImConversationDO> {
.orderByDesc(ImConversationDO::getId));
}
default ImConversationDO selectByNo(String no){
return selectOne(new LambdaQueryWrapperX<ImConversationDO>().eq(ImConversationDO::getNo, no));
}
}

View File

@ -0,0 +1,30 @@
package cn.iocoder.yudao.module.im.dal.mysql.group;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupDO;
import org.apache.ibatis.annotations.Mapper;
import cn.iocoder.yudao.module.im.controller.admin.group.vo.*;
/**
* Mapper
*
* @author 芋道源码
*/
@Mapper
public interface ImGroupMapper extends BaseMapperX<ImGroupDO> {
default PageResult<ImGroupDO> selectPage(ImGroupPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<ImGroupDO>()
.likeIfPresent(ImGroupDO::getGroupName, reqVO.getGroupName())
.eqIfPresent(ImGroupDO::getOwnerId, reqVO.getOwnerId())
.eqIfPresent(ImGroupDO::getHeadImage, reqVO.getHeadImage())
.eqIfPresent(ImGroupDO::getHeadImageThumb, reqVO.getHeadImageThumb())
.eqIfPresent(ImGroupDO::getNotice, reqVO.getNotice())
.eqIfPresent(ImGroupDO::getRemark, reqVO.getRemark())
.betweenIfPresent(ImGroupDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(ImGroupDO::getId));
}
}

View File

@ -0,0 +1,35 @@
package cn.iocoder.yudao.module.im.dal.mysql.groupmember;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.im.controller.admin.groupmember.vo.ImGroupMemberPageReqVO;
import cn.iocoder.yudao.module.im.dal.dataobject.groupmember.GroupMemberDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* 群成员 Mapper
*
* @author 芋道源码
*/
@Mapper
public interface ImGroupMemberMapper extends BaseMapperX<GroupMemberDO> {
default PageResult<GroupMemberDO> selectPage(ImGroupMemberPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<GroupMemberDO>()
.eqIfPresent(GroupMemberDO::getGroupId, reqVO.getGroupId())
.eqIfPresent(GroupMemberDO::getUserId, reqVO.getUserId())
.likeIfPresent(GroupMemberDO::getNickname, reqVO.getNickname())
.eqIfPresent(GroupMemberDO::getAvatar, reqVO.getAvatar())
.likeIfPresent(GroupMemberDO::getAliasName, reqVO.getAliasName())
.eqIfPresent(GroupMemberDO::getRemark, reqVO.getRemark())
.betweenIfPresent(GroupMemberDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(GroupMemberDO::getId));
}
default List<GroupMemberDO> selectListByGroupId(Long groupId) {
return selectList(new LambdaQueryWrapperX<GroupMemberDO>().eq(GroupMemberDO::getGroupId, groupId));
}
}

View File

@ -13,7 +13,7 @@ import org.apache.ibatis.annotations.Mapper;
* @author 芋道源码
*/
@Mapper
public interface InboxMapper extends BaseMapperX<ImInboxDO> {
public interface ImInboxMapper extends BaseMapperX<ImInboxDO> {
default PageResult<ImInboxDO> selectPage(ImInboxPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<ImInboxDO>()

View File

@ -5,9 +5,8 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationPageReqVO;
import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationSaveReqVO;
import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ImConversationDO;
import cn.iocoder.yudao.module.im.dal.mysql.conversation.ConversationMapper;
import cn.iocoder.yudao.module.im.dal.mysql.conversation.ImConversationMapper;
import cn.iocoder.yudao.module.im.enums.conversation.ImConversationTypeEnum;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
@ -25,13 +24,13 @@ import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.CONVERSATION_N
public class ImConversationServiceImpl implements ImConversationService {
@Resource
private ConversationMapper conversationMapper;
private ImConversationMapper imConversationMapper;
@Override
public Long createConversation(ImConversationSaveReqVO createReqVO) {
// 插入
ImConversationDO conversation = BeanUtils.toBean(createReqVO, ImConversationDO.class);
conversationMapper.insert(conversation);
imConversationMapper.insert(conversation);
// 返回
return conversation.getId();
}
@ -42,7 +41,7 @@ public class ImConversationServiceImpl implements ImConversationService {
validateConversationExists(updateReqVO.getId());
// 更新
ImConversationDO updateObj = BeanUtils.toBean(updateReqVO, ImConversationDO.class);
conversationMapper.updateById(updateObj);
imConversationMapper.updateById(updateObj);
}
@Override
@ -50,23 +49,23 @@ public class ImConversationServiceImpl implements ImConversationService {
// 校验存在
validateConversationExists(id);
// 删除
conversationMapper.deleteById(id);
imConversationMapper.deleteById(id);
}
private void validateConversationExists(Long id) {
if (conversationMapper.selectById(id) == null) {
if (imConversationMapper.selectById(id) == null) {
throw exception(CONVERSATION_NOT_EXISTS);
}
}
@Override
public ImConversationDO getConversation(Long id) {
return conversationMapper.selectById(id);
return imConversationMapper.selectById(id);
}
@Override
public PageResult<ImConversationDO> getConversationPage(ImConversationPageReqVO pageReqVO) {
return conversationMapper.selectPage(pageReqVO);
return imConversationMapper.selectPage(pageReqVO);
}
@Override
@ -86,10 +85,9 @@ public class ImConversationServiceImpl implements ImConversationService {
conversation.setPinned(false);
// 根据 no 查询是否存在,不存在则新增
QueryWrapper<ImConversationDO> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("no", conversation.getNo());
if (conversationMapper.selectOne(queryWrapper) == null) {
conversationMapper.insert(conversation);
ImConversationDO imConversationDO = imConversationMapper.selectByNo(conversation.getNo());
if (imConversationDO == null) {
imConversationMapper.insert(conversation);
}
}

View File

@ -0,0 +1,53 @@
package cn.iocoder.yudao.module.im.service.group;
import jakarta.validation.*;
import cn.iocoder.yudao.module.im.controller.admin.group.vo.*;
import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
/**
* Service 接口
*
* @author 芋道源码
*/
public interface ImGroupService {
/**
* 创建群
*
* @param createReqVO 创建信息
* @return 编号
*/
Long createGroup(@Valid ImGroupSaveReqVO createReqVO);
/**
* 更新群
*
* @param updateReqVO 更新信息
*/
void updateGroup(@Valid ImGroupSaveReqVO updateReqVO);
/**
* 删除群
*
* @param id 编号
*/
void deleteGroup(Long id);
/**
* 获得群
*
* @param id 编号
* @return
*/
ImGroupDO getGroup(Long id);
/**
* 获得群分页
*
* @param pageReqVO 分页查询
* @return 群分页
*/
PageResult<ImGroupDO> getGroupPage(ImGroupPageReqVO pageReqVO);
}

View File

@ -0,0 +1,71 @@
package cn.iocoder.yudao.module.im.service.group;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import cn.iocoder.yudao.module.im.controller.admin.group.vo.*;
import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.im.dal.mysql.group.ImGroupMapper;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.*;
/**
* Service 实现类
*
* @author 芋道源码
*/
@Service
@Validated
public class ImGroupServiceImpl implements ImGroupService {
@Resource
private ImGroupMapper imGroupMapper;
@Override
public Long createGroup(ImGroupSaveReqVO createReqVO) {
// 插入
ImGroupDO group = BeanUtils.toBean(createReqVO, ImGroupDO.class);
imGroupMapper.insert(group);
// 返回
return group.getId();
}
@Override
public void updateGroup(ImGroupSaveReqVO updateReqVO) {
// 校验存在
validateGroupExists(updateReqVO.getId());
// 更新
ImGroupDO updateObj = BeanUtils.toBean(updateReqVO, ImGroupDO.class);
imGroupMapper.updateById(updateObj);
}
@Override
public void deleteGroup(Long id) {
// 校验存在
validateGroupExists(id);
// 删除
imGroupMapper.deleteById(id);
}
private void validateGroupExists(Long id) {
if (imGroupMapper.selectById(id) == null) {
throw exception(GROUP_NOT_EXISTS);
}
}
@Override
public ImGroupDO getGroup(Long id) {
return imGroupMapper.selectById(id);
}
@Override
public PageResult<ImGroupDO> getGroupPage(ImGroupPageReqVO pageReqVO) {
return imGroupMapper.selectPage(pageReqVO);
}
}

View File

@ -0,0 +1,63 @@
package cn.iocoder.yudao.module.im.service.groupmember;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.im.controller.admin.groupmember.vo.ImGroupMemberPageReqVO;
import cn.iocoder.yudao.module.im.controller.admin.groupmember.vo.ImGroupMemberSaveReqVO;
import cn.iocoder.yudao.module.im.dal.dataobject.groupmember.GroupMemberDO;
import jakarta.validation.Valid;
import java.util.List;
/**
* 群成员 Service 接口
*
* @author 芋道源码
*/
public interface ImGroupMemberService {
/**
* 创建群成员
*
* @param createReqVO 创建信息
* @return 编号
*/
Long createGroupMember(@Valid ImGroupMemberSaveReqVO createReqVO);
/**
* 更新群成员
*
* @param updateReqVO 更新信息
*/
void updateGroupMember(@Valid ImGroupMemberSaveReqVO updateReqVO);
/**
* 删除群成员
*
* @param id 编号
*/
void deleteGroupMember(Long id);
/**
* 获得群成员
*
* @param id 编号
* @return 群成员
*/
GroupMemberDO getGroupMember(Long id);
/**
* 获得群成员分页
*
* @param pageReqVO 分页查询
* @return 群成员分页
*/
PageResult<GroupMemberDO> getGroupMemberPage(ImGroupMemberPageReqVO pageReqVO);
/**
* 根据群组id查询群成员
*
* @param groupId 群组id
* @return 群成员列表
*/
List<GroupMemberDO> selectByGroupId(Long groupId);
}

View File

@ -0,0 +1,78 @@
package cn.iocoder.yudao.module.im.service.groupmember;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import cn.iocoder.yudao.module.im.controller.admin.groupmember.vo.*;
import cn.iocoder.yudao.module.im.dal.dataobject.groupmember.GroupMemberDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.im.dal.mysql.groupmember.ImGroupMemberMapper;
import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.*;
/**
* 群成员 Service 实现类
*
* @author 芋道源码
*/
@Service
@Validated
public class ImGroupMemberServiceImpl implements ImGroupMemberService {
@Resource
private ImGroupMemberMapper imGroupMemberMapper;
@Override
public Long createGroupMember(ImGroupMemberSaveReqVO createReqVO) {
// 插入
GroupMemberDO groupMember = BeanUtils.toBean(createReqVO, GroupMemberDO.class);
imGroupMemberMapper.insert(groupMember);
// 返回
return groupMember.getId();
}
@Override
public void updateGroupMember(ImGroupMemberSaveReqVO updateReqVO) {
// 校验存在
validateGroupMemberExists(updateReqVO.getId());
// 更新
GroupMemberDO updateObj = BeanUtils.toBean(updateReqVO, GroupMemberDO.class);
imGroupMemberMapper.updateById(updateObj);
}
@Override
public void deleteGroupMember(Long id) {
// 校验存在
validateGroupMemberExists(id);
// 删除
imGroupMemberMapper.deleteById(id);
}
private void validateGroupMemberExists(Long id) {
if (imGroupMemberMapper.selectById(id) == null) {
throw exception(GROUP_MEMBER_NOT_EXISTS);
}
}
@Override
public GroupMemberDO getGroupMember(Long id) {
return imGroupMemberMapper.selectById(id);
}
@Override
public PageResult<GroupMemberDO> getGroupMemberPage(ImGroupMemberPageReqVO pageReqVO) {
return imGroupMemberMapper.selectPage(pageReqVO);
}
@Override
public List<GroupMemberDO> selectByGroupId(Long groupId) {
return imGroupMemberMapper.selectListByGroupId(groupId);
}
}

View File

@ -5,7 +5,7 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.im.controller.admin.inbox.vo.ImInboxPageReqVO;
import cn.iocoder.yudao.module.im.controller.admin.inbox.vo.ImInboxSaveReqVO;
import cn.iocoder.yudao.module.im.dal.dataobject.inbox.ImInboxDO;
import cn.iocoder.yudao.module.im.dal.mysql.inbox.InboxMapper;
import cn.iocoder.yudao.module.im.dal.mysql.inbox.ImInboxMapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
@ -23,13 +23,13 @@ import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.INBOX_NOT_EXIS
public class ImInboxServiceImpl implements ImInboxService {
@Resource
private InboxMapper inboxMapper;
private ImInboxMapper imInboxMapper;
@Override
public Long createInbox(ImInboxSaveReqVO createReqVO) {
// 插入
ImInboxDO inbox = BeanUtils.toBean(createReqVO, ImInboxDO.class);
inboxMapper.insert(inbox);
imInboxMapper.insert(inbox);
// 返回
return inbox.getId();
}
@ -40,7 +40,7 @@ public class ImInboxServiceImpl implements ImInboxService {
validateInboxExists(updateReqVO.getId());
// 更新
ImInboxDO updateObj = BeanUtils.toBean(updateReqVO, ImInboxDO.class);
inboxMapper.updateById(updateObj);
imInboxMapper.updateById(updateObj);
}
@Override
@ -48,23 +48,23 @@ public class ImInboxServiceImpl implements ImInboxService {
// 校验存在
validateInboxExists(id);
// 删除
inboxMapper.deleteById(id);
imInboxMapper.deleteById(id);
}
private void validateInboxExists(Long id) {
if (inboxMapper.selectById(id) == null) {
if (imInboxMapper.selectById(id) == null) {
throw exception(INBOX_NOT_EXISTS);
}
}
@Override
public ImInboxDO getInbox(Long id) {
return inboxMapper.selectById(id);
return imInboxMapper.selectById(id);
}
@Override
public PageResult<ImInboxDO> getInboxPage(ImInboxPageReqVO pageReqVO) {
return inboxMapper.selectPage(pageReqVO);
return imInboxMapper.selectPage(pageReqVO);
}
}

View File

@ -69,4 +69,12 @@ public interface ImMessageService {
* @param messageStatus 消息状态
*/
void updateMessageStatus(Long messageId, Integer messageStatus);
/**
* 保存群聊消息
* @param message 消息
* @param fromUserId 发送者用户ID
* @return id
*/
ImMessageDO saveGroupMessage(ImSendMessage message, Long fromUserId);
}

View File

@ -76,18 +76,22 @@ public class ImMessageServiceImpl implements ImMessageService {
@Override
public ImMessageDO savePrivateMessage(ImSendMessage message, Long senderId) {
public ImMessageDO savePrivateMessage(ImSendMessage message, Long fromUserId) {
return saveImMessageDO(message, fromUserId);
}
private ImMessageDO saveImMessageDO(ImSendMessage message, Long fromUserId) {
ImMessageDO imMessageDO = new ImMessageDO();
imMessageDO.setClientMessageId(message.getClientMessageId());
imMessageDO.setSenderId(senderId);
imMessageDO.setSenderId(fromUserId);
imMessageDO.setReceiverId(message.getReceiverId());
//查询发送人昵称和发送人头像
AdminUserRespDTO user = adminUserApi.getUser(senderId);
AdminUserRespDTO user = adminUserApi.getUser(fromUserId);
imMessageDO.setSenderNickname(user.getNickname());
imMessageDO.setSenderAvatar(user.getAvatar());
imMessageDO.setConversationType(message.getConversationType());
imMessageDO.setContentType(message.getContentType());
imMessageDO.setConversationNo(senderId + "_" + message.getReceiverId());
imMessageDO.setConversationNo(fromUserId + "_" + message.getReceiverId());
imMessageDO.setContent(message.getContent());
//消息来源 100-用户发送200-系统发送一般是通知不能为空
imMessageDO.setSendFrom(100);
@ -108,4 +112,9 @@ public class ImMessageServiceImpl implements ImMessageService {
imMessageMapper.updateById(imMessageDO);
}
@Override
public ImMessageDO saveGroupMessage(ImSendMessage message, Long fromUserId) {
return saveImMessageDO(message, fromUserId);
}
}

View File

@ -5,11 +5,13 @@ import cn.iocoder.yudao.framework.websocket.core.listener.WebSocketMessageListen
import cn.iocoder.yudao.framework.websocket.core.sender.WebSocketMessageSender;
import cn.iocoder.yudao.framework.websocket.core.util.WebSocketFrameworkUtils;
import cn.iocoder.yudao.module.im.controller.admin.inbox.vo.ImInboxSaveReqVO;
import cn.iocoder.yudao.module.im.dal.dataobject.groupmember.GroupMemberDO;
import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO;
import cn.iocoder.yudao.module.im.dal.redis.inbox.SequenceGeneratorRedisDao;
import cn.iocoder.yudao.module.im.enums.conversation.ImConversationTypeEnum;
import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum;
import cn.iocoder.yudao.module.im.service.conversation.ImConversationService;
import cn.iocoder.yudao.module.im.service.groupmember.ImGroupMemberService;
import cn.iocoder.yudao.module.im.service.inbox.ImInboxService;
import cn.iocoder.yudao.module.im.service.message.ImMessageService;
import cn.iocoder.yudao.module.im.websocket.message.ImReceiveMessage;
@ -19,6 +21,8 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketSession;
import java.util.List;
/**
* WebSocket im
*
@ -28,6 +32,7 @@ import org.springframework.web.socket.WebSocketSession;
@Slf4j
public class ImWebSocketMessageListener implements WebSocketMessageListener<ImSendMessage> {
public static final String IM_MESSAGE_RECEIVE = "im-message-receive";
@Resource
private WebSocketMessageSender webSocketMessageSender; // WebSocket消息发送器
@Resource
@ -37,6 +42,8 @@ public class ImWebSocketMessageListener implements WebSocketMessageListener<ImSe
@Resource
private ImInboxService imInboxService; // IM收件箱服务
@Resource
private ImGroupMemberService imGroupMemberService; // 群成员服务
@Resource
private SequenceGeneratorRedisDao sequenceGeneratorRedisDao; // 序列生成器Redis DAO
/**
@ -51,32 +58,70 @@ public class ImWebSocketMessageListener implements WebSocketMessageListener<ImSe
// 如果是私人消息处理私人消息
if (message.getConversationType().equals(ImConversationTypeEnum.PRIVATE.getType())) {
ImMessageDO imMessageDO = imMessageService.savePrivateMessage(message, fromUserId); // 保存私人消息
handlePrivateMessage(fromUserId, imMessageDO, message);
handlePrivateMessage(fromUserId, message);
} else if (message.getConversationType().equals(ImConversationTypeEnum.GROUP.getType())) {
//处理群聊消息
handleGroupMessage(fromUserId, message);
} else {
log.error("[onMessage][消息类型({}) 未支持]", message.getConversationType());
}
}
/**
* 处理群聊消息
*
* @param fromUserId 发送者用户ID
* @param message 发送的IM消息
*/
private void handleGroupMessage(Long fromUserId, ImSendMessage message) {
ImMessageDO imMessageDO = imMessageService.saveGroupMessage(message, fromUserId); // 保存群聊消息
Long groupId = message.getReceiverId();
// 发送消息给群聊成员
List<GroupMemberDO> groupMemberDOList = imGroupMemberService.selectByGroupId(groupId);
groupMemberDOList.forEach(groupMemberDO -> {
//过滤掉自己
if (groupMemberDO.getUserId().equals(fromUserId)) {
return;
}
Long receiverSequence = sequenceGeneratorRedisDao.generateSequence(groupMemberDO.getUserId()); // 生成接收者序列
Long receiverInboxId = createAndSaveInbox(groupMemberDO.getUserId(), imMessageDO.getId(), receiverSequence); // 创建并保存接收者收件箱
sendMessage(groupMemberDO.getUserId(), receiverInboxId, imMessageDO, message, receiverSequence);
});
Long fromUserSequence = sequenceGeneratorRedisDao.generateSequence(fromUserId); // 生成发送者序列
Long fromUserInboxId = createAndSaveInbox(fromUserId, imMessageDO.getId(), fromUserSequence); // 创建并保存发送者收件箱
// 发送消息给发送者
sendMessage(fromUserId, fromUserInboxId, imMessageDO, message, fromUserSequence);
// 更新消息状态为成功
imMessageService.updateMessageStatus(imMessageDO.getId(), ImMessageStatusEnum.SUCCESS.getStatus());
}
/**
* 处理私人消息
*
* @param fromUserId 发送者用户ID
* @param imMessageDO IM消息数据对象
* @param message 发送的IM消息
* @param fromUserId 发送者用户ID
* @param message 发送的IM消息
*/
private void handlePrivateMessage(Long fromUserId, ImMessageDO imMessageDO, ImSendMessage message) {
private void handlePrivateMessage(Long fromUserId, ImSendMessage message) {
ImMessageDO imMessageDO = imMessageService.savePrivateMessage(message, fromUserId); // 保存私人消息
Long receiverId = message.getReceiverId();
Long fromUserSequence = sequenceGeneratorRedisDao.generateSequence(fromUserId); // 生成发送者序列
Long fromUserInboxId = createAndSaveInbox(fromUserId, imMessageDO.getId(), fromUserSequence); // 创建并保存发送者收件箱
Long receiverSequence = sequenceGeneratorRedisDao.generateSequence(fromUserId); // 生成接收者序列
Long receiverSequence = sequenceGeneratorRedisDao.generateSequence(message.getReceiverId()); // 生成接收者序列
Long receiverInboxId = createAndSaveInbox(message.getReceiverId(), imMessageDO.getId(), receiverSequence); // 创建并保存接收者收件箱
// 发送消息给接收者和发送者
sendMessage(fromUserId, receiverInboxId, imMessageDO, message, "im-message-receive", fromUserSequence);
sendMessage(fromUserId, fromUserInboxId, imMessageDO, message, "im-message-receive", receiverSequence);
sendMessage(fromUserId, fromUserInboxId, imMessageDO, message, fromUserSequence);
sendMessage(receiverId, receiverInboxId, imMessageDO, message, receiverSequence);
// 更新消息状态为成功
imMessageService.updateMessageStatus(imMessageDO.getId(), ImMessageStatusEnum.SUCCESS.getStatus());
// 保存私人会话只有在 client 操作会话已读置顶才会延迟创建
//imConversationService.savePrivateConversation(fromUserId, message.getReceiverId());
//imConversationService.savePrivateConversation(fromUserId, receiverId);
}
/**
@ -99,20 +144,19 @@ public class ImWebSocketMessageListener implements WebSocketMessageListener<ImSe
* @param inboxId 收件箱ID
* @param imMessageDO IM消息数据对象
* @param message 发送的IM消息
* @param messageType 消息类型
* @param sequence 序列
*/
private void sendMessage(Long fromUserId, Long inboxId, ImMessageDO imMessageDO, ImSendMessage message, String messageType, Long sequence) {
private void sendMessage(Long fromUserId, Long inboxId, ImMessageDO imMessageDO, ImSendMessage message, Long sequence) {
ImReceiveMessage receiveMessage = new ImReceiveMessage(); // 创建接收消息
receiveMessage.setFromId(fromUserId); // 设置发送者ID
receiveMessage.setConversationType(ImConversationTypeEnum.PRIVATE.getType()); // 设置会话类型为私人
receiveMessage.setConversationType(message.getConversationType()); // 设置会话类型
receiveMessage.setContentType(message.getContentType()); // 设置内容类型
receiveMessage.setContent(message.getContent()); // 设置内容
receiveMessage.setMessageId(imMessageDO.getId()); // 设置消息ID
receiveMessage.setInboxId(inboxId); // 设置收件箱ID
receiveMessage.setSendTime(imMessageDO.getSendTime()); // 设置发送时间
receiveMessage.setSequence(sequence); // 设置序列
webSocketMessageSender.sendObject(UserTypeEnum.ADMIN.getValue(), fromUserId, messageType, receiveMessage); // 发送消息
webSocketMessageSender.sendObject(UserTypeEnum.ADMIN.getValue(), fromUserId, ImWebSocketMessageListener.IM_MESSAGE_RECEIVE, receiveMessage); // 发送消息
}
/**

View File

@ -1,6 +1,6 @@
<?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="cn.iocoder.yudao.module.im.dal.mysql.conversation.ConversationMapper">
<mapper namespace="cn.iocoder.yudao.module.im.dal.mysql.conversation.ImConversationMapper">
<!--
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。

View File

@ -1,6 +1,6 @@
<?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="cn.iocoder.yudao.module.im.dal.mysql.inbox.InboxMapper">
<mapper namespace="cn.iocoder.yudao.module.im.dal.mysql.group.ImGroupMapper">
<!--
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。

View File

@ -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="cn.iocoder.yudao.module.im.dal.mysql.groupmember.ImGroupMemberMapper">
<!--
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
文档可见https://www.iocoder.cn/MyBatis/x-plugins/
-->
</mapper>

View File

@ -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="cn.iocoder.yudao.module.im.dal.mysql.inbox.ImInboxMapper">
<!--
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
文档可见https://www.iocoder.cn/MyBatis/x-plugins/
-->
</mapper>

View File

@ -9,7 +9,7 @@ import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.*;
import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ImConversationDO;
import cn.iocoder.yudao.module.im.dal.mysql.conversation.ConversationMapper;
import cn.iocoder.yudao.module.im.dal.mysql.conversation.ImConversationMapper;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import org.springframework.context.annotation.Import;
@ -33,7 +33,7 @@ public class ImConversationServiceImplTest extends BaseDbUnitTest {
private ImConversationServiceImpl conversationService;
@Resource
private ConversationMapper conversationMapper;
private ImConversationMapper imConversationMapper;
@Test
public void testCreateConversation_success() {
@ -45,7 +45,7 @@ public class ImConversationServiceImplTest extends BaseDbUnitTest {
// 断言
assertNotNull(conversationId);
// 校验记录的属性是否正确
ImConversationDO conversation = conversationMapper.selectById(conversationId);
ImConversationDO conversation = imConversationMapper.selectById(conversationId);
assertPojoEquals(createReqVO, conversation, "id");
}
@ -53,7 +53,7 @@ public class ImConversationServiceImplTest extends BaseDbUnitTest {
public void testUpdateConversation_success() {
// mock 数据
ImConversationDO dbConversation = randomPojo(ImConversationDO.class);
conversationMapper.insert(dbConversation);// @Sql: 先插入出一条存在的数据
imConversationMapper.insert(dbConversation);// @Sql: 先插入出一条存在的数据
// 准备参数
ImConversationSaveReqVO updateReqVO = randomPojo(ImConversationSaveReqVO.class, o -> {
o.setId(dbConversation.getId()); // 设置更新的 ID
@ -62,7 +62,7 @@ public class ImConversationServiceImplTest extends BaseDbUnitTest {
// 调用
conversationService.updateConversation(updateReqVO);
// 校验是否更新正确
ImConversationDO conversation = conversationMapper.selectById(updateReqVO.getId()); // 获取最新的
ImConversationDO conversation = imConversationMapper.selectById(updateReqVO.getId()); // 获取最新的
assertPojoEquals(updateReqVO, conversation);
}
@ -79,14 +79,14 @@ public class ImConversationServiceImplTest extends BaseDbUnitTest {
public void testDeleteConversation_success() {
// mock 数据
ImConversationDO dbConversation = randomPojo(ImConversationDO.class);
conversationMapper.insert(dbConversation);// @Sql: 先插入出一条存在的数据
imConversationMapper.insert(dbConversation);// @Sql: 先插入出一条存在的数据
// 准备参数
Long id = dbConversation.getId();
// 调用
conversationService.deleteConversation(id);
// 校验数据不存在了
assertNull(conversationMapper.selectById(id));
assertNull(imConversationMapper.selectById(id));
}
@Test
@ -111,21 +111,21 @@ public class ImConversationServiceImplTest extends BaseDbUnitTest {
o.setLastReadTime(null);
o.setCreateTime(null);
});
conversationMapper.insert(dbConversation);
imConversationMapper.insert(dbConversation);
// 测试 userId 不匹配
conversationMapper.insert(cloneIgnoreId(dbConversation, o -> o.setUserId(null)));
imConversationMapper.insert(cloneIgnoreId(dbConversation, o -> o.setUserId(null)));
// 测试 conversationType 不匹配
conversationMapper.insert(cloneIgnoreId(dbConversation, o -> o.setConversationType(null)));
imConversationMapper.insert(cloneIgnoreId(dbConversation, o -> o.setConversationType(null)));
// 测试 targetId 不匹配
conversationMapper.insert(cloneIgnoreId(dbConversation, o -> o.setTargetId(null)));
imConversationMapper.insert(cloneIgnoreId(dbConversation, o -> o.setTargetId(null)));
// 测试 no 不匹配
conversationMapper.insert(cloneIgnoreId(dbConversation, o -> o.setNo(null)));
imConversationMapper.insert(cloneIgnoreId(dbConversation, o -> o.setNo(null)));
// 测试 pinned 不匹配
conversationMapper.insert(cloneIgnoreId(dbConversation, o -> o.setPinned(null)));
imConversationMapper.insert(cloneIgnoreId(dbConversation, o -> o.setPinned(null)));
// 测试 lastReadTime 不匹配
conversationMapper.insert(cloneIgnoreId(dbConversation, o -> o.setLastReadTime(null)));
imConversationMapper.insert(cloneIgnoreId(dbConversation, o -> o.setLastReadTime(null)));
// 测试 createTime 不匹配
conversationMapper.insert(cloneIgnoreId(dbConversation, o -> o.setCreateTime(null)));
imConversationMapper.insert(cloneIgnoreId(dbConversation, o -> o.setCreateTime(null)));
// 准备参数
ImConversationPageReqVO reqVO = new ImConversationPageReqVO();
reqVO.setUserId(null);

View File

@ -0,0 +1,147 @@
package cn.iocoder.yudao.module.im.service.group;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import jakarta.annotation.Resource;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.im.controller.admin.group.vo.*;
import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupDO;
import cn.iocoder.yudao.module.im.dal.mysql.group.ImGroupMapper;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import org.springframework.context.annotation.Import;
import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
import static org.junit.jupiter.api.Assertions.*;
/**
* {@link ImGroupServiceImpl} 的单元测试类
*
* @author 芋道源码
*/
@Import(ImGroupServiceImpl.class)
public class ImGroupServiceImplTest extends BaseDbUnitTest {
@Resource
private ImGroupServiceImpl groupService;
@Resource
private ImGroupMapper imGroupMapper;
@Test
public void testCreateGroup_success() {
// 准备参数
ImGroupSaveReqVO createReqVO = randomPojo(ImGroupSaveReqVO.class).setId(null);
// 调用
Long groupId = groupService.createGroup(createReqVO);
// 断言
assertNotNull(groupId);
// 校验记录的属性是否正确
ImGroupDO group = imGroupMapper.selectById(groupId);
assertPojoEquals(createReqVO, group, "id");
}
@Test
public void testUpdateGroup_success() {
// mock 数据
ImGroupDO dbGroup = randomPojo(ImGroupDO.class);
imGroupMapper.insert(dbGroup);// @Sql: 先插入出一条存在的数据
// 准备参数
ImGroupSaveReqVO updateReqVO = randomPojo(ImGroupSaveReqVO.class, o -> {
o.setId(dbGroup.getId()); // 设置更新的 ID
});
// 调用
groupService.updateGroup(updateReqVO);
// 校验是否更新正确
ImGroupDO group = imGroupMapper.selectById(updateReqVO.getId()); // 获取最新的
assertPojoEquals(updateReqVO, group);
}
@Test
public void testUpdateGroup_notExists() {
// 准备参数
ImGroupSaveReqVO updateReqVO = randomPojo(ImGroupSaveReqVO.class);
// 调用, 并断言异常
assertServiceException(() -> groupService.updateGroup(updateReqVO), GROUP_NOT_EXISTS);
}
@Test
public void testDeleteGroup_success() {
// mock 数据
ImGroupDO dbGroup = randomPojo(ImGroupDO.class);
imGroupMapper.insert(dbGroup);// @Sql: 先插入出一条存在的数据
// 准备参数
Long id = dbGroup.getId();
// 调用
groupService.deleteGroup(id);
// 校验数据不存在了
assertNull(imGroupMapper.selectById(id));
}
@Test
public void testDeleteGroup_notExists() {
// 准备参数
Long id = randomLongId();
// 调用, 并断言异常
assertServiceException(() -> groupService.deleteGroup(id), GROUP_NOT_EXISTS);
}
@Test
@Disabled // TODO 请修改 null 为需要的值然后删除 @Disabled 注解
public void testGetGroupPage() {
// mock 数据
ImGroupDO dbGroup = randomPojo(ImGroupDO.class, o -> { // 等会查询到
o.setGroupName(null);
o.setOwnerId(null);
o.setHeadImage(null);
o.setHeadImageThumb(null);
o.setNotice(null);
o.setRemark(null);
o.setCreateTime(null);
});
imGroupMapper.insert(dbGroup);
// 测试 groupName 不匹配
imGroupMapper.insert(cloneIgnoreId(dbGroup, o -> o.setGroupName(null)));
// 测试 ownerId 不匹配
imGroupMapper.insert(cloneIgnoreId(dbGroup, o -> o.setOwnerId(null)));
// 测试 headImage 不匹配
imGroupMapper.insert(cloneIgnoreId(dbGroup, o -> o.setHeadImage(null)));
// 测试 headImageThumb 不匹配
imGroupMapper.insert(cloneIgnoreId(dbGroup, o -> o.setHeadImageThumb(null)));
// 测试 notice 不匹配
imGroupMapper.insert(cloneIgnoreId(dbGroup, o -> o.setNotice(null)));
// 测试 remark 不匹配
imGroupMapper.insert(cloneIgnoreId(dbGroup, o -> o.setRemark(null)));
// 测试 createTime 不匹配
imGroupMapper.insert(cloneIgnoreId(dbGroup, o -> o.setCreateTime(null)));
// 准备参数
ImGroupPageReqVO reqVO = new ImGroupPageReqVO();
reqVO.setGroupName(null);
reqVO.setOwnerId(null);
reqVO.setHeadImage(null);
reqVO.setHeadImageThumb(null);
reqVO.setNotice(null);
reqVO.setRemark(null);
reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
// 调用
PageResult<ImGroupDO> pageResult = groupService.getGroupPage(reqVO);
// 断言
assertEquals(1, pageResult.getTotal());
assertEquals(1, pageResult.getList().size());
assertPojoEquals(dbGroup, pageResult.getList().get(0));
}
}

View File

@ -0,0 +1,147 @@
package cn.iocoder.yudao.module.im.service.groupmember;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import jakarta.annotation.Resource;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.im.controller.admin.groupmember.vo.*;
import cn.iocoder.yudao.module.im.dal.dataobject.groupmember.GroupMemberDO;
import cn.iocoder.yudao.module.im.dal.mysql.groupmember.ImGroupMemberMapper;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import org.springframework.context.annotation.Import;
import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
import static org.junit.jupiter.api.Assertions.*;
/**
* {@link ImGroupMemberServiceImpl} 的单元测试类
*
* @author 芋道源码
*/
@Import(ImGroupMemberServiceImpl.class)
public class ImGroupMemberServiceImplTest extends BaseDbUnitTest {
@Resource
private ImGroupMemberServiceImpl groupMemberService;
@Resource
private ImGroupMemberMapper imGroupMemberMapper;
@Test
public void testCreateGroupMember_success() {
// 准备参数
ImGroupMemberSaveReqVO createReqVO = randomPojo(ImGroupMemberSaveReqVO.class).setId(null);
// 调用
Long groupMemberId = groupMemberService.createGroupMember(createReqVO);
// 断言
assertNotNull(groupMemberId);
// 校验记录的属性是否正确
GroupMemberDO groupMember = imGroupMemberMapper.selectById(groupMemberId);
assertPojoEquals(createReqVO, groupMember, "id");
}
@Test
public void testUpdateGroupMember_success() {
// mock 数据
GroupMemberDO dbGroupMember = randomPojo(GroupMemberDO.class);
imGroupMemberMapper.insert(dbGroupMember);// @Sql: 先插入出一条存在的数据
// 准备参数
ImGroupMemberSaveReqVO updateReqVO = randomPojo(ImGroupMemberSaveReqVO.class, o -> {
o.setId(dbGroupMember.getId()); // 设置更新的 ID
});
// 调用
groupMemberService.updateGroupMember(updateReqVO);
// 校验是否更新正确
GroupMemberDO groupMember = imGroupMemberMapper.selectById(updateReqVO.getId()); // 获取最新的
assertPojoEquals(updateReqVO, groupMember);
}
@Test
public void testUpdateGroupMember_notExists() {
// 准备参数
ImGroupMemberSaveReqVO updateReqVO = randomPojo(ImGroupMemberSaveReqVO.class);
// 调用, 并断言异常
assertServiceException(() -> groupMemberService.updateGroupMember(updateReqVO), GROUP_MEMBER_NOT_EXISTS);
}
@Test
public void testDeleteGroupMember_success() {
// mock 数据
GroupMemberDO dbGroupMember = randomPojo(GroupMemberDO.class);
imGroupMemberMapper.insert(dbGroupMember);// @Sql: 先插入出一条存在的数据
// 准备参数
Long id = dbGroupMember.getId();
// 调用
groupMemberService.deleteGroupMember(id);
// 校验数据不存在了
assertNull(imGroupMemberMapper.selectById(id));
}
@Test
public void testDeleteGroupMember_notExists() {
// 准备参数
Long id = randomLongId();
// 调用, 并断言异常
assertServiceException(() -> groupMemberService.deleteGroupMember(id), GROUP_MEMBER_NOT_EXISTS);
}
@Test
@Disabled // TODO 请修改 null 为需要的值然后删除 @Disabled 注解
public void testGetGroupMemberPage() {
// mock 数据
GroupMemberDO dbGroupMember = randomPojo(GroupMemberDO.class, o -> { // 等会查询到
o.setGroupId(null);
o.setUserId(null);
o.setNickname(null);
o.setAvatar(null);
o.setAliasName(null);
o.setRemark(null);
o.setCreateTime(null);
});
imGroupMemberMapper.insert(dbGroupMember);
// 测试 groupId 不匹配
imGroupMemberMapper.insert(cloneIgnoreId(dbGroupMember, o -> o.setGroupId(null)));
// 测试 userId 不匹配
imGroupMemberMapper.insert(cloneIgnoreId(dbGroupMember, o -> o.setUserId(null)));
// 测试 nickname 不匹配
imGroupMemberMapper.insert(cloneIgnoreId(dbGroupMember, o -> o.setNickname(null)));
// 测试 avatar 不匹配
imGroupMemberMapper.insert(cloneIgnoreId(dbGroupMember, o -> o.setAvatar(null)));
// 测试 aliasName 不匹配
imGroupMemberMapper.insert(cloneIgnoreId(dbGroupMember, o -> o.setAliasName(null)));
// 测试 remark 不匹配
imGroupMemberMapper.insert(cloneIgnoreId(dbGroupMember, o -> o.setRemark(null)));
// 测试 createTime 不匹配
imGroupMemberMapper.insert(cloneIgnoreId(dbGroupMember, o -> o.setCreateTime(null)));
// 准备参数
ImGroupMemberPageReqVO reqVO = new ImGroupMemberPageReqVO();
reqVO.setGroupId(null);
reqVO.setUserId(null);
reqVO.setNickname(null);
reqVO.setAvatar(null);
reqVO.setAliasName(null);
reqVO.setRemark(null);
reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
// 调用
PageResult<GroupMemberDO> pageResult = groupMemberService.getGroupMemberPage(reqVO);
// 断言
assertEquals(1, pageResult.getTotal());
assertEquals(1, pageResult.getList().size());
assertPojoEquals(dbGroupMember, pageResult.getList().get(0));
}
}

View File

@ -9,7 +9,7 @@ import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.im.controller.admin.inbox.vo.*;
import cn.iocoder.yudao.module.im.dal.dataobject.inbox.ImInboxDO;
import cn.iocoder.yudao.module.im.dal.mysql.inbox.InboxMapper;
import cn.iocoder.yudao.module.im.dal.mysql.inbox.ImInboxMapper;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import org.springframework.context.annotation.Import;
@ -33,7 +33,7 @@ public class ImInboxServiceImplTest extends BaseDbUnitTest {
private ImInboxServiceImpl inboxService;
@Resource
private InboxMapper inboxMapper;
private ImInboxMapper imInboxMapper;
@Test
public void testCreateInbox_success() {
@ -45,7 +45,7 @@ public class ImInboxServiceImplTest extends BaseDbUnitTest {
// 断言
assertNotNull(inboxId);
// 校验记录的属性是否正确
ImInboxDO inbox = inboxMapper.selectById(inboxId);
ImInboxDO inbox = imInboxMapper.selectById(inboxId);
assertPojoEquals(createReqVO, inbox, "id");
}
@ -53,7 +53,7 @@ public class ImInboxServiceImplTest extends BaseDbUnitTest {
public void testUpdateInbox_success() {
// mock 数据
ImInboxDO dbInbox = randomPojo(ImInboxDO.class);
inboxMapper.insert(dbInbox);// @Sql: 先插入出一条存在的数据
imInboxMapper.insert(dbInbox);// @Sql: 先插入出一条存在的数据
// 准备参数
ImInboxSaveReqVO updateReqVO = randomPojo(ImInboxSaveReqVO.class, o -> {
o.setId(dbInbox.getId()); // 设置更新的 ID
@ -62,7 +62,7 @@ public class ImInboxServiceImplTest extends BaseDbUnitTest {
// 调用
inboxService.updateInbox(updateReqVO);
// 校验是否更新正确
ImInboxDO inbox = inboxMapper.selectById(updateReqVO.getId()); // 获取最新的
ImInboxDO inbox = imInboxMapper.selectById(updateReqVO.getId()); // 获取最新的
assertPojoEquals(updateReqVO, inbox);
}
@ -79,14 +79,14 @@ public class ImInboxServiceImplTest extends BaseDbUnitTest {
public void testDeleteInbox_success() {
// mock 数据
ImInboxDO dbInbox = randomPojo(ImInboxDO.class);
inboxMapper.insert(dbInbox);// @Sql: 先插入出一条存在的数据
imInboxMapper.insert(dbInbox);// @Sql: 先插入出一条存在的数据
// 准备参数
Long id = dbInbox.getId();
// 调用
inboxService.deleteInbox(id);
// 校验数据不存在了
assertNull(inboxMapper.selectById(id));
assertNull(imInboxMapper.selectById(id));
}
@Test
@ -108,15 +108,15 @@ public class ImInboxServiceImplTest extends BaseDbUnitTest {
o.setSequence(null);
o.setCreateTime(null);
});
inboxMapper.insert(dbInbox);
imInboxMapper.insert(dbInbox);
// 测试 userId 不匹配
inboxMapper.insert(cloneIgnoreId(dbInbox, o -> o.setUserId(null)));
imInboxMapper.insert(cloneIgnoreId(dbInbox, o -> o.setUserId(null)));
// 测试 messageId 不匹配
inboxMapper.insert(cloneIgnoreId(dbInbox, o -> o.setMessageId(null)));
imInboxMapper.insert(cloneIgnoreId(dbInbox, o -> o.setMessageId(null)));
// 测试 sequence 不匹配
inboxMapper.insert(cloneIgnoreId(dbInbox, o -> o.setSequence(null)));
imInboxMapper.insert(cloneIgnoreId(dbInbox, o -> o.setSequence(null)));
// 测试 createTime 不匹配
inboxMapper.insert(cloneIgnoreId(dbInbox, o -> o.setCreateTime(null)));
imInboxMapper.insert(cloneIgnoreId(dbInbox, o -> o.setCreateTime(null)));
// 准备参数
ImInboxPageReqVO reqVO = new ImInboxPageReqVO();
reqVO.setUserId(null);