102 lines
2.5 KiB
TypeScript
102 lines
2.5 KiB
TypeScript
"use client";
|
|
|
|
import {
|
|
RadarChart,
|
|
Radar,
|
|
PolarGrid,
|
|
PolarAngleAxis,
|
|
PolarRadiusAxis,
|
|
ResponsiveContainer,
|
|
Legend,
|
|
Tooltip,
|
|
} from "recharts";
|
|
|
|
interface RadarDataItem {
|
|
platform?: string;
|
|
dimension?: string;
|
|
label: string;
|
|
[brand: string]: string | number | undefined;
|
|
}
|
|
|
|
interface CompetitorRadarChartProps {
|
|
data: RadarDataItem[];
|
|
brandName: string;
|
|
competitors: { name: string; color: string }[];
|
|
}
|
|
|
|
const DEFAULT_COLORS = [
|
|
"hsl(221.2 83.2% 53.3%)",
|
|
"hsl(346.8 77.2% 49.8%)",
|
|
"hsl(24.6 95% 53.1%)",
|
|
"hsl(142.1 76.2% 36.3%)",
|
|
"hsl(262.1 83.3% 57.8%)",
|
|
];
|
|
|
|
export function CompetitorRadarChart({
|
|
data,
|
|
brandName,
|
|
competitors,
|
|
}: CompetitorRadarChartProps) {
|
|
return (
|
|
<ResponsiveContainer width="100%" height={400}>
|
|
<RadarChart
|
|
data={data}
|
|
margin={{ top: 20, right: 20, bottom: 20, left: 20 }}
|
|
>
|
|
<PolarGrid stroke="hsl(var(--border))" />
|
|
<PolarAngleAxis
|
|
dataKey="label"
|
|
tick={{ fontSize: 12, fill: "hsl(var(--foreground))" }}
|
|
/>
|
|
<PolarRadiusAxis
|
|
angle={30}
|
|
domain={[0, 100]}
|
|
tick={{ fontSize: 10, fill: "hsl(var(--muted-foreground))" }}
|
|
/>
|
|
<Tooltip
|
|
contentStyle={{
|
|
backgroundColor: "hsl(var(--card))",
|
|
border: "1px solid hsl(var(--border))",
|
|
borderRadius: "var(--radius)",
|
|
}}
|
|
formatter={(value: number) => [`评分: ${value}`, ""]}
|
|
/>
|
|
<Legend
|
|
wrapperStyle={{ fontSize: 12 }}
|
|
formatter={(value) => (
|
|
<span style={{ color: "hsl(var(--foreground))" }}>{value}</span>
|
|
)}
|
|
/>
|
|
{/* 己方品牌 - 使用主色调 */}
|
|
<Radar
|
|
name={brandName}
|
|
dataKey={brandName}
|
|
stroke="hsl(221.2 83.2% 53.3%)"
|
|
fill="hsl(221.2 83.2% 53.3%)"
|
|
fillOpacity={0.3}
|
|
strokeWidth={2}
|
|
/>
|
|
{/* 竞品 */}
|
|
{competitors.map((competitor, index) => (
|
|
<Radar
|
|
key={competitor.name}
|
|
name={competitor.name}
|
|
dataKey={competitor.name}
|
|
stroke={
|
|
competitor.color ||
|
|
DEFAULT_COLORS[(index + 1) % DEFAULT_COLORS.length]
|
|
}
|
|
fill={
|
|
competitor.color ||
|
|
DEFAULT_COLORS[(index + 1) % DEFAULT_COLORS.length]
|
|
}
|
|
fillOpacity={0.15}
|
|
strokeWidth={2}
|
|
strokeDasharray="4 4"
|
|
/>
|
|
))}
|
|
</RadarChart>
|
|
</ResponsiveContainer>
|
|
);
|
|
}
|