You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

109 lines
3.6 KiB

import {
XAxis,
YAxis,
CartesianGrid,
Tooltip,
ResponsiveContainer,
ReferenceLine,
Area,
AreaChart
} from 'recharts';
import type { SentimentTrend } from '@/types';
interface SentimentTrendProps {
data: SentimentTrend[];
}
export function SentimentTrendChart({ data }: SentimentTrendProps) {
const CustomTooltip = ({ active, payload, label }: any) => {
if (active && payload && payload.length) {
const value = payload[0].value;
let sentiment = '中性';
let color = '#f97316';
if (value <= 20) { sentiment = '极度恐惧'; color = '#dc2626'; }
else if (value <= 40) { sentiment = '恐惧'; color = '#ef4444'; }
else if (value <= 60) { sentiment = '中性'; color = '#f97316'; }
else if (value <= 80) { sentiment = '贪婪'; color = '#22c55e'; }
else { sentiment = '极度贪婪'; color = '#16a34a'; }
return (
<div className="bg-[#141414] border border-white/10 rounded-lg p-3 shadow-xl">
<p className="text-white/60 text-sm">{label}</p>
<p className="text-white font-bold text-lg">{value}</p>
<p style={{ color }} className="text-sm">{sentiment}</p>
</div>
);
}
return null;
};
return (
<div className="w-full h-[300px]">
<ResponsiveContainer width="100%" height="100%">
<AreaChart data={data} margin={{ top: 10, right: 10, left: 0, bottom: 0 }}>
<defs>
<linearGradient id="sentimentGradient" x1="0" y1="0" x2="0" y2="1">
<stop offset="5%" stopColor="#a855f7" stopOpacity={0.3}/>
<stop offset="95%" stopColor="#a855f7" stopOpacity={0}/>
</linearGradient>
</defs>
<CartesianGrid strokeDasharray="3 3" stroke="rgba(255,255,255,0.05)" />
<XAxis
dataKey="date"
stroke="rgba(255,255,255,0.3)"
tick={{ fill: 'rgba(255,255,255,0.5)', fontSize: 11 }}
tickLine={false}
/>
<YAxis
domain={[0, 100]}
stroke="rgba(255,255,255,0.3)"
tick={{ fill: 'rgba(255,255,255,0.5)', fontSize: 11 }}
tickLine={false}
tickFormatter={(value) => `${value}`}
/>
<Tooltip content={<CustomTooltip />} />
{/* 参考线 */}
<ReferenceLine y={20} stroke="#dc2626" strokeDasharray="3 3" opacity={0.5} />
<ReferenceLine y={40} stroke="#ef4444" strokeDasharray="3 3" opacity={0.5} />
<ReferenceLine y={60} stroke="#22c55e" strokeDasharray="3 3" opacity={0.5} />
<ReferenceLine y={80} stroke="#16a34a" strokeDasharray="3 3" opacity={0.5} />
<Area
type="monotone"
dataKey="value"
stroke="#a855f7"
strokeWidth={2}
fill="url(#sentimentGradient)"
animationDuration={1000}
/>
</AreaChart>
</ResponsiveContainer>
{/* 图例 */}
<div className="flex justify-center gap-6 mt-4 text-xs">
<div className="flex items-center gap-2">
<div className="w-3 h-3 rounded-full bg-red-600"></div>
<span className="text-white/50"></span>
</div>
<div className="flex items-center gap-2">
<div className="w-3 h-3 rounded-full bg-orange-500"></div>
<span className="text-white/50"></span>
</div>
<div className="flex items-center gap-2">
<div className="w-3 h-3 rounded-full bg-green-600"></div>
<span className="text-white/50"></span>
</div>
</div>
</div>
);
}