态势感知平台-全球开源风险态势感知监控中心-全球威胁情报分析与检测4个接口对接
This commit is contained in:
@@ -60,19 +60,14 @@ Vue 3 适配版代码
|
|||||||
import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue';
|
import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue';
|
||||||
import * as echarts from 'echarts';
|
import * as echarts from 'echarts';
|
||||||
import worldJson from './world.json';
|
import worldJson from './world.json';
|
||||||
|
import { mapVulnStatsPage1, mapRegionStatsPage1, mapDataPage1, mapVulnTypeStatsPage1 } from '@/api/jyh/situation';
|
||||||
|
|
||||||
// 响应式数据
|
// 响应式数据
|
||||||
const chartDiv = ref(null);
|
const chartDiv = ref(null);
|
||||||
let myChart = null;
|
let myChart = null;
|
||||||
let timer = null;
|
let timer = null;
|
||||||
|
|
||||||
const vulnStats = ref([
|
const vulnStats = ref([]);
|
||||||
{ name: 'XSS 跨站脚本', value: 32.1, color: '#ef4444' },
|
|
||||||
{ name: 'SQL 注入', value: 11.9, color: '#f97316' },
|
|
||||||
{ name: '内存缓冲区溢出', value: 10.9, color: '#eab308' },
|
|
||||||
{ name: '输入验证不当', value: 9.3, color: '#3b82f6' },
|
|
||||||
{ name: '信息泄露', value: 8.0, color: '#10b981' },
|
|
||||||
]);
|
|
||||||
|
|
||||||
const regionStats = ref([
|
const regionStats = ref([
|
||||||
{ name: 'United States', score: 435202 },
|
{ name: 'United States', score: 435202 },
|
||||||
@@ -82,11 +77,8 @@ const regionStats = ref([
|
|||||||
{ name: 'Germany', score: 126397 },
|
{ name: 'Germany', score: 126397 },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const alerts = [
|
// 实时情报数据状态
|
||||||
{ title: "高危漏洞通告", desc: "Apache Log4j2 远程代码执行漏洞复现" },
|
const alerts = ref([]);
|
||||||
{ title: "僵尸网络活动", desc: "Mirai 变种正在扫描 IoT 设备端口 23" },
|
|
||||||
{ title: "APT 组织活动", desc: "OceanLotus 组织针对金融行业的钓鱼攻击" },
|
|
||||||
];
|
|
||||||
|
|
||||||
const currentAlert = ref(null);
|
const currentAlert = ref(null);
|
||||||
let alertIndex = 0;
|
let alertIndex = 0;
|
||||||
@@ -100,35 +92,116 @@ const geoCoordMap = {
|
|||||||
'Moscow': [37.6173, 55.7558],
|
'Moscow': [37.6173, 55.7558],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 获取实时情报数据
|
||||||
|
const fetchAlertsData = async () => {
|
||||||
|
try {
|
||||||
|
const response = await mapVulnTypeStatsPage1();
|
||||||
|
if (response.code === 200) {
|
||||||
|
alerts.value = response.data || [];
|
||||||
|
if (alerts.value.length > 0) {
|
||||||
|
currentAlert.value = alerts.value[0];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error('获取实时情报数据失败:', response.msg);
|
||||||
|
// 如果接口调用失败,使用默认数据
|
||||||
|
alerts.value = [
|
||||||
|
{ title: "高危漏洞通告", desc: "Apache Log4j2 远程代码执行漏洞复现" },
|
||||||
|
{ title: "僵尸网络活动", desc: "Mirai 变种正在扫描 IoT 设备端口 23" },
|
||||||
|
{ title: "APT 组织活动", desc: "OceanLotus 组织针对金融行业的钓鱼攻击" },
|
||||||
|
];
|
||||||
|
if (alerts.value.length > 0) {
|
||||||
|
currentAlert.value = alerts.value[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('请求实时情报数据时发生错误:', error);
|
||||||
|
// 发生异常时使用默认数据
|
||||||
|
alerts.value = [
|
||||||
|
{ title: "高危漏洞通告", desc: "Apache Log4j2 远程代码执行漏洞复现" },
|
||||||
|
{ title: "僵尸网络活动", desc: "Mirai 变种正在扫描 IoT 设备端口 23" },
|
||||||
|
{ title: "APT 组织活动", desc: "OceanLotus 组织针对金融行业的钓鱼攻击" },
|
||||||
|
];
|
||||||
|
if (alerts.value.length > 0) {
|
||||||
|
currentAlert.value = alerts.value[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 逻辑方法
|
// 逻辑方法
|
||||||
const startAlertRotation = () => {
|
const startAlertRotation = () => {
|
||||||
currentAlert.value = alerts[0];
|
if (alerts.value.length > 0) {
|
||||||
|
currentAlert.value = alerts.value[0];
|
||||||
|
}
|
||||||
timer = setInterval(() => {
|
timer = setInterval(() => {
|
||||||
alertIndex = (alertIndex + 1) % alerts.length;
|
if (alerts.value.length > 0) {
|
||||||
currentAlert.value = null;
|
alertIndex = (alertIndex + 1) % alerts.value.length;
|
||||||
setTimeout(() => {
|
currentAlert.value = null;
|
||||||
currentAlert.value = alerts[alertIndex];
|
setTimeout(() => {
|
||||||
}, 500);
|
currentAlert.value = alerts.value[alertIndex];
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
}, 3500);
|
}, 3500);
|
||||||
};
|
};
|
||||||
|
|
||||||
const setChart = () => {
|
// 地图数据状态
|
||||||
|
const mapData = ref([]);
|
||||||
|
const scatterData = ref([]);
|
||||||
|
|
||||||
|
// 获取地图数据
|
||||||
|
const fetchMapData = async () => {
|
||||||
|
try {
|
||||||
|
const response = await mapDataPage1();
|
||||||
|
if (response.code === 200) {
|
||||||
|
mapData.value = response.data;
|
||||||
|
} else {
|
||||||
|
console.error('获取地图数据失败:', response.msg);
|
||||||
|
// 如果接口调用失败,使用默认数据
|
||||||
|
mapData.value = [
|
||||||
|
{ name: 'China', value: 100 },
|
||||||
|
{ name: 'United States', value: 80 },
|
||||||
|
{ name: 'Russia', value: 60 },
|
||||||
|
{ name: 'Brazil', value: 40 },
|
||||||
|
{ name: 'Canada', value: 30 },
|
||||||
|
{ name: 'Australia', value: 20 },
|
||||||
|
{ name: 'India', value: 50 },
|
||||||
|
{ name: 'Germany', value: 45 },
|
||||||
|
{ name: 'United Kingdom', value: 40 },
|
||||||
|
{ name: 'France', value: 35 },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('请求地图数据时发生错误:', error);
|
||||||
|
// 发生异常时使用默认数据
|
||||||
|
mapData.value = [
|
||||||
|
{ name: 'China', value: 100 },
|
||||||
|
{ name: 'United States', value: 80 },
|
||||||
|
{ name: 'Russia', value: 60 },
|
||||||
|
{ name: 'Brazil', value: 40 },
|
||||||
|
{ name: 'Canada', value: 30 },
|
||||||
|
{ name: 'Australia', value: 20 },
|
||||||
|
{ name: 'India', value: 50 },
|
||||||
|
{ name: 'Germany', value: 45 },
|
||||||
|
{ name: 'United Kingdom', value: 40 },
|
||||||
|
{ name: 'France', value: 35 },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const setChart = async () => {
|
||||||
if (!chartDiv.value) return;
|
if (!chartDiv.value) return;
|
||||||
echarts.registerMap('world', worldJson);
|
echarts.registerMap('world', worldJson);
|
||||||
const mapData = [
|
|
||||||
{ name: 'China', value: 100 },
|
|
||||||
{ name: 'United States', value: 80 },
|
|
||||||
{ name: 'Russia', value: 60 },
|
|
||||||
{ name: 'Brazil', value: 40 },
|
|
||||||
{ name: 'Canada', value: 30 },
|
|
||||||
{ name: 'Australia', value: 20 },
|
|
||||||
{ name: 'India', value: 50 },
|
|
||||||
{ name: 'Germany', value: 45 },
|
|
||||||
{ name: 'United Kingdom', value: 40 },
|
|
||||||
{ name: 'France', value: 35 },
|
|
||||||
];
|
|
||||||
|
|
||||||
const scatterData = [
|
// 初始化散点数据
|
||||||
|
const geoCoordMap = {
|
||||||
|
'Beijing': [116.407395, 39.904211],
|
||||||
|
'Shanghai': [121.473701, 31.230416],
|
||||||
|
'Guangzhou': [113.264385, 23.129112],
|
||||||
|
'Chengdu': [104.066541, 30.572269],
|
||||||
|
'Washington': [-77.036871, 38.907192],
|
||||||
|
'Moscow': [37.6173, 55.7558],
|
||||||
|
};
|
||||||
|
|
||||||
|
const scatterDataLocal = [
|
||||||
{ name: '北京中心', value: [...geoCoordMap['Beijing'], 100] },
|
{ name: '北京中心', value: [...geoCoordMap['Beijing'], 100] },
|
||||||
{ name: '上海节点', value: [...geoCoordMap['Shanghai'], 80] },
|
{ name: '上海节点', value: [...geoCoordMap['Shanghai'], 80] },
|
||||||
{ name: '广州节点', value: [...geoCoordMap['Guangzhou'], 70] },
|
{ name: '广州节点', value: [...geoCoordMap['Guangzhou'], 70] },
|
||||||
@@ -186,13 +259,13 @@ const setChart = () => {
|
|||||||
name: 'Threat Distribution',
|
name: 'Threat Distribution',
|
||||||
type: 'map',
|
type: 'map',
|
||||||
geoIndex: 0,
|
geoIndex: 0,
|
||||||
data: mapData
|
data: mapData.value
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Key Nodes',
|
name: 'Key Nodes',
|
||||||
type: 'effectScatter',
|
type: 'effectScatter',
|
||||||
coordinateSystem: 'geo',
|
coordinateSystem: 'geo',
|
||||||
data: scatterData,
|
data: scatterDataLocal,
|
||||||
symbolSize: (val) => val[2] / 5,
|
symbolSize: (val) => val[2] / 5,
|
||||||
showEffectOn: 'render',
|
showEffectOn: 'render',
|
||||||
rippleEffect: {
|
rippleEffect: {
|
||||||
@@ -222,10 +295,76 @@ const setChart = () => {
|
|||||||
myChart.setOption(option);
|
myChart.setOption(option);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 获取漏洞类型统计数据
|
||||||
|
const fetchVulnStats = async () => {
|
||||||
|
try {
|
||||||
|
const response = await mapVulnStatsPage1();
|
||||||
|
if (response.code === 200) {
|
||||||
|
// 为每个数据项添加颜色
|
||||||
|
const colors = ['#ef4444', '#f97316', '#eab308', '#3b82f6', '#10b981', '#8b5cf6', '#ec4899', '#06b6d4'];
|
||||||
|
vulnStats.value = response.data.map((item, index) => ({
|
||||||
|
...item,
|
||||||
|
color: colors[index % colors.length]
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
console.error('获取漏洞类型统计数据失败:', response.msg);
|
||||||
|
// 如果接口调用失败,使用默认数据
|
||||||
|
vulnStats.value = [
|
||||||
|
{ name: 'XSS 跨站脚本', value: 32.1, color: '#ef4444' },
|
||||||
|
{ name: 'SQL 注入', value: 11.9, color: '#f97316' },
|
||||||
|
{ name: '内存缓冲区溢出', value: 10.9, color: '#eab308' },
|
||||||
|
{ name: '输入验证不当', value: 9.3, color: '#3b82f6' },
|
||||||
|
{ name: '信息泄露', value: 8.0, color: '#10b981' },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('请求漏洞类型统计数据时发生错误:', error);
|
||||||
|
// 发生异常时使用默认数据
|
||||||
|
vulnStats.value = [
|
||||||
|
{ name: 'XSS 跨站脚本', value: 32.1, color: '#ef4444' },
|
||||||
|
{ name: 'SQL 注入', value: 11.9, color: '#f97316' },
|
||||||
|
{ name: '内存缓冲区溢出', value: 10.9, color: '#eab308' },
|
||||||
|
{ name: '输入验证不当', value: 9.3, color: '#3b82f6' },
|
||||||
|
{ name: '信息泄露', value: 8.0, color: '#10b981' },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取威胁情报地域排行数据
|
||||||
|
const fetchRegionStats = async () => {
|
||||||
|
try {
|
||||||
|
const response = await mapRegionStatsPage1();
|
||||||
|
if (response.code === 200) {
|
||||||
|
regionStats.value = response.data;
|
||||||
|
} else {
|
||||||
|
console.error('获取威胁情报地域排行数据失败:', response.msg);
|
||||||
|
// 如果接口调用失败,使用默认数据
|
||||||
|
regionStats.value = [
|
||||||
|
{ name: 'United States', score: 435202 },
|
||||||
|
{ name: 'India', score: 252054 },
|
||||||
|
{ name: 'China (中国)', score: 184085 },
|
||||||
|
{ name: 'Brazil', score: 174811 },
|
||||||
|
{ name: 'Germany', score: 126397 },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('请求威胁情报地域排行数据时发生错误:', error);
|
||||||
|
// 发生异常时使用默认数据
|
||||||
|
regionStats.value = [
|
||||||
|
{ name: 'United States', score: 435202 },
|
||||||
|
{ name: 'India', score: 252054 },
|
||||||
|
{ name: 'China (中国)', score: 184085 },
|
||||||
|
{ name: 'Brazil', score: 174811 },
|
||||||
|
{ name: 'Germany', score: 126397 },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 生命周期钩子
|
// 生命周期钩子
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await nextTick(); // 确保 DOM 已渲染
|
await nextTick(); // 确保 DOM 已渲染
|
||||||
setChart();
|
await Promise.all([fetchVulnStats(), fetchRegionStats(), fetchMapData(), fetchAlertsData()]); // 同时获取所有统计数据
|
||||||
|
await setChart(); // 等待图表设置完成
|
||||||
startAlertRotation();
|
startAlertRotation();
|
||||||
window.addEventListener('resize', handleResize);
|
window.addEventListener('resize', handleResize);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user