态势感知平台-全球开源风险态势感知监控中心编程语言安全态势接口对接
This commit is contained in:
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user