import React, { useState, useEffect } from 'react'; import { SearchHistoryItem, KnowledgeGroup } from '../types'; import { searchHistoryService } from '../services/searchHistoryService'; import { useToast } from '../contexts/ToastContext'; import { useLanguage } from '../contexts/LanguageContext'; import { useConfirm } from '../contexts/ConfirmContext'; import { MessageCircle, Trash2, Clock, Users } from 'lucide-react'; interface SearchHistoryListProps { groups: KnowledgeGroup[]; onSelectHistory: (historyId: string) => void; onDeleteHistory?: (historyId: string) => void; } export const SearchHistoryList: React.FC = ({ groups, onSelectHistory, onDeleteHistory }) => { const [histories, setHistories] = useState([]); const [loading, setLoading] = useState(true); const [page, setPage] = useState(1); const [hasMore, setHasMore] = useState(true); const { showError, showSuccess } = useToast(); const { confirm } = useConfirm(); const { t, language } = useLanguage(); const loadHistories = async (pageNum: number = 1, append: boolean = false) => { try { setLoading(true); const response = await searchHistoryService.getHistories(pageNum, 20); if (append) { setHistories(prev => [...prev, ...response.histories]); } else { setHistories(response.histories); } setHasMore(response.histories.length === 20); setPage(pageNum); } catch (error) { showError(t('loadingHistoriesFailed')); } finally { setLoading(false); } }; useEffect(() => { loadHistories(); }, []); const handleDelete = async (historyId: string, e: React.MouseEvent) => { e.stopPropagation(); if (!(await confirm(t('confirmDeleteHistory')))) return; try { await searchHistoryService.deleteHistory(historyId); setHistories(prev => prev.filter(h => h.id !== historyId)); onDeleteHistory?.(historyId); showSuccess(t('deleteHistorySuccess')); } catch (error) { showError(t('deleteHistoryFailed')); } }; const loadMore = () => { if (!loading && hasMore) { loadHistories(page + 1, true); } }; const formatDate = (dateString: string) => { const date = new Date(dateString); const now = new Date(); const diffMs = now.getTime() - date.getTime(); const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24)); // Determine locale for standard date functions const localeMap: Record = { 'zh': 'zh-CN', 'en': 'en-US', 'ja': 'ja-JP' }; const locale = localeMap[language] || 'ja-JP'; if (diffDays === 0) { return date.toLocaleTimeString(locale, { hour: '2-digit', minute: '2-digit' }); } else if (diffDays === 1) { return t('yesterday'); } else if (diffDays < 7) { return t('daysAgo', diffDays); } else { return date.toLocaleDateString(locale); } }; const getGroupNames = (selectedGroups: string[] | null) => { if (!selectedGroups || selectedGroups.length === 0) { return t('allKnowledgeGroups'); } return selectedGroups .map(id => groups.find(g => g.id === id)?.name) .filter(Boolean) .join(', '); }; if (loading && histories.length === 0) { return (
{t('loading')}
); } if (histories.length === 0) { return (
{t('noHistory')}
{t('noHistoryDesc')}
); } return (
{histories.map((history) => (
onSelectHistory(history.id)} className="p-4 bg-white rounded-lg border hover:shadow-sm cursor-pointer transition-all group" >
{history.title}
{t('historyMessages', history.messageCount)}
{formatDate(history.lastMessageAt)}
{getGroupNames(history.selectedGroups)}
))} {hasMore && ( )}
); };