import IconFont from '@/components/IconFont'; import { Dropdown, Input, Menu } from 'antd'; import classNames from 'classnames'; import { useEffect, useState, forwardRef, ForwardRefRenderFunction, useImperativeHandle, } from 'react'; import { useLocation } from 'umi'; import ConversationModal from './components/ConversationModal'; import { deleteConversation, getAllConversations, saveConversation } from './service'; import styles from './style.less'; import { ConversationDetailType, DefaultEntityType } from './type'; import { DEFAULT_CONVERSATION_NAME } from './constants'; import moment from 'moment'; import { SearchOutlined } from '@ant-design/icons'; type Props = { currentConversation?: ConversationDetailType; collapsed?: boolean; isCopilotMode?: boolean; defaultModelName?: string; defaultEntityFilter?: DefaultEntityType; triggerNewConversation?: boolean; onNewConversationTriggered?: () => void; onSelectConversation: ( conversation: ConversationDetailType, name?: string, modelId?: number, entityId?: string, ) => void; }; const Conversation: ForwardRefRenderFunction = ( { currentConversation, collapsed, isCopilotMode, defaultModelName, defaultEntityFilter, triggerNewConversation, onNewConversationTriggered, onSelectConversation, }, ref, ) => { const location = useLocation(); const { q, cid, modelId, entityId } = (location as any).query; const [conversations, setConversations] = useState([]); const [editModalVisible, setEditModalVisible] = useState(false); const [editConversation, setEditConversation] = useState(); const [searchValue, setSearchValue] = useState(''); useImperativeHandle(ref, () => ({ updateData, onAddConversation, })); const updateData = async () => { const { data } = await getAllConversations(); const conversationList = data || []; setConversations(conversationList.slice(0, 500)); return conversationList; }; const initData = async () => { const data = await updateData(); if (data.length > 0) { const chatId = localStorage.getItem('CONVERSATION_ID') || cid; if (chatId) { const conversation = data.find((item: any) => item.chatId === +chatId); if (conversation) { onSelectConversation(conversation); } else { onSelectConversation(data[0]); } } else { onSelectConversation(data[0]); } } else { onAddConversation(); } }; useEffect(() => { if (triggerNewConversation) { const conversationName = defaultEntityFilter?.entityName && window.location.pathname.includes('detail') ? defaultEntityFilter.entityName : defaultModelName; onAddConversation({ name: conversationName, type: 'CUSTOMIZE', modelId: defaultEntityFilter?.modelId, entityId: defaultEntityFilter?.entityId, }); onNewConversationTriggered?.(); } }, [triggerNewConversation]); useEffect(() => { if (triggerNewConversation) { return; } if (q && cid === undefined && window.location.href.includes('/workbench/chat')) { onAddConversation({ name: q, modelId: modelId ? +modelId : undefined, entityId }); } else { initData(); } }, [q]); const addConversation = async (name?: string) => { await saveConversation(name || DEFAULT_CONVERSATION_NAME); return updateData(); }; const onDeleteConversation = async (id: number) => { await deleteConversation(id); initData(); }; const onAddConversation = async ({ name, modelId, entityId, type, }: { name?: string; modelId?: number; entityId?: string; type?: string; } = {}) => { const data = await addConversation(name); onSelectConversation(data[0], type || name, modelId, entityId); }; const onOperate = (key: string, conversation: ConversationDetailType) => { if (key === 'editName') { setEditConversation(conversation); setEditModalVisible(true); } else if (key === 'delete') { onDeleteConversation(conversation.chatId); } }; const conversationClass = classNames(styles.conversation, { [styles.collapsed]: collapsed, [styles.copilotMode]: isCopilotMode, }); const convertTime = (date: string) => { moment.locale('zh-cn'); const now = moment(); const inputDate = moment(date); const diffMinutes = now.diff(inputDate, 'minutes'); if (diffMinutes < 1) { return '刚刚'; } else if (inputDate.isSame(now, 'day')) { return inputDate.format('HH:mm'); } else if (inputDate.isSame(now.subtract(1, 'day'), 'day')) { return '昨天'; } return inputDate.format('MM/DD'); }; const onSearchValueChange = (e: React.ChangeEvent) => { setSearchValue(e.target.value); }; return (
} className={styles.searchTask} value={searchValue} onChange={onSearchValueChange} allowClear />
{conversations .filter( (conversation) => searchValue === '' || conversation.chatName.toLowerCase().includes(searchValue.toLowerCase()), ) .map((item) => { const conversationItemClass = classNames(styles.conversationItem, { [styles.activeConversationItem]: currentConversation?.chatId === item.chatId, }); return ( { onOperate(key, item); }} /> } trigger={['contextMenu']} >
{ onSelectConversation(item); }} >
{item.chatName}
{convertTime(item.lastTime || '')}
{item.lastQuestion}
); })}
{ setEditModalVisible(false); }} onFinish={() => { setEditModalVisible(false); updateData(); }} />
); }; export default forwardRef(Conversation);