删除聊天记录功能开发

This commit is contained in:
冯辉
2026-03-16 14:28:38 +08:00
parent 23a286cb64
commit 5046e7467f
2 changed files with 209 additions and 4 deletions

View File

@@ -1,7 +1,18 @@
<template> <template>
<view class="chat-container"> <view class="chat-container">
<!-- 选择模式操作栏 -->
<view v-if="isSelectMode" class="select-mode-header">
<view class="select-header-left">
<view class="select-count">{{ selectedMessages.length }} 条已选择</view>
<view class="select-all" @click="selectAllMessages">全选</view>
</view>
<view class="select-header-right">
<view class="cancel-btn" @click="exitSelectMode">取消</view>
<view class="delete-btn" @click="deleteSelectedMessages" :disabled="selectedMessages.length === 0">删除</view>
</view>
</view>
<!-- Tab切换 --> <!-- Tab切换 -->
<view class="tab-container"> <view v-else class="tab-container">
<view <view
class="tab-item" class="tab-item"
:class="{ active: activeTab === 'policy' }" :class="{ active: activeTab === 'policy' }"
@@ -74,7 +85,15 @@
:id="'msg-' + index" :id="'msg-' + index"
class="chat-item" class="chat-item"
:class="{ self: msg.self }" :class="{ self: msg.self }"
@longpress="handleLongPress(msg, index)"
@click="isSelectMode ? toggleSelectMessage(index) : null"
> >
<!-- 选择框 -->
<view v-if="isSelectMode" class="message-checkbox">
<view class="checkbox" :class="{ checked: selectedMessages.includes(index) }">
<uni-icons v-if="selectedMessages.includes(index)" type="success" size="24" color="#FFFFFF"></uni-icons>
</view>
</view>
<view class="message" v-if="msg.self"> <view class="message" v-if="msg.self">
<view class="msg-filecontent" v-if="msg.files.length"> <view class="msg-filecontent" v-if="msg.files.length">
<view <view
@@ -96,7 +115,7 @@
:content="msg.displayText" :content="msg.displayText"
:typing="isTyping && messages.length - 1 === index" :typing="isTyping && messages.length - 1 === index"
></md-render> ></md-render>
<view class="message-controll" v-show="showControll(index)"> <view class="message-controll" v-show="showControll(index) && !isSelectMode">
<view class="controll-left"> <view class="controll-left">
<image <image
class="controll-icon btn-light" class="controll-icon btn-light"
@@ -134,7 +153,7 @@
<!-- guess --> <!-- guess -->
<view <view
class="guess" class="guess"
v-if="showGuess && !msg.self && messages.length - 1 === index && msg.displayText" v-if="showGuess && !msg.self && messages.length - 1 === index && msg.displayText && !isSelectMode"
> >
<view class="gulist"> <view class="gulist">
<view <view
@@ -386,6 +405,9 @@ const cancelThreshold = 100;
const speechIndex = ref(0); const speechIndex = ref(0);
const isAudioPermission = ref(false); const isAudioPermission = ref(false);
const feebackData = ref(null); const feebackData = ref(null);
// 删除功能相关状态
const isSelectMode = ref(false);
const selectedMessages = ref([]);
// ref for DOM element // ref for DOM element
const voiceBtn = ref(null); const voiceBtn = ref(null);
const feeback = ref(null); const feeback = ref(null);
@@ -942,6 +964,88 @@ function shouldShowMessage(msg) {
} }
} }
// 长按事件处理函数
function handleLongPress(msg, index) {
isSelectMode.value = true;
selectedMessages.value = [index];
// 如果长按的是用户消息同时选中对应的AI回复
if (msg.self) {
const nextIndex = index + 1;
if (nextIndex < messages.value.length && !messages.value[nextIndex].self) {
selectedMessages.value.push(nextIndex);
}
}
}
// 选择/取消选择消息
function toggleSelectMessage(index) {
const msg = messages.value[index];
const idx = selectedMessages.value.indexOf(index);
if (idx > -1) {
// 取消选择
selectedMessages.value.splice(idx, 1);
// 如果取消选择的是用户消息同时取消选择对应的AI回复
if (msg.self) {
const nextIndex = index + 1;
if (nextIndex < messages.value.length && !messages.value[nextIndex].self) {
const aiIdx = selectedMessages.value.indexOf(nextIndex);
if (aiIdx > -1) {
selectedMessages.value.splice(aiIdx, 1);
}
}
}
if (selectedMessages.value.length === 0) {
isSelectMode.value = false;
}
} else {
// 选择消息
selectedMessages.value.push(index);
// 如果选择的是用户消息同时选择对应的AI回复
if (msg.self) {
const nextIndex = index + 1;
if (nextIndex < messages.value.length && !messages.value[nextIndex].self) {
if (!selectedMessages.value.includes(nextIndex)) {
selectedMessages.value.push(nextIndex);
}
}
}
}
}
// 退出选择模式
function exitSelectMode() {
isSelectMode.value = false;
selectedMessages.value = [];
}
// 全选消息
function selectAllMessages() {
selectedMessages.value = messages.value.map((_, index) => index);
}
// 删除选中消息
function deleteSelectedMessages() {
if (selectedMessages.value.length === 0) return;
uni.showModal({
content: `确定删除${selectedMessages.value.length}条消息吗?`,
success(res) {
if (res.confirm) {
// 调用store中的删除方法
useChatGroupDBStore().deleteMessages(selectedMessages.value);
// 退出选择模式
exitSelectMode();
$api.msg('消息删除成功');
}
}
});
}
defineExpose({ scrollToBottom, closeGuess, closeFile, changeQueries, handleTouchCancel, switchTab }); defineExpose({ scrollToBottom, closeGuess, closeFile, changeQueries, handleTouchCancel, switchTab });
</script> </script>
@@ -1473,4 +1577,88 @@ image-margin-top = 40rpx
.tab-item:active { .tab-item:active {
background-color: #F5F5F5; background-color: #F5F5F5;
} }
/* 选择模式样式 */
.select-mode-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 44rpx;
height: 88rpx;
background: #FFFFFF;
border-bottom: 2rpx solid #F4F4F4;
z-index: 10;
}
.select-header-left {
display: flex;
align-items: center;
gap: 24rpx;
}
.select-count {
font-size: 28rpx;
color: #333333;
font-weight: 500;
}
.select-all {
font-size: 28rpx;
color: #256BFA;
font-weight: 500;
}
.select-header-right {
display: flex;
align-items: center;
gap: 32rpx;
}
.cancel-btn {
font-size: 28rpx;
color: #666666;
font-weight: 500;
}
.delete-btn {
font-size: 28rpx;
color: #FF4444;
font-weight: 500;
}
.delete-btn:disabled {
color: #CCCCCC;
}
/* 消息选择框样式 */
.message-checkbox {
margin-right: 12rpx;
display: flex;
align-items: flex-start;
padding-top: 8rpx;
}
.checkbox {
width: 40rpx;
height: 40rpx;
border: 2rpx solid #CCCCCC;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
.checkbox.checked {
background-color: #256BFA;
border-color: #256BFA;
}
/* 调整消息项布局,为选择框留出空间 */
.chat-item {
position: relative;
}
.chat-item .message {
flex: 1;
}
</style> </style>

View File

@@ -335,6 +335,22 @@ const useChatGroupDBStore = defineStore("messageGroup", () => {
})) }))
} }
// 删除消息
async function deleteMessages(indices) {
// 按索引从大到小排序,避免删除时索引变化
const sortedIndices = [...indices].sort((a, b) => b - a);
// 从内存中删除消息
for (const index of sortedIndices) {
const message = messages.value[index];
if (message && message.id) {
// 从本地数据库中删除
await baseDB.db.delete(massageName.value, message.id);
}
messages.value.splice(index, 1);
}
}
return { return {
messages, messages,
isTyping, isTyping,
@@ -348,7 +364,8 @@ const useChatGroupDBStore = defineStore("messageGroup", () => {
changeDialogue, changeDialogue,
getStearm, getStearm,
getHistory, getHistory,
badFeedback badFeedback,
deleteMessages
}; };
}); });