From 11bd48dedca2a337bd9b1246f83394604cc418e8 Mon Sep 17 00:00:00 2001 From: xiao12feng8 <16507319+xiao12feng8@user.noreply.gitee.com> Date: Thu, 8 Jan 2026 16:01:50 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=88=E5=B9=B6bug=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/model/chat/PrivateMessageBurn.java | 68 ++++++++ .../common/request/SendMessageRequest.java | 3 + .../common/response/BurnViewResponse.java | 32 ++++ .../common/response/ChatMessageResponse.java | 12 ++ .../controller/ConversationController.java | 9 ++ .../service/dao/PrivateMessageBurnDao.java | 7 + .../service/service/ConversationService.java | 3 + .../service/impl/ConversationServiceImpl.java | 146 +++++++++++++++++- .../sql/create_private_message_burn_table.sql | 15 ++ 9 files changed, 291 insertions(+), 4 deletions(-) create mode 100644 Zhibo/zhibo-h/crmeb-common/src/main/java/com/zbkj/common/model/chat/PrivateMessageBurn.java create mode 100644 Zhibo/zhibo-h/crmeb-common/src/main/java/com/zbkj/common/response/BurnViewResponse.java create mode 100644 Zhibo/zhibo-h/crmeb-service/src/main/java/com/zbkj/service/dao/PrivateMessageBurnDao.java create mode 100644 Zhibo/zhibo-h/sql/create_private_message_burn_table.sql diff --git a/Zhibo/zhibo-h/crmeb-common/src/main/java/com/zbkj/common/model/chat/PrivateMessageBurn.java b/Zhibo/zhibo-h/crmeb-common/src/main/java/com/zbkj/common/model/chat/PrivateMessageBurn.java new file mode 100644 index 00000000..171c5821 --- /dev/null +++ b/Zhibo/zhibo-h/crmeb-common/src/main/java/com/zbkj/common/model/chat/PrivateMessageBurn.java @@ -0,0 +1,68 @@ +package com.zbkj.common.model.chat; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import javax.persistence.*; +import java.io.Serializable; +import java.util.Date; + +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("eb_private_message_burn") +@Entity +@Table(name = "eb_private_message_burn", indexes = { + @Index(name = "uk_message_id", columnList = "message_id", unique = true), + @Index(name = "idx_conversation_id", columnList = "conversation_id"), + @Index(name = "idx_burn_at", columnList = "burn_at") +}) +@ApiModel(value = "PrivateMessageBurn对象", description = "阅后即焚消息状态") +public class PrivateMessageBurn implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "ID") + @TableId(value = "id", type = IdType.AUTO) + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ApiModelProperty(value = "消息ID") + @Column(name = "message_id", nullable = false) + private Long messageId; + + @ApiModelProperty(value = "会话ID") + @Column(name = "conversation_id", nullable = false) + private Long conversationId; + + @ApiModelProperty(value = "销毁秒数") + @Column(name = "burn_seconds") + private Integer burnSeconds; + + @ApiModelProperty(value = "首次查看时间") + @Column(name = "viewed_at") + private Date viewedAt; + + @ApiModelProperty(value = "销毁时间") + @Column(name = "burn_at") + private Date burnAt; + + @ApiModelProperty(value = "是否已销毁") + @Column(name = "burned", columnDefinition = "TINYINT(1) DEFAULT 0") + private Boolean burned; + + @ApiModelProperty(value = "创建时间") + @Column(name = "create_time") + private Date createTime; + + @ApiModelProperty(value = "更新时间") + @Column(name = "update_time") + private Date updateTime; +} diff --git a/Zhibo/zhibo-h/crmeb-common/src/main/java/com/zbkj/common/request/SendMessageRequest.java b/Zhibo/zhibo-h/crmeb-common/src/main/java/com/zbkj/common/request/SendMessageRequest.java index 6445f321..ad5195c1 100644 --- a/Zhibo/zhibo-h/crmeb-common/src/main/java/com/zbkj/common/request/SendMessageRequest.java +++ b/Zhibo/zhibo-h/crmeb-common/src/main/java/com/zbkj/common/request/SendMessageRequest.java @@ -28,6 +28,9 @@ public class SendMessageRequest implements Serializable { @ApiModelProperty(value = "语音时长(可选)") private Integer duration; + @ApiModelProperty(value = "阅后即焚秒数(可选,仅messageType=burn_image时使用)") + private Integer burnSeconds; + // 兼容旧字段 public String getMessage() { return content; diff --git a/Zhibo/zhibo-h/crmeb-common/src/main/java/com/zbkj/common/response/BurnViewResponse.java b/Zhibo/zhibo-h/crmeb-common/src/main/java/com/zbkj/common/response/BurnViewResponse.java new file mode 100644 index 00000000..916dac6a --- /dev/null +++ b/Zhibo/zhibo-h/crmeb-common/src/main/java/com/zbkj/common/response/BurnViewResponse.java @@ -0,0 +1,32 @@ +package com.zbkj.common.response; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; + +@Data +@ApiModel(value = "BurnViewResponse对象", description = "阅后即焚图片查看响应") +public class BurnViewResponse implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "消息ID") + private Long messageId; + + @ApiModelProperty(value = "媒体URL(可为空,已销毁或无权限时不返回)") + private String mediaUrl; + + @ApiModelProperty(value = "销毁秒数") + private Integer burnSeconds; + + @ApiModelProperty(value = "首次查看时间戳(毫秒)") + private Long viewedAt; + + @ApiModelProperty(value = "销毁时间戳(毫秒)") + private Long burnAt; + + @ApiModelProperty(value = "是否已销毁") + private Boolean burned; +} diff --git a/Zhibo/zhibo-h/crmeb-common/src/main/java/com/zbkj/common/response/ChatMessageResponse.java b/Zhibo/zhibo-h/crmeb-common/src/main/java/com/zbkj/common/response/ChatMessageResponse.java index 3878b347..98ff5745 100644 --- a/Zhibo/zhibo-h/crmeb-common/src/main/java/com/zbkj/common/response/ChatMessageResponse.java +++ b/Zhibo/zhibo-h/crmeb-common/src/main/java/com/zbkj/common/response/ChatMessageResponse.java @@ -57,6 +57,18 @@ public class ChatMessageResponse implements Serializable { @ApiModelProperty(value = "语音时长(秒)") private Integer duration; + @ApiModelProperty(value = "阅后即焚秒数(仅messageType=burn_image时)") + private Integer burnSeconds; + + @ApiModelProperty(value = "首次查看时间戳(毫秒,仅messageType=burn_image时)") + private Long viewedAt; + + @ApiModelProperty(value = "销毁时间戳(毫秒,仅messageType=burn_image时)") + private Long burnAt; + + @ApiModelProperty(value = "是否已销毁(仅messageType=burn_image时)") + private Boolean burned; + @ApiModelProperty(value = "是否已读") private Boolean isRead; diff --git a/Zhibo/zhibo-h/crmeb-front/src/main/java/com/zbkj/front/controller/ConversationController.java b/Zhibo/zhibo-h/crmeb-front/src/main/java/com/zbkj/front/controller/ConversationController.java index 7496a302..14ae3881 100644 --- a/Zhibo/zhibo-h/crmeb-front/src/main/java/com/zbkj/front/controller/ConversationController.java +++ b/Zhibo/zhibo-h/crmeb-front/src/main/java/com/zbkj/front/controller/ConversationController.java @@ -2,6 +2,7 @@ package com.zbkj.front.controller; import com.zbkj.common.model.chat.Conversation; import com.zbkj.common.request.SendMessageRequest; +import com.zbkj.common.response.BurnViewResponse; import com.zbkj.common.response.ChatMessageResponse; import com.zbkj.common.response.ConversationResponse; import com.zbkj.common.result.CommonResult; @@ -157,4 +158,12 @@ public class ConversationController { Integer userId = userService.getUserIdException(); return CommonResult.success(conversationService.recallMessage(id, userId)); } + + @ApiOperation(value = "查看阅后即焚图片(触发计时)") + @ApiImplicitParam(name = "id", value = "消息ID", required = true) + @PostMapping("/messages/{id}/burn/view") + public CommonResult viewBurnImage(@PathVariable Long id) { + Integer userId = userService.getUserIdException(); + return CommonResult.success(conversationService.viewBurnImage(id, userId)); + } } diff --git a/Zhibo/zhibo-h/crmeb-service/src/main/java/com/zbkj/service/dao/PrivateMessageBurnDao.java b/Zhibo/zhibo-h/crmeb-service/src/main/java/com/zbkj/service/dao/PrivateMessageBurnDao.java new file mode 100644 index 00000000..c1393d1b --- /dev/null +++ b/Zhibo/zhibo-h/crmeb-service/src/main/java/com/zbkj/service/dao/PrivateMessageBurnDao.java @@ -0,0 +1,7 @@ +package com.zbkj.service.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.zbkj.common.model.chat.PrivateMessageBurn; + +public interface PrivateMessageBurnDao extends BaseMapper { +} diff --git a/Zhibo/zhibo-h/crmeb-service/src/main/java/com/zbkj/service/service/ConversationService.java b/Zhibo/zhibo-h/crmeb-service/src/main/java/com/zbkj/service/service/ConversationService.java index 6c6059c9..e95f674c 100644 --- a/Zhibo/zhibo-h/crmeb-service/src/main/java/com/zbkj/service/service/ConversationService.java +++ b/Zhibo/zhibo-h/crmeb-service/src/main/java/com/zbkj/service/service/ConversationService.java @@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.service.IService; import com.zbkj.common.model.chat.Conversation; import com.zbkj.common.model.chat.PrivateMessage; import com.zbkj.common.request.SendMessageRequest; +import com.zbkj.common.response.BurnViewResponse; import com.zbkj.common.response.ChatMessageResponse; import com.zbkj.common.response.ConversationResponse; @@ -78,4 +79,6 @@ public interface ConversationService extends IService { * 发送消息(带详细参数) */ PrivateMessage sendMessage(Long conversationId, Integer senderId, String messageType, String content, String mediaUrl); + + BurnViewResponse viewBurnImage(Long messageId, Integer userId); } diff --git a/Zhibo/zhibo-h/crmeb-service/src/main/java/com/zbkj/service/service/impl/ConversationServiceImpl.java b/Zhibo/zhibo-h/crmeb-service/src/main/java/com/zbkj/service/service/impl/ConversationServiceImpl.java index 16459baf..042ef53a 100644 --- a/Zhibo/zhibo-h/crmeb-service/src/main/java/com/zbkj/service/service/impl/ConversationServiceImpl.java +++ b/Zhibo/zhibo-h/crmeb-service/src/main/java/com/zbkj/service/service/impl/ConversationServiceImpl.java @@ -6,12 +6,15 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.zbkj.common.exception.CrmebException; import com.zbkj.common.model.chat.Conversation; import com.zbkj.common.model.chat.PrivateMessage; +import com.zbkj.common.model.chat.PrivateMessageBurn; import com.zbkj.common.model.user.User; import com.zbkj.common.request.SendMessageRequest; +import com.zbkj.common.response.BurnViewResponse; import com.zbkj.common.response.ChatMessageResponse; import com.zbkj.common.response.ConversationResponse; import com.zbkj.service.dao.ConversationDao; import com.zbkj.service.dao.PrivateMessageDao; +import com.zbkj.service.dao.PrivateMessageBurnDao; import com.zbkj.service.dao.UserBlacklistDao; import com.zbkj.service.service.ConversationService; import com.zbkj.service.service.OnlineStatusService; @@ -36,6 +39,9 @@ public class ConversationServiceImpl extends ServiceImpl uw = new LambdaUpdateWrapper<>(); @@ -236,6 +271,84 @@ public class ConversationServiceImpl extends ServiceImpl() + .eq(PrivateMessageBurn::getMessageId, messageId) + .last("LIMIT 1")); + + if (burn == null) { + throw new CrmebException("阅后状态不存在"); + } + + Date now = new Date(); + + boolean burned = Boolean.TRUE.equals(burn.getBurned()); + if (!burned && burn.getBurnAt() != null && burn.getBurnAt().getTime() <= now.getTime()) { + burn.setBurned(true); + burn.setUpdateTime(now); + privateMessageBurnDao.updateById(burn); + burned = true; + } + + BurnViewResponse resp = new BurnViewResponse(); + resp.setMessageId(messageId); + resp.setBurnSeconds(burn.getBurnSeconds()); + resp.setViewedAt(burn.getViewedAt() != null ? burn.getViewedAt().getTime() : null); + resp.setBurnAt(burn.getBurnAt() != null ? burn.getBurnAt().getTime() : null); + resp.setBurned(burned); + + if (burned) { + resp.setMediaUrl(null); + return resp; + } + + boolean isSender = message.getSenderId().equals(userId); + boolean isReceiver = message.getReceiverId().equals(userId); + + if (isReceiver) { + if (burn.getViewedAt() == null) { + burn.setViewedAt(now); + long burnAtMs = now.getTime() + (burn.getBurnSeconds() != null ? burn.getBurnSeconds() : 0) * 1000L; + burn.setBurnAt(new Date(burnAtMs)); + burn.setUpdateTime(now); + privateMessageBurnDao.updateById(burn); + + resp.setViewedAt(burn.getViewedAt().getTime()); + resp.setBurnAt(burn.getBurnAt().getTime()); + resp.setMediaUrl(message.getMediaUrl()); + } else { + // 接收方只允许查看一次 + resp.setMediaUrl(null); + } + return resp; + } + + if (isSender) { + resp.setMediaUrl(message.getMediaUrl()); + return resp; + } + + resp.setMediaUrl(null); + return resp; + } + @Override @Transactional(rollbackFor = Exception.class) public Boolean deleteMessage(Long messageId, Integer userId) { @@ -395,6 +508,26 @@ public class ConversationServiceImpl extends ServiceImpl() + .eq(PrivateMessageBurn::getMessageId, messageId) + .last("LIMIT 1")); + if (burn == null) { + return; + } + + response.setBurnSeconds(burn.getBurnSeconds()); + response.setViewedAt(burn.getViewedAt() != null ? burn.getViewedAt().getTime() : null); + response.setBurnAt(burn.getBurnAt() != null ? burn.getBurnAt().getTime() : null); + + boolean burned = Boolean.TRUE.equals(burn.getBurned()); + if (!burned && burn.getBurnAt() != null && burn.getBurnAt().getTime() <= System.currentTimeMillis()) { + burned = true; + } + response.setBurned(burned); + } + /** * 转换消息列表为响应对象列表 */ @@ -425,6 +558,11 @@ public class ConversationServiceImpl extends ServiceImpl