feat: 消息聊天最近列表支持删除会话

This commit is contained in:
2026-04-03 17:15:02 +08:00
parent dc666897c6
commit 4ac6e85aca
4 changed files with 52 additions and 2 deletions

View File

@@ -276,4 +276,12 @@ public class MessageController {
messageService.markAsRead(id); messageService.markAsRead(id);
return ResponseEntity.ok(Map.of("message", "已标记已读")); return ResponseEntity.ok(Map.of("message", "已标记已读"));
} }
@DeleteMapping("/conversation/{withUserId}")
public ResponseEntity<?> deleteConversation(
@AuthenticationPrincipal UserPrincipal principal,
@PathVariable Long withUserId) {
messageService.deleteConversation(principal.getUserId(), withUserId);
return ResponseEntity.ok(Map.of("message", "已删除"));
}
} }

View File

@@ -4,6 +4,8 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.filesystem.entity.Message; import com.filesystem.entity.Message;
import com.filesystem.mapper.MessageMapper; import com.filesystem.mapper.MessageMapper;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.*; import java.util.*;
@@ -15,7 +17,15 @@ public class MessageService {
@Resource @Resource
private MessageMapper messageMapper; private MessageMapper messageMapper;
@Autowired
private StringRedisTemplate redisTemplate;
private static final String CONV_DELETED_KEY = "msg:del:";
public List<Message> getMessages(Long userId1, Long userId2) { public List<Message> getMessages(Long userId1, Long userId2) {
String convKey = buildConvKey(userId1, userId2);
String deletedKey = CONV_DELETED_KEY + userId1 + ":" + convKey;
return messageMapper.selectList( return messageMapper.selectList(
new LambdaQueryWrapper<Message>() new LambdaQueryWrapper<Message>()
.and(wrapper -> wrapper .and(wrapper -> wrapper
@@ -27,6 +37,31 @@ public class MessageService {
); );
} }
/**
* 删除与某个用户的聊天记录(双向,本人会看不到)
*/
public void deleteConversation(Long userId, Long withUserId) {
String convKey = buildConvKey(userId, withUserId);
String deletedKey = CONV_DELETED_KEY + userId + ":" + convKey;
// 保留7天
redisTemplate.opsForValue().set(deletedKey, "1", java.time.Duration.ofDays(7));
}
/**
* 检查与某人的对话是否已被当前用户删除
*/
public boolean isConversationDeleted(Long userId, Long withUserId) {
String convKey = buildConvKey(userId, withUserId);
String deletedKey = CONV_DELETED_KEY + userId + ":" + convKey;
return Boolean.TRUE.equals(redisTemplate.hasKey(deletedKey));
}
private String buildConvKey(Long userId1, Long userId2) {
long min = Math.min(userId1, userId2);
long max = Math.max(userId1, userId2);
return min + "_" + max;
}
public Message sendMessage(Long fromUserId, Long toUserId, String content, String type) { public Message sendMessage(Long fromUserId, Long toUserId, String content, String type) {
Message message = new Message(); Message message = new Message();
message.setFromUserId(fromUserId); message.setFromUserId(fromUserId);

View File

@@ -10,6 +10,8 @@ export const getUnreadList = () => request.get('/messages/unreadList')
export const markAsRead = (id) => request.post(`/messages/${id}/read`) export const markAsRead = (id) => request.post(`/messages/${id}/read`)
export const deleteConversation = (withUserId) => request.delete(`/messages/conversation/${withUserId}`)
export const getUsers = () => request.get('/messages/users') export const getUsers = () => request.get('/messages/users')
// 聊天文件上传(图片和文件统一接口) // 聊天文件上传(图片和文件统一接口)

View File

@@ -217,7 +217,7 @@ import { ref, computed, onMounted, onUnmounted, nextTick } from 'vue'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import { ChatLineRound, User, Search, Close, Loading, Picture, Paperclip, Download, ChatDotRound, Promotion } from '@element-plus/icons-vue' import { ChatLineRound, User, Search, Close, Loading, Picture, Paperclip, Download, ChatDotRound, Promotion } from '@element-plus/icons-vue'
import { useUserStore } from '@/store/user' import { useUserStore } from '@/store/user'
import { getUsers, getMessages, sendMessage as sendMessageApi, uploadChatFile, getUnreadList } from '@/api/message' import { getUsers, getMessages, sendMessage as sendMessageApi, uploadChatFile, getUnreadList, deleteConversation } from '@/api/message'
import { chatService } from '@/services/chat' import { chatService } from '@/services/chat'
const props = defineProps({ modelValue: Boolean }) const props = defineProps({ modelValue: Boolean })
@@ -571,7 +571,12 @@ const downloadFile = async (msg) => {
// ======== 其他操作 ======== // ======== 其他操作 ========
const deleteRecentChat = (chat) => { const deleteRecentChat = async (chat) => {
try {
await deleteConversation(chat.id)
} catch (e) {
// 即使 API 失败也删本地
}
const idx = recentChats.value.findIndex(c => c.id === chat.id) const idx = recentChats.value.findIndex(c => c.id === chat.id)
if (idx > -1) recentChats.value.splice(idx, 1) if (idx > -1) recentChats.value.splice(idx, 1)
if (currentContact.value?.id === chat.id) currentContact.value = null if (currentContact.value?.id === chat.id) currentContact.value = null