态势感知平台-全球开源风险态势感知监控中心抽离情报流组件
This commit is contained in:
272
src/views/Jyh/security/components/IntelligenceFeed.vue
Normal file
272
src/views/Jyh/security/components/IntelligenceFeed.vue
Normal file
@@ -0,0 +1,272 @@
|
|||||||
|
<template>
|
||||||
|
<div class="index-module__NV_5cW__chartCard list-card">
|
||||||
|
<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>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, onMounted, onUnmounted, watch, nextTick } from 'vue';
|
||||||
|
|
||||||
|
// 接收外部数据作为属性
|
||||||
|
const props = defineProps<{
|
||||||
|
initialData?: Array<any>;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
// 情报流数据
|
||||||
|
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 个伪造开源组件,包含后门程序'
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 如果提供了初始数据,则使用提供的数据
|
||||||
|
watch(() => props.initialData, (newData) => {
|
||||||
|
if (newData && newData.length > 0) {
|
||||||
|
feedList.value = newData;
|
||||||
|
}
|
||||||
|
}, { immediate: true });
|
||||||
|
|
||||||
|
// 1. 定义滚动容器的ref
|
||||||
|
const scrollContainer1 = 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 : null;
|
||||||
|
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. 组件挂载时启动滚动
|
||||||
|
onMounted(() => {
|
||||||
|
nextTick(() => {
|
||||||
|
autoScroll(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 8. 组件卸载时清除定时器
|
||||||
|
onUnmounted(() => {
|
||||||
|
Object.keys(scrollTimers).forEach(key => {
|
||||||
|
const k = Number(key);
|
||||||
|
if (scrollTimers[k]) {
|
||||||
|
clearInterval(scrollTimers[k]!);
|
||||||
|
scrollTimers[k] = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/* 使用主页面相同的CSS类定义以确保样式一致性 */
|
||||||
|
.index-module__NV_5cW__chartCard {
|
||||||
|
-webkit-backdrop-filter: blur(10px);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
background: #ffffffe6;
|
||||||
|
border: 1px solid #ffffff4d;
|
||||||
|
border-radius: 1rem;
|
||||||
|
padding: 1.5rem;
|
||||||
|
box-shadow: 0 4px 16px #00000014;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.index-module__NV_5cW__chartCard.list-card {
|
||||||
|
padding: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chartCard__title {
|
||||||
|
color: #333;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
margin: 0 0 1rem 0;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chartCard__container {
|
||||||
|
width: 100%;
|
||||||
|
height: 300px; /* 图表高度 */
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 列表容器样式:隐藏原生滚动条(可选,视觉更美观) */
|
||||||
|
.chartCard__container.list-container {
|
||||||
|
height: auto;
|
||||||
|
max-height: 300px; /* 限制列表高度,超出滚动 */
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 0 0.5rem;
|
||||||
|
/* 隐藏滚动条 */
|
||||||
|
scrollbar-width: none; /* Firefox */
|
||||||
|
-ms-overflow-style: none; /* IE/Edge */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 隐藏webkit内核浏览器的滚动条 */
|
||||||
|
.chartCard__container.list-container::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 项目列表样式 */
|
||||||
|
.project-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 1rem;
|
||||||
|
padding: 0.8rem;
|
||||||
|
background: #f8f9fa;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
border-left: 3px solid #2951E0;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 鼠标悬停项目项时的样式 */
|
||||||
|
.project-item:hover {
|
||||||
|
background: #f0f4ff;
|
||||||
|
transform: translateX(2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-info {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-rank {
|
||||||
|
min-width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #2951E0;
|
||||||
|
color: #fff;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
flex-shrink: 0;
|
||||||
|
padding: 0 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 特定类型的颜色定义 - 使用中文类名 */
|
||||||
|
/* .project-rank.CISA {
|
||||||
|
background: #ff0000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-rank.投毒 {
|
||||||
|
background: #ffa500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-rank.CNVD {
|
||||||
|
background: #ffff00;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-rank.GitHub {
|
||||||
|
background: #0000ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-rank.修复 {
|
||||||
|
background: #008000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-rank.供应链 {
|
||||||
|
background: #800080;
|
||||||
|
} */
|
||||||
|
|
||||||
|
.project-name {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user