态势感知平台-全球开源风险态势感知监控中心编程语言安全态势接口对接

This commit is contained in:
d266377
2026-01-27 16:40:15 +08:00
parent e495e3ec9f
commit e9d8e48514

View File

@@ -9,8 +9,9 @@
</template>
<script lang="ts" setup>
import { ref, nextTick, onMounted, onUnmounted } from 'vue';
import { ref, nextTick, onMounted, onUnmounted, watch } from 'vue';
import * as echarts from 'echarts';
import { scatterDataPage1 } from '@/api/jyh/situation';
// 空数据标识
const isEmpty = ref({
@@ -22,11 +23,61 @@ const chartInstances = ref<{ [key: string]: echarts.ECharts | null }>({
scatterChart: null
});
// 气泡图数据
const scatterData = {
// 基于真实数据:[代码活跃度(X), 漏洞密度(Y), 漏洞总数(Size), 语言名称(Name)]
// 活跃度基于新增项目数量漏洞密度基于CWE分布统计
scatterData: [
// 气泡图数据 - 响应式数据
const scatterData = ref({
scatterData: [] as any[],
midX: 50,
midY: 50,
quadrantColors: {
Q1: '#BF232A', // [高密度, 低活跃度] - 极高风险
Q2: '#FF4900', // [高密度, 高活跃度] - 高风险,需密切关注
Q3: '#00B43E', // [低密度, 低活跃度] - 低风险,但维护成本高
Q4: '#0063D0' // [低密度, 高活跃度] - 健康生态
}
});
// 获取后端数据
const fetchScatterData = async () => {
try {
console.log('开始请求编程语言安全态势数据...');
const response = await scatterDataPage1();
console.log('API响应:', response);
if (response?.code === 200) {
console.log('API返回的数据:', response.data);
// 处理后端返回的数据格式
const processedData = processBackendScatterData(response.data);
scatterData.value.scatterData = processedData;
// 更新空数据标识
isEmpty.value.scatterData = !processedData || processedData.length === 0;
} else {
console.error('获取编程语言安全态势数据失败:', response?.msg || '未知错误');
// 设置默认数据
setDefaultScatterData();
}
} catch (error) {
console.error('获取编程语言安全态势数据异常:', error);
// 发生异常时设置默认数据
setDefaultScatterData();
}
};
// 处理后端返回的数据格式
const processBackendScatterData = (backendData: any[]) => {
// 后端返回的数据已经是正确的格式,直接转换即可
return backendData.map(item => [
item.x, // 代码活跃度(X)
item.y, // 漏洞密度(Y)
item.size, // 漏洞总数(Size)
item.name // 语言名称(Name)
]);
};
// 设置默认数据
const setDefaultScatterData = () => {
scatterData.value.scatterData = [
[95, 75, 450, 'JavaScript'], // 最高活跃度9,345,046个项目
[90, 70, 380, 'Python'], // 高活跃度9,261,587个项目
[85, 65, 320, 'TypeScript'], // 高增长78.1%增长率
@@ -37,22 +88,8 @@ const scatterData = {
[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'
}
];
isEmpty.value.scatterData = false;
};
// 初始化气泡图
@@ -73,17 +110,17 @@ const initScatterChart = () => {
chartInstances.value.scatterChart = myChart;
// 数据处理
const data = scatterData.scatterData.map(item => ({
const data = scatterData.value.scatterData.map(item => ({
value: [item[0], item[1], item[2]],
name: item[3]
}));
// 计算四象限颜色
const getColor = (x: number, y: number) => {
if (x < scatterData.midX && y >= scatterData.midY) return scatterData.quadrantColors.Q1; // 高密度, 低活跃度 - 极高风险
if (x >= scatterData.midX && y >= scatterData.midY) return scatterData.quadrantColors.Q2; // 高密度, 高活跃度 - 高风险
if (x < scatterData.midX && y < scatterData.midY) return scatterData.quadrantColors.Q3; // 低密度, 低活跃度 - 低风险
return scatterData.quadrantColors.Q4; // 低密度, 高活跃度 - 健康生态
if (x < scatterData.value.midX && y >= scatterData.value.midY) return scatterData.value.quadrantColors.Q1; // 高密度, 低活跃度 - 极高风险
if (x >= scatterData.value.midX && y >= scatterData.value.midY) return scatterData.value.quadrantColors.Q2; // 高密度, 高活跃度 - 高风险
if (x < scatterData.value.midX && y < scatterData.value.midY) return scatterData.value.quadrantColors.Q3; // 低密度, 低活跃度 - 低风险
return scatterData.value.quadrantColors.Q4; // 低密度, 高活跃度 - 健康生态
};
myChart.setOption({
@@ -139,13 +176,23 @@ const initScatterChart = () => {
}, 0);
};
// 在组件挂载后初始化图表
onMounted(() => {
// 在组件挂载后获取数据并初始化图表
onMounted(async () => {
await fetchScatterData();
nextTick(() => {
initScatterChart();
});
});
// 监听数据变化,重新初始化图表
watch(scatterData, () => {
if (!isEmpty.value.scatterData) {
nextTick(() => {
initScatterChart();
});
}
}, { deep: true });
// 在组件卸载前清理资源
onUnmounted(() => {
if (chartInstances.value.scatterChart) {