feat: 历史记录面板(回填/删除/清空)

This commit is contained in:
2026-06-17 00:25:26 +08:00
parent 3c56fc45d3
commit ec20a5d083
@@ -1,8 +1,73 @@
import { useQrState } from '../store/qrContext';
import { MODE_LABELS, type HistoryEntry } from '../types';
export default function HistoryList() { export default function HistoryList() {
const { state, dispatch } = useQrState();
const handleClick = (entry: HistoryEntry) => {
dispatch({ type: 'SET_MODE', payload: entry.mode as any });
try {
const formData = JSON.parse(entry.content);
dispatch({ type: 'SET_FORM_DATA', payload: formData });
} catch {
dispatch({ type: 'SET_FORM_DATA', payload: { text: entry.content } });
}
};
const handleDelete = (e: React.MouseEvent, id: string) => {
e.stopPropagation();
dispatch({ type: 'REMOVE_HISTORY', payload: id });
};
const handleClear = () => {
dispatch({ type: 'SET_HISTORY', payload: [] });
};
const formatTime = (ts: number) => {
const d = new Date(ts);
return `${d.getHours().toString().padStart(2, '0')}:${d.getMinutes().toString().padStart(2, '0')}`;
};
return ( return (
<div className="flex flex-col h-full"> <div className="flex flex-col h-full">
<div className="text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2">📋 </div> <div className="flex items-center justify-between mb-2">
<p className="text-xs text-gray-400 text-center py-4"></p> <span className="text-xs font-semibold text-gray-400 uppercase tracking-wider">
📋
</span>
{state.history.length > 0 && (
<button onClick={handleClear}
className="text-xs text-red-400 hover:text-red-600 transition-colors">
</button>
)}
</div>
<div className="flex-1 overflow-y-auto space-y-1">
{state.history.length === 0 && (
<p className="text-xs text-gray-400 text-center py-4"></p>
)}
{state.history.map(entry => (
<div key={entry.id}
onClick={() => handleClick(entry)}
className="group flex items-center justify-between px-2 py-1.5 rounded-lg text-xs cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800 transition-all">
<div className="flex-1 min-w-0">
<div className="flex items-center gap-1.5">
<span className="px-1 py-0.5 rounded text-[10px] font-medium bg-blue-100 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400">
{MODE_LABELS[entry.mode as keyof typeof MODE_LABELS] || entry.mode}
</span>
<span className="text-gray-400">{formatTime(entry.timestamp)}</span>
</div>
<span className="text-gray-500 dark:text-gray-400 truncate block mt-0.5">
{entry.content.length > 20 ? entry.content.slice(0, 20) + '...' : entry.content}
</span>
</div>
<button onClick={(e) => handleDelete(e, entry.id)}
className="opacity-0 group-hover:opacity-100 text-red-400 hover:text-red-600 ml-1 transition-all text-lg leading-none">
×
</button>
</div>
))}
</div>
</div> </div>
); );
} }