可视化:Vue 2 把画像和异常亮出来
数据链路都跑通了,最后一篇讲讲怎么把这些数据画出来,并且真的能用。
老实说,可视化这块一开始我没太当回事——数据都算好了,画几个图表能有多难?做完才发现,做出来好看和做出来有用,中间隔着一个太平洋。看板真正的价值不是展示数据,是让异常自动浮出来。
看板要回答什么问题
我们的看板服务两类人,问题不同:
- Team Lead:我的团队现在有没有风险?谁状态不对?哪个模块成了单点?
- 个人(开发者本人):我自己的画像长什么样?我在团队里大概什么位置?
所以看板分了三块:
- 个人画像页:某个开发者四个维度的雷达图 + 趋势
- 团队视图:分布、排名(脱敏,不公开)、异常清单
- 风险监控页:单点依赖、协作孤岛、突变告警
下面一个个说。
个人画像页:雷达图是核心
雷达图是个人画像最直观的展示方式。四个维度(提交 / 代码 / 协作 / 产出)各算一个 0-100 的归一化分数,画一张五维或者四维的雷达图。
1 | <!-- ProfileChart.vue 简化版 --> |
这里有个细节我特别想强调:雷达图上一定要画一条”团队均值”的虚线作为参考。否则一个 78 分的提交维度到底是高是低,看的人完全没概念。配上参考圈,一眼就能看出”这个同学协作特别强,但产出偏弱”。
雷达图旁边再配一个 90 天的趋势线,看每个维度是不是在变化。单点静态的画像用处不大,趋势才有信号。
团队视图:分布比排名重要
第二版上线的时候,我们做了一份”团队内排名榜”,结果没两天就被吐槽了——任何形式的排名都会逼着大家刷数据,哪怕你不公开只给 Lead 看,Lead 跟人聊的时候也会无意泄露。
所以第三版改成只看分布:
- 每个维度的直方图 + 箱线图
- 标注离群点(散点图,不显示具体人名,点击才查)
- 团队整体的月度趋势
1 | <!-- TeamDistribution.vue --> |
看板的克制比堆功能重要。该让 Lead 自己点进去看的,就不要直接列出来,隐私和数据准确性都靠这种克制保护。
风险监控:异常自动浮出来
这是整个看板真正有价值的一块。前面所有的工作,最后都是为了这一页能自动把风险亮出来。
我们做了几个关键的异常识别:
1. 单点依赖
某个仓库 / 模块,过去 90 天内只有一个人在动 → 这就是单点依赖。这个人生病、离职、休假,对应模块就停摆。
1 | -- 简化逻辑:90 天内某模块提交者只有一个人 |
这种在面板上用红色卡片直接列出来,一眼就能看到。
2. 协作孤岛
某同学过去 30 天既没评审别人,也没被别人评审。这种基本就是在”单干”——要么是在做一个独立项目,要么是已经被边缘化了。两种情况都值得 Lead 关注。
1 | // 协作网络的节点 |
3. 突变告警
某个指标在短时间内大幅下跌。比如:
- 协作维度分数从 80 跌到 20(过去 14 天 vs 前 14 天)
- 评审参与次数从平均每周 8 次跌到 0
- 代码量突然下降 70% 以上
这种突变通常意味着:这个人要么在憋大招(搞一个大重构),要么状态已经不对了。两种情况 Lead 都该聊一聊。
1 | <!-- AlertList.vue --> |
我们最终没接邮件 / 钉钉推送,故意不接。理由很简单:推送一多就会被忽略,看板这种”主动来看”的形式反而更容易被认真对待。这一点也是上线半年之后才想明白的。
一个真实场景
讲一个具体场景吧。看板上线大概两个月后,某 Team Lead 找我说,他在面板上看到自己组里某同学:
- 提交维度还正常
- 代码维度稍微下降
- 协作维度从前 30% 跌到了倒数 10%
- 产出维度正常
聊完发现,那位同学最近一个月都在帮另一个组做支援,已经事实上不在这个 Lead 的组里了——但人事关系还没走。这种情况靠以前的人工周会是发现不了的,看板倒先亮了出来。
我觉得这才是可视化的真正价值:不是为了好看,是让那些”看不出但应该被看到”的事情浮出来。
Vue 2 的工程小细节
最后补几个 Vue 2 工程上的小经验:
- ECharts 用按需引入,别整包 import。看板首屏本来就要画好几个图,整包 import 会让 bundle 直接膨胀到几 MB。
1
2
3
4
5
6
7
8
9
10
11// 只引入雷达图和散点图
import * as echarts from 'echarts/core';
import { RadarChart, ScatterChart } from 'echarts/charts';
import { TooltipComponent, GridComponent } from 'echarts/components';
import { CanvasRenderer } from 'echarts/renderers';
echarts.use([
RadarChart, ScatterChart,
TooltipComponent, GridComponent,
CanvasRenderer,
]); - 数据用 Vuex 集中管理,分页面按 module 拆。不要让某个组件自己 fetch 数据,否则切换页面回来之后状态全丢。
- 大表用虚拟滚动(vue-virtual-scroller),团队视图动辄几百行,不虚拟化会卡。
- 后端聚合过的数据再给前端,不要把原始
git_commit_file这种几千万行的表让前端去 group by。
整套系统回顾
四篇写完了,回顾一下整个 CoreTeam 用户画像系统的链路:
- 指标定义:四维度(提交 / 代码 / 协作 / 产出),互为牵制
- 数据管道:PyDriller 解析 Git → MySQL 原始表 + 作者映射表
- 指标计算:AirFlow 四层 DAG(准备 → 清洗 → 归一 → 汇总),去噪规则可解释
- 可视化:Vue 2 + ECharts,重点不在展示数据,在亮出异常
整套链路跑通之后,最大体会就是开篇那句话——做工程师画像,技术不是最难的,最难的永远是定义清楚”什么算贡献”。技术方案都好换,定义错了改回来要伤一阵子。
希望这四篇对想做类似系统的同学有点参考。