diff --git a/src/mocks/handlers/index.js b/src/mocks/handlers/index.js index bce489c7..233bc60e 100644 --- a/src/mocks/handlers/index.js +++ b/src/mocks/handlers/index.js @@ -12,6 +12,7 @@ import { stockHandlers } from './stock'; import { companyHandlers } from './company'; import { marketHandlers } from './market'; import { financialHandlers } from './financial'; +import { limitAnalyseHandlers } from './limitAnalyse'; // 可以在这里添加更多的 handlers // import { userHandlers } from './user'; @@ -28,5 +29,6 @@ export const handlers = [ ...companyHandlers, ...marketHandlers, ...financialHandlers, + ...limitAnalyseHandlers, // ...userHandlers, ]; diff --git a/src/mocks/handlers/limitAnalyse.js b/src/mocks/handlers/limitAnalyse.js new file mode 100644 index 00000000..b4b8e154 --- /dev/null +++ b/src/mocks/handlers/limitAnalyse.js @@ -0,0 +1,228 @@ +// src/mocks/handlers/limitAnalyse.js +// 涨停分析相关的 Mock Handlers + +import { http, HttpResponse } from 'msw'; + +// 模拟延迟 +const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms)); + +// 生成可用日期列表(最近30个交易日) +const generateAvailableDates = () => { + const dates = []; + const today = new Date(); + let count = 0; + + for (let i = 0; i < 60 && count < 30; i++) { + const date = new Date(today); + date.setDate(date.getDate() - i); + const dayOfWeek = date.getDay(); + + // 跳过周末 + if (dayOfWeek !== 0 && dayOfWeek !== 6) { + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const day = String(date.getDate()).padStart(2, '0'); + dates.push(`${year}${month}${day}`); + count++; + } + } + + return dates; +}; + +// 生成板块数据 +const generateSectors = (count = 8) => { + const sectorNames = [ + '人工智能', 'ChatGPT', '数字经济', + '新能源汽车', '光伏', '锂电池', + '半导体', '芯片', '5G通信', + '医疗器械', '创新药', '中药', + '白酒', '食品饮料', '消费电子', + '军工', '航空航天', '新材料' + ]; + + const sectors = []; + for (let i = 0; i < Math.min(count, sectorNames.length); i++) { + const stockCount = Math.floor(Math.random() * 15) + 5; + const stocks = []; + + for (let j = 0; j < stockCount; j++) { + stocks.push({ + code: `${Math.random() > 0.5 ? '6' : '0'}${String(Math.floor(Math.random() * 100000)).padStart(5, '0')}`, + name: `${sectorNames[i]}股票${j + 1}`, + latest_limit_time: `${Math.floor(Math.random() * 4) + 9}:${String(Math.floor(Math.random() * 60)).padStart(2, '0')}:${String(Math.floor(Math.random() * 60)).padStart(2, '0')}`, + limit_up_count: Math.floor(Math.random() * 3) + 1, + price: (Math.random() * 100 + 10).toFixed(2), + change_pct: (Math.random() * 5 + 5).toFixed(2), + turnover_rate: (Math.random() * 30 + 5).toFixed(2), + volume: Math.floor(Math.random() * 100000000 + 10000000), + amount: (Math.random() * 1000000000 + 100000000).toFixed(2), + limit_type: Math.random() > 0.7 ? '一字板' : (Math.random() > 0.5 ? 'T字板' : '普通涨停'), + 封单金额: (Math.random() * 500000000).toFixed(2), + }); + } + + sectors.push({ + sector_name: sectorNames[i], + stock_count: stockCount, + avg_limit_time: `${Math.floor(Math.random() * 2) + 10}:${String(Math.floor(Math.random() * 60)).padStart(2, '0')}`, + stocks: stocks, + }); + } + + return sectors; +}; + +// 生成高位股数据 +const generateHighPositionStocks = () => { + const stocks = []; + const stockNames = [ + '宁德时代', '比亚迪', '隆基绿能', '东方财富', '中际旭创', + '京东方A', '海康威视', '立讯精密', '三一重工', '恒瑞医药' + ]; + + for (let i = 0; i < stockNames.length; i++) { + const code = `${Math.random() > 0.5 ? '6' : '0'}${String(Math.floor(Math.random() * 100000)).padStart(5, '0')}`; + const continuousDays = Math.floor(Math.random() * 8) + 3; + + stocks.push({ + code: code, + name: stockNames[i], + continuous_limit_days: continuousDays, + total_gain_pct: (continuousDays * 10).toFixed(2), + recent_limit_dates: Array.from({ length: Math.min(continuousDays, 5) }, (_, j) => { + const date = new Date(); + date.setDate(date.getDate() - j); + return date.toISOString().split('T')[0].replace(/-/g, ''); + }), + sector: ['人工智能', 'ChatGPT', '数字经济'][Math.floor(Math.random() * 3)], + current_price: (Math.random() * 100 + 20).toFixed(2), + market_cap: (Math.random() * 5000 + 500).toFixed(2) + '亿', + }); + } + + return stocks; +}; + +// 生成词云数据 +const generateWordCloudData = () => { + const keywords = [ + '人工智能', 'ChatGPT', 'AI芯片', '大模型', '算力', + '新能源', '光伏', '锂电池', '储能', '充电桩', + '半导体', '芯片', 'EDA', '国产替代', '集成电路', + '医疗', '创新药', 'CXO', '医疗器械', '生物医药', + '消费', '白酒', '食品', '零售', '餐饮', + '金融', '券商', '保险', '银行', '金融科技' + ]; + + return keywords.map(keyword => ({ + text: keyword, + value: Math.floor(Math.random() * 50) + 10, + category: ['科技', '新能源', '医疗', '消费', '金融'][Math.floor(Math.random() * 5)], + })); +}; + +// 生成每日分析数据 +const generateDailyAnalysis = (date) => { + const sectors = generateSectors(); + const totalStocks = sectors.reduce((sum, sector) => sum + sector.stock_count, 0); + + return { + date: date, + total_stocks: totalStocks, + total_sectors: sectors.length, + avg_limit_time: '10:35:24', + market_sentiment: Math.random() > 0.5 ? '强势' : '震荡', + limit_up_ratio: (Math.random() * 3 + 1).toFixed(2) + '%', + sectors: sectors, + high_position_stocks: generateHighPositionStocks(), + summary: { + early_limit_count: Math.floor(totalStocks * 0.3), + mid_limit_count: Math.floor(totalStocks * 0.5), + late_limit_count: Math.floor(totalStocks * 0.2), + one_word_board: Math.floor(totalStocks * 0.15), + continuous_limit: generateHighPositionStocks().length, + } + }; +}; + +// Mock Handlers +export const limitAnalyseHandlers = [ + // 1. 获取可用日期列表 + http.get('http://111.198.58.126:5001/api/v1/dates/available', async () => { + await delay(300); + + const availableDates = generateAvailableDates(); + + return HttpResponse.json({ + success: true, + events: availableDates, + message: '可用日期列表获取成功', + }); + }), + + // 2. 获取每日分析数据 + http.get('http://111.198.58.126:5001/api/v1/analysis/daily/:date', async ({ params }) => { + await delay(500); + + const { date } = params; + const data = generateDailyAnalysis(date); + + return HttpResponse.json({ + success: true, + data: data, + message: `${date} 每日分析数据获取成功`, + }); + }), + + // 3. 获取词云数据 + http.get('http://111.198.58.126:5001/api/v1/analysis/wordcloud/:date', async ({ params }) => { + await delay(300); + + const { date } = params; + const wordCloudData = generateWordCloudData(); + + return HttpResponse.json({ + success: true, + data: wordCloudData, + message: `${date} 词云数据获取成功`, + }); + }), + + // 4. 混合搜索(POST) + http.post('http://111.198.58.126:5001/api/v1/stocks/search/hybrid', async ({ request }) => { + await delay(400); + + const body = await request.json(); + const { query, type = 'all', mode = 'hybrid' } = body; + + // 生成模拟搜索结果 + const results = []; + const count = Math.floor(Math.random() * 10) + 5; + + for (let i = 0; i < count; i++) { + results.push({ + code: `${Math.random() > 0.5 ? '6' : '0'}${String(Math.floor(Math.random() * 100000)).padStart(5, '0')}`, + name: `${query || '搜索'}相关股票${i + 1}`, + sector: ['人工智能', 'ChatGPT', '新能源'][Math.floor(Math.random() * 3)], + limit_date: new Date().toISOString().split('T')[0].replace(/-/g, ''), + limit_time: `${Math.floor(Math.random() * 4) + 9}:${String(Math.floor(Math.random() * 60)).padStart(2, '0')}`, + price: (Math.random() * 100 + 10).toFixed(2), + change_pct: (Math.random() * 10).toFixed(2), + match_score: (Math.random() * 0.5 + 0.5).toFixed(2), + }); + } + + return HttpResponse.json({ + success: true, + data: { + query: query, + type: type, + mode: mode, + results: results, + total: results.length, + }, + message: '搜索完成', + }); + }), +];