useMessageEdit.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import { useCallback, useState } from 'react';
  2. import { Toast, Modal } from '@douyinfe/semi-ui';
  3. import { useTranslation } from 'react-i18next';
  4. import { getTextContent, buildApiPayload, createLoadingAssistantMessage } from '../utils/messageUtils';
  5. import { MESSAGE_ROLES } from '../utils/constants';
  6. export const useMessageEdit = (
  7. setMessage,
  8. inputs,
  9. parameterEnabled,
  10. sendRequest,
  11. saveMessages
  12. ) => {
  13. const { t } = useTranslation();
  14. const [editingMessageId, setEditingMessageId] = useState(null);
  15. const [editValue, setEditValue] = useState('');
  16. const handleMessageEdit = useCallback((targetMessage) => {
  17. const editableContent = getTextContent(targetMessage);
  18. setEditingMessageId(targetMessage.id);
  19. setEditValue(editableContent);
  20. }, []);
  21. const handleEditSave = useCallback(() => {
  22. if (!editingMessageId || !editValue.trim()) return;
  23. setMessage(prevMessages => {
  24. const messageIndex = prevMessages.findIndex(msg => msg.id === editingMessageId);
  25. if (messageIndex === -1) return prevMessages;
  26. const targetMessage = prevMessages[messageIndex];
  27. let newContent;
  28. if (Array.isArray(targetMessage.content)) {
  29. newContent = targetMessage.content.map(item =>
  30. item.type === 'text' ? { ...item, text: editValue.trim() } : item
  31. );
  32. } else {
  33. newContent = editValue.trim();
  34. }
  35. const updatedMessages = prevMessages.map(msg =>
  36. msg.id === editingMessageId ? { ...msg, content: newContent } : msg
  37. );
  38. // 处理用户消息编辑后的重新生成
  39. if (targetMessage.role === MESSAGE_ROLES.USER) {
  40. const hasSubsequentAssistantReply = messageIndex < prevMessages.length - 1 &&
  41. prevMessages[messageIndex + 1].role === MESSAGE_ROLES.ASSISTANT;
  42. if (hasSubsequentAssistantReply) {
  43. Modal.confirm({
  44. title: t('消息已编辑'),
  45. content: t('检测到该消息后有AI回复,是否删除后续回复并重新生成?'),
  46. okText: t('重新生成'),
  47. cancelText: t('仅保存'),
  48. onOk: () => {
  49. const messagesUntilUser = updatedMessages.slice(0, messageIndex + 1);
  50. setMessage(messagesUntilUser);
  51. // 编辑后保存(重新生成的情况)
  52. setTimeout(() => saveMessages(), 0);
  53. setTimeout(() => {
  54. const payload = buildApiPayload(messagesUntilUser, null, inputs, parameterEnabled);
  55. setMessage(prevMsg => [...prevMsg, createLoadingAssistantMessage()]);
  56. sendRequest(payload, inputs.stream);
  57. }, 100);
  58. },
  59. onCancel: () => {
  60. setMessage(updatedMessages);
  61. // 编辑后保存(仅保存的情况)
  62. setTimeout(() => saveMessages(), 0);
  63. }
  64. });
  65. return prevMessages;
  66. }
  67. }
  68. // 编辑后保存(普通情况)
  69. setTimeout(() => saveMessages(), 0);
  70. return updatedMessages;
  71. });
  72. setEditingMessageId(null);
  73. setEditValue('');
  74. Toast.success({ content: t('消息已更新'), duration: 2 });
  75. }, [editingMessageId, editValue, t, inputs, parameterEnabled, sendRequest, setMessage, saveMessages]);
  76. const handleEditCancel = useCallback(() => {
  77. setEditingMessageId(null);
  78. setEditValue('');
  79. }, []);
  80. return {
  81. editingMessageId,
  82. editValue,
  83. setEditValue,
  84. handleMessageEdit,
  85. handleEditSave,
  86. handleEditCancel
  87. };
  88. };