refactor: streamline message editing and enhance error handling

- Removed unnecessary database update in useMessageOperations during message editing.
- Improved user feedback for missing original user messages by integrating localized error messages in multiple languages.
- Simplified event listener for message sending in Messages component.
- Enhanced message resend logic in messages slice to ensure proper error handling and state updates.
This commit is contained in:
kangfenmao 2025-03-15 15:11:36 +08:00
parent d1087ec87c
commit a30cfb53bf
9 changed files with 34 additions and 22 deletions

View File

@ -1,4 +1,3 @@
import db from '@renderer/databases'
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService' import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
import store, { useAppDispatch, useAppSelector } from '@renderer/store' import store, { useAppDispatch, useAppSelector } from '@renderer/store'
import { import {
@ -63,11 +62,8 @@ export function useMessageOperations(topic: Topic) {
updates updates
}) })
) )
await db.topics.update(topic.id, {
messages: messages.map((m) => (m.id === messageId ? { ...m, ...updates } : m))
})
}, },
[dispatch, messages, topic.id] [dispatch, topic.id]
) )
/** /**

View File

@ -248,7 +248,8 @@
"render": { "render": {
"description": "Failed to render formula. Please check if the formula format is correct", "description": "Failed to render formula. Please check if the formula format is correct",
"title": "Render Error" "title": "Render Error"
} },
"user_message_not_found": "Cannot find original user message to resend"
}, },
"export": { "export": {
"assistant": "Assistant", "assistant": "Assistant",

View File

@ -248,7 +248,8 @@
"render": { "render": {
"description": "数式のレンダリングに失敗しました。数式の形式が正しいか確認してください", "description": "数式のレンダリングに失敗しました。数式の形式が正しいか確認してください",
"title": "レンダリングエラー" "title": "レンダリングエラー"
} },
"user_message_not_found": "元のユーザーメッセージを見つけることができませんでした"
}, },
"export": { "export": {
"assistant": "アシスタント", "assistant": "アシスタント",

View File

@ -248,7 +248,8 @@
"render": { "render": {
"description": "Не удалось рендерить формулу. Пожалуйста, проверьте, правильно ли формат формулы", "description": "Не удалось рендерить формулу. Пожалуйста, проверьте, правильно ли формат формулы",
"title": "Ошибка рендеринга" "title": "Ошибка рендеринга"
} },
"user_message_not_found": "Не удалось найти исходное сообщение пользователя"
}, },
"export": { "export": {
"assistant": "Ассистент", "assistant": "Ассистент",

View File

@ -248,7 +248,8 @@
"render": { "render": {
"description": "渲染公式失败,请检查公式格式是否正确", "description": "渲染公式失败,请检查公式格式是否正确",
"title": "渲染错误" "title": "渲染错误"
} },
"user_message_not_found": "无法找到原始用户消息"
}, },
"export": { "export": {
"assistant": "助手", "assistant": "助手",

View File

@ -248,7 +248,8 @@
"render": { "render": {
"description": "渲染公式失敗,請檢查公式格式是否正確", "description": "渲染公式失敗,請檢查公式格式是否正確",
"title": "渲染錯誤" "title": "渲染錯誤"
} },
"user_message_not_found": "無法找到原始用戶訊息"
}, },
"export": { "export": {
"assistant": "助手", "assistant": "助手",

View File

@ -120,10 +120,10 @@ const MessageMenubar: FC<Props> = (props) => {
) : null ) : null
} }
}) })
if (editedText && editedText !== message.content && resendMessage) {
// 同步修改store中用户消息 if (editedText && editedText !== message.content) {
await editMessage(message.id, { content: editedText }) await editMessage(message.id, { content: editedText })
handleResendUserMessage({ ...message, content: editedText }) resendMessage && handleResendUserMessage({ ...message, content: editedText })
} }
}, [message, editMessage, handleResendUserMessage, t]) }, [message, editMessage, handleResendUserMessage, t])

View File

@ -68,9 +68,7 @@ const Messages: React.FC<MessagesProps> = ({ assistant, topic, setActiveTopic })
useEffect(() => { useEffect(() => {
const unsubscribes = [ const unsubscribes = [
EventEmitter.on(EVENT_NAMES.SEND_MESSAGE, () => { EventEmitter.on(EVENT_NAMES.SEND_MESSAGE, scrollToBottom),
scrollToBottom()
}),
EventEmitter.on(EVENT_NAMES.CLEAR_MESSAGES, async (data: Topic) => { EventEmitter.on(EVENT_NAMES.CLEAR_MESSAGES, async (data: Topic) => {
const defaultTopic = getDefaultTopic(assistant.id) const defaultTopic = getDefaultTopic(assistant.id)

View File

@ -1,6 +1,7 @@
import { createAsyncThunk, createSelector, createSlice, type PayloadAction } from '@reduxjs/toolkit' import { createAsyncThunk, createSelector, createSlice, type PayloadAction } from '@reduxjs/toolkit'
import db from '@renderer/databases' import db from '@renderer/databases'
import { autoRenameTopic, TopicManager } from '@renderer/hooks/useTopic' import { autoRenameTopic, TopicManager } from '@renderer/hooks/useTopic'
import i18n from '@renderer/i18n'
import { fetchChatCompletion } from '@renderer/services/ApiService' import { fetchChatCompletion } from '@renderer/services/ApiService'
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService' import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
import { getAssistantMessage, resetAssistantMessage } from '@renderer/services/MessagesService' import { getAssistantMessage, resetAssistantMessage } from '@renderer/services/MessagesService'
@ -8,7 +9,7 @@ import type { AppDispatch, RootState } from '@renderer/store'
import type { Assistant, Message, Topic } from '@renderer/types' import type { Assistant, Message, Topic } from '@renderer/types'
import { Model } from '@renderer/types' import { Model } from '@renderer/types'
import { clearTopicQueue, getTopicQueue, waitForTopicQueue } from '@renderer/utils/queue' import { clearTopicQueue, getTopicQueue, waitForTopicQueue } from '@renderer/utils/queue'
import { throttle } from 'lodash' import { cloneDeep, throttle } from 'lodash'
export interface MessagesState { export interface MessagesState {
messagesByTopic: Record<string, Message[]> messagesByTopic: Record<string, Message[]>
@ -139,6 +140,9 @@ const messagesSlice = createSlice({
const message = topicMessages.find((msg) => msg.id === messageId) const message = topicMessages.find((msg) => msg.id === messageId)
if (message) { if (message) {
Object.assign(message, updates) Object.assign(message, updates)
db.topics.update(topicId, {
messages: topicMessages.map((m) => (m.id === message.id ? cloneDeep(message) : m))
})
} }
} }
}, },
@ -282,10 +286,9 @@ export const sendMessage =
const messageToReset = options.resendAssistantMessage const messageToReset = options.resendAssistantMessage
if (Array.isArray(messageToReset)) { if (Array.isArray(messageToReset)) {
assistantMessages = messageToReset.map((m) => { assistantMessages = messageToReset.map((m) => {
const { model, id } = m const resetMessage = resetAssistantMessage(m, assistant.model)
const resetMessage = resetAssistantMessage(m, model)
// 更新状态 // 更新状态
dispatch(updateMessage({ topicId: topic.id, messageId: id, updates: resetMessage })) dispatch(updateMessage({ topicId: topic.id, messageId: m.id, updates: resetMessage }))
// 使用重置后的消息 // 使用重置后的消息
return resetMessage return resetMessage
}) })
@ -337,10 +340,12 @@ export const sendMessage =
}) })
) )
} }
for (const assistantMessage of assistantMessages) { for (const assistantMessage of assistantMessages) {
// for of会收到await 影响,在暂停的时候会因为异步的原因有概率拿不到数据 // for of会收到await 影响,在暂停的时候会因为异步的原因有概率拿不到数据
dispatch(setStreamMessage({ topicId: topic.id, message: assistantMessage })) dispatch(setStreamMessage({ topicId: topic.id, message: assistantMessage }))
} }
const queue = getTopicQueue(topic.id) const queue = getTopicQueue(topic.id)
for (const assistantMessage of assistantMessages) { for (const assistantMessage of assistantMessages) {
@ -469,8 +474,15 @@ export const resendMessage =
// 如果是助手消息,找到对应的用户消息 // 如果是助手消息,找到对应的用户消息
const userMessage = topicMessages.find((m) => m.id === message.askId && m.role === 'user') const userMessage = topicMessages.find((m) => m.id === message.askId && m.role === 'user')
if (!userMessage) { if (!userMessage) {
console.error('Cannot find original user message to resend') dispatch(
return dispatch(setError('Cannot find original user message to resend')) updateMessage({
topicId: topic.id,
messageId: message.id,
updates: { status: 'error', error: { message: i18n.t('error.user_message_not_found') } }
})
)
console.error(i18n.t('error.user_message_not_found'))
return dispatch(setError(i18n.t('error.user_message_not_found')))
} }
if (isMentionModel) { if (isMentionModel) {
@ -509,6 +521,7 @@ export const loadTopicMessagesThunk = (topic: Topic) => async (dispatch: AppDisp
dispatch(setTopicLoading({ topicId: topic.id, loading: false })) dispatch(setTopicLoading({ topicId: topic.id, loading: false }))
} }
} }
// Modified clearMessages thunk // Modified clearMessages thunk
export const clearTopicMessagesThunk = (topic: Topic) => async (dispatch: AppDispatch) => { export const clearTopicMessagesThunk = (topic: Topic) => async (dispatch: AppDispatch) => {
try { try {