竞品评分可视化(Recharts)
在 youteacher_analyze 里,竞争格局由两张客户端 React 图表呈现,都基于 Recharts,另有一个薄薄的 Mermaid 封装用来画图。两张图回答的是同一个问题——每个竞品在 ESL 教师招聘市场里处在什么位置——但编码方式不同:一张是多维度雷达图,一张是双轴散点图。
两种图形
CompetitorHexagonChart 是一张 RPG "角色属性"式的雷达图。它把 7 个竞品放在 6 个维度上——Verification/Trust、Community、Jobs Listed、Candidate Pool、Technology、Company Size——每个维度打 0–100 分。它由 Recharts 原语组合而成:一个跑在共享 radarData 数组上的 RadarChart,加上 PolarGrid、以维度名为键的 PolarAngleAxis、固定 [0, 100] 定义域的 PolarRadiusAxis,以及每个竞品一条的 <Radar> 系列。每个竞品带有各自的描边/填充色,填充半透明,好让重叠的形状仍然读得清。
CompetitivePositioningChart 是一张双轴 ScatterChart——横轴 Technology Level、纵轴 Trust Level,都是 [0, 100]。每个竞品是一个点,逐点的 color 通过 <Cell> 施加。虚线参考线把平面切成四象限,并标出 "Target Zone"(高技术、高信任)与 "Danger Zone"(低技术、低信任)。自定义的 LabelList 在每个点上方渲染竞品名,自定义 Tooltip 在悬停时给出精确的 tech/trust 分数。
分数与证据同行
最有特点的设计取舍是:每个数字分数都带着产出它的定性证据一起走。在雷达图里,radarData 里的数字并非孤立存在——一个平行的 competitors 数组按竞品保存一个 evidence 对象,每个维度对应一条短字符串(verification、community、jobsListed、candidatePool、technology、companySize)。组件把这些证据字符串在图表下方重新渲染出来,让读者能看到某个竞品为什么得这个分,而不只是它的形状。
在证据之下,一份评分标尺(rubric)把定性→定量的映射写清楚:每个维度分档(0–20、20–40……80–100),配上这一档意味着什么的白话定义,以及哪个竞品落在这里、为什么。于是分数是作为可推导、可辩护的东西呈现的,而不是断言——图表是结论,标尺是方法,证据字符串是收据。
交互
雷达图维护一个 selectedCompetitors 状态(默认全选)。左侧一个可点击的图例把每个竞品切进切出;只有被选中的才作为 <Radar> 系列传入、并在证据列表里回显。这样读者可以只留两三个竞品来比较各自的形状,而不至于让雷达变成一团乱麻。
Mermaid 封装
MermaidDiagram 是一个很薄的客户端组件:接收一个 chart 字符串,在 effect 里调用 mermaid.initialize 再 mermaid.render,把得到的 SVG 注入一个 ref 的 <div>。它为每张图生成一个随机 id,避免一页上多张图相互冲突。它是两张定制 Recharts 图之外的通用画图后路。
为什么这么做
雷达和散点是"多竞品对比"最自然的两种编码。雷达回答每个竞品在所有维度上的整体画像;散点回答它们在最要紧的两个轴上如何聚类。把分数绑定到内联证据和一份明确标尺,才是让可视化保持诚实的关键——它把主观的竞争判读变成读者可以逐维度核查的东西。