fix: 修复 ConceptStatsPanel API Mock 数据格式问题
解决控制台 "无法访问概念统计API" 错误,完善 Mock Service Worker 的统计数据返回格式 **问题原因** 1. Mock 模式下,`/statistics` 端点返回的数据格式不完整 2. 缺少必需的 `success` 和 `data` 包装层 3. 缺少 5 个必需字段:`hot_concepts`, `cold_concepts`, `active_concepts`, `volatile_concepts`, `momentum_concepts` **修复内容** 1. 创建 `generateConceptStats()` 函数(lines 50-104) - 生成热门概念(涨幅前5) - 生成冷门概念(跌幅前5) - 生成活跃概念(新闻+研报最多) - 生成波动概念(波动率最高) - 生成动量概念(连续上涨天数最多) 2. 更新 `http://111.198.58.126:16801/statistics` handler(lines 273-300) - 返回完整的统计数据格式 - 包装为 `{ success: true, data: {...} }` - 支持 `min_stock_count`, `days`, `start_date`, `end_date` 参数 3. 新增 `/concept-api/statistics` handler(lines 302-329) - 覆盖 nginx 代理路由 - 与直接 API 返回相同格式的数据 - 确保两个端点都能正常工作 **数据格式** ```json { "success": true, "data": { "hot_concepts": [...], "cold_concepts": [...], "active_concepts": [...], "volatile_concepts": [...], "momentum_concepts": [...] }, "note": "Mock 数据", "params": { ... }, "updated_at": "2025-10-30T..." } ``` **测试结果** - ✅ 编译成功 - ✅ ConceptStatsPanel 可以正确接收 Mock 数据 - ✅ 不再显示 "无法访问概念统计API" 错误 - ✅ 两个 API 端点(代理 + 直接)都已覆盖 **文件修改** - src/mocks/handlers/concept.js (+79 lines) - 新增 generateConceptStats() 函数 - 更新 /statistics handler - 新增 /concept-api/statistics handler
This commit is contained in:
@@ -47,6 +47,62 @@ const generatePopularConcepts = (size = 20) => {
|
||||
return results;
|
||||
};
|
||||
|
||||
// 生成完整的概念统计数据(用于 ConceptStatsPanel)
|
||||
const generateConceptStats = () => {
|
||||
// 热门概念(涨幅最大的前5)
|
||||
const hot_concepts = [
|
||||
{ name: '小米大模型', change_pct: 18.76, stock_count: 12, news_count: 35 },
|
||||
{ name: '人工智能', change_pct: 15.67, stock_count: 45, news_count: 23 },
|
||||
{ name: '新能源汽车', change_pct: 12.34, stock_count: 38, news_count: 18 },
|
||||
{ name: '芯片概念', change_pct: 9.87, stock_count: 52, news_count: 31 },
|
||||
{ name: '5G通信', change_pct: 8.45, stock_count: 29, news_count: 15 },
|
||||
];
|
||||
|
||||
// 冷门概念(跌幅最大的前5)
|
||||
const cold_concepts = [
|
||||
{ name: '房地产', change_pct: -8.76, stock_count: 33, news_count: 12 },
|
||||
{ name: '煤炭开采', change_pct: -6.54, stock_count: 25, news_count: 8 },
|
||||
{ name: '传统零售', change_pct: -5.43, stock_count: 19, news_count: 6 },
|
||||
{ name: '钢铁冶炼', change_pct: -4.21, stock_count: 28, news_count: 9 },
|
||||
{ name: '纺织服装', change_pct: -3.98, stock_count: 15, news_count: 4 },
|
||||
];
|
||||
|
||||
// 活跃概念(新闻+研报最多的前5)
|
||||
const active_concepts = [
|
||||
{ name: '人工智能', news_count: 89, report_count: 15, total_mentions: 104 },
|
||||
{ name: '芯片概念', news_count: 76, report_count: 12, total_mentions: 88 },
|
||||
{ name: '新能源汽车', news_count: 65, report_count: 18, total_mentions: 83 },
|
||||
{ name: '生物医药', news_count: 54, report_count: 9, total_mentions: 63 },
|
||||
{ name: '量子科技', news_count: 41, report_count: 7, total_mentions: 48 },
|
||||
];
|
||||
|
||||
// 波动最大的概念(前5)
|
||||
const volatile_concepts = [
|
||||
{ name: '区块链', volatility: 23.45, avg_change: 3.21, max_change: 12.34 },
|
||||
{ name: '元宇宙', volatility: 21.87, avg_change: 2.98, max_change: 11.76 },
|
||||
{ name: '虚拟现实', volatility: 19.65, avg_change: -1.23, max_change: 9.87 },
|
||||
{ name: '游戏概念', volatility: 18.32, avg_change: 4.56, max_change: 10.45 },
|
||||
{ name: '在线教育', volatility: 17.89, avg_change: -2.11, max_change: 8.76 },
|
||||
];
|
||||
|
||||
// 动量概念(连续上涨的前5)
|
||||
const momentum_concepts = [
|
||||
{ name: '数字经济', consecutive_days: 5, total_change: 18.76, avg_daily: 3.75 },
|
||||
{ name: '云计算', consecutive_days: 4, total_change: 14.32, avg_daily: 3.58 },
|
||||
{ name: '物联网', consecutive_days: 4, total_change: 12.89, avg_daily: 3.22 },
|
||||
{ name: '大数据', consecutive_days: 3, total_change: 11.45, avg_daily: 3.82 },
|
||||
{ name: '工业互联网', consecutive_days: 3, total_change: 9.87, avg_daily: 3.29 },
|
||||
];
|
||||
|
||||
return {
|
||||
hot_concepts,
|
||||
cold_concepts,
|
||||
active_concepts,
|
||||
volatile_concepts,
|
||||
momentum_concepts
|
||||
};
|
||||
};
|
||||
|
||||
// 概念相关的 Handlers
|
||||
export const conceptHandlers = [
|
||||
// 搜索概念(热门概念)
|
||||
@@ -214,23 +270,60 @@ export const conceptHandlers = [
|
||||
}
|
||||
}),
|
||||
|
||||
// 获取统计数据
|
||||
// 获取统计数据(直接访问外部 API)
|
||||
http.get('http://111.198.58.126:16801/statistics', async ({ request }) => {
|
||||
await delay(300);
|
||||
|
||||
const url = new URL(request.url);
|
||||
const minStockCount = parseInt(url.searchParams.get('min_stock_count') || '3');
|
||||
const days = parseInt(url.searchParams.get('days') || '7');
|
||||
const startDate = url.searchParams.get('start_date');
|
||||
const endDate = url.searchParams.get('end_date');
|
||||
|
||||
console.log('[Mock Concept] 获取统计数据:', { minStockCount, days });
|
||||
console.log('[Mock Concept] 获取统计数据 (直接API):', { minStockCount, days, startDate, endDate });
|
||||
|
||||
// 生成完整的统计数据
|
||||
const statsData = generateConceptStats();
|
||||
|
||||
return HttpResponse.json({
|
||||
total_concepts: 150,
|
||||
active_concepts: 120,
|
||||
avg_stock_count: 25,
|
||||
top_concepts: generatePopularConcepts(10),
|
||||
success: true,
|
||||
data: statsData,
|
||||
note: 'Mock 数据',
|
||||
params: {
|
||||
min_stock_count: minStockCount,
|
||||
days: days,
|
||||
start_date: startDate,
|
||||
end_date: endDate
|
||||
},
|
||||
updated_at: new Date().toISOString()
|
||||
});
|
||||
}),
|
||||
|
||||
// 获取统计数据(通过 nginx 代理)
|
||||
http.get('/concept-api/statistics', async ({ request }) => {
|
||||
await delay(300);
|
||||
|
||||
const url = new URL(request.url);
|
||||
const minStockCount = parseInt(url.searchParams.get('min_stock_count') || '3');
|
||||
const days = parseInt(url.searchParams.get('days') || '7');
|
||||
const startDate = url.searchParams.get('start_date');
|
||||
const endDate = url.searchParams.get('end_date');
|
||||
|
||||
console.log('[Mock Concept] 获取统计数据 (nginx代理):', { minStockCount, days, startDate, endDate });
|
||||
|
||||
// 生成完整的统计数据
|
||||
const statsData = generateConceptStats();
|
||||
|
||||
return HttpResponse.json({
|
||||
success: true,
|
||||
data: statsData,
|
||||
note: 'Mock 数据(通过 nginx 代理)',
|
||||
params: {
|
||||
min_stock_count: minStockCount,
|
||||
days: days,
|
||||
start_date: startDate,
|
||||
end_date: endDate
|
||||
},
|
||||
updated_at: new Date().toISOString()
|
||||
});
|
||||
}),
|
||||
|
||||
Reference in New Issue
Block a user