Commit b4ad4ff1 by Future

支持双向撤销,删除消息修改

parent 31427855
......@@ -2,13 +2,14 @@ package com.wecloud.im.controller;
import com.wecloud.im.param.GetReadersParam;
import com.wecloud.im.param.ImHistoryMessagePageParam;
import com.wecloud.im.param.MsgDeleteParam;
import com.wecloud.im.param.add.ImMsgRecall;
import com.wecloud.im.param.add.ImMsgUpdate;
import com.wecloud.im.service.ImMessageService;
import com.wecloud.im.vo.ImMessageOfflineListVo;
import com.wecloud.im.vo.OfflineMsgDto;
import com.wecloud.im.vo.ReaderList;
import com.wecloud.im.vo.ReaderVo;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.controller.BaseController;
import io.geekidea.springbootplus.framework.core.pagination.Paging;
......@@ -17,6 +18,7 @@ import io.geekidea.springbootplus.framework.log.enums.OperationLogType;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
......@@ -51,6 +53,21 @@ public class ImMessageController extends BaseController {
}
/**
* 删除消息
*/
@PostMapping("/delete")
@ApiOperation(value = "删除消息", notes = "单条消息与批量消息删除共用")
public ApiResult<Boolean> deleteMsg(@RequestBody MsgDeleteParam param) {
if(param == null) {
return ApiResult.fail(ApiCode.PARAMETER_EXCEPTION, null);
}
if (CollectionUtils.isEmpty(param.getMsgIds())) {
return ApiResult.fail("请选择要删除");
}
return imMessageService.deleteMsg(param);
}
/**
* 修改消息体
*/
@PostMapping("/updateMsgById")
......@@ -90,61 +107,5 @@ public class ImMessageController extends BaseController {
return ApiResult.ok(readerList);
}
//
// /**
// * 添加消息存储表
// */
// @PostMapping("/add")
// @OperationLog(name = "添加消息存储表", type = OperationLogType.ADD)
// @ApiOperation(value = "添加消息存储表")
// public ApiResult<Boolean> addImMessage(@Validated(Add.class) @RequestBody ImMessage imMessage) throws Exception {
// boolean flag = imMessageService.saveImMessage(imMessage);
// return ApiResult.result(flag);
// }
//
// /**
// * 修改消息存储表
// */
// @PostMapping("/update")
// @OperationLog(name = "修改消息存储表", type = OperationLogType.UPDATE)
// @ApiOperation(value = "修改消息存储表")
// public ApiResult<Boolean> updateImMessage(@Validated(Update.class) @RequestBody ImMessage imMessage) throws Exception {
// boolean flag = imMessageService.updateImMessage(imMessage);
// return ApiResult.result(flag);
// }
//
// /**
// * 删除消息存储表
// */
// @PostMapping("/delete/{id}")
// @OperationLog(name = "删除消息存储表", type = OperationLogType.DELETE)
// @ApiOperation(value = "删除消息存储表")
// public ApiResult<Boolean> deleteImMessage(@PathVariable("id") Long id) throws Exception {
// boolean flag = imMessageService.deleteImMessage(id);
// return ApiResult.result(flag);
// }
//
// /**
// * 获取消息存储表详情
// */
// @GetMapping("/info/{id}")
// @OperationLog(name = "消息存储表详情", type = OperationLogType.INFO)
// @ApiOperation(value = "消息存储表详情")
// public ApiResult<ImMessageQueryVo> getImMessage(@PathVariable("id") Long id) throws Exception {
// ImMessageQueryVo imMessageQueryVo = imMessageService.getImMessageById(id);
// return ApiResult.ok(imMessageQueryVo);
// }
//
// /**
// * 消息存储表分页列表
// */
// @PostMapping("/getPageList")
// @OperationLog(name = "消息存储表分页列表", type = OperationLogType.PAGE)
// @ApiOperation(value = "消息存储表分页列表")
// public ApiResult<Paging<ImMessageQueryVo>> getImMessagePageList(@Validated @RequestBody ImMessagePageParam imMessagePageParam) throws Exception {
// Paging<ImMessageQueryVo> paging = imMessageService.getImMessagePageList(imMessagePageParam);
// return ApiResult.ok(paging);
// }
}
......@@ -76,4 +76,7 @@ public class ImMessage extends BaseEntity {
@ApiModelProperty("消息类型")
private Integer msgType;
@ApiModelProperty("是否删除 1-未删除 2-已删除")
private Integer isDelete;
}
......@@ -24,6 +24,10 @@ import java.util.Map;
public class ImMessageOnlineSend extends BaseEntity {
private static final long serialVersionUID = 1L;
/**
* 消息类型
* @see com.wecloud.im.ws.enums.MsgTypeEnum
*/
@ApiModelProperty("消息类型")
private Integer type;
......
package com.wecloud.im.param;
import com.wecloud.im.ws.model.request.PushVO;
import io.geekidea.springbootplus.framework.common.entity.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.util.List;
/**
* @Author wenzhida
* @Date 2022/2/16 10:21
* @Description 消息删除入参
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ApiModel(value = "消息删除入参")
public class MsgDeleteParam extends BaseEntity {
private static final long serialVersionUID = 3930222684211662765L;
@ApiModelProperty("消息id列表")
private List<Long> msgIds;
@ApiModelProperty("自定义推送字段")
private PushVO push;
}
......@@ -7,6 +7,7 @@ import com.wecloud.im.param.ChatContentVo;
import com.wecloud.im.param.GetReadersParam;
import com.wecloud.im.param.ImClientSimpleDto;
import com.wecloud.im.param.ImHistoryMessagePageParam;
import com.wecloud.im.param.MsgDeleteParam;
import com.wecloud.im.param.add.ImMsgRecall;
import com.wecloud.im.param.add.ImMsgSendToOnlineClient;
import com.wecloud.im.param.add.ImMsgUpdate;
......@@ -54,6 +55,13 @@ public interface ImMessageService extends BaseService<ImMessage> {
ApiResult<Boolean> updateMsgWithdrawById(ImMsgRecall imMsgRecall);
/**
* 删除消息
* @param param
* @return
*/
ApiResult<Boolean> deleteMsg(MsgDeleteParam param);
/**
* 修改消息体
*
* @param imMsgUpdate
......
......@@ -18,6 +18,7 @@ import com.wecloud.im.param.ChatContentVo;
import com.wecloud.im.param.GetReadersParam;
import com.wecloud.im.param.ImClientSimpleDto;
import com.wecloud.im.param.ImHistoryMessagePageParam;
import com.wecloud.im.param.MsgDeleteParam;
import com.wecloud.im.param.add.ImMsgRecall;
import com.wecloud.im.param.add.ImMsgSendToOnlineClient;
import com.wecloud.im.param.add.ImMsgUpdate;
......@@ -31,6 +32,7 @@ import com.wecloud.im.vo.ImMessageOfflineListVo;
import com.wecloud.im.vo.OfflineMsgDto;
import com.wecloud.im.vo.ReaderList;
import com.wecloud.im.vo.ReaderVo;
import com.wecloud.im.ws.enums.MsgTypeEnum;
import com.wecloud.im.ws.enums.WsResponseCmdEnum;
import com.wecloud.im.ws.model.WsResponse;
import com.wecloud.im.ws.model.request.PushVO;
......@@ -196,20 +198,18 @@ public class ImMessageServiceImpl extends BaseServiceImpl<ImMessageMapper, ImMes
@Override
@Transactional(rollbackFor = Exception.class)
public ApiResult<Boolean> updateMsgWithdrawById(ImMsgRecall imMsgRecall) {
ImClient imClientSender = imClientService.getCurentClient();
ImClient currentClient = imClientService.getCurentClient();
// 查询imApplication
ImApplication imApplication = imApplicationService.getCacheById(imClientSender.getFkAppid());
ImApplication imApplication = imApplicationService.getCacheById(currentClient.getFkAppid());
if (imApplication == null) {
log.info("imApplication为空");
return ApiResult.fail();
return ApiResult.fail("查无应用信息");
}
// 判断该消息是否是该客户端发送
ImMessage messageById = this.getById(imMsgRecall.getMsgId());
if (!messageById.getSender().equals(imClientSender.getId())) {
log.error("判断该消息是否是该客户端发送");
return ApiResult.fail();
// 判断该消息是否是该客户端发送 todo 单向撤回、双向撤回开关可配置
Boolean withdrawOther = true;
if (!withdrawOther && !messageById.getSender().equals(currentClient.getId())) {
return ApiResult.fail("不可撤回别人发送的消息");
}
if (messageById.getWithdraw()) {
return ApiResult.ok();
......@@ -223,18 +223,15 @@ public class ImMessageServiceImpl extends BaseServiceImpl<ImMessageMapper, ImMes
boolean saveOk = this.updateById(messageById);
if (saveOk) {
// 查询该会话所有成员
List<ImConversationMembers> membersList = imConversationMembersService.list(
new QueryWrapper<ImConversationMembers>().lambda()
.eq(ImConversationMembers::getFkConversationId, messageById.getFkConversationId())
.notIn(ImConversationMembers::getFkClientId, imClientSender.getId())
.notIn(ImConversationMembers::getFkClientId, currentClient.getId())
);
if (membersList.isEmpty()) {
log.info("membersList为空,toConversationId:" + messageById.getFkConversationId());
return ApiResult.fail();
return ApiResult.fail("该会话成员列表为空");
}
// 遍历发送
for (ImConversationMembers conversationMembers : membersList) {
......@@ -262,8 +259,9 @@ public class ImMessageServiceImpl extends BaseServiceImpl<ImMessageMapper, ImMes
// 封装响应的实体
ImMessageOnlineSend imMessageOnlineSend = new ImMessageOnlineSend();
BeanUtils.copyProperties(messageById, imMessageOnlineSend);
imMessageOnlineSend.setType(MsgTypeEnum.MSG_WITHDRAW.getUriCode());
imMessageOnlineSend.setMsgId(messageById.getId());
imMessageOnlineSend.setSender(imClientSender.getClientId());
imMessageOnlineSend.setSender(currentClient.getClientId());
imMessageOnlineSend.setContent(null);
imMessageOnlineSend.setConversationId(conversationMembers.getFkConversationId());
imMessageOnlineSend.setWithdraw(Boolean.TRUE);
......@@ -294,6 +292,100 @@ public class ImMessageServiceImpl extends BaseServiceImpl<ImMessageMapper, ImMes
}
@Override
public ApiResult<Boolean> deleteMsg(MsgDeleteParam param) {
ImClient currentClient = imClientService.getCurentClient();
// 查询imApplication
ImApplication imApplication = imApplicationService.getCacheById(currentClient.getFkAppid());
if (imApplication == null) {
return ApiResult.fail("查无应用信息");
}
// todo 单向撤回、双向撤回开关可配置
Boolean deleteOther = true;
List<ImMessage> imMessageList = this.listByIds(param.getMsgIds());
if (CollectionUtils.isEmpty(imMessageList)) {
return ApiResult.fail("查无消息");
}
for (ImMessage message : imMessageList) {
// 判断该消息是否是该客户端发送
if (!deleteOther && !message.getSender().equals(currentClient.getId())) {
return ApiResult.fail("不可删除别人发送的消息");
}
if (message.getIsDelete() == 2) {
continue;
}
// 修改消息体
message.setIsDelete(2);
message.setUpdateDate(new Date());
boolean saveOk = this.updateById(message);
if (saveOk) {
// 查询该会话所有成员
List<ImConversationMembers> membersList = imConversationMembersService.list(
new QueryWrapper<ImConversationMembers>().lambda()
.eq(ImConversationMembers::getFkConversationId, message.getFkConversationId())
.notIn(ImConversationMembers::getFkClientId, currentClient.getId())
);
if (membersList.isEmpty()) {
log.info("membersList为空,toConversationId:" + message.getFkConversationId());
return ApiResult.fail("该会话成员列表为空");
}
// 遍历发送
for (ImConversationMembers conversationMembers : membersList) {
// // 保存收件箱
// long imInboxId = SnowflakeUtil.getId();
// ImInbox imInbox = new ImInbox();
// imInbox.setId(imInboxId);
// imInbox.setCreateTime(new Date());
// imInbox.setFkAppid(imApplication.getId());
// imInbox.setReceiver(conversationMembers.getFkClientId());
// imInbox.setFkMsgId(messageId);
// imInbox.setReadMsgStatus(0);
// imInbox.setReceiverMsgStatus(0);
// imInbox.setFkConversationId(toConversationId);
// imInboxService.save(imInbox);
// 查询接收方
ImClient imClientReceiver = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
.eq(ImClient::getFkAppid, imApplication.getId())
.eq(ImClient::getId, conversationMembers.getFkClientId()));
if (imClientReceiver == null) {
continue;
}
// 封装响应的实体
ImMessageOnlineSend imMessageOnlineSend = new ImMessageOnlineSend();
BeanUtils.copyProperties(message, imMessageOnlineSend);
imMessageOnlineSend.setType(MsgTypeEnum.MSG_DELETE.getUriCode());
imMessageOnlineSend.setMsgId(message.getId());
imMessageOnlineSend.setSender(currentClient.getClientId());
imMessageOnlineSend.setContent(null);
imMessageOnlineSend.setConversationId(conversationMembers.getFkConversationId());
imMessageOnlineSend.setEvent(Boolean.TRUE);
// 向接收方推送
WsResponse<ImMessageOnlineSend> responseModel = new WsResponse<>();
responseModel.setCmd(WsResponseCmdEnum.ONLINE_EVENT_MSG.getCmdCode());
ApiResult<Boolean> result = ApiResult.result(ApiCode.SUCCESS);
responseModel.setCode(result.getCode());
responseModel.setMsg(result.getMessage());
responseModel.setData(imMessageOnlineSend);
responseModel.setReqId(null);
channelSender.sendMsg(responseModel, imClientReceiver.getId());
// 获取自定义推送字段
PushVO pushVO = param.getPush();
// 异步推送系统通知消息
asyncPush.push(pushVO, imClientReceiver, imApplication);
}
return ApiResult.ok();
} else {
return ApiResult.fail("删除消息错误,稍后重试");
}
}
return ApiResult.ok();
}
@Override
@Transactional(rollbackFor = Exception.class)
public ApiResult<Boolean> updateMsgById(ImMsgUpdate imMsgUpdate) {
......
......@@ -29,6 +29,12 @@ public enum MsgTypeEnum {
// 成为新群主 -1013
CONVERSATION_NEW_CREATOR(-1013),
// 消息撤回 -1016
MSG_WITHDRAW(-1016),
// 消息删除 -1017
MSG_DELETE(-1017),
;
private final int uriCode;
......
......@@ -48,6 +48,7 @@
WHERE im_inbox.fk_conversation_id = #{conversationId}
AND im_inbox.receiver = #{clientId}
AND im_inbox.receiver_msg_status = 0
AND im_message.is_delete = 1
</select>
<select id="getHistoryMsgConversationId" resultType="com.wecloud.im.vo.OfflineMsgDto">
SELECT im_message.id AS msgId,
......@@ -69,7 +70,7 @@
AND receiver_msg_status = 0) AS not_receiver_count
FROM `im_message`
INNER JOIN `im_client` ON `im_client`.id = `im_message`.sender
WHERE fk_conversation_id = #{param.conversationId}
WHERE fk_conversation_id = #{param.conversationId} and im_message.is_delete = 1
<if test="param.msgIdStart != null">
AND im_message.id > #{param.msgIdStart}
</if>
......
......@@ -52,7 +52,7 @@
AS not_receiver_count
from im_message msg INNER JOIN `im_client` client ON client.id = msg.sender
where
(msg.fk_conversation_id = #{lastestMsg.conversationId} and msg.id > #{lastestMsg.lastestReceiveMsgId} )
(and msg.is_delete = 1 and msg.fk_conversation_id = #{lastestMsg.conversationId} and msg.id > #{lastestMsg.lastestReceiveMsgId} )
</foreach>
......
-- 在feature-cluster 2021年12月22日之后,需要执行的的sql增量脚本
-- 在feature-cluster 2021年12月22日之后,需要执行的的sql增量脚本
......@@ -62,4 +62,6 @@ CREATE TABLE `im_friend_recommend`
-- 2022年01月21日17:31:16 何威 将type参数上移一层
ALTER TABLE `im_message`
ADD COLUMN`msg_type` int(2) NULL DEFAULT NULL COMMENT '消息类型' AFTER`send_status`;
\ No newline at end of file
ADD COLUMN`msg_type` int(2) NULL DEFAULT NULL COMMENT '消息类型' AFTER`send_status`;
ALTER TABLE im_message ADD COLUMN is_delete tinyint NOT NULL DEFAULT '1' COMMENT '是否删除 1-未删除 2-删除';
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment