import React, { useCallback, useRef, useState, useMemo } from 'react'; import type { MouseEvent } from 'react'; import { AddIcon } from '@chakra-ui/icons'; import { Box, Button, Flex, useTheme, Menu, MenuList, MenuItem, useOutsideClick } from '@chakra-ui/react'; import { ChatIcon } from '@chakra-ui/icons'; import { useQuery } from '@tanstack/react-query'; import { useRouter } from 'next/router'; import { useLoading } from '@/hooks/useLoading'; import { useUserStore } from '@/store/user'; import { formatTimeToChatTime } from '@/utils/tools'; import MyIcon from '@/components/Icon'; import type { HistoryItemType, ExportChatType } from '@/types/chat'; import { useChatStore } from '@/store/chat'; import { useScreen } from '@/hooks/useScreen'; import ModelList from './ModelList'; import styles from '../index.module.scss'; const PcSliderBar = ({ isPcDevice, onclickDelHistory, onclickExportChat }: { isPcDevice: boolean; onclickDelHistory: (historyId: string) => Promise; onclickExportChat: (type: ExportChatType) => void; }) => { const router = useRouter(); const { modelId = '', chatId = '' } = router.query as { modelId: string; chatId: string }; const theme = useTheme(); const { isPc } = useScreen({ defaultIsPc: isPcDevice }); const ContextMenuRef = useRef(null); const { Loading, setIsLoading } = useLoading(); const [contextMenuData, setContextMenuData] = useState<{ left: number; top: number; history: HistoryItemType; }>(); const { history, loadHistory } = useChatStore(); const { myModels, myCollectionModels, loadMyModels } = useUserStore(); const models = useMemo( () => [...myModels, ...myCollectionModels], [myCollectionModels, myModels] ); useQuery(['loadModels'], () => loadMyModels(false)); // close contextMenu useOutsideClick({ ref: ContextMenuRef, handler: () => setTimeout(() => { setContextMenuData(undefined); }) }); const { isLoading: isLoadingHistory } = useQuery(['loadingHistory'], () => loadHistory({ pageNum: 1 }) ); const onclickContextMenu = useCallback( (e: MouseEvent, history: HistoryItemType) => { e.preventDefault(); // 阻止默认右键菜单 if (!isPc) return; setContextMenuData({ left: e.clientX + 15, top: e.clientY + 10, history }); }, [isPc] ); return ( {/* 新对话 */} {isPc && ( {models.length > 1 && ( )} )} {/* chat history */} {history.map((item) => ( { if (item._id === chatId) return; if (isPc) { router.replace(`/chat?modelId=${item.modelId}&chatId=${item._id}`); } else { router.push(`/chat?modelId=${item.modelId}&chatId=${item._id}`); } }} onContextMenu={(e) => onclickContextMenu(e, item)} > {item.title} {formatTimeToChatTime(item.updateTime)} {item.latestChat || '……'} {/* phone quick delete */} {!isPc && ( { e.stopPropagation(); setIsLoading(true); try { await onclickDelHistory(item._id); } catch (error) { console.log(error); } setIsLoading(false); }} /> )} ))} {!isLoadingHistory && history.length === 0 && ( 还没有聊天记录 )} {/* context menu */} {contextMenuData && ( { setIsLoading(true); try { await onclickDelHistory(contextMenuData.history._id); if (contextMenuData.history._id === chatId) { router.replace(`/chat?modelId=${modelId}`); } } catch (error) { console.log(error); } setIsLoading(false); }} > 删除记录 onclickExportChat('html')}>导出HTML格式 onclickExportChat('pdf')}>导出PDF格式 onclickExportChat('md')}>导出Markdown格式 )} ); }; export default PcSliderBar;