diff --git a/src/views/Jyh/security/index.vue b/src/views/Jyh/security/index.vue
index 08d4292..e4ff643 100644
--- a/src/views/Jyh/security/index.vue
+++ b/src/views/Jyh/security/index.vue
@@ -66,26 +66,6 @@
@@ -419,6 +343,85 @@ const chartData = ref({
{ name: 'Go', data: [60, 65, 70, 72, 75] }
]
},
+ // 编程语言使用趋势数据
+ languageTrend: {
+ years: ['2017', '2018', '2019', '2020', '2021', '2022', '2023', '2024'],
+ series: [
+ {
+ name: 'JavaScript',
+ type: 'established',
+ color: '#FAC858',
+ data: [65, 64, 69, 70, 69, 65, 61, 61]
+ },
+ {
+ name: 'Python',
+ type: 'established',
+ color: '#5470C6',
+ data: [32, 41, 49, 55, 52, 53, 54, 60]
+ },
+ {
+ name: 'HTML/CSS',
+ type: 'established',
+ color: '#91CC75',
+ data: [60, 55, 61, 61, 60, 54, 52, 52]
+ },
+ {
+ name: 'SQL',
+ type: 'established',
+ color: '#9254DE',
+ data: [42, 47, 56, 56, 54, 49, 52, 50]
+ },
+ {
+ name: 'Java',
+ type: 'established',
+ color: '#EE6666',
+ data: [47, 51, 50, 54, 49, 48, 49, 49]
+ },
+ {
+ name: 'TypeScript',
+ type: 'emerging',
+ color: '#73C0DE',
+ data: [12, 17, 25, 28, 29, 34, 34, 50]
+ },
+ {
+ name: 'Shell',
+ type: 'established',
+ color: '#52C41A',
+ data: [29, 29, 40, 39, 37, 34, 34, 41]
+ },
+ {
+ name: 'C++',
+ type: 'established',
+ color: '#FF6E00',
+ data: [17, 18, 20, 27, 23, 25, 25, 21]
+ },
+ {
+ name: 'C#',
+ type: 'established',
+ color: '#722ED1',
+ data: [20, 22, 24, 22, 21, 23, 21, 19]
+ },
+ {
+ name: 'Go',
+ type: 'emerging',
+ color: '#00DDFF',
+ data: [8, 12, 18, 19, 17, 19, 17, 14]
+ },
+ {
+ name: 'PHP',
+ type: 'declining',
+ color: '#F5222D',
+ data: [30, 26, 29, 27, 32, 20, 18, 15]
+ },
+ {
+ name: 'Rust',
+ type: 'emerging',
+ color: '#FC8452',
+ data: [2, 2, 5, 7, 6, 9, 10, 10]
+ }
+ ]
+ },
+
// 高危组件数据(基于真实开源项目使用情况和漏洞统计)
highRiskComponent: [
{ name: 'Log4j2', cvss: 9.8, vulnCount: 15, usage: '1200万+', desc: 'CVE-2021-44228等严重RCE漏洞' },
@@ -1029,6 +1032,77 @@ const initHighRiskComponentChart = () => {
});
};
+// 初始化编程语言使用趋势堆叠面积图
+const initLanguageTrendChart = () => {
+ const el = document.getElementById('languageTrendChart');
+ if (!el) return;
+
+ if (chartInstances.value.languageTrendChart) {
+ chartInstances.value.languageTrendChart.dispose();
+ }
+
+ const myChart = echarts.init(el);
+ chartInstances.value.languageTrendChart = myChart;
+
+ // 准备堆叠面积图数据
+ const series = chartData.value.languageTrend.series.map(item => ({
+ name: item.name,
+ type: 'line',
+ stack: '总量',
+ areaStyle: {
+ color: item.color
+ },
+ lineStyle: {
+ width: 1,
+ color: item.color
+ },
+ symbol: 'none',
+ data: item.data
+ }));
+
+ myChart.setOption({
+ tooltip: {
+ trigger: 'axis',
+ axisPointer: {
+ type: 'cross',
+ label: {
+ backgroundColor: '#6a7985'
+ }
+ },
+ formatter: (params: any) => {
+ let res = `
${params[0].name}年
`;
+ params.forEach((p: any) => {
+ res += `
${p.seriesName}: ${p.value}%
`;
+ });
+ return res;
+ }
+ },
+ legend: {
+ top: 0,
+ textStyle: { fontSize: 12 },
+ data: chartData.value.languageTrend.series.map(item => item.name)
+ },
+ grid: { left: '3%', right: '4%', bottom: '3%', top: '15%', containLabel: true },
+ xAxis: [
+ {
+ type: 'category',
+ boundaryGap: false,
+ data: chartData.value.languageTrend.years,
+ axisLabel: { fontSize: 12 }
+ }
+ ],
+ yAxis: [
+ {
+ type: 'value',
+ name: '使用率(%)',
+ nameTextStyle: { fontSize: 12 },
+ axisLabel: { fontSize: 12 }
+ }
+ ],
+ series: series
+ });
+};
+
// 初始化武汉市语言与技术竞争趋势(折线图)
const initLanguageTechChart = () => {
const el = document.getElementById('languageTechChart');
@@ -1102,7 +1176,8 @@ const initCharts = () => {
highRiskComponent: chartData.value.highRiskComponent.length === 0,
industryDistribution: chartData.value.industryDistribution.length === 0,
cveData: chartData.value.cveData.global.cveCount.every(item => item === 0) &&
- chartData.value.cveData.regional.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))
};
// 初始化各图表
@@ -1114,6 +1189,7 @@ const initCharts = () => {
if (!isEmpty.value.highRiskComponent) nextTick(() => initHighRiskComponentChart());
if (!isEmpty.value.industryDistribution) nextTick(() => initIndustryDistributionChart());
if (!isEmpty.value.cveData) nextTick(() => initCVEChart());
+ if (!isEmpty.value.languageTrend) nextTick(() => initLanguageTrendChart());
};
// 页面resize时重绘图表
@@ -1346,7 +1422,7 @@ onMounted(() => {
font-size: 1.1rem;
font-weight: 600;
margin: 0 0 1rem 0;
- text-align: center;
+ text-align: left;
}
.chartCard__container {