feat: 添加mock数据
This commit is contained in:
@@ -155,5 +155,190 @@ export const conceptHandlers = [
|
||||
total: stocks.length,
|
||||
concept_id: conceptId
|
||||
});
|
||||
}),
|
||||
|
||||
// 获取最新交易日期
|
||||
http.get('http://111.198.58.126:16801/price/latest', async () => {
|
||||
await delay(200);
|
||||
|
||||
const today = new Date();
|
||||
const dateStr = today.toISOString().split('T')[0].replace(/-/g, '');
|
||||
|
||||
console.log('[Mock Concept] 获取最新交易日期:', dateStr);
|
||||
|
||||
return HttpResponse.json({
|
||||
latest_date: dateStr,
|
||||
timestamp: today.toISOString()
|
||||
});
|
||||
}),
|
||||
|
||||
// 搜索概念(硬编码 URL)
|
||||
http.post('http://111.198.58.126:16801/search', async ({ request }) => {
|
||||
await delay(300);
|
||||
|
||||
try {
|
||||
const body = await request.json();
|
||||
const { query = '', size = 20, page = 1, sort_by = 'change_pct' } = body;
|
||||
|
||||
console.log('[Mock Concept] 搜索概念 (硬编码URL):', { query, size, page, sort_by });
|
||||
|
||||
let results = generatePopularConcepts(size);
|
||||
|
||||
if (query) {
|
||||
results = results.filter(item =>
|
||||
item.concept.toLowerCase().includes(query.toLowerCase())
|
||||
);
|
||||
}
|
||||
|
||||
if (sort_by === 'change_pct') {
|
||||
results.sort((a, b) => b.price_info.avg_change_pct - a.price_info.avg_change_pct);
|
||||
} else if (sort_by === 'stock_count') {
|
||||
results.sort((a, b) => b.stock_count - a.stock_count);
|
||||
} else if (sort_by === 'hot_score') {
|
||||
results.sort((a, b) => b.hot_score - a.hot_score);
|
||||
}
|
||||
|
||||
return HttpResponse.json({
|
||||
results,
|
||||
total: results.length,
|
||||
page,
|
||||
size,
|
||||
message: '搜索成功'
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('[Mock Concept] 搜索失败:', error);
|
||||
return HttpResponse.json(
|
||||
{ results: [], total: 0, error: '搜索失败' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}),
|
||||
|
||||
// 获取统计数据
|
||||
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');
|
||||
|
||||
console.log('[Mock Concept] 获取统计数据:', { minStockCount, days });
|
||||
|
||||
return HttpResponse.json({
|
||||
total_concepts: 150,
|
||||
active_concepts: 120,
|
||||
avg_stock_count: 25,
|
||||
top_concepts: generatePopularConcepts(10),
|
||||
min_stock_count: minStockCount,
|
||||
days: days,
|
||||
updated_at: new Date().toISOString()
|
||||
});
|
||||
}),
|
||||
|
||||
// 获取概念价格时间序列
|
||||
http.get('http://111.198.58.126:16801/concept/:conceptId/price-timeseries', async ({ params, request }) => {
|
||||
await delay(300);
|
||||
|
||||
const { conceptId } = params;
|
||||
const url = new URL(request.url);
|
||||
const startDate = url.searchParams.get('start_date');
|
||||
const endDate = url.searchParams.get('end_date');
|
||||
|
||||
console.log('[Mock Concept] 获取价格时间序列:', { conceptId, startDate, endDate });
|
||||
|
||||
// 生成时间序列数据
|
||||
const timeseries = [];
|
||||
const start = new Date(startDate || '2024-01-01');
|
||||
const end = new Date(endDate || new Date());
|
||||
const daysDiff = Math.ceil((end - start) / (1000 * 60 * 60 * 24));
|
||||
|
||||
for (let i = 0; i <= daysDiff; i++) {
|
||||
const date = new Date(start);
|
||||
date.setDate(date.getDate() + i);
|
||||
|
||||
// 跳过周末
|
||||
if (date.getDay() !== 0 && date.getDay() !== 6) {
|
||||
timeseries.push({
|
||||
date: date.toISOString().split('T')[0],
|
||||
avg_change_pct: (Math.random() * 8 - 2).toFixed(2),
|
||||
stock_count: Math.floor(Math.random() * 30) + 10,
|
||||
volume: Math.floor(Math.random() * 1000000000)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return HttpResponse.json({
|
||||
concept_id: conceptId,
|
||||
timeseries: timeseries,
|
||||
start_date: startDate,
|
||||
end_date: endDate
|
||||
});
|
||||
}),
|
||||
|
||||
// 获取概念相关新闻
|
||||
http.get('http://111.198.58.126:21891/news', async ({ request }) => {
|
||||
await delay(300);
|
||||
|
||||
const url = new URL(request.url);
|
||||
const conceptName = url.searchParams.get('concept_name');
|
||||
const startDate = url.searchParams.get('start_date');
|
||||
const endDate = url.searchParams.get('end_date');
|
||||
|
||||
console.log('[Mock Concept] 获取概念新闻:', { conceptName, startDate, endDate });
|
||||
|
||||
const news = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const date = new Date();
|
||||
date.setDate(date.getDate() - i);
|
||||
|
||||
news.push({
|
||||
id: `news_${i}`,
|
||||
title: `${conceptName || '概念'}相关新闻标题 ${i + 1}`,
|
||||
content: `这是关于${conceptName || '概念'}的新闻内容摘要...`,
|
||||
source: ['新浪财经', '东方财富', '财联社', '证券时报'][Math.floor(Math.random() * 4)],
|
||||
publish_time: date.toISOString(),
|
||||
url: `https://example.com/news/${i}`
|
||||
});
|
||||
}
|
||||
|
||||
return HttpResponse.json({
|
||||
news: news,
|
||||
total: news.length,
|
||||
concept_name: conceptName
|
||||
});
|
||||
}),
|
||||
|
||||
// 获取概念相关研报
|
||||
http.get('http://111.198.58.126:8811/reports', async ({ request }) => {
|
||||
await delay(300);
|
||||
|
||||
const url = new URL(request.url);
|
||||
const conceptName = url.searchParams.get('concept_name');
|
||||
const startDate = url.searchParams.get('start_date');
|
||||
const endDate = url.searchParams.get('end_date');
|
||||
|
||||
console.log('[Mock Concept] 获取概念研报:', { conceptName, startDate, endDate });
|
||||
|
||||
const reports = [];
|
||||
for (let i = 0; i < 5; i++) {
|
||||
const date = new Date();
|
||||
date.setDate(date.getDate() - i * 2);
|
||||
|
||||
reports.push({
|
||||
id: `report_${i}`,
|
||||
title: `${conceptName || '概念'}行业研究报告 ${i + 1}`,
|
||||
abstract: `本报告深入分析了${conceptName || '概念'}行业的发展趋势和投资机会...`,
|
||||
author: ['中信证券', '国泰君安', '华泰证券', '招商证券'][Math.floor(Math.random() * 4)],
|
||||
publish_time: date.toISOString(),
|
||||
rating: ['买入', '增持', '中性'][Math.floor(Math.random() * 3)],
|
||||
url: `https://example.com/report/${i}`
|
||||
});
|
||||
}
|
||||
|
||||
return HttpResponse.json({
|
||||
reports: reports,
|
||||
total: reports.length,
|
||||
concept_name: conceptName
|
||||
});
|
||||
})
|
||||
];
|
||||
|
||||
@@ -923,4 +923,78 @@ export const eventHandlers = [
|
||||
}
|
||||
});
|
||||
}),
|
||||
|
||||
// ==================== 历史事件对比相关 ====================
|
||||
|
||||
// 获取历史事件相关股票
|
||||
http.get('/api/historical-events/:eventId/stocks', async ({ params }) => {
|
||||
await delay(500);
|
||||
|
||||
const { eventId } = params;
|
||||
|
||||
console.log('[Mock] 获取历史事件相关股票, eventId:', eventId);
|
||||
|
||||
// 生成历史事件相关股票数据
|
||||
const generateHistoricalEventStocks = (count = 10) => {
|
||||
const stocks = [];
|
||||
const sectors = ['半导体', '新能源', '医药', '消费电子', '人工智能', '5G通信'];
|
||||
const stockNames = [
|
||||
'中芯国际', '长江存储', '华为海思', '紫光国微', '兆易创新',
|
||||
'宁德时代', '比亚迪', '隆基绿能', '阳光电源', '亿纬锂能',
|
||||
'恒瑞医药', '迈瑞医疗', '药明康德', '泰格医药', '康龙化成',
|
||||
'立讯精密', '歌尔声学', '京东方A', 'TCL科技', '海康威视',
|
||||
'科大讯飞', '商汤科技', '寒武纪', '海光信息', '中兴通讯'
|
||||
];
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
const stockCode = `${Math.random() > 0.5 ? '6' : '0'}${String(Math.floor(Math.random() * 100000)).padStart(5, '0')}`;
|
||||
const changePct = (Math.random() * 15 - 3).toFixed(2); // -3% ~ +12%
|
||||
const correlation = (Math.random() * 0.4 + 0.6).toFixed(2); // 0.6 ~ 1.0
|
||||
|
||||
stocks.push({
|
||||
id: `stock_${i}`,
|
||||
stock_code: `${stockCode}.${Math.random() > 0.5 ? 'SH' : 'SZ'}`,
|
||||
stock_name: stockNames[i % stockNames.length],
|
||||
sector: sectors[Math.floor(Math.random() * sectors.length)],
|
||||
correlation: parseFloat(correlation),
|
||||
event_day_change_pct: parseFloat(changePct),
|
||||
relation_desc: {
|
||||
data: [
|
||||
{
|
||||
query_part: `该公司是${sectors[Math.floor(Math.random() * sectors.length)]}行业龙头,受事件影响显著,市场关注度高,订单量同比增长${Math.floor(Math.random() * 50 + 20)}%`,
|
||||
sentences: `根据行业研究报告,该公司在${sectors[Math.floor(Math.random() * sectors.length)]}领域具有核心技术优势,产能利用率达到${Math.floor(Math.random() * 20 + 80)}%,随着事件的深入发展,公司业绩有望持续受益。机构预测未来三年复合增长率将达到${Math.floor(Math.random() * 30 + 15)}%以上`,
|
||||
match_score: correlation > 0.8 ? '好' : (correlation > 0.6 ? '中' : '一般'),
|
||||
author: ['中信证券', '国泰君安', '华泰证券', '招商证券'][Math.floor(Math.random() * 4)],
|
||||
declare_date: new Date(Date.now() - Math.floor(Math.random() * 90) * 24 * 60 * 60 * 1000).toISOString(),
|
||||
report_title: `${stockNames[i % stockNames.length]}深度研究报告`
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 按相关度降序排序
|
||||
return stocks.sort((a, b) => b.correlation - a.correlation);
|
||||
};
|
||||
|
||||
try {
|
||||
const stocks = generateHistoricalEventStocks(15);
|
||||
|
||||
return HttpResponse.json({
|
||||
success: true,
|
||||
data: stocks,
|
||||
message: '获取历史事件相关股票成功'
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('[Mock] 获取历史事件相关股票失败:', error);
|
||||
return HttpResponse.json(
|
||||
{
|
||||
success: false,
|
||||
error: '获取历史事件相关股票失败',
|
||||
data: []
|
||||
},
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}),
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user