From 5c8f9273c4eda8a5e6d2eb59d56f0946dd77fe74 Mon Sep 17 00:00:00 2001 From: d266377 Date: Tue, 27 Jan 2026 14:42:50 +0800 Subject: [PATCH] =?UTF-8?q?=E6=80=81=E5=8A=BF=E6=84=9F=E7=9F=A5=E4=B8=AD?= =?UTF-8?q?=E5=BF=83-=E5=85=A8=E7=90=83=E5=BC=80=E6=BA=90=E9=A3=8E?= =?UTF-8?q?=E9=99=A9=E6=80=81=E5=8A=BF=E6=84=9F=E7=9F=A5=E4=B8=AD=E5=BF=83?= =?UTF-8?q?=E7=BC=96=E7=A8=8B=E8=AF=AD=E8=A8=80=E5=AE=89=E5=85=A8=E6=80=81?= =?UTF-8?q?=E5=8A=BF=E7=BB=84=E4=BB=B6=E6=8A=BD=E7=A6=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Jyh/security/components/ScatterChart.vue | 213 ++++++++++++++++ src/views/Jyh/security/index.vue | 231 +----------------- 2 files changed, 218 insertions(+), 226 deletions(-) create mode 100644 src/views/Jyh/security/components/ScatterChart.vue diff --git a/src/views/Jyh/security/components/ScatterChart.vue b/src/views/Jyh/security/components/ScatterChart.vue new file mode 100644 index 0000000..a5ca95b --- /dev/null +++ b/src/views/Jyh/security/components/ScatterChart.vue @@ -0,0 +1,213 @@ + + + + + \ No newline at end of file diff --git a/src/views/Jyh/security/index.vue b/src/views/Jyh/security/index.vue index d1a2626..fbddea3 100644 --- a/src/views/Jyh/security/index.vue +++ b/src/views/Jyh/security/index.vue @@ -55,22 +55,10 @@ -
-

漏洞等级分布

-
-
-
-
-
+ - -
-

编程语言安全态势

-
-
-
-
-
+ + @@ -85,6 +73,8 @@ import HighRiskComponentRank from './components/HighRiskComponentRank.vue'; import IntelligenceFeed from './components/IntelligenceFeed.vue'; import CveTrendChart from './components/CveTrendChart.vue'; import VulnerabilityLanguageChart from './components/VulnerabilityLanguageChart.vue'; +import VulnerabilitySeverityChart from './components/VulnerabilitySeverityChart.vue'; +import ScatterChart from './components/ScatterChart.vue'; import StatsGlass from '@/views/Jyh/security/StatsGlass.vue'; // 页面尺寸响应式 @@ -181,73 +171,9 @@ const chartData = ref({ }, - // 漏洞占比数据 - vulnerabilitySeverity: { - categories: ['2024Q1', '2024Q2', '2024Q3', '2024Q4', '2025Q1', '2025Q2', '2025Q3', '2025Q4'], - series: [ - { - name: '高危漏洞', - type: 'bar', - stack: 'total', - itemStyle: { color: '#FF4D4F' }, - barWidth: 16, - data: [35, 42, 58, 45, 67, 78, 62, 85, 92] - }, - { - name: '中危漏洞', - type: 'bar', - stack: 'total', - itemStyle: { color: '#FAAD14' }, - barWidth: 16, - data: [65, 72, 88, 95, 112, 105, 120, 135, 128] - }, - { - name: '低危漏洞', - type: 'bar', - stack: 'total', - itemStyle: { color: '#36CFC9' }, - barWidth: 16, - data: [120, 135, 150, 142, 165, 180, 175, 190, 210] - } - ] - }, - - - - // 气泡图数据 - // 基于真实数据:[代码活跃度(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' - } }); - // 空数据标识 const isEmpty = ref({ university: false, @@ -480,132 +406,9 @@ const initDeveloperChart = () => { -// 初始化高危漏洞占比图表 -const initVulnerabilitySeverityChart = () => { - const el = document.getElementById('vulnerabilitySeverityChart'); - if (!el) return; - if (chartInstances.value.vulnerabilitySeverityChart) { - chartInstances.value.vulnerabilitySeverityChart.dispose(); - } - const myChart = echarts.init(el); - chartInstances.value.vulnerabilitySeverityChart = myChart; - myChart.setOption({ - tooltip: { - trigger: 'axis', - axisPointer: { - type: 'shadow' - }, - formatter: (params: any) => { - let res = `
${params[0].name}
`; - let total = 0; - params.forEach((p: any) => { - total += p.value; - }); - params.forEach((p: any) => { - const percentage = ((p.value / total) * 100).toFixed(1); - res += `
${p.seriesName}: ${p.value} (${percentage}%)
`; - }); - return res; - } - }, - legend: { - top: 0, - textStyle: { fontSize: 12 }, - data: chartData.value.vulnerabilitySeverity.series.map(item => item.name) - }, - grid: { left: '3%', right: '4%', bottom: '3%', top: '15%', containLabel: true }, - xAxis: [ - { - type: 'category', - data: chartData.value.vulnerabilitySeverity.categories, - axisLabel: { fontSize: 12 } - } - ], - yAxis: [ - { - type: 'value', - name: '漏洞数量', - nameTextStyle: { fontSize: 12 }, - axisLabel: { fontSize: 12 } - } - ], - series: chartData.value.vulnerabilitySeverity.series - }); -}; - -// 初始化气泡图 -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 = () => { @@ -679,10 +482,6 @@ const initCharts = () => { languageTech: chartData.value.languageTech.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 }; // 初始化各图表 @@ -692,11 +491,6 @@ const initCharts = () => { if (!isEmpty.value.developer) nextTick(() => initDeveloperChart()); if (!isEmpty.value.languageTech) nextTick(() => initLanguageTechChart()); - - - - if (!isEmpty.value.vulnerabilitySeverity) nextTick(() => initVulnerabilitySeverityChart()); - if (!isEmpty.value.scatterData) nextTick(() => initScatterChart()); }; // 页面resize时重绘图表 @@ -1053,21 +847,6 @@ onMounted(() => { } /* 与示例一致的空数据样式 */ -.num-empty { - height: 10px; - border-top: 2px solid #2951E0; - width: 100%; - background: linear-gradient(180deg, rgba(41, 81, 224, 0.12) 0%, rgba(41, 81, 224, 0.04) 100%); - position: absolute; - top: 50%; - left: 0; - transform: translateY(-50%); -} - -.chart { - width: 100%; - height: 100%; -} .index-module__NV_5cW__sectionHeader { flex-wrap: wrap;