feat: 添加 RTK Query 集成用于事件数据获取(实验性)...

This commit is contained in:
zdl
2025-11-06 01:25:44 +08:00
parent 273ff5f72d
commit 31e5a4ee48
2 changed files with 149 additions and 1 deletions

144
src/store/api/eventsApi.js Normal file
View File

@@ -0,0 +1,144 @@
// 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;

View File

@@ -7,6 +7,7 @@ import stockReducer from './slices/stockSlice';
import authModalReducer from './slices/authModalSlice';
import subscriptionReducer from './slices/subscriptionSlice';
import posthogMiddleware from './middleware/posthogMiddleware';
import { eventsApi } from './api/eventsApi'; // ✅ RTK Query API
export const store = configureStore({
reducer: {
@@ -16,6 +17,7 @@ export const store = configureStore({
stock: stockReducer, // ✅ 股票和事件数据管理
authModal: authModalReducer, // ✅ 认证弹窗状态管理
subscription: subscriptionReducer, // ✅ 订阅信息状态管理
[eventsApi.reducerPath]: eventsApi.reducer, // ✅ RTK Query 事件 API
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
@@ -29,7 +31,9 @@ export const store = configureStore({
'stock/fetchStockQuotes/fulfilled',
],
},
}).concat(posthogMiddleware), // ✅ PostHog 自动追踪中间件
})
.concat(posthogMiddleware) // ✅ PostHog 自动追踪中间件
.concat(eventsApi.middleware), // ✅ RTK Query 中间件(自动缓存、去重、重试)
});
export default store;