feat: 添加数据

This commit is contained in:
zdl
2025-10-26 14:11:24 +08:00
parent a5702b631c
commit 05307d6501
3 changed files with 213 additions and 1 deletions

124
src/mocks/data/kline.js Normal file
View File

@@ -0,0 +1,124 @@
// src/mocks/data/kline.js
// K线数据生成函数
/**
* 生成分时数据 (timeline)
* 用于展示当日分钟级别的价格走势
*/
export const generateTimelineData = (indexCode) => {
const data = [];
const basePrice = getBasePrice(indexCode);
const today = new Date();
// 生成早盘数据 (09:30 - 11:30)
const morningStart = new Date(today.setHours(9, 30, 0, 0));
const morningEnd = new Date(today.setHours(11, 30, 0, 0));
generateTimeRange(data, morningStart, morningEnd, basePrice, 'morning');
// 生成午盘数据 (13:00 - 15:00)
const afternoonStart = new Date(today.setHours(13, 0, 0, 0));
const afternoonEnd = new Date(today.setHours(15, 0, 0, 0));
generateTimeRange(data, afternoonStart, afternoonEnd, basePrice, 'afternoon');
return data;
};
/**
* 生成日线数据 (daily)
* 用于获取历史收盘价等数据
*/
export const generateDailyData = (indexCode, days = 30) => {
const data = [];
const basePrice = getBasePrice(indexCode);
const today = new Date();
for (let i = days - 1; i >= 0; i--) {
const date = new Date(today);
date.setDate(date.getDate() - i);
// 跳过周末
const dayOfWeek = date.getDay();
if (dayOfWeek === 0 || dayOfWeek === 6) continue;
const open = basePrice * (1 + (Math.random() * 0.04 - 0.02));
const close = open * (1 + (Math.random() * 0.03 - 0.015));
const high = Math.max(open, close) * (1 + Math.random() * 0.015);
const low = Math.min(open, close) * (1 - Math.random() * 0.015);
const volume = Math.floor(Math.random() * 50000000000 + 10000000000);
data.push({
date: formatDate(date),
time: formatDate(date),
open: parseFloat(open.toFixed(2)),
close: parseFloat(close.toFixed(2)),
high: parseFloat(high.toFixed(2)),
low: parseFloat(low.toFixed(2)),
volume: volume,
prev_close: i === 0 ? parseFloat((basePrice * 0.99).toFixed(2)) : data[data.length - 1]?.close
});
}
return data;
};
/**
* 生成时间范围内的数据
*/
function generateTimeRange(data, startTime, endTime, basePrice, session) {
const current = new Date(startTime);
let price = basePrice;
// 波动趋势(早盘和午盘可能有不同的走势)
const trend = session === 'morning' ? Math.random() * 0.02 - 0.01 : Math.random() * 0.015 - 0.005;
while (current <= endTime) {
// 添加随机波动
const volatility = (Math.random() - 0.5) * 0.005;
price = price * (1 + trend / 120 + volatility); // 每分钟微小变化
const volume = Math.floor(Math.random() * 500000000 + 100000000);
data.push({
time: formatTime(current),
price: parseFloat(price.toFixed(2)),
close: parseFloat(price.toFixed(2)),
volume: volume,
prev_close: basePrice
});
// 增加1分钟
current.setMinutes(current.getMinutes() + 1);
}
}
/**
* 获取不同指数的基准价格
*/
function getBasePrice(indexCode) {
const basePrices = {
'000001.SH': 3200, // 上证指数
'399001.SZ': 10500, // 深证成指
'399006.SZ': 2100 // 创业板指
};
return basePrices[indexCode] || 3000;
}
/**
* 格式化时间为 HH:mm
*/
function formatTime(date) {
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
return `${hours}:${minutes}`;
}
/**
* 格式化日期为 YYYY-MM-DD
*/
function formatDate(date) {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}

View File

@@ -2,6 +2,7 @@
// 股票相关的 Mock Handlers
import { http, HttpResponse } from 'msw';
import { generateTimelineData, generateDailyData } from '../data/kline';
// 模拟延迟
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
@@ -140,4 +141,87 @@ export const stockHandlers = [
);
}
}),
// 获取指数K线数据
http.get('/api/index/:indexCode/kline', async ({ params, request }) => {
await delay(300);
const { indexCode } = params;
const url = new URL(request.url);
const type = url.searchParams.get('type') || 'timeline';
const eventTime = url.searchParams.get('event_time');
console.log('[Mock Stock] 获取指数K线数据:', { indexCode, type, eventTime });
try {
let data;
if (type === 'timeline') {
data = generateTimelineData(indexCode);
} else if (type === 'daily') {
data = generateDailyData(indexCode, 30);
} else {
return HttpResponse.json(
{ error: '不支持的类型' },
{ status: 400 }
);
}
return HttpResponse.json({
success: true,
data: data,
index_code: indexCode,
type: type,
message: '获取成功'
});
} catch (error) {
console.error('[Mock Stock] 获取K线数据失败:', error);
return HttpResponse.json(
{ error: '获取K线数据失败' },
{ status: 500 }
);
}
}),
// 获取股票K线数据
http.get('/api/stock/:stockCode/kline', async ({ params, request }) => {
await delay(300);
const { stockCode } = params;
const url = new URL(request.url);
const type = url.searchParams.get('type') || 'timeline';
const eventTime = url.searchParams.get('event_time');
console.log('[Mock Stock] 获取股票K线数据:', { stockCode, type, eventTime });
try {
let data;
if (type === 'timeline') {
// 股票使用指数的数据生成逻辑,但价格基数不同
data = generateTimelineData('000001.SH'); // 可以根据股票代码调整
} else if (type === 'daily') {
data = generateDailyData('000001.SH', 30);
} else {
return HttpResponse.json(
{ error: '不支持的类型' },
{ status: 400 }
);
}
return HttpResponse.json({
success: true,
data: data,
stock_code: stockCode,
type: type,
message: '获取成功'
});
} catch (error) {
console.error('[Mock Stock] 获取股票K线数据失败:', error);
return HttpResponse.json(
{ error: '获取K线数据失败' },
{ status: 500 }
);
}
}),
];