Files
Situation-Awareness-Platfor…/src/views/Jyh/ThreatIntelligence/index.vue

569 lines
12 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="threat-page">
<header class="page-header">
<div class="header-content">
<h1 class="page-title">威胁情报库</h1>
<div class="main-search-wrapper">
<div class="search-input-group">
<input
v-model="mainKeyword"
type="text"
placeholder="搜索关键字IP地址 域名 恶意文件哈希"
class="main-search-input"
/>
<button class="search-icon-btn">
<i class="icon-search d-icon icon-search"></i>
</button>
</div>
</div>
</div>
<div class="header-illustration">
<div class="shield-graphic"></div>
</div>
</header>
<main class="main-container">
<div class="content-layout">
<div class="list-column">
<div class="threat-list">
<div
v-for="(item, index) in threatList"
:key="index"
class="threat-card vuln-card"
:class="getCardBorderClass(item.severity)"
>
<div class="card-top">
<h3 class="threat-title vuln-title">{{ item.title }}</h3>
<div class="threat-icon-wrapper vuln-icon-wrapper" :class="item.iconType">
<i class="d-icon" :class="item.iconClass"></i>
</div>
</div>
<div class="card-meta">
<span class="indicator-tag cnnvd-tag">
{{ item.indicatorType }}{{ item.indicatorValue }}
</span>
<span
v-if="item.severity"
class="severity-tag level-tag"
:class="getLevelClass(item.severity)"
>
{{ item.severity }}
</span>
</div>
<div class="card-footer">
<span class="date-item">首次发现{{ item.firstSeen }}</span>
<span class="date-item">最后活动{{ item.lastActivity }}</span>
</div>
</div>
</div>
<div class="pagination-wrapper">
<d-pagination
:total="125678"
:page-size="10"
:page-index="1"
show-page-selector
></d-pagination>
</div>
</div>
<div class="sidebar-column">
<div class="filter-card">
<div class="filter-header">高级筛选</div>
<div class="filter-body-expanded">
<div class="filter-item">
<label>威胁等级</label>
<d-select v-model="filter.severity" placeholder="请选择" :options="severityOptions"></d-select>
</div>
<div class="filter-item">
<label>情报类型</label>
<d-select v-model="filter.type" placeholder="请选择" :options="threatTypeOptions"></d-select>
</div>
<div v-if="!isFilterCollapsed" class="filter-item">
<label>所属组织</label>
<d-input v-model="filter.organization" placeholder="APT组织名称"></d-input>
</div>
<div class="filter-item">
<label>活动时间</label>
<d-select v-model="filter.dateType" placeholder="时间类型" :options="dateTypeOptions"></d-select>
</div>
<div v-if="!isFilterCollapsed" class="filter-item">
<label>查询时间</label>
<div class="date-range-mock">
<input placeholder="开始日期" class="date-input"/>
<span class="separator">-</span>
<input placeholder="结束日期" class="date-input"/>
</div>
</div>
<div class="filter-actions">
<d-button variant="solid" color="primary" class="confirm-btn">查询</d-button>
<d-button class="reset-btn">重置</d-button>
</div>
</div>
<div class="collapse-link">
<a href="#" @click.prevent="isFilterCollapsed = !isFilterCollapsed">
{{ isFilterCollapsed ? '展开' : '收起' }}
<i class="d-icon" :class="isFilterCollapsed ? 'icon-chevron-down-2' : 'icon-chevron-up-2'"></i>
</a>
</div>
</div>
<d-button class="download-btn" variant="solid" color="primary" icon="icon-download">
<i class="d-icon icon-download"></i> 导出情报数据
</d-button>
</div>
</div>
</main>
</div>
</template>
<script setup>
import {ref} from 'vue';
const mainKeyword = ref('');
const isFilterCollapsed = ref(false);
// 模拟威胁情报数据
const threatList = ref([
{
title: '针对金融行业的钓鱼活动C2: 192.168.1.1',
severity: '危急',
indicatorType: 'IP',
indicatorValue: '192.168.1.1',
firstSeen: '2025-11-20',
lastActivity: '2025-12-04',
iconType: 'red',
iconClass: 'icon-lock-private', // 模拟一个红色锁图标
},
{
title: 'APT-XYZ组织最新使用的恶意域名',
severity: '高危',
indicatorType: 'Domain',
indicatorValue: 'evil-updates.com',
firstSeen: '2025-12-01',
lastActivity: '2025-12-05',
iconType: 'orange',
iconClass: 'icon-lock-private',
},
{
title: '新型勒索软件变种Ransom.VariantA',
severity: '中危',
indicatorType: 'Hash',
indicatorValue: 'A1B2C3D4E5F67890',
firstSeen: '2025-12-03',
lastActivity: '2025-12-05',
iconType: 'yellow',
iconClass: 'icon-lock-private',
},
{
title: '僵尸网络C&C服务器更新',
severity: '中危',
indicatorType: 'IP',
indicatorValue: '203.0.113.44',
firstSeen: '2025-12-04',
lastActivity: '2025-12-04',
iconType: 'yellow',
iconClass: 'icon-lock-private',
},
{
title: '普通信息泄漏警告',
severity: '低危',
indicatorType: 'URL',
indicatorValue: 'example.com/login',
firstSeen: '2025-12-05',
lastActivity: '2025-12-05',
iconType: 'blue',
iconClass: 'icon-lock-private',
},
]);
// 筛选表单数据
const filter = ref({
severity: '',
type: '',
organization: '',
dateType: '首次发现',
});
const severityOptions = [
{label: '危急', value: 'critical'},
{label: '高危', value: 'high'},
{label: '中危', value: 'medium'},
{label: '低危', value: 'low'}
];
const threatTypeOptions = [
{label: '恶意IP', value: 'ip'},
{label: '恶意域名', value: 'domain'},
{label: '恶意文件哈希', value: 'hash'}
];
const dateTypeOptions = [
{label: '首次发现', value: 'first'},
{label: '最后活动', value: 'last'}
];
// 辅助函数:获取标签颜色类
const getLevelClass = (severity) => {
if (severity === '危急') return 'tag-critical';
if (severity === '高危') return 'tag-high';
if (severity === '中危') return 'tag-medium';
return 'tag-low';
};
// 辅助函数:获取卡片左边框颜色类
const getCardBorderClass = (severity) => {
if (severity === '危急') return 'border-critical';
if (severity === '高危') return 'border-high';
if (severity === '中危') return 'border-medium';
return 'border-low';
};
const highlightKeyword = (text) => {
return text;
};
</script>
<style lang="scss" scoped>
.threat-page {
background-color: #f0f2f5;
min-height: 100vh;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
color: #333;
}
.page-header {
background-color: #0f1724;
padding: 60px 0 100px;
position: relative;
overflow: hidden;
text-align: center;
/* 假设背景图路径正确 */
background-image: url(@/assets/v3/louDong_back.4bfd0a5.png);
}
.page-title {
color: #fff;
font-size: 36px;
font-weight: 500;
margin-bottom: 30px;
letter-spacing: 2px;
}
.main-search-wrapper {
max-width: 800px;
margin: 0 auto;
}
.search-input-group {
display: flex;
background-color: #fff;
border-radius: 4px;
overflow: hidden;
height: 50px;
}
.main-search-input {
flex: 1;
border: none;
outline: none;
padding: 0 20px;
font-size: 14px;
color: #333;
}
.search-icon-btn {
width: 50px;
background: none;
border: none;
cursor: pointer;
color: #3d7fff;
font-size: 18px;
display: flex;
align-items: center;
justify-content: center;
}
.header-illustration {
position: absolute;
top: 0;
right: 0;
height: 100%;
width: 400px;
background: radial-gradient(circle at 70% 50%, rgba(61, 127, 255, 0.1), transparent 60%);
pointer-events: none;
z-index: 1;
}
.main-container {
max-width: 1300px;
margin: 40px auto;
position: relative;
z-index: 10;
padding: 0 20px;
}
.content-layout {
display: flex;
gap: 20px;
align-items: flex-start;
}
.list-column {
flex: 1;
}
.sidebar-column {
width: 320px;
flex-shrink: 0;
}
.threat-card {
background-color: #fff;
margin-bottom: 16px;
padding: 20px;
border-radius: 4px;
transition: all 0.3s ease;
cursor: pointer;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.04);
}
.threat-card:hover {
transform: translateY(-5px);
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
}
.threat-card.border-low {
border-left: 4px solid #3d7fff;
}
/* 蓝色 (低危) */
.threat-card.border-medium {
border-left: 4px solid #feca57;
}
/* 黄色 (中危) */
.threat-card.border-high {
border-left: 4px solid #ff9f43;
}
/* 橙色 (高危) */
.threat-card.border-critical {
border-left: 4px solid #ff4757;
}
/* 红色 (危急) */
.card-top {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 10px;
}
.threat-title {
font-size: 16px;
font-weight: 600;
color: #333;
margin: 0;
line-height: 1.4;
}
.threat-title:hover {
color: #3d7fff;
}
.threat-icon-wrapper {
width: 32px;
height: 32px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-left: 15px;
flex-shrink: 0;
}
.threat-icon-wrapper.blue {
background-color: #e6f7ff;
color: #1890ff;
}
.threat-icon-wrapper.yellow {
background-color: #fffbe6;
color: #faad14;
}
.threat-icon-wrapper.orange {
background-color: #fff2e8;
color: #fa541c;
}
.threat-icon-wrapper.red {
background-color: #ffe6e6;
color: #ff4757;
}
/* 新增红色图标背景 */
.card-meta {
display: flex;
align-items: center;
margin-bottom: 15px;
}
.indicator-tag {
background-color: #eff6ff;
color: #3d7fff;
font-size: 12px;
padding: 4px 8px;
border-radius: 2px;
margin-right: 10px;
}
.severity-tag {
font-size: 12px;
padding: 4px 12px;
border-radius: 2px;
color: #fff;
}
.tag-low {
background-color: #1890ff;
}
.tag-medium {
background-color: #feca57;
color: #fff;
}
.tag-high {
background-color: #ff9f43;
}
.tag-critical {
background-color: #ff4757;
}
/* 红色 */
.card-footer {
font-size: 12px;
color: #999;
}
.date-item {
margin-right: 30px;
}
.pagination-wrapper {
margin-top: 20px;
display: flex;
justify-content: flex-end;
}
.filter-card {
background-color: #fff;
border-radius: 4px;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.04);
padding: 20px;
margin-bottom: 20px;
}
.filter-header {
font-size: 16px;
font-weight: 600;
margin-bottom: 20px;
color: #333;
}
.filter-body-expanded {
transition: max-height 0.3s ease-in-out;
overflow: hidden;
}
.filter-item {
margin-bottom: 15px;
}
.filter-item label {
display: block;
font-size: 13px;
color: #666;
margin-bottom: 8px;
}
:deep(.devui-select), :deep(.devui-input__inner) {
width: 100%;
}
.date-range-mock {
display: flex;
align-items: center;
gap: 5px;
}
.date-input {
flex: 1;
border: 1px solid #dcdfe6;
border-radius: 2px;
height: 32px;
padding: 0 10px;
font-size: 12px;
color: #666;
width: 100%;
}
.filter-actions {
display: flex;
gap: 10px;
margin-top: 25px;
justify-content: center;
}
.confirm-btn {
background-color: #3d7fff !important;
border-color: #3d7fff !important;
}
.reset-btn {
border: 1px solid #dcdfe6;
color: #666;
}
.collapse-link {
text-align: right;
margin-top: 10px;
padding-top: 10px;
border-top: 1px solid #eee;
}
.collapse-link a {
color: #3d7fff;
font-size: 12px;
text-decoration: none;
}
.collapse-link .d-icon {
margin-left: 5px;
}
.download-btn {
width: 100%;
background-color: #3d7fff !important;
border-color: #3d7fff !important;
height: 40px;
font-size: 14px;
}
</style>