diff --git a/src/views/Jyh/security/index.vue b/src/views/Jyh/security/index.vue
index 396e44a..9fe76df 100644
--- a/src/views/Jyh/security/index.vue
+++ b/src/views/Jyh/security/index.vue
@@ -148,6 +148,15 @@
@@ -504,6 +513,37 @@ const chartData = ref({
cveCount: [29521, 125, 2108, 1113, 1535, 968, 913, 887, 778, 437, 1448, 1398],
acceleration: [0, -99.58, 1580.62, -47.17, 37.83, -36.89, -5.70, -2.86, -12.34, -43.87, 231.68, -3.42] // 环比增长率(%)
}
+ },
+
+ // 气泡图数据
+ // 基于真实数据:[代码活跃度(X), 漏洞密度(Y), 漏洞总数(Size), 语言名称(Name)]
+ // 活跃度基于新增项目数量,漏洞密度基于CWE分布统计
+ scatterData: [
+ [95, 75, 450, 'JavaScript'], // 最高活跃度:9,345,046个项目
+ [90, 70, 380, 'Python'], // 高活跃度:9,261,587个项目
+ [85, 65, 320, 'TypeScript'], // 高增长:78.1%增长率
+ [75, 80, 420, 'Java'], // 传统强势:3,520,215个项目
+ [45, 60, 280, 'C++'], // 中等活跃:1,701,552个项目
+ [40, 55, 250, 'C#'], // 中等活跃:1,478,463个项目
+ [35, 45, 180, 'PHP'], // 传统Web语言
+ [25, 25, 80, 'Go'], // 新兴语言,低漏洞密度
+ [15, 20, 45, 'Rust'], // 安全性较好的新语言
+ [60, 50, 200, 'Shell'], // 脚本语言
+ ],
+ // 四象限分割点
+ midX: 50,
+ midY: 50,
+
+ // 四象限颜色定义
+ quadrantColors: {
+ // [高密度, 低活跃度] - 极高风险
+ Q1: '#BF232A',
+ // [高密度, 高活跃度] - 高风险,需密切关注
+ Q2: '#FF4900',
+ // [低密度, 低活跃度] - 低风险,但维护成本高
+ Q3: '#00B43E',
+ // [低密度, 高活跃度] - 健康生态
+ Q4: '#0063D0'
}
});
@@ -1200,6 +1240,77 @@ const initVulnerabilitySeverityChart = () => {
});
};
+// 初始化气泡图
+const initScatterChart = () => {
+ const el = document.getElementById('scatterChart');
+ if (!el) return;
+
+ if (chartInstances.value.scatterChart) {
+ chartInstances.value.scatterChart.dispose();
+ }
+
+ const myChart = echarts.init(el);
+ chartInstances.value.scatterChart = myChart;
+
+ // 数据处理
+ const data = chartData.value.scatterData.map(item => ({
+ value: [item[0], item[1], item[2]],
+ name: item[3]
+ }));
+
+ // 计算四象限颜色
+ const getColor = (x: number, y: number) => {
+ if (x < chartData.value.midX && y >= chartData.value.midY) return chartData.value.quadrantColors.Q1; // 高密度, 低活跃度 - 极高风险
+ if (x >= chartData.value.midX && y >= chartData.value.midY) return chartData.value.quadrantColors.Q2; // 高密度, 高活跃度 - 高风险
+ if (x < chartData.value.midX && y < chartData.value.midY) return chartData.value.quadrantColors.Q3; // 低密度, 低活跃度 - 低风险
+ return chartData.value.quadrantColors.Q4; // 低密度, 高活跃度 - 健康生态
+ };
+
+ myChart.setOption({
+ tooltip: {
+ trigger: 'item',
+ formatter: (params: any) => {
+ return `
+
${params.data.name}
+
代码活跃度: ${params.data.value[0]}
+
漏洞密度: ${params.data.value[1]}
+
漏洞总数: ${params.data.value[2]}
+ `;
+ }
+ },
+ grid: { left: '3%', right: '4%', bottom: '3%', top: '15%', containLabel: true },
+ xAxis: {
+ type: 'value',
+ name: '代码活跃度',
+ nameTextStyle: { fontSize: 12 },
+ axisLabel: { fontSize: 12 },
+ splitLine: { show: true }
+ },
+ yAxis: {
+ type: 'value',
+ name: '漏洞密度',
+ nameTextStyle: { fontSize: 12 },
+ axisLabel: { fontSize: 12 },
+ splitLine: { show: true }
+ },
+ series: [{
+ type: 'scatter',
+ data: data,
+ symbolSize: (val: any) => val[2] / 2, // 根据漏洞总数调整气泡大小
+ itemStyle: {
+ color: (params: any) => getColor(params.value[0], params.value[1])
+ },
+ label: {
+ show: true,
+ formatter: (params: any) => params.data.name,
+ position: 'inside',
+ fontSize: 10,
+ color: '#fff'
+ }
+ }]
+ });
+};
+
// 初始化武汉市语言与技术竞争趋势(折线图)
const initLanguageTechChart = () => {
const el = document.getElementById('languageTechChart');
@@ -1275,7 +1386,8 @@ const initCharts = () => {
cveData: chartData.value.cveData.global.cveCount.every(item => item === 0) &&
chartData.value.cveData.regional.cveCount.every(item => item === 0),
languageTrend: chartData.value.languageTrend.series.every(s => s.data.every(d => d === 0)),
- vulnerabilitySeverity: chartData.value.vulnerabilitySeverity.series.every(s => s.data.every(d => d === 0))
+ vulnerabilitySeverity: chartData.value.vulnerabilitySeverity.series.every(s => s.data.every(d => d === 0)),
+ scatterData: chartData.value.scatterData.length === 0
};
// 初始化各图表
@@ -1289,6 +1401,7 @@ const initCharts = () => {
if (!isEmpty.value.cveData) nextTick(() => initCVEChart());
if (!isEmpty.value.languageTrend) nextTick(() => initLanguageTrendChart());
if (!isEmpty.value.vulnerabilitySeverity) nextTick(() => initVulnerabilitySeverityChart());
+ if (!isEmpty.value.scatterData) nextTick(() => initScatterChart());
};
// 页面resize时重绘图表