/** * 事件服务层 * 复用 Web 端的 eventService 逻辑 */ import { apiRequest } from './api'; /** * 股票服务 * 获取股票实时报价等 */ export const stockService = { /** * 批量获取股票报价 * @param {string[]} codes - 股票代码数组 * @param {string} eventTime - 可选的事件时间 * @returns {Promise} 报价数据 {code: {name, price, change}} */ getQuotes: async (codes, eventTime = null) => { try { const requestBody = { codes }; if (eventTime) { requestBody.event_time = eventTime; } console.log('[StockService] 获取股票报价:', { codes: codes.slice(0, 5), eventTime }); const response = await apiRequest('/api/stock/quotes', { method: 'POST', body: JSON.stringify(requestBody), }); if (response.success && response.data) { console.log('[StockService] 报价响应成功:', Object.keys(response.data).length, '只股票'); return response.data; } else { console.warn('[StockService] 报价响应格式异常:', response); return {}; } } catch (error) { console.error('[StockService] getQuotes 错误:', error); throw error; } }, }; export const eventService = { /** * 获取事件列表 * @param {object} params - 查询参数 * @param {number} params.page - 页码 * @param {number} params.per_page - 每页数量 * @param {string} params.sort - 排序方式 (new/hot/importance) * @param {string} params.importance - 重要性筛选 (S/A/B/C) * @param {string} params.q - 搜索关键词 * @returns {Promise} 事件列表和分页信息 */ getEvents: (params = {}) => { // 过滤空值和内部字段 const cleanParams = Object.fromEntries( Object.entries(params).filter( ([key, v]) => v !== null && v !== undefined && v !== '' && !key.startsWith('_') ) ); const query = new URLSearchParams(cleanParams).toString(); return apiRequest(`/api/events?${query}`); }, /** * 获取热点事件 * @param {object} params - 查询参数 * @returns {Promise} 热点事件列表 */ getHotEvents: (params = {}) => { const query = new URLSearchParams(params).toString(); return apiRequest(`/api/events/hot?${query}`); }, /** * 获取热门关键词 * @param {number} limit - 返回数量限制 * @returns {Promise} 热门关键词列表 */ getPopularKeywords: (limit = 20) => { return apiRequest(`/api/events/keywords/popular?limit=${limit}`); }, /** * 获取事件详情 * @param {number} eventId - 事件ID * @returns {Promise} 事件详情 */ getEventDetail: async (eventId) => { return await apiRequest(`/api/events/${eventId}`); }, /** * 获取事件相关股票 * @param {number} eventId - 事件ID * @returns {Promise} 相关股票列表 */ getRelatedStocks: async (eventId) => { return await apiRequest(`/api/events/${eventId}/stocks`); }, /** * 获取事件相关概念 * @param {number} eventId - 事件ID * @returns {Promise} 相关概念列表 */ getRelatedConcepts: async (eventId) => { return await apiRequest(`/api/events/${eventId}/concepts`); }, /** * 切换事件关注状态 * @param {number} eventId - 事件ID * @param {boolean} isFollowing - 是否关注 * @returns {Promise} 关注状态 */ toggleFollow: async (eventId, isFollowing) => { return await apiRequest(`/api/events/${eventId}/follow`, { method: 'POST', body: JSON.stringify({ is_following: isFollowing }), }); }, /** * 情绪投票(看多/看空) * @param {number} eventId - 事件ID * @param {string} voteType - 投票类型 'bullish' | 'bearish' | null * @returns {Promise} 投票结果 */ sentimentVote: async (eventId, voteType) => { return await apiRequest(`/api/events/${eventId}/sentiment-vote`, { method: 'POST', body: JSON.stringify({ vote_type: voteType }), }); }, /** * 获取历史事件 * @param {number} eventId - 事件ID * @returns {Promise} 历史事件列表 */ getHistoricalEvents: async (eventId) => { return await apiRequest(`/api/events/${eventId}/historical`); }, /** * 获取事件帖子 * @param {number} eventId - 事件ID * @param {object} params - 查询参数 * @returns {Promise} 帖子列表 */ getEventPosts: async (eventId, params = {}) => { const query = new URLSearchParams(params).toString(); return await apiRequest(`/api/events/${eventId}/posts?${query}`); }, /** * 创建帖子 * @param {number} eventId - 事件ID * @param {object} data - 帖子数据 * @returns {Promise} 创建结果 */ createPost: async (eventId, data) => { return await apiRequest(`/api/events/${eventId}/posts`, { method: 'POST', body: JSON.stringify(data), }); }, /** * 获取传导链数据 * @param {number} eventId - 事件ID * @returns {Promise} 传导链数据 */ getTransmissionChain: async (eventId) => { return await apiRequest(`/api/events/${eventId}/transmission`); }, /** * 获取桑基图数据 * @param {number} eventId - 事件ID * @returns {Promise} 桑基图数据 */ getSankeyData: async (eventId) => { return await apiRequest(`/api/events/${eventId}/sankey-data`); }, /** * 获取事件有效性统计(今日统计面板数据) * @param {number} days - 天数 * @param {string} date - 可选日期 * @returns {Promise} 统计数据 */ getEffectivenessStats: async (days = 1, date = '') => { const dateParam = date ? `&date=${date}` : ''; return await apiRequest(`/api/v1/events/effectiveness-stats?days=${days}${dateParam}`); }, /** * 获取市场实时统计 * @returns {Promise} 市场统计数据 */ getMarketStats: async () => { return await apiRequest('/api/v1/market/realtime-stats'); }, /** * 获取主线/题材事件数据 * @param {object} params - 查询参数 * @param {string} params.group_by - 分组级别 (lv1/lv2/lv3 或具体概念ID) * @param {number} params.recent_days - 最近天数(与 start_date/end_date 二选一) * @param {string} params.start_date - 开始时间 (YYYY-MM-DD HH:mm:ss) * @param {string} params.end_date - 结束时间 (YYYY-MM-DD HH:mm:ss) * @returns {Promise} 主线事件分组数据 */ getMainlineEvents: async (params = {}) => { const { group_by = 'lv1', recent_days, start_date, end_date } = params; // 构建查询参数 const queryParams = new URLSearchParams(); queryParams.append('group_by', group_by); // 优先使用 start_date/end_date,否则使用 recent_days if (start_date && end_date) { queryParams.append('start_date', start_date); queryParams.append('end_date', end_date); } else if (recent_days) { queryParams.append('recent_days', recent_days); } return await apiRequest(`/api/events/mainline?${queryParams.toString()}`); }, }; export default eventService;