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;