Skip to content

Commit 29fdda8

Browse files
committed
feat: Implement create new chat functionality in MessageItem and integrate with MessageList and ChatWindow components
1 parent d9400a6 commit 29fdda8

4 files changed

Lines changed: 117 additions & 2 deletions

File tree

src/renderer/src/components/pages/chat/ChatWindow.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,18 @@ const ChatWindow = forwardRef<ChatWindowRef, ChatWindowProps>(({ chatId }, ref)
124124
chatInputRef.current?.insertQuote(text)
125125
}, [])
126126

127+
const handleCreateNewChat = useCallback((text: string) => {
128+
// 生成对话标题(取前30个字符)
129+
const title = text.length > 30 ? text.substring(0, 30) + '...' : text
130+
131+
// 创建新对话并打开
132+
const { createChatWithInitialMessage } = usePagesStore.getState()
133+
const newChatId = createChatWithInitialMessage(title, text, chat?.folderId, chatId)
134+
135+
// 切换到新创建的对话
136+
setActiveTab(newChatId)
137+
}, [chat?.folderId, chatId, setActiveTab])
138+
127139
const handleOpenSettings = useCallback(() => {
128140
const settingsPageId = createAndOpenSettingsPage('llm') // 从聊天窗口点击设置通常是想配置模型
129141
setActiveTab(settingsPageId)
@@ -321,6 +333,7 @@ const ChatWindow = forwardRef<ChatWindowRef, ChatWindowProps>(({ chatId }, ref)
321333
onSwitchBranch={handleSwitchBranch}
322334
// 引用相关props
323335
onQuote={handleQuote}
336+
onCreateNewChat={handleCreateNewChat}
324337
// 折叠相关props
325338
collapsedMessages={collapsedMessagesForChat}
326339
onToggleMessageCollapse={handleToggleMessageCollapse}

src/renderer/src/components/pages/chat/MessageItem.tsx

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ import {
1616
DownOutlined,
1717
UpOutlined,
1818
DeleteOutlined,
19-
MessageOutlined
19+
MessageOutlined,
20+
PlusCircleOutlined
2021
} from '@ant-design/icons'
2122
import { ChatMessage, LLMConfig } from '../../../types/type'
2223
import BranchNavigator from './BranchNavigator'
@@ -50,6 +51,7 @@ interface MessageItemProps {
5051
onModelChange?: (messageId: string, newModelId: string) => void
5152
onDelete?: (messageId: string) => void
5253
onQuote?: (text: string) => void
54+
onCreateNewChat?: (text: string) => void
5355
// 折叠相关
5456
isCollapsed?: boolean
5557
onToggleCollapse?: (messageId: string) => void
@@ -78,6 +80,7 @@ const MessageItem = React.memo(function MessageItem({
7880
onModelChange,
7981
onDelete,
8082
onQuote,
83+
onCreateNewChat,
8184
isCollapsed = false,
8285
onToggleCollapse,
8386
searchQuery,
@@ -231,6 +234,22 @@ const MessageItem = React.memo(function MessageItem({
231234
onQuote?.(quotedText)
232235
}
233236

237+
// 处理创建新对话
238+
const handleCreateNewChat = () => {
239+
const selection = window.getSelection()
240+
let textToUse = ''
241+
242+
if (selection && selection.toString().trim()) {
243+
// 如果有选中文本,使用选中的文本
244+
textToUse = selection.toString().trim()
245+
} else {
246+
// 如果没有选中文本,使用整个消息内容
247+
textToUse = currentContent
248+
}
249+
250+
onCreateNewChat?.(textToUse)
251+
}
252+
234253
// 右键菜单项
235254
const contextMenuItems = [
236255
{
@@ -245,6 +264,13 @@ const MessageItem = React.memo(function MessageItem({
245264
icon: <MessageOutlined />,
246265
onClick: handleQuote,
247266
disabled: !onQuote
267+
},
268+
{
269+
key: 'newChat',
270+
label: '新建对话',
271+
icon: <PlusCircleOutlined />,
272+
onClick: handleCreateNewChat,
273+
disabled: !onCreateNewChat
248274
}
249275
]
250276

src/renderer/src/components/pages/chat/MessageList.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ interface MessageListProps {
2525
onSwitchBranch?: (messageId: string, branchIndex: number) => void
2626
onStopGeneration?: () => void
2727
onQuote?: (text: string) => void
28+
onCreateNewChat?: (text: string) => void
2829
// 折叠相关
2930
collapsedMessages?: string[]
3031
onToggleMessageCollapse?: (messageId: string) => void
@@ -50,7 +51,8 @@ const MessageList = React.memo(function MessageList({
5051
collapsedMessages = [],
5152
onToggleMessageCollapse,
5253
onOpenSettings,
53-
onQuote
54+
onQuote,
55+
onCreateNewChat
5456
}: MessageListProps) {
5557
const messagesEndRef = useRef<HTMLDivElement>(null)
5658
const messagesContainerRef = useRef<HTMLDivElement>(null)
@@ -353,6 +355,7 @@ const MessageList = React.memo(function MessageList({
353355
onModelChange={onModelChange}
354356
onDelete={onDeleteMessage}
355357
onQuote={onQuote}
358+
onCreateNewChat={onCreateNewChat}
356359
// 折叠相关
357360
isCollapsed={collapsedMessages.includes(message.id)}
358361
onToggleCollapse={onToggleMessageCollapse}

src/renderer/src/stores/pagesStore.ts

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ export interface PagesActions {
5252
createAndOpenCrosstabChat: (title: string, folderId?: string, lineage?: PageLineage) => string
5353
createAndOpenObjectChat: (title: string, folderId?: string, lineage?: PageLineage) => string
5454
createAndOpenSettingsPage: (defaultActiveTab?: string) => string
55+
createChatWithInitialMessage: (title: string, initialMessage: string, folderId?: string, sourcePageId?: string) => string
5556

5657
// 复杂页面创建功能
5758
createChatFromCell: (params: {
@@ -600,6 +601,78 @@ export const usePagesStore = create<PagesState & PagesActions>()(
600601
}
601602
},
602603

604+
createChatWithInitialMessage: (title, initialMessage, folderId, sourcePageId) => {
605+
try {
606+
const timestamp = Date.now()
607+
608+
// 如果没有指定order,获取同文件夹下的最小order值
609+
const siblingFolders = get().folders.filter(f => f.parentId === folderId)
610+
const siblingPages = get().pages.filter(p => p.folderId === folderId && p.type !== 'settings')
611+
612+
// 获取所有同级项的最小order值
613+
const allOrders = [
614+
...siblingFolders.map(f => f.order || 0),
615+
...siblingPages.map(p => p.order || 0)
616+
]
617+
618+
const minOrder = allOrders.length > 0
619+
? Math.min(...allOrders)
620+
: 1000
621+
622+
// 创建用户消息
623+
const userMessage = {
624+
id: uuidv4(),
625+
role: 'user' as const,
626+
content: initialMessage,
627+
timestamp: timestamp
628+
}
629+
630+
const newPage: Page = {
631+
id: uuidv4(),
632+
title,
633+
type: 'regular',
634+
createdAt: timestamp,
635+
updatedAt: timestamp,
636+
order: minOrder - 1000, // 新页面添加到最前面
637+
folderId,
638+
messages: [userMessage],
639+
messageMap: { [userMessage.id]: userMessage },
640+
currentPath: [userMessage.id],
641+
rootMessageId: undefined,
642+
...(sourcePageId && {
643+
lineage: {
644+
source: 'other' as const,
645+
sourcePageId,
646+
sourceContext: {
647+
customContext: {
648+
action: 'create_chat_with_text',
649+
originalText: initialMessage
650+
}
651+
},
652+
generatedPageIds: [],
653+
generatedAt: timestamp,
654+
description: `从消息文本创建新对话`
655+
}
656+
})
657+
}
658+
659+
set((state) => {
660+
state.pages.push(newPage)
661+
})
662+
663+
// 同时保存到 IndexedDB
664+
pagesStorage.savePage(newPage)
665+
666+
const { setSelectedNode } = useUIStore.getState()
667+
setSelectedNode(newPage.id, 'chat')
668+
669+
return newPage.id
670+
} catch (error) {
671+
handleStoreError('pagesStore', 'createChatWithInitialMessage', error)
672+
throw error
673+
}
674+
},
675+
603676
// 复杂页面创建功能
604677
createChatFromCell: (params) => {
605678
try {

0 commit comments

Comments
 (0)