态势感知平台-全球开源风险态势感知监控中心情报流组件补充
This commit is contained in:
@@ -43,23 +43,7 @@
|
|||||||
<!-- 高危组件Top 10 -->
|
<!-- 高危组件Top 10 -->
|
||||||
<HighRiskComponentRank />
|
<HighRiskComponentRank />
|
||||||
|
|
||||||
<div class="index-module__NV_5cW__chartCard list-card">
|
<IntelligenceFeed />
|
||||||
<h3 class="chartCard__title">情报流</h3>
|
|
||||||
<!-- 新增:ref + 鼠标事件 -->
|
|
||||||
<div class="chartCard__container list-container"
|
|
||||||
ref="scrollContainer1"
|
|
||||||
@mouseenter="pauseScroll(1)"
|
|
||||||
@mouseleave="resumeScroll(1)">
|
|
||||||
<div class="project-list">
|
|
||||||
<div class="project-item" v-for="(item, index) in feedList" :key="index">
|
|
||||||
<span class="project-rank" :class="item.type">{{ item.type }}</span>
|
|
||||||
<div class="project-info">
|
|
||||||
<span class="project-name">{{ item.content }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="index-module__NV_5cW__chartCard chartCard__wide">
|
<div class="index-module__NV_5cW__chartCard chartCard__wide">
|
||||||
<div class="chartCard__header">
|
<div class="chartCard__header">
|
||||||
@@ -127,6 +111,7 @@ import { usePageResize } from '@/utils/hooks/usePageResize';
|
|||||||
import ThreatIntelMap from './components/ThreatIntelMap.vue';
|
import ThreatIntelMap from './components/ThreatIntelMap.vue';
|
||||||
import IndustryDistribution from './components/IndustryDistribution.vue';
|
import IndustryDistribution from './components/IndustryDistribution.vue';
|
||||||
import HighRiskComponentRank from './components/HighRiskComponentRank.vue';
|
import HighRiskComponentRank from './components/HighRiskComponentRank.vue';
|
||||||
|
import IntelligenceFeed from './components/IntelligenceFeed.vue';
|
||||||
import StatsGlass from '@/views/Jyh/security/StatsGlass.vue';
|
import StatsGlass from '@/views/Jyh/security/StatsGlass.vue';
|
||||||
|
|
||||||
// 页面尺寸响应式
|
// 页面尺寸响应式
|
||||||
@@ -146,33 +131,7 @@ const excellentProjects = ref([
|
|||||||
{ name: 'NextDenovo', desc: '高效且精确的长读长纠错与组装工具', org: '武汉希望组生物科技有限公司' }
|
{ name: 'NextDenovo', desc: '高效且精确的长读长纠错与组装工具', org: '武汉希望组生物科技有限公司' }
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// 情报流数据
|
|
||||||
const feedList = ref([
|
|
||||||
{
|
|
||||||
type: 'CISA',
|
|
||||||
content: 'CISA KEV新增: WordPress 的 OneClick Chat to Order 插件,存在不安全的直接对象引用漏洞 (CVE-2025-13526) '
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: '投毒',
|
|
||||||
content: '投毒监控: npm 基建级包大规模投毒事件,影响chalk, debug, ansi-styles 等 18 个包'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'CNVD',
|
|
||||||
content: 'CNVD预警: Google Chrome信息泄露漏洞(CNVD-2025-3038304)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'GitHub',
|
|
||||||
content: 'GitHub安全通告: MovableType 软件的 ContentType 页面 "编辑分类集" 功能存在存储型跨站脚本漏洞'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: '修复',
|
|
||||||
content: '漏洞修复: Node.js 发布 v20.11.0 版本,修复 3 个高危漏洞'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: '供应链',
|
|
||||||
content: '供应链预警: Maven 中央仓库发现 12 个伪造开源组件,包含后门程序'
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 2. 2025武汉市优秀开源软件项目
|
// 2. 2025武汉市优秀开源软件项目
|
||||||
const excellentProjects2025 = ref([
|
const excellentProjects2025 = ref([
|
||||||
@@ -428,82 +387,7 @@ const chartInstances = ref<{ [key: string]: echarts.ECharts | null }>({
|
|||||||
CVEChart: null
|
CVEChart: null
|
||||||
});
|
});
|
||||||
|
|
||||||
// ===================== 新增:列表自动滚动逻辑 =====================
|
|
||||||
// 1. 定义滚动容器的ref
|
|
||||||
const scrollContainer1 = ref<HTMLDivElement | null>(null); // 第一个列表容器
|
|
||||||
const scrollContainer2 = ref<HTMLDivElement | null>(null); // 第二个列表容器
|
|
||||||
|
|
||||||
// 2. 存储定时器(键:1/2,值:定时器ID)
|
|
||||||
const scrollTimers: { [key: number]: NodeJS.Timeout | null } = {
|
|
||||||
1: null,
|
|
||||||
2: null
|
|
||||||
};
|
|
||||||
|
|
||||||
// 3. 滚动配置
|
|
||||||
const scrollStep = 1; // 每次滚动的步长(像素,越小越流畅)
|
|
||||||
const scrollInterval = 20; // 滚动间隔(毫秒,越小越流畅)
|
|
||||||
|
|
||||||
// 4. 通用自动滚动函数
|
|
||||||
const autoScroll = (containerKey: number) => {
|
|
||||||
// 获取对应容器
|
|
||||||
const container = containerKey === 1 ? scrollContainer1.value : scrollContainer2.value;
|
|
||||||
if (!container) return;
|
|
||||||
|
|
||||||
// 获取列表内容元素(project-list)
|
|
||||||
const projectList = container.querySelector('.project-list') as HTMLDivElement;
|
|
||||||
if (!projectList) return;
|
|
||||||
|
|
||||||
// 若内容高度 ≤ 容器高度,不执行滚动
|
|
||||||
if (projectList.scrollHeight <= container.clientHeight) {
|
|
||||||
// 清除现有定时器
|
|
||||||
if (scrollTimers[containerKey]) {
|
|
||||||
clearInterval(scrollTimers[containerKey]!);
|
|
||||||
scrollTimers[containerKey] = null;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 清除现有定时器(避免重复)
|
|
||||||
if (scrollTimers[containerKey]) {
|
|
||||||
clearInterval(scrollTimers[containerKey]!);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 启动定时器滚动
|
|
||||||
scrollTimers[containerKey] = setInterval(() => {
|
|
||||||
// 向下滚动步长
|
|
||||||
container.scrollTop += scrollStep;
|
|
||||||
|
|
||||||
// 滚动到底部时,重置为0(循环滚动)
|
|
||||||
// 加1是为了兼容像素精度问题
|
|
||||||
if (projectList.scrollHeight - container.scrollTop <= container.clientHeight + 1) {
|
|
||||||
container.scrollTop = 0; // 直接重置(也可以用平滑滚动:container.scrollTo({ top: 0, behavior: 'smooth' }))
|
|
||||||
}
|
|
||||||
}, scrollInterval);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 5. 暂停滚动
|
|
||||||
const pauseScroll = (containerKey: number) => {
|
|
||||||
if (scrollTimers[containerKey]) {
|
|
||||||
clearInterval(scrollTimers[containerKey]!);
|
|
||||||
scrollTimers[containerKey] = null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 6. 恢复滚动
|
|
||||||
const resumeScroll = (containerKey: number) => {
|
|
||||||
autoScroll(containerKey);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 7. 组件卸载时清除所有定时器
|
|
||||||
onUnmounted(() => {
|
|
||||||
Object.keys(scrollTimers).forEach(key => {
|
|
||||||
const k = Number(key);
|
|
||||||
if (scrollTimers[k]) {
|
|
||||||
clearInterval(scrollTimers[k]!);
|
|
||||||
scrollTimers[k] = null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// CVE视图切换方法
|
// CVE视图切换方法
|
||||||
const switchCveView = (view: 'global' | 'regional') => {
|
const switchCveView = (view: 'global' | 'regional') => {
|
||||||
@@ -1148,18 +1032,12 @@ const initCharts = () => {
|
|||||||
// 页面resize时重绘图表
|
// 页面resize时重绘图表
|
||||||
watch(widthType, () => {
|
watch(widthType, () => {
|
||||||
initCharts();
|
initCharts();
|
||||||
// 重新启动滚动(防止resize后滚动失效)
|
|
||||||
autoScroll(1);
|
|
||||||
autoScroll(2);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 挂载时初始化
|
// 挂载时初始化
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
initCharts();
|
initCharts();
|
||||||
// 启动列表自动滚动
|
|
||||||
autoScroll(1);
|
|
||||||
autoScroll(2);
|
|
||||||
}, 100);
|
}, 100);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user