update pay ui

This commit is contained in:
2025-12-11 07:32:30 +08:00
parent f545c9ec15
commit 8c6ebe01ed
5 changed files with 1379 additions and 321 deletions

View File

@@ -3,6 +3,207 @@
* 用于处理异动标注等图表相关逻辑
*/
/**
* 异动类型配置 - 科技感配色方案
*/
export const ALERT_TYPE_CONFIG = {
surge_up: {
label: '急涨',
color: '#ff4d4f',
gradient: ['#ff4d4f', '#ff7a45'],
icon: 'TrendingUp',
bgAlpha: 0.15,
description: '概念板块出现快速上涨异动',
},
surge: {
label: '异动',
color: '#ff7a45',
gradient: ['#ff7a45', '#ffa940'],
icon: 'Zap',
bgAlpha: 0.12,
description: '概念板块出现明显异动信号',
},
surge_down: {
label: '急跌',
color: '#52c41a',
gradient: ['#52c41a', '#73d13d'],
icon: 'TrendingDown',
bgAlpha: 0.15,
description: '概念板块出现快速下跌异动',
},
volume_surge_up: {
label: '放量急涨',
color: '#eb2f96',
gradient: ['#eb2f96', '#f759ab'],
icon: 'Activity',
bgAlpha: 0.15,
description: '成交量放大伴随价格急涨,资金关注度高',
},
shrink_surge_up: {
label: '缩量急涨',
color: '#722ed1',
gradient: ['#722ed1', '#9254de'],
icon: 'Rocket',
bgAlpha: 0.15,
description: '成交量萎缩但价格急涨,筹码锁定良好',
},
volume_oscillation: {
label: '放量震荡',
color: '#13c2c2',
gradient: ['#13c2c2', '#36cfc9'],
icon: 'Waves',
bgAlpha: 0.12,
description: '成交量放大但价格震荡,多空分歧加大',
},
limit_up: {
label: '涨停潮',
color: '#fa541c',
gradient: ['#fa541c', '#ff7a45'],
icon: 'Flame',
bgAlpha: 0.15,
description: '板块内多只股票涨停,热度极高',
},
rank_jump: {
label: '排名跃升',
color: '#1890ff',
gradient: ['#1890ff', '#40a9ff'],
icon: 'ArrowUpCircle',
bgAlpha: 0.12,
description: '概念板块排名快速上升,关注度提升',
},
volume_spike: {
label: '放量异动',
color: '#faad14',
gradient: ['#faad14', '#ffc53d'],
icon: 'BarChart3',
bgAlpha: 0.12,
description: '成交量出现突发性放大',
},
};
/**
* 指标配置 - 包含详细提示说明
*/
export const METRIC_CONFIG = {
final_score: {
label: '综合评分',
unit: '分',
tooltip: '综合规则评分和机器学习评分的最终得分分数越高表示异动信号越强。60分以上值得关注80分以上为强信号。',
format: (v) => Math.round(v),
getColor: (v) => {
if (v >= 80) return '#ff4d4f';
if (v >= 60) return '#fa8c16';
if (v >= 40) return '#faad14';
return '#8c8c8c';
},
},
rule_score: {
label: '规则评分',
unit: '分',
tooltip: '基于预设规则计算的评分,包括涨跌幅、成交量、涨停数等多维度指标。',
format: (v) => Math.round(v),
},
ml_score: {
label: 'AI评分',
unit: '分',
tooltip: '机器学习模型预测的评分,基于历史数据训练,预测该异动后续表现概率。',
format: (v) => Math.round(v),
},
confirm_ratio: {
label: '确认率',
unit: '%',
tooltip: '异动信号的确认程度。100%表示信号完全确认数值越高表示异动越稳定、越可靠。低于60%的信号可能是噪音。',
format: (v) => Math.round(v * 100),
getColor: (v) => {
if (v >= 0.8) return '#52c41a';
if (v >= 0.6) return '#faad14';
return '#ff4d4f';
},
},
alpha: {
label: '超额收益',
unit: '%',
tooltip: '概念板块相对于大盘的超额涨跌幅Alpha。正值表示跑赢大盘负值表示跑输大盘。该指标反映板块的相对强弱。',
format: (v) => v?.toFixed(2),
getColor: (v) => v >= 0 ? '#ff4d4f' : '#52c41a',
showSign: true,
},
alpha_zscore: {
label: 'Alpha强度',
unit: 'σ',
tooltip: 'Alpha的Z-Score标准化值衡量超额收益的统计显著性。|值|>2表示异常强|值|>1.5表示较强。正值表示异常上涨,负值表示异常下跌。',
format: (v) => v?.toFixed(2),
getColor: (v) => v >= 0 ? '#ff4d4f' : '#52c41a',
showSign: true,
},
amt_zscore: {
label: '成交额强度',
unit: 'σ',
tooltip: '成交额的Z-Score标准化值衡量当前成交额相对于历史的异常程度。>2表示成交额异常放大资金活跃度高。',
format: (v) => v?.toFixed(2),
getColor: (v) => {
if (v >= 2) return '#eb2f96';
if (v >= 1) return '#faad14';
return '#8c8c8c';
},
},
rank_zscore: {
label: '排名变化强度',
unit: 'σ',
tooltip: '板块排名变化的Z-Score值。正值表示排名上升速度异常>2表示排名跃升显著。',
format: (v) => v?.toFixed(2),
showSign: true,
},
momentum_3m: {
label: '3分钟动量',
unit: '',
tooltip: '过去3分钟的价格动量指标反映短期趋势强度。正值表示上涨动量负值表示下跌动量。',
format: (v) => v?.toFixed(3),
getColor: (v) => v >= 0 ? '#ff4d4f' : '#52c41a',
showSign: true,
},
momentum_5m: {
label: '5分钟动量',
unit: '',
tooltip: '过去5分钟的价格动量指标比3分钟动量更稳定过滤掉更多噪音。',
format: (v) => v?.toFixed(3),
getColor: (v) => v >= 0 ? '#ff4d4f' : '#52c41a',
showSign: true,
},
limit_up_ratio: {
label: '涨停占比',
unit: '%',
tooltip: '板块内涨停股票数量占总股票数的比例。>10%表示板块热度高,>20%表示涨停潮。',
format: (v) => Math.round(v * 100),
getColor: (v) => {
if (v >= 0.2) return '#ff4d4f';
if (v >= 0.1) return '#fa8c16';
if (v >= 0.05) return '#faad14';
return '#8c8c8c';
},
},
};
/**
* 触发规则配置
*/
export const TRIGGERED_RULES_CONFIG = {
alpha_moderate: { label: 'Alpha中等', color: '#ff7a45', description: '超额收益达到中等水平' },
alpha_strong: { label: 'Alpha强', color: '#ff4d4f', description: '超额收益达到强势水平' },
amt_moderate: { label: '成交额中等', color: '#faad14', description: '成交额异常放大中等' },
amt_strong: { label: '成交额强', color: '#fa8c16', description: '成交额异常放大明显' },
limit_up_moderate: { label: '涨停中等', color: '#eb2f96', description: '涨停股票数量适中' },
limit_up_extreme: { label: '涨停极端', color: '#ff4d4f', description: '涨停股票数量很多' },
momentum_3m_moderate: { label: '3分钟动量', color: '#1890ff', description: '短期动量信号触发' },
momentum_3m_strong: { label: '3分钟强动量', color: '#096dd9', description: '短期强动量信号' },
combo_alpha_amt: { label: 'Alpha+成交额', color: '#722ed1', description: '超额收益和成交额双重确认' },
combo_alpha_limitup: { label: 'Alpha+涨停', color: '#eb2f96', description: '超额收益和涨停双重确认' },
early_session: { label: '早盘信号', color: '#13c2c2', description: '开盘30分钟内的异动' },
'decay:accelerating': { label: '加速中', color: '#52c41a', description: '异动正在加速' },
'decay:stable': { label: '稳定', color: '#1890ff', description: '异动保持稳定' },
'decay:fading': { label: '衰减中', color: '#8c8c8c', description: '异动正在衰减' },
};
/**
* 获取异动标注的配色和符号
* @param {string} alertType - 异动类型
@@ -10,42 +211,41 @@
* @returns {Object} { color, symbol, symbolSize }
*/
export const getAlertStyle = (alertType, importanceScore = 0.5) => {
let color = '#ff6b6b';
let symbol = 'pin';
let symbolSize = 35;
const config = ALERT_TYPE_CONFIG[alertType] || ALERT_TYPE_CONFIG.surge;
const baseSize = 30;
const sizeBonus = Math.min(importanceScore * 20, 15);
let symbol = 'pin';
switch (alertType) {
case 'surge_up':
case 'surge':
color = '#ff4757';
case 'volume_surge_up':
case 'shrink_surge_up':
symbol = 'triangle';
symbolSize = 30 + Math.min(importanceScore * 20, 15);
break;
case 'surge_down':
color = '#2ed573';
symbol = 'path://M0,0 L10,0 L5,10 Z'; // 向下三角形
symbolSize = 30 + Math.min(importanceScore * 20, 15);
symbol = 'path://M0,0 L10,0 L5,10 Z';
break;
case 'limit_up':
color = '#ff6348';
symbol = 'diamond';
symbolSize = 28;
break;
case 'rank_jump':
color = '#3742fa';
symbol = 'circle';
symbolSize = 25;
break;
case 'volume_spike':
color = '#ffa502';
case 'volume_oscillation':
symbol = 'rect';
symbolSize = 25;
break;
default:
break;
symbol = 'pin';
}
return { color, symbol, symbolSize };
return {
color: config.color,
gradient: config.gradient,
symbol,
symbolSize: baseSize + sizeBonus,
};
};
/**
@@ -54,16 +254,30 @@ export const getAlertStyle = (alertType, importanceScore = 0.5) => {
* @returns {string} 显示标签
*/
export const getAlertTypeLabel = (alertType) => {
const labels = {
surge: '急涨',
surge_up: '暴涨',
surge_down: '暴跌',
limit_up: '涨停增加',
rank_jump: '排名跃升',
volume_spike: '放量',
unknown: '异动',
return ALERT_TYPE_CONFIG[alertType]?.label || alertType || '异动';
};
/**
* 获取异动类型的详细描述
* @param {string} alertType - 异动类型
* @returns {string} 描述
*/
export const getAlertTypeDescription = (alertType) => {
return ALERT_TYPE_CONFIG[alertType]?.description || '概念板块出现异动信号';
};
/**
* 获取异动类型的配色
* @param {string} alertType - 异动类型
* @returns {Object} { color, gradient, bgAlpha }
*/
export const getAlertTypeColor = (alertType) => {
const config = ALERT_TYPE_CONFIG[alertType] || ALERT_TYPE_CONFIG.surge;
return {
color: config.color,
gradient: config.gradient,
bgAlpha: config.bgAlpha,
};
return labels[alertType] || alertType;
};
/**
@@ -88,7 +302,7 @@ export const getAlertMarkPoints = (alerts, times, prices, priceMax, maxCount = 1
const timeIndex = times.indexOf(alert.time);
const price = timeIndex >= 0 ? prices[timeIndex] : (alert.index_price || priceMax);
const { color, symbol, symbolSize } = getAlertStyle(
const { color, gradient, symbol, symbolSize } = getAlertStyle(
alert.alert_type,
alert.final_score / 100 || alert.importance_score || 0.5
);
@@ -113,23 +327,33 @@ export const getAlertMarkPoints = (alerts, times, prices, priceMax, maxCount = 1
symbol,
symbolSize,
itemStyle: {
color,
borderColor: '#fff',
borderWidth: 1,
shadowBlur: 3,
shadowColor: 'rgba(0,0,0,0.2)',
color: {
type: 'linear',
x: 0, y: 0, x2: 0, y2: 1,
colorStops: [
{ offset: 0, color: gradient[0] },
{ offset: 1, color: gradient[1] },
],
},
borderColor: 'rgba(255,255,255,0.8)',
borderWidth: 2,
shadowBlur: 8,
shadowColor: `${color}66`,
},
label: {
show: true,
position: isDown ? 'bottom' : 'top',
formatter: '{b}',
fontSize: 9,
color: '#333',
backgroundColor: isDown ? 'rgba(46, 213, 115, 0.9)' : 'rgba(255,255,255,0.9)',
padding: [2, 4],
borderRadius: 2,
fontSize: 10,
fontWeight: 500,
color: isDown ? '#52c41a' : '#ff4d4f',
backgroundColor: 'rgba(255,255,255,0.95)',
padding: [3, 6],
borderRadius: 4,
borderColor: color,
borderWidth: 1,
shadowBlur: 4,
shadowColor: 'rgba(0,0,0,0.1)',
},
alertData: alert, // 存储原始数据
};
@@ -153,8 +377,45 @@ export const formatScore = (score) => {
*/
export const getScoreColor = (score) => {
const s = score || 0;
if (s >= 80) return '#ff4757';
if (s >= 60) return '#ff6348';
if (s >= 40) return '#ffa502';
return '#747d8c';
if (s >= 80) return '#ff4d4f';
if (s >= 60) return '#fa8c16';
if (s >= 40) return '#faad14';
return '#8c8c8c';
};
/**
* 获取分数等级标签
* @param {number} score - 分数 (0-100)
* @returns {Object} { label, color }
*/
export const getScoreLevel = (score) => {
const s = score || 0;
if (s >= 80) return { label: '强信号', color: '#ff4d4f' };
if (s >= 60) return { label: '中等', color: '#fa8c16' };
if (s >= 40) return { label: '一般', color: '#faad14' };
return { label: '弱信号', color: '#8c8c8c' };
};
/**
* 格式化指标值
* @param {string} metricKey - 指标键名
* @param {number} value - 值
* @returns {Object} { formatted, color, showSign }
*/
export const formatMetric = (metricKey, value) => {
const config = METRIC_CONFIG[metricKey];
if (!config || value === null || value === undefined) {
return { formatted: '-', color: '#8c8c8c', showSign: false };
}
const formatted = config.format(value);
const color = config.getColor ? config.getColor(value) : '#8c8c8c';
return {
formatted: config.showSign && value > 0 ? `+${formatted}` : formatted,
color,
unit: config.unit,
label: config.label,
tooltip: config.tooltip,
};
};