- Update yarn.lock - Add project implementation docs in docs/ - Add personal internship experience notes in 实习讲解/
22 KiB
全球风险监测模块 — 面试版
简历原话:"参与开发全球风险监测模块,实现威胁情报地图、CVE趋势分析、高危组件排行等10+数据可视化组件"
这篇文档帮你理解这个模块到底做了什么、怎么做的,以及面试时怎么讲。
一、先搞清楚:这个模块是什么?
全球风险监测模块是一个完整的数据可视化大屏,路由为 /security,页面标题为"全球开源风险态势感知监控中心"。页面上展示了 10+ 个 ECharts 图表组件,从全球威胁地图到高危组件排行、从 CVE 趋势到编程语言安全态势,覆盖了威胁情报的多个维度。
一句话概括:我用 ECharts 6.x 实现了一个安全态势数据可视化大屏,包含 10+ 个不同类型的图表组件(地图、柱状图、折线图、饼图、面积图、散点图等),展示了全球开源威胁情报的多个维度。
二、页面长什么样?(整体布局)
┌─────────────────────────────────────────────────────────────┐
│ StatsGlass(统计卡片:4 项全球汇总指标) │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ 🛡️ ThreatIntelMap(全球威胁情报地图) │ │
│ │ 世界地图热力 + 关键节点散点 + 实时警报 │ │
│ └───────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │IndustryDist │ │HighRisk │ │Intelligence │ │
│ │行业分布饼图 │ │高危组件Top10 │ │实时情报动态流 │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ CveTrendChart(CVE 月度趋势 柱状图+折线图) │ │
│ └───────────────────────────────────────────────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ VulnerabilityLanguageChart(12种语言漏洞趋势面积图) │ │
│ └───────────────────────────────────────────────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ VulnerabilitySeverityChart(漏洞等级堆叠柱状图) │ │
│ └───────────────────────────────────────────────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ ScatterChart(编程语言安全态势气泡散点图) │ │
│ └───────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
页面使用暗色科技风背景(#020617),每个图表卡片有毛玻璃效果(backdrop-filter: blur),鼠标悬停有上浮动画。
三、10+ 个组件一览
| 组件 | 图表类型 | 数据来源 | 直观展示什么 |
|---|---|---|---|
| ThreatIntelMap | 世界地图 + 热力 + 散点 | /api/v1/page1/map/mapData 等 4 个接口 |
全球威胁分布热力图,北京/上海/华盛顿等 6 个关键节点,实时漏洞类型分布面板 |
| ChinaSecurityMap | 中国地图 + 攻击路径 | 懒加载中国 GeoJSON | 各省威胁热力、安全监测节点、城市间攻击路径动画 |
| CveTrendChart | 柱状图 + 折线图(双轴) | /api/v1/page1/cveData/global |
CVE 数量柱状图 + 环比增长率折线图,支持全球/区域切换 |
| HighRiskComponentRank | 横向柱状图 | /api/v1/page1/highRiskComponent |
Top 10 高危开源组件,按 CVSS 评分排序,颜色标识严重程度 |
| VulnerabilitySeverityChart | 堆叠柱状图 | /api/v1/page1/vulnerabilitySeverity |
高/中/低危漏洞数量按季度堆叠分布(2024Q1-2025Q4) |
| VulnerabilityLanguageChart | 堆叠面积图 | /api/v1/page1/languageTrend |
12 种编程语言 2017-2024 年的漏洞趋势变化 |
| ScatterChart | 气泡散点图 | /api/v1/page1/scatterData |
编程语言安全态势:X 轴代码活跃度、Y 轴漏洞密度、气泡大小=漏洞总数 |
| IndustryDistribution | 环形饼图 | /api/v1/page1/industryDistribution |
开源风险在 AI、云计算、大数据等 8 大行业的分布占比 |
| IntelligenceFeed | 自动滚动列表 | /api/v1/page1/feedList |
实时安全情报流,带类型标签(CISA/Poisoning/CNVD/GitHub) |
| StatsGlass | 毛玻璃统计卡片 | /api/v1/page1/overviewData |
4 项全球汇总指标(企业数、高校数、社区活跃度、项目数) |
除了以上 10 个独立组件,主页面 index.vue 中还有 5 个内联 ECharts 图表:
| 内联图表 | 图表类型 | 展示内容 |
|---|---|---|
| 高校开源参与分布 | 环形饼图 | 华中科大、武大等高校参与度 |
| 社区区域分布 | 柱状图 | 武昌区、洪山区等社区分布 |
| OSS Compass 排行 | 横向柱状图 | OpenHarmony、MindSpore 等开源项目排行 |
| 开发者排行榜 | 横向柱状图 | 武汉开源开发者 Top 10 |
| 语言技术趋势 | 多系列折线图 | Java、Python、Rust、仓颉等 5 种语言的趋势 |
合计:15+ 个图表组件。
四、怎么实现的?(面试核心)
所有图表组件遵循统一的 三步模式:获取数据 → 初始化图表 → 清理销毁。
4.1 统一的开发模式(每个组件都一样)
// 以 HighRiskComponentRank 为例
import * as echarts from 'echarts';
import { highRiskComponentPage1 } from '@/api/jyh/situation';
// ====== 步骤 1:获取数据 ======
const fetchData = async () => {
try {
const response = await highRiskComponentPage1();
if (response.data.code === 200) {
componentData.value = response.data.data; // ✅ 成功:用后端数据
} else {
componentData.value = [...defaultData]; // ⚠️ 失败:用兜底数据
}
} catch (error) {
componentData.value = [...defaultData]; // ❌ 异常:用兜底数据
}
};
// ====== 步骤 2:初始化图表 ======
const initChart = () => {
if (chartInstance) chartInstance.dispose(); // 先销毁旧实例
chartInstance = echarts.init(chartRef.value); // 创建新实例
chartInstance.setOption({
// ... 图表配置(tooltip、grid、xAxis、yAxis、series 等)
});
window.addEventListener('resize', handleResize); // 响应窗口大小变化
};
// ====== 步骤 3:清理销毁 ======
onUnmounted(() => {
if (chartInstance) chartInstance.dispose(); // 组件卸载时销毁,防止内存泄漏
window.removeEventListener('resize', handleResize);
});
面试话术:
"所有图表组件遵循统一的开发模式:第一,通过 API 获取数据,接口失败时自动降级为预设的兜底数据,保证图表不会白屏;第二,使用 echarts.init 初始化图表,通过 setOption 配置图表样式和交互;第三,组件卸载时调用 dispose 销毁实例,移除 resize 监听,防止内存泄漏。切换数据时会先 dispose 旧实例再重新 init,确保图表完全刷新。"
4.2 全球威胁情报地图(技术含量最高)
ThreatIntelMap 是整个模块最复杂的组件,综合使用了多种 ECharts 地图能力:
// ThreatIntelMap.vue — 核心配置(简化版)
echarts.registerMap('world', worldJson); // 注册世界地图 GeoJSON
const option = {
// 1. 视觉映射:热力渐变
visualMap: {
min: 0, max: 100,
inRange: { color: ['#1e3c72', '#2a5298', '#24b6d8', '#facc15', '#ef4444'] }
},
// 2. 地理坐标系:世界地图
geo: {
map: 'world', roam: true, zoom: 1.2,
itemStyle: { areaColor: '#0f172a', borderColor: '#1e293b' }
},
// 3. 三个数据系列
series: [
{
name: 'Threat Distribution',
type: 'map', // ← 地图热力层
geoIndex: 0,
data: mapData // 国家→风险值
},
{
name: 'Key Nodes',
type: 'effectScatter', // ← 涟漪散点层(关键安全节点)
coordinateSystem: 'geo',
data: scatterData, // 北京、上海、华盛顿等 6 个节点
rippleEffect: { scale: 3 }
},
]
};
同时在地图叠加层渲染了三个信息面板:
- 左侧面板:漏洞类型分布 Top 5(XSS 32.1%、SQL 注入 11.9% 等),带进度条动画
- 右侧面板:威胁情报地域排行(美国 435,202 次、印度 252,054 次等)
- 底部卡片:实时安全警报(自动轮播,3.5 秒切换一条,带脉冲动画)
面试话术:
"全球威胁地图是整个模块最复杂的组件。它用到了 ECharts 的地图系列 + effectScatter 涟漪散点图的组合,在 GeoJSON 世界地图上叠加了两层数据——国家热力层展示威胁分布,散点层标记 6 个关键安全节点。地图上还有三个信息面板——漏洞类型分布、地域排行、实时警报。世界地图的 GeoJSON 文件通过动态 import 懒加载,只在用户进入这个页面时才下载,不打包进主 bundle。"
4.3 CVE 月度趋势 — 双轴组合图
// CveTrendChart.vue — 双 Y 轴组合图(柱状图 + 折线图)
const option = {
tooltip: { trigger: 'axis' },
// 两个 Y 轴:左边 CVE 数量,右边增长率百分比
yAxis: [
{ type: 'value', name: 'CVE数量', position: 'left' }, // ← 对应柱状图
{ type: 'value', name: '环比增长率(%)', position: 'right' } // ← 对应折线图
],
series: [
{
name: 'CVE数量',
type: 'bar', // ← 柱状图,左轴
data: cveCount,
itemStyle: { color: new echarts.graphic.LinearGradient(...) } // 渐变色
},
{
name: '环比增长率',
type: 'line', // ← 折线图,右轴
yAxisIndex: 1, // 使用右轴
data: acceleration,
smooth: true, // 平滑曲线
itemStyle: { color: '#ef4444' } // 红色
}
]
};
支持通过按钮切换"全球视图"和"区域视图",切换时重新请求对应的 API 接口并重新渲染图表。
4.4 高危组件 Top 10 — 横向柱状图 + CVSS 颜色标识
// HighRiskComponentRank.vue — 颜色随 CVSS 评分变化
series: [{
type: 'bar',
data: cvssScores,
itemStyle: {
color: (params) => {
if (params.value >= 9.0) return '#ef4444'; // 红色 — 严重
if (params.value >= 7.0) return '#f97316'; // 橙色 — 高危
if (params.value >= 4.0) return '#eab308'; // 黄色 — 中危
return '#22c55e'; // 绿色 — 低危
}
},
label: { show: true, position: 'right' } // 数值标签显示在柱子右侧
}]
Y 轴设置 inverse: true,让 CVSS 评分最高的组件显示在最上面。
4.5 漏洞等级分布 — 堆叠柱状图
// VulnerabilitySeverityChart.vue — 三个系列堆叠
series: [
{ name: '高危漏洞', type: 'bar', stack: 'total', color: '#FF4D4F', data: [...] },
{ name: '中危漏洞', type: 'bar', stack: 'total', color: '#FAAD14', data: [...] },
{ name: '低危漏洞', type: 'bar', stack: 'total', color: '#36CFC9', data: [...] },
]
// 三个系列的 stack 值都是 'total',ECharts 会自动堆叠
// tooltip 中计算每个等级占总数的百分比
4.6 三个重要的设计细节
细节 1:每个组件都有 API 失败兜底
// 所有图表组件的共同特点:API 失败时用硬编码数据兜底
try {
const res = await apiFunction();
if (res.data.code === 200) {
chartData.value = res.data.data; // ✅ 后端数据
} else {
chartData.value = DEFAULT_DATA; // ⚠️ 兜底数据
}
} catch {
chartData.value = DEFAULT_DATA; // ❌ 网络异常,兜底数据
}
为什么这样设计? 态势大屏在演示时不能白屏。即使后端挂了,至少展示兜底数据让页面是完整的。
细节 2:图表实例的 dispose → init 生命周期
// 切换数据时:先销毁旧实例,再创建新实例
if (chartInstance) chartInstance.dispose(); // 销毁旧实例(释放内存)
chartInstance = echarts.init(el); // 创建新实例
chartInstance.setOption(option); // 渲染新数据
// 组件卸载时:销毁实例 + 移除监听
onUnmounted(() => {
chartInstance?.dispose(); // 防止内存泄漏
window.removeEventListener('resize', handler);
});
为什么不用 myChart.setOption() 更新? 当数据维度变化时(如 CVE 趋势图切换全球/区域视图、X 轴月份数变化),直接 setOption 会有残留配置。先 dispose 再 init 是最稳妥的做法。
细节 3:地图数据的懒加载
// 世界地图 GeoJSON 通过 import 在组件内引用
import worldJson from './world.json'; // 只在 ThreatIntelMap 组件被加载时才下载
// 中国地图 GeoJSON 通过动态函数加载(utils/mapLoader.js)
export const loadChinaMap = async () => {
await import('/china.js'); // 只在进入中国地图页面时才下载(几百 KB)
};
五、完整的数据流
页面加载 (/security)
│
├──→ StatsGlass 调 overviewDataPage1 ← /api/v1/page1/overviewData
├──→ ThreatIntelMap 调 4 个 map API ← /api/v1/page1/map/*
├──→ IndustryDistribution 调 industryDistributionPage1 ← /api/v1/page1/industryDistribution
├──→ HighRiskComponentRank 调 highRiskComponentPage1 ← /api/v1/page1/highRiskComponent
├──→ IntelligenceFeed 调 feedListPage1 ← /api/v1/page1/feedList
├──→ CveTrendChart 调 cveDataGlobal + regional ← /api/v1/page1/cveData/*
├──→ VulnerabilityLang 调 languageTrendPage1 ← /api/v1/page1/languageTrend
├──→ VulnerabilitySev 调 vulnerabilitySeverityPage1 ← /api/v1/page1/vulnerabilitySeverity
├──→ ScatterChart 调 scatterDataPage1 ← /api/v1/page1/scatterData
└──→ 5 个内联图表 硬编码数据(武汉市开源生态展示)
共 13 个后端 API 接口,全部以 /api/v1/page1/ 为前缀,定义在 src/api/jyh/situation.ts 中。
六、面试问答准备
Q1:"参与开发全球风险监测模块"具体做了什么?
我参与开发了全球开源风险态势感知监控中心这个大屏页面,用 ECharts 6.x 实现了 10+ 个数据可视化组件。具体包括:全球威胁情报地图(世界地图热力 + 关键节点散点 + 实时警报面板)、CVE 月度趋势图(双轴柱状图+折线图,支持全球/区域切换)、高危组件 Top 10 排行(横向柱状图,按 CVSS 评分颜色标识)、漏洞等级分布(高/中/低危堆叠柱状图)、编程语言漏洞趋势面积图(12 种语言 2017-2024)、编程语言安全态势气泡图(活跃度 vs 漏洞密度)等。页面采用暗色科技风主题,毛玻璃卡片布局,每个组件都有 API 失败兜底数据。
Q2:10+ 个图表组件,代码怎么组织的?
每个图表都是一个独立的 Vue SFC 组件(如 ThreatIntelMap.vue、CveTrendChart.vue),在主页面 index.vue 中通过 import 引入并组合布局。所有组件遵循统一的开发模式:获取数据(调 API,失败用兜底数据)→ 初始化图表(echarts.init + setOption)→ 清理销毁(dispose + 移除监听)。组件之间互不依赖,可以独立开发和调试。
Q3:地图是怎么做的?
我用 ECharts 的 map 系列实现。世界地图使用 GeoJSON 数据(world.json),通过 echarts.registerMap 注册后在地理坐标系上渲染。地图上叠加了两层数据:map 系列展示国家热力分布(通过 visualMap 控制颜色渐变),effectScatter 系列展示关键安全节点(北京、上海、华盛顿等 6 个点,带涟漪动画)。还在地图四个角叠加了信息面板——漏洞类型分布、地域排行、实时警报。
Q4:图表性能怎么考虑的?
三个方面的处理:第一,地图 GeoJSON 文件(几百 KB)使用懒加载,只在 ThreatIntelMap 组件渲染时才下载;第二,每个图表组件在卸载时调用 echartsInstance.dispose() 销毁实例并移除 resize 监听,防止内存泄漏;第三,图表切换数据时(如 CVE 全球/区域切换),先 dispose 再重新 init,避免 setOption 合并残留配置导致的问题。
Q5:如果后端 API 挂了,页面会白屏吗?
不会。每个图表组件都设计了数据降级策略——API 请求失败或返回异常时,自动使用预设的兜底数据渲染。比如高危组件 Top 10 的兜底数据包含了 Log4j2(9.8)、Struts2(9.7)、OpenSSL(9.6)等真实的公开漏洞数据。这样即使后端挂了,大屏依然能完整展示,不影响演示效果。
Q6:ECharts 的 setOption 和 dispose+init 有什么区别?为什么你的组件用 dispose+init?
setOption 适合增量更新——数据变了但图表类型、轴配置不变时,用 setOption 合并新配置即可,不会闪烁。但我的组件有些场景下图表维度会变化(比如 CVE 趋势图切换全球/区域时,数据量和走势完全不同),直接 setOption 可能残留旧配置。所以统一采用 dispose + init 的方式,确保每次都是全新渲染。代价是有短暂闪烁,但数据一致性能保证。
Q7:你用到了哪些 ECharts 图表类型?
地图(map)、涟漪散点图(effectScatter)、柱状图(bar,含堆叠柱状图)、折线图(line)、饼图(pie/环形图)、面积图(area/堆叠面积图)、散点图/气泡图(scatter)、热力 visualMap。总共大概 7-8 种图表类型的组合使用。
七、关键数字(面试时用)
| 数据 | 数字 |
|---|---|
| 独立图表组件数 | 10 个(import 引入的子组件) |
| 内联图表数 | 5 个(index.vue 中直接写的) |
| 图表总数 | 15+ 个 |
| ECharts 图表类型 | 8 种(map、effectScatter、bar、line、pie、area、scatter、visualMap) |
| 后端 API 接口 | 13 个(/api/v1/page1/*) |
| API 接口文件 | src/api/jyh/situation.ts(50 个端点,其中 13 个属于此模块) |
| 地图 GeoJSON 文件 | 2 个(world.json + china.js) |
| 暗色主题背景色 | #020617 |
| 毛玻璃卡片效果 | backdrop-filter: blur(10px) |
八、涉及的源码文件(需要看的时候查)
| 做什么 | 文件在哪 |
|---|---|
| 主页面(布局 + 5 个内联图表) | src/views/Jyh/security/index.vue |
| 全球威胁情报地图 | src/views/Jyh/security/components/ThreatIntelMap.vue |
| 中国安全态势地图 | src/views/Jyh/security/components/ChinaSecurityMap.vue |
| CVE 月度趋势图 | src/views/Jyh/security/components/CveTrendChart.vue |
| 高危组件 Top 10 排行 | src/views/Jyh/security/components/HighRiskComponentRank.vue |
| 漏洞等级分布图 | src/views/Jyh/security/components/VulnerabilitySeverityChart.vue |
| 编程语言漏洞趋势图 | src/views/Jyh/security/components/VulnerabilityLanguageChart.vue |
| 编程语言安全态势气泡图 | src/views/Jyh/security/components/ScatterChart.vue |
| 行业分布饼图 | src/views/Jyh/security/components/IndustryDistribution.vue |
| 实时情报动态流 | src/views/Jyh/security/components/IntelligenceFeed.vue |
| 统计卡片 | src/views/Jyh/security/StatsGlass.vue |
| 世界地图 GeoJSON | src/views/Jyh/security/components/world.json |
| 所有态势感知 API | src/api/jyh/situation.ts |
| 关联页面:威胁情报库 | src/views/Jyh/ThreatIntelligence/index.vue |
| 关联页面:漏洞数据库 | src/views/Jyh/VulnerabilityDatabase/index.vue |