// 趋势徽标: 上升 / 下降 / 持平 / 震荡 // props: // trend: 'up' | 'down' | 'flat' | 'volatile' // showText: 是否显示文字 (默认 true) const META = { up: { icon: '\u2191', text: '上升' }, down: { icon: '\u2193', text: '下降' }, flat: { icon: '=', text: '持平' }, volatile: { icon: '\u223F', text: '震荡' }, } // 根据最近 N 个数据点计算趋势: // - 数据不足 2 个 → flat // - 取最近 6 个点的变化, 整体涨幅 < 1% → flat // - 单调递增 → up, 单调递减 → down // - 其余 (有升有降) → volatile // 返回: { trend, change } (change 为百分比变化, 保留 1 位小数) export function calcTrend(rows) { if (!rows || rows.length < 2) return { trend: 'flat', change: 0 } const N = Math.min(6, rows.length) const recent = rows.slice(-N).map((r) => r.value).filter((v) => typeof v === 'number') if (recent.length < 2) return { trend: 'flat', change: 0 } const first = recent[0] const last = recent[recent.length - 1] const change = first === 0 ? 0 : ((last - first) / Math.abs(first)) * 100 if (Math.abs(change) < 1) return { trend: 'flat', change } let up = 0, down = 0 for (let i = 1; i < recent.length; i++) { if (recent[i] > recent[i - 1]) up++ else if (recent[i] < recent[i - 1]) down++ } if (up === recent.length - 1) return { trend: 'up', change } if (down === recent.length - 1) return { trend: 'down', change } return { trend: 'volatile', change } } // 取数据序列最后一个有效点: { month, value } 或 null export function lastPoint(data) { const rows = (data && data.rows) || [] for (let i = rows.length - 1; i >= 0; i--) { if (rows[i] && typeof rows[i].value === 'number') return rows[i] } return null } export default function TrendBadge({ trend, showText = true }) { const m = META[trend] || META.flat return ( {m.icon} {showText && {m.text}} ) }