update pay ui

This commit is contained in:
2025-12-09 16:27:56 +08:00
parent e8763331cc
commit b40ca0e23c
22 changed files with 3637 additions and 8176 deletions

View File

@@ -346,7 +346,173 @@ export const marketHandlers = [
});
}),
// 11. 市场统计数据(个股中心页面使用
// 11. 热点概览数据(大盘分时 + 概念异动
http.get('/api/market/hotspot-overview', async ({ request }) => {
await delay(300);
const url = new URL(request.url);
const date = url.searchParams.get('date');
const tradeDate = date || new Date().toISOString().split('T')[0];
// 生成分时数据240个点9:30-11:30 + 13:00-15:00
const timeline = [];
const basePrice = 3900 + Math.random() * 100; // 基准价格 3900-4000
const prevClose = basePrice;
let currentPrice = basePrice;
let cumulativeVolume = 0;
// 上午时段 9:30-11:30 (120分钟)
for (let i = 0; i < 120; i++) {
const hour = 9 + Math.floor((i + 30) / 60);
const minute = (i + 30) % 60;
const time = `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`;
// 模拟价格波动
const volatility = 0.002; // 0.2%波动
const drift = (Math.random() - 0.5) * 0.001; // 微小趋势
currentPrice = currentPrice * (1 + (Math.random() - 0.5) * volatility + drift);
const volume = Math.floor(Math.random() * 500000 + 100000); // 成交量
cumulativeVolume += volume;
timeline.push({
time,
price: parseFloat(currentPrice.toFixed(2)),
volume: cumulativeVolume,
change_pct: parseFloat(((currentPrice - prevClose) / prevClose * 100).toFixed(2))
});
}
// 下午时段 13:00-15:00 (120分钟)
for (let i = 0; i < 120; i++) {
const hour = 13 + Math.floor(i / 60);
const minute = i % 60;
const time = `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`;
// 下午波动略小
const volatility = 0.0015;
const drift = (Math.random() - 0.5) * 0.0008;
currentPrice = currentPrice * (1 + (Math.random() - 0.5) * volatility + drift);
const volume = Math.floor(Math.random() * 400000 + 80000);
cumulativeVolume += volume;
timeline.push({
time,
price: parseFloat(currentPrice.toFixed(2)),
volume: cumulativeVolume,
change_pct: parseFloat(((currentPrice - prevClose) / prevClose * 100).toFixed(2))
});
}
// 生成概念异动数据
const conceptNames = [
'人工智能', 'AI眼镜', '机器人', '核电', '国企', '卫星导航',
'福建自贸区', '两岸融合', 'CRO', '三季报增长', '百货零售',
'人形机器人', '央企', '数据中心', 'CPO', '新能源', '电网设备',
'氢能源', '算力租赁', '厦门国资', '乳业', '低空安防', '创新药',
'商业航天', '控制权变更', '文化传媒', '海峡两岸'
];
const alertTypes = ['surge_up', 'surge_down', 'volume_spike', 'limit_up', 'rank_jump'];
// 生成 15-25 个异动
const alertCount = Math.floor(Math.random() * 10) + 15;
const alerts = [];
const usedTimes = new Set();
for (let i = 0; i < alertCount; i++) {
// 随机选择一个时间点
let timeIdx;
let attempts = 0;
do {
timeIdx = Math.floor(Math.random() * timeline.length);
attempts++;
} while (usedTimes.has(timeIdx) && attempts < 50);
if (attempts >= 50) continue;
// 同一时间可以有多个异动
const time = timeline[timeIdx].time;
const conceptName = conceptNames[Math.floor(Math.random() * conceptNames.length)];
const alertType = alertTypes[Math.floor(Math.random() * alertTypes.length)];
// 根据类型生成 alpha
let alpha;
if (alertType === 'surge_up') {
alpha = parseFloat((Math.random() * 3 + 2).toFixed(2)); // +2% ~ +5%
} else if (alertType === 'surge_down') {
alpha = parseFloat((-Math.random() * 3 - 1.5).toFixed(2)); // -1.5% ~ -4.5%
} else {
alpha = parseFloat((Math.random() * 4 - 1).toFixed(2)); // -1% ~ +3%
}
const finalScore = Math.floor(Math.random() * 40 + 45); // 45-85分
const ruleScore = Math.floor(Math.random() * 30 + 40);
const mlScore = Math.floor(Math.random() * 30 + 40);
alerts.push({
concept_id: `CONCEPT_${1000 + i}`,
concept_name: conceptName,
time,
alert_type: alertType,
alpha,
alpha_delta: parseFloat((Math.random() * 2 - 0.5).toFixed(2)),
amt_ratio: parseFloat((Math.random() * 5 + 1).toFixed(2)),
limit_up_count: alertType === 'limit_up' ? Math.floor(Math.random() * 5 + 1) : 0,
limit_up_ratio: parseFloat((Math.random() * 0.3).toFixed(3)),
final_score: finalScore,
rule_score: ruleScore,
ml_score: mlScore,
trigger_reason: finalScore >= 65 ? '规则强信号' : (mlScore >= 70 ? 'ML强信号' : '融合触发'),
importance_score: parseFloat((finalScore / 100).toFixed(2)),
index_price: timeline[timeIdx].price
});
}
// 按时间排序
alerts.sort((a, b) => a.time.localeCompare(b.time));
// 统计异动类型
const alertSummary = alerts.reduce((acc, alert) => {
acc[alert.alert_type] = (acc[alert.alert_type] || 0) + 1;
return acc;
}, {});
// 计算指数统计
const prices = timeline.map(t => t.price);
const latestPrice = prices[prices.length - 1];
const highPrice = Math.max(...prices);
const lowPrice = Math.min(...prices);
const changePct = ((latestPrice - prevClose) / prevClose * 100);
console.log('[Mock Market] 获取热点概览数据:', {
date: tradeDate,
timelinePoints: timeline.length,
alertCount: alerts.length
});
return HttpResponse.json({
success: true,
data: {
index: {
code: '000001.SH',
name: '上证指数',
latest_price: latestPrice,
prev_close: prevClose,
high: highPrice,
low: lowPrice,
change_pct: parseFloat(changePct.toFixed(2)),
timeline
},
alerts,
alert_summary: alertSummary
},
trade_date: tradeDate
});
}),
// 12. 市场统计数据(个股中心页面使用)
http.get('/api/market/statistics', async ({ request }) => {
await delay(200);
const url = new URL(request.url);