145 lines
4.1 KiB
JavaScript
145 lines
4.1 KiB
JavaScript
// 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;
|