// src/hooks/useFollowingEvents.js // 关注事件管理自定义 Hook import { useState, useCallback } from 'react'; import { useToast } from '@chakra-ui/react'; import { logger } from '../utils/logger'; import { getApiBase } from '../utils/apiConfig'; const EVENTS_PAGE_SIZE = 8; /** * 关注事件管理 Hook * 提供事件加载、分页、取消关注等功能 * * @returns {{ * followingEvents: Array, * eventsLoading: boolean, * eventsPage: number, * setEventsPage: Function, * EVENTS_PAGE_SIZE: number, * loadFollowingEvents: Function, * handleUnfollowEvent: Function * }} */ export const useFollowingEvents = () => { const toast = useToast(); const [followingEvents, setFollowingEvents] = useState([]); const [eventsLoading, setEventsLoading] = useState(false); const [eventsPage, setEventsPage] = useState(1); // 加载关注的事件 const loadFollowingEvents = useCallback(async () => { try { setEventsLoading(true); const base = getApiBase(); const resp = await fetch(base + '/api/account/events/following', { credentials: 'include', cache: 'no-store', headers: { 'Cache-Control': 'no-cache' } }); if (resp.ok) { const data = await resp.json(); if (data && data.success && Array.isArray(data.data)) { // 合并重复的事件(用最新的数据) const eventMap = new Map(); for (const evt of data.data) { if (evt && evt.id) { eventMap.set(evt.id, evt); } } const merged = Array.from(eventMap.values()); // 按创建时间降序排列(假设事件有 created_at 或 id) if (merged.length > 0 && merged[0].created_at) { merged.sort((a, b) => new Date(b.created_at || 0) - new Date(a.created_at || 0)); } else { merged.sort((a, b) => (b.id || 0) - (a.id || 0)); } setFollowingEvents(merged); } else { setFollowingEvents([]); } } else { setFollowingEvents([]); } } catch (e) { logger.warn('useFollowingEvents', '加载关注事件失败', { error: e.message }); setFollowingEvents([]); } finally { setEventsLoading(false); } }, []); // 取消关注事件 const handleUnfollowEvent = useCallback(async (eventId) => { try { const base = getApiBase(); const resp = await fetch(base + `/api/events/${eventId}/follow`, { method: 'POST', credentials: 'include' }); const data = await resp.json().catch(() => ({})); if (resp.ok && data && data.success !== false) { setFollowingEvents((prev) => { const updated = (prev || []).filter((x) => x.id !== eventId); const newMaxPage = Math.max(1, Math.ceil((updated.length || 0) / EVENTS_PAGE_SIZE)); setEventsPage((p) => Math.min(p, newMaxPage)); return updated; }); toast({ title: '已取消关注该事件', status: 'info', duration: 1500 }); } else { toast({ title: '操作失败', status: 'error', duration: 2000 }); } } catch (e) { toast({ title: '网络错误,操作失败', status: 'error', duration: 2000 }); } }, [toast]); return { followingEvents, eventsLoading, eventsPage, setEventsPage, EVENTS_PAGE_SIZE, loadFollowingEvents, handleUnfollowEvent }; };