阶段一 - 核心优化: - 所有子组件添加 React.memo 防止不必要重渲染 - 图表组件统一使用 EChartsWrapper 替代 ReactECharts - 提取 isForecastYear、IMPORTANT_METRICS 到 constants.ts - DetailTable 样式提取为 DETAIL_TABLE_STYLES 常量 阶段二 - 架构优化: - 新增 hooks/useForecastData.ts:数据获取 + Map 缓存 + AbortController - 新增 services/forecastService.ts:API 封装层 - 新增 utils/chartFormatters.ts:图表格式化工具函数 - 主组件精简:79行 → 63行,添加错误处理和重试功能 优化效果: - 消除 4 处 isForecastYear 重复定义 - 样式从每次渲染重建改为常量复用 - 添加请求缓存,避免频繁切换时重复请求 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
190 lines
4.6 KiB
TypeScript
190 lines
4.6 KiB
TypeScript
/**
|
|
* 盈利预测报表常量和图表配置
|
|
*/
|
|
|
|
// 黑金主题配色
|
|
export const THEME = {
|
|
gold: '#D4AF37',
|
|
goldLight: 'rgba(212, 175, 55, 0.1)',
|
|
goldBorder: 'rgba(212, 175, 55, 0.3)',
|
|
bgDark: '#1A202C',
|
|
text: '#E2E8F0',
|
|
textSecondary: '#A0AEC0',
|
|
positive: '#E53E3E',
|
|
negative: '#10B981',
|
|
// 预测区域背景色
|
|
forecastBg: 'rgba(212, 175, 55, 0.08)',
|
|
};
|
|
|
|
// 图表配色方案 - 优化对比度
|
|
export const CHART_COLORS = {
|
|
income: '#D4AF37', // 收入 - 金色
|
|
profit: '#F6AD55', // 利润 - 橙金色
|
|
growth: '#10B981', // 增长率 - 翠绿色
|
|
eps: '#DAA520', // EPS - 金菊色
|
|
epsAvg: '#4A5568', // EPS行业平均 - 灰色
|
|
pe: '#D4AF37', // PE - 金色
|
|
peg: '#38B2AC', // PEG - 青色(优化对比度)
|
|
};
|
|
|
|
// ECharts 基础配置(黑金主题)
|
|
export const BASE_CHART_CONFIG = {
|
|
backgroundColor: 'transparent',
|
|
textStyle: {
|
|
color: THEME.text,
|
|
},
|
|
tooltip: {
|
|
backgroundColor: 'rgba(26, 32, 44, 0.98)',
|
|
borderColor: THEME.goldBorder,
|
|
borderWidth: 1,
|
|
padding: [12, 16],
|
|
textStyle: {
|
|
color: THEME.text,
|
|
fontSize: 13,
|
|
},
|
|
// 智能避让配置
|
|
confine: true,
|
|
appendToBody: true,
|
|
extraCssText: 'box-shadow: 0 4px 20px rgba(0,0,0,0.3); border-radius: 6px;',
|
|
},
|
|
legend: {
|
|
textStyle: {
|
|
color: THEME.textSecondary,
|
|
},
|
|
},
|
|
grid: {
|
|
left: 50,
|
|
right: 20,
|
|
bottom: 40,
|
|
top: 40,
|
|
containLabel: false,
|
|
},
|
|
xAxis: {
|
|
axisLine: {
|
|
lineStyle: {
|
|
color: THEME.goldBorder,
|
|
},
|
|
},
|
|
axisLabel: {
|
|
color: THEME.textSecondary,
|
|
rotate: 30,
|
|
},
|
|
splitLine: {
|
|
show: false,
|
|
},
|
|
},
|
|
yAxis: {
|
|
axisLine: {
|
|
lineStyle: {
|
|
color: THEME.goldBorder,
|
|
},
|
|
},
|
|
axisLabel: {
|
|
color: THEME.textSecondary,
|
|
},
|
|
splitLine: {
|
|
lineStyle: {
|
|
color: 'rgba(212, 175, 55, 0.1)',
|
|
},
|
|
},
|
|
},
|
|
};
|
|
|
|
// 图表高度
|
|
export const CHART_HEIGHT = 280;
|
|
|
|
// ============================================
|
|
// 工具函数
|
|
// ============================================
|
|
|
|
/**
|
|
* 判断是否为预测年份(包含 E 后缀)
|
|
* @param year 年份字符串,如 "2024E"
|
|
*/
|
|
export const isForecastYear = (year: string): boolean => year.includes('E');
|
|
|
|
/**
|
|
* 重要指标列表(用于表格行高亮)
|
|
*/
|
|
export const IMPORTANT_METRICS = ['归母净利润', 'ROE', 'EPS', '营业总收入'];
|
|
|
|
// ============================================
|
|
// DetailTable 样式
|
|
// ============================================
|
|
|
|
/**
|
|
* 详细数据表格样式 - 斑马纹、等宽字体、预测列区分
|
|
*/
|
|
export const DETAIL_TABLE_STYLES = `
|
|
/* 固定列背景 */
|
|
.forecast-detail-table .ant-table-cell-fix-left,
|
|
.forecast-detail-table .ant-table-cell-fix-right {
|
|
background: #1A202C !important;
|
|
}
|
|
.forecast-detail-table .ant-table-thead .ant-table-cell-fix-left,
|
|
.forecast-detail-table .ant-table-thead .ant-table-cell-fix-right {
|
|
background: rgba(26, 32, 44, 0.98) !important;
|
|
}
|
|
.forecast-detail-table .ant-table-tbody > tr:hover > td.ant-table-cell-fix-left {
|
|
background: #242d3d !important;
|
|
}
|
|
|
|
/* 指标标签样式 */
|
|
.forecast-detail-table .metric-tag {
|
|
background: rgba(212, 175, 55, 0.15);
|
|
border-color: rgba(212, 175, 55, 0.3);
|
|
color: #D4AF37;
|
|
font-weight: 500;
|
|
}
|
|
|
|
/* 重要指标行高亮 */
|
|
.forecast-detail-table .important-row {
|
|
background: rgba(212, 175, 55, 0.06) !important;
|
|
}
|
|
.forecast-detail-table .important-row .metric-tag {
|
|
background: rgba(212, 175, 55, 0.25);
|
|
color: #FFD700;
|
|
font-weight: 600;
|
|
}
|
|
|
|
/* 斑马纹 - 奇数行 */
|
|
.forecast-detail-table .ant-table-tbody > tr:nth-child(odd) > td {
|
|
background: rgba(255, 255, 255, 0.02);
|
|
}
|
|
.forecast-detail-table .ant-table-tbody > tr:nth-child(odd):hover > td {
|
|
background: rgba(212, 175, 55, 0.08) !important;
|
|
}
|
|
|
|
/* 等宽字体 - 数值列 */
|
|
.forecast-detail-table .data-cell {
|
|
font-family: 'SF Mono', 'Monaco', 'Menlo', 'Consolas', monospace;
|
|
font-variant-numeric: tabular-nums;
|
|
letter-spacing: -0.02em;
|
|
}
|
|
|
|
/* 预测列样式 */
|
|
.forecast-detail-table .forecast-col {
|
|
background: rgba(212, 175, 55, 0.04) !important;
|
|
font-style: italic;
|
|
}
|
|
.forecast-detail-table .ant-table-thead .forecast-col {
|
|
color: #FFD700 !important;
|
|
font-weight: 600;
|
|
}
|
|
|
|
/* 负数红色显示 */
|
|
.forecast-detail-table .negative-value {
|
|
color: #FC8181;
|
|
}
|
|
|
|
/* 正增长绿色 */
|
|
.forecast-detail-table .positive-growth {
|
|
color: #68D391;
|
|
}
|
|
|
|
/* 表头预测/历史分隔线 */
|
|
.forecast-detail-table .forecast-divider {
|
|
border-left: 2px solid rgba(212, 175, 55, 0.5) !important;
|
|
}
|
|
`;
|