// src/store/api/eventsApi.js // RTK Query API for Events - 事件数据获取 API import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; import { logger } from '../../utils/logger'; /** * Events API Slice - 使用 RTK Query 管理事件数据 * * 特性: * - ✅ 自动缓存管理(按 queryKey 缓存) * - ✅ 自动去重请求 * - ✅ 返回第一页刷新数据(invalidateTags) * - ✅ 预加载支持(prefetch) * - ✅ 统一在 Redux DevTools 中调试 * - ✅ 无需额外 Provider */ export const eventsApi = createApi({ reducerPath: 'eventsApi', // 基础查询配置 baseQuery: fetchBaseQuery({ baseUrl: '/api', prepareHeaders: (headers) => { // 可以在这里添加认证 token // const token = localStorage.getItem('token'); // if (token) { // headers.set('Authorization', `Bearer ${token}`); // } return headers; }, }), // 标签类型定义(用于缓存失效) tagTypes: ['Events'], // API 端点定义 endpoints: (builder) => ({ /** * 获取分页事件列表 * * @param {Object} params * @param {number} params.page - 页码 * @param {number} params.per_page - 每页数量 * @param {string} params.mode - 显示模式(vertical / four-row) * @param {string} params.sort - 排序方式 * @param {string} params.importance - 重要性筛选 * @param {string} params.q - 搜索关键词 * @param {string} params.date_range - 日期范围 * @param {string} params.industry_code - 行业代码 * * @returns {Object} { events: Array, pagination: Object } */ getEvents: builder.query({ query: ({ page = 1, per_page = 5, mode = 'vertical', ...filters }) => { logger.debug('eventsApi', 'getEvents 请求', { page, per_page, mode, filters, }); return { url: '/events', params: { page, per_page, ...filters, }, }; }, // 🔥 缓存标签:用于缓存失效 providesTags: (result, error, { page, mode }) => { if (error) return []; return [ { type: 'Events', id: `${mode}-${page}` }, // 具体页面的标签 { type: 'Events', id: `${mode}-LIST` }, // 模式的总标签 ]; }, // 转换响应数据 transformResponse: (response) => { logger.debug('eventsApi', 'getEvents 响应', { eventsCount: response.data?.events?.length, total: response.data?.pagination?.total, }); if (!response.success || !response.data?.events) { throw new Error('数据格式错误'); } return { events: response.data.events, pagination: response.data.pagination || {}, }; }, // 错误处理 transformErrorResponse: (response) => { logger.error('eventsApi', 'getEvents 失败', new Error(response.status)); return { status: response.status, message: response.data?.message || '获取事件数据失败', }; }, // 🔥 keepUnusedDataFor: 缓存保留时间(秒) keepUnusedDataFor: 600, // 10分钟 // 🔥 合并查询结果(用于无限滚动) // serializeQueryArgs: ({ endpointName, queryArgs }) => { // const { mode, ...filters } = queryArgs; // return `${endpointName}(${mode})`; // }, // merge: (currentCache, newItems) => { // currentCache.events.push(...newItems.events); // }, // forceRefetch: ({ currentArg, previousArg }) => { // return currentArg.page !== previousArg?.page; // }, }), /** * 预加载下一页(性能优化) * * 用法: * dispatch(eventsApi.util.prefetch('getEvents', { page: 2, ... })) */ }), }); // 导出自动生成的 Hooks export const { useGetEventsQuery, useLazyGetEventsQuery, // 手动触发的版本 usePrefetch, // 预加载 Hook } = eventsApi; // 导出工具方法 export const { util: { invalidateTags, prefetch }, } = eventsApi;