Tcode平台改造升级-安全事件中心页面开发

This commit is contained in:
fmk1023
2025-12-05 16:54:27 +08:00
parent e7150457c4
commit 1e2d8f775d
9 changed files with 1271 additions and 57 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

BIN
src/assets/v3/newspic1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 464 KiB

View File

@@ -370,7 +370,7 @@
<h4 class="item-tit">实时情报推送</h4>
<ul class="hover-child">
<li class="child-item"><a href="javascript:;" target="_blank" class="LNK">实时推送 CISA KEV 列表及供应链攻击情报 IOC</a></li>
<li class="child-item child-item-2"><a href="javascript:;" target="_blank" class="LNK"><i class="ico-dp"></i> [ 订阅情报 > ]</a></li>
<li class="child-item child-item-2"><router-link to="/ThreatIntelligence" class="LNK"><i class="ico-dp"></i> [ 订阅情报 > ]</router-link></li>
</ul>
</li>
<!-- 安全事件中心 -->
@@ -379,7 +379,7 @@
<h4 class="item-tit">事件复盘分析</h4>
<ul class="hover-child">
<li class="child-item"><a href="javascript:;" target="_blank" class="LNK">全球重大开源安全事件历史档案与复盘分析</a></li>
<li class="child-item child-item-2"><a href="javascript:;" target="_blank" class="LNK"><i class="ico-dp"></i> [ 查看事件 > ]</a></li>
<li class="child-item child-item-2"><router-link to="/News" class="LNK"><i class="ico-dp"></i> [ 查看事件 > ]</router-link></li>
</ul>
</li>
</ul>

View File

@@ -213,6 +213,32 @@ export default [
asideMenu: 'drawer' // 左侧菜单抽屉模式
}
},
{
path: '/ThreatIntelligence',
name: 'ThreatIntelligence',
component: () => import('@/views/Jyh/ThreatIntelligence/index.vue'),
meta: {
title: '威胁情报库',
reportTitle: '威胁情报库',
className: 'w-full min-w-full',
hiddenFooter: true,
hasMobile: true,
asideMenu: 'drawer' // 左侧菜单抽屉模式
}
},
{
path: '/News',
name: 'News',
component: () => import('@/views/Jyh/News/index.vue'),
meta: {
title: '安全事件中心',
reportTitle: '安全事件中心',
className: 'w-full min-w-full',
hiddenFooter: true,
hasMobile: true,
asideMenu: 'drawer' // 左侧菜单抽屉模式
}
},
{
path: 'Insights',
name: 'Insights',

View File

@@ -0,0 +1,48 @@
<template>
<div class="mod-banner">
<div class="txt xyCenter"><p class="zh Jdh">安全事件中心</p>
<p class="en Jdh">Security Events Center</p></div>
</div>
</template>
<script>
</script>
<style lang="scss" scoped>
.pg-news .mod-banner {
background: url(@/assets/v3/banner.C3KTEfES.png) no-repeat 50%;
background-size: 100% 100%;
height: 400px;
position: relative
}
.pg-news .mod-banner .txt {
left: 50%;
position: absolute;
text-align: center;
top: 50%
}
.pg-news .mod-banner .txt .zh {
color: #fff;
font-size: 40px;
font-style: normal;
font-weight: 400;
letter-spacing: 2px;
letter-spacing: 1px;
line-height: 56px
}
.pg-news .mod-banner .txt .en {
color: #fff;
font-size: 14px;
font-weight: 400;
letter-spacing: 9px;
line-height: 20px
}
.xyCenter {
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
</style>

View File

@@ -0,0 +1,336 @@
<template>
<div class="pg-news">
<div class="mod-news Jdh">
<div
class="news-item"
v-for="(item, index) in newsList"
:key="index"
>
<img
:src="item.thumb"
:alt="item.title"
class="thumb"
>
<div class="thumb-r">
<h3 class="MultiLine EASE">
<a
:href="item.link"
rel="nofollow"
class="EASE"
target="_blank"
>
{{ item.title }}
</a>
</h3>
<div class="desc MultiLine">{{ item.desc }}</div>
<div class="meta">
<i class="ICO"></i>
<span class="time">发布时间{{ item.time }}</span>
</div>
</div>
</div>
</div>
<d-pagination
v-model:current-page="currentPage"
:total="total"
:page-size="pageSize"
:show-page-sizes="false"
:show-jumper="false"
:show-total="false"
class="comPaging"
@page-change="handlePageChange"
>
<template #prev-text>&lt;</template>
<template #next-text>&gt;</template>
<template #total="{ total, pageCount }">
<span class="total"> {{ pageCount }} </span>
</template>
</d-pagination>
</div>
</template>
<script setup>
import { ref } from 'vue';
import newsPic from '@/assets/v3/newspic1.png';
const newsList = ref([
{
thumb: newsPic, // 使用引入的图片变量
title: 'Log4j2 漏洞变种再现!开源组件供应链安全风险升级',
link: 'https://mp.weixin.qq.com/s/xxxxxx',
desc: '2025年12月安全研究人员发现Log4j2漏洞新型变种CVE-2025-XXXX该变种绕过了传统防护规则影响超过10万个开源项目。开源安全联盟已发布紧急修复指南建议企业立即对开源组件进行全量扫描。',
time: '2025/12/03'
},
{
thumb: newsPic, // 所有项都用这个变量
title: 'OSV漏洞数据库新增10万+开源组件漏洞数据覆盖9大主流语言',
link: 'https://mp.weixin.qq.com/s/xxxxxx',
desc: '近日开源漏洞数据库OSV完成年度最大规模数据更新新增10万+条开源组件漏洞记录覆盖Java、Python、Go、C++等9大主流开发语言。本次更新首次纳入鸿蒙生态开源组件漏洞数据进一步完善国产化开源安全体系。',
time: '2025/12/03'
},
// 剩余8项的 thumb 全部替换为 newsPic
{
thumb: newsPic,
title: '开源供应链安全平台上线!一键检测项目依赖漏洞与恶意包',
link: 'https://mp.weixin.qq.com/s/xxxxxx',
desc: '在2025开源安全峰会上国内首款开源供应链安全检测平台正式发布。该平台可自动化扫描项目依赖树识别恶意开源包、漏洞组件及许可证合规风险目前已接入Maven、NPM、PyPI等12大主流开源仓库。',
time: '2025/11/25'
},
{
thumb: newsPic,
title: 'PyPI仓库再现恶意包攻击伪装成热门AI库窃取开发者数据',
link: 'https://mp.weixin.qq.com/s/xxxxxx',
desc: '2025年11月安全团队监测到PyPI开源仓库中出现一批仿冒热门AI框架的恶意包累计下载量超5万次。该恶意包会在安装时窃取开发者本地配置文件及代码仓库密钥开源安全应急响应中心已紧急下架相关包并发布预警。',
time: '2025/11/19'
},
{
thumb: newsPic,
title: '开源安全奖励计划升级最高悬赏50万元征集核心组件漏洞',
link: 'https://mp.weixin.qq.com/s/xxxxxx',
desc: '2025年11月开源安全奖励计划OSRP完成规则升级将漏洞悬赏范围扩展至国产化开源组件最高单笔悬赏金额提升至50万元。本次升级重点覆盖政务、金融领域常用开源中间件鼓励白帽黑客参与开源生态安全建设。',
time: '2025/11/14'
},
{
thumb: newsPic,
title: '进博会首发开源安全治理AI平台实现漏洞秒级检测',
link: 'https://mp.weixin.qq.com/s/xxxxxx',
desc: '11月5日至10日第八届进博会期间开源安全领域首款AI治理平台正式发布。该平台基于大模型技术可实时分析开源代码仓库变动秒级识别漏洞、后门及合规风险已在多家央企完成试点落地。',
time: '2025/11/10'
},
{
thumb: newsPic,
title: '开源安全白皮书2025发布90%企业存在开源组件合规风险',
link: 'https://mp.weixin.qq.com/s/xxxxxx',
desc: '2025年11月《中国开源安全发展白皮书》正式发布。报告显示国内90%以上企业在使用开源组件时存在许可证合规风险其中35%的企业曾因开源漏洞导致业务中断。白皮书同时提出了开源安全治理的“三全”标准:全生命周期、全场景、全链路。',
time: '2025/11/03'
},
{
thumb: newsPic,
title: '开源安全企业入选专精特新“小巨人”AI检测技术成核心优势',
link: 'https://mp.weixin.qq.com/s/xxxxxx',
desc: '近日北京市第七批专精特新“小巨人”企业名单公示某开源安全企业凭借AI驱动的开源组件漏洞检测技术成功入选。该企业自研的开源安全扫描引擎误报率低于0.5%检测速度较行业平均水平提升3倍。',
time: '2025/10/27'
},
{
thumb: newsPic,
title: '国资国企开源安全联盟成立,共建国产化开源安全体系',
link: 'https://mp.weixin.qq.com/s/xxxxxx',
desc: '10月15日国资国企开源安全联盟在北京正式成立联盟成员涵盖30余家央企及开源安全企业。联盟将重点推进国产化开源组件的漏洞治理、合规审计及供应链安全建设首批落地10个开源安全共性技术攻关项目。',
time: '2025/10/21'
},
{
thumb: newsPic,
title: '“创客中国”开源安全赛道收官AI渗透检测项目获一等奖',
link: 'https://mp.weixin.qq.com/s/xxxxxx',
desc: '近日第十届“创客中国”创新创业大赛开源安全赛道决赛落幕基于大模型的开源组件AI渗透检测项目斩获一等奖。该项目可自动化模拟黑客攻击发现开源组件隐藏漏洞目前已申请发明专利12项。',
time: '2025/10/16'
}
]);
const currentPage = ref(1); // 当前页
const pageSize = ref(10); // 每页条数原有每页10条
const total = ref(70); // 总条数7页×10条
// 分页切换事件
const handlePageChange = (page) => {
console.log('切换到第', page, '页');
// 此处可对接接口获取对应页数据
// 示例fetchNewsList(page);
};
</script>
<style lang="scss" scoped>
.pg-news {
.mod-news {
background-color: #fafafa;
margin: 0 auto;
max-width: 1259px;
padding: 40px 0 0;
.news-item {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
color: #333;
cursor: pointer;
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 24px;
padding: 35px 0;
text-align: justify;
&:not(:last-child) {
border-bottom: 1px solid #d8d8d8;
}
&:hover h3 a {
color: #4bad52;
}
.thumb {
display: block;
height: 191px;
-o-object-fit: cover;
object-fit: cover;
width: 340px;
-ms-flex-negative: 0;
border-radius: 8px;
flex-shrink: 0;
}
.thumb-r {
padding: 0 0 0 57px;
}
h3 {
color: #333;
font-size: 20px;
font-style: normal;
font-weight: 400;
line-height: 30px;
margin: 0 0 10px;
max-height: 60px;
text-align: justify;
}
.desc {
font-weight: 400;
letter-spacing: .5px;
margin: 0 0 14px;
}
.meta {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
color: #b0afaf;
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 24px;
text-align: justify;
.ICO {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAQAAABLCVATAAAAAXNSR0IArs4c6QAAAddJREFUeNqtljtLw1AUxy/0C9jxnmh0EcGlLrp0EXEV6SKCzSg4+NhEcVInt+Kio+0qCk6CYIJDEVwUxEpx6CbioNAIohH/YohtHicvzDlDk9vbX+8597yECBE1L8uyKg1qkkkmNaUhq7Ks5kUakSXSySIwapEuS4kgVKQ6i3BrnYrRlJxSiYU4qlRELoQy0ENnSTG2ng308JhGKsyvNoKoXMrTdE7lMzC5bxhfeW4K/9DuDSa48Mhg6IZfip+NYhdbvjUnRElPCpnBKb4ALPq/0e2cCkkGjw5hAw/4k4lA4qh5IbU4yDgO8IaufEIN7JGaUGrhCBXzqHcAFt7tzzsuCGpCGjykgB08us7xhkvn6ZDZLQ1BzeDyFI7xCbc8Yx/fzvMm98dNQaZ3aQm38EsLK/jovM1yIFNQ27s0gWsf5gbTeHG9FzhQmzGtD9uOW39FxxhaHiOJN413dtFx7SEGceU53wULkoaQ1ZCsxjoq6MWJz9A9HlSNCUgt4PhlHlSOTZE5PHlAk2xvsdtUXNIOu8yz0M/t0ROXkQW82qB73rBSisI2gnMAR1GFLXmpXcVadKnNrPhn2I6ya5DZtewMh4gsx5osBy3X6KcpNffop9SkFj76/QC1at54IoZE9wAAAABJRU5ErkJggg==);
display: block;
height: 18px;
margin: 0 10px 0 0;
width: 18px;
}
}
}
}
// DevUI分页组件样式覆盖保持原有样式
.comPaging {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
padding: 36px 0 79px;
-webkit-box-pack: center;
-ms-flex-pack: center;
color: #333;
font-size: 14px;
font-style: normal;
font-weight: 400;
justify-content: center;
line-height: 24px;
text-align: justify;
// 覆盖DevUI默认样式
:deep(.devui-pagination) {
display: flex;
align-items: center;
.devui-pagination-item {
margin: 0 3px;
transition: all .4s ease-out;
height: 32px;
line-height: 32px;
min-width: 32px;
padding: 0 12px;
text-align: center;
border: none;
border-radius: 0;
&.devui-pagination-item-active {
background: #333;
border-radius: 50%;
color: #fff;
&:hover {
color: #fff;
}
}
&:hover {
color: #4bad52;
}
&.devui-pagination-prev,
&.devui-pagination-next {
font-size: 16px;
}
&[disabled] {
color: #cecece;
cursor: not-allowed;
}
}
.devui-pagination-ellipsis {
margin: 0 3px;
}
.total {
margin-left: 8px;
}
}
}
}
// 响应式样式保留
@media (max-width: 1023px) {
.pg-news .comPaging {
-ms-flex-wrap: wrap;
flex-wrap: wrap;
font-size: 12px;
gap: 8px;
padding: 20px 0 40px;
&>* {
margin: 0;
}
:deep(.devui-pagination-item) {
font-size: 12px;
height: 28px;
line-height: 28px;
min-width: 28px;
padding: 0 8px;
&.devui-pagination-prev,
&.devui-pagination-next {
font-size: 14px;
min-width: 32px;
}
}
:deep(.total) {
font-size: 12px;
text-align: center;
}
}
}
</style>

View File

@@ -0,0 +1,16 @@
<template>
<div class="pg-news">
<ModBanner />
<ModNews />
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import ModBanner from './ModBanner.vue'
import ModNews from './ModNews.vue'
</script>
<style lang="scss" scoped>
</style>

View File

@@ -0,0 +1,568 @@
<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>

View File

@@ -14,7 +14,7 @@
class="main-search-input"
/>
<button class="search-icon-btn">
<i class="icon-search d-icon d-icon-search"></i>
<i class="icon-search d-icon icon-search"></i>
</button>
</div>
</div>
@@ -95,9 +95,9 @@
<div class="filter-item">
<label>查询时间</label>
<div class="date-range-mock">
<input placeholder="开始日期" class="date-input" />
<input placeholder="开始日期" class="date-input"/>
<span class="separator">-</span>
<input placeholder="结束日期" class="date-input" />
<input placeholder="结束日期" class="date-input"/>
</div>
</div>
@@ -110,13 +110,13 @@
<div class="collapse-link">
<a href="#" @click.prevent="isFilterCollapsed = !isFilterCollapsed">
{{ isFilterCollapsed ? '展开' : '收起' }}
<i class="d-icon" :class="isFilterCollapsed ? 'd-icon-arrow-down' : 'd-icon-arrow-up'"></i>
<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 d-icon-download"></i> 下载漏洞数据
<i class="d-icon icon-download"></i> 下载漏洞数据
</d-button>
</div>
@@ -126,7 +126,7 @@
</template>
<script setup>
import { ref } from 'vue';
import {ref} from 'vue';
// 假设已安装 vue-devui部分组件需要按需引入或全局注册
// import { DButton, DSelect, DInput, DPagination } from 'vue-devui';
@@ -135,11 +135,51 @@ const isFilterCollapsed = ref(true); // 【新增:控制高级搜索的展开/
// 模拟漏洞数据 (保持不变)
const vulnList = ref([
{ title: 'FreePBX SQL注入漏洞', cnnvd: 'CNNVD-202512-423', level: '低危', createTime: '2025-12-04', updateTime: '2025-12-04', iconType: 'blue', iconClass: 'icon-bug' },
{ title: 'WordPress Plugin CSSIgniter Shortcodes 跨站脚本漏洞', cnnvd: 'CNNVD-202512-422', level: '中危', createTime: '2025-12-03', updateTime: '2025-12-04', iconType: 'yellow', iconClass: 'icon-bug' },
{ title: 'WordPress Plugin Modula Image Gallery 路径遍历漏洞', cnnvd: 'CNNVD-202512-421', level: '高危', createTime: '2025-12-03', updateTime: '2025-12-04', iconType: 'orange', iconClass: 'icon-bug' },
{ title: 'WordPress Plugin Modula Image Gallery 代码问题漏洞', cnnvd: 'CNNVD-202512-420', level: '危', createTime: '2025-12-03', updateTime: '2025-12-04', iconType: 'orange', iconClass: 'icon-bug' },
{ title: 'WordPress Plugin MXChat 信息泄露漏洞', cnnvd: 'CNNVD-202512-419', level: '中危', createTime: '2025-12-03', updateTime: '2025-12-04', iconType: 'yellow', iconClass: 'icon-bug' },
{
title: 'FreePBX SQL注入漏洞',
cnnvd: 'CNNVD-202512-423',
level: '危',
createTime: '2025-12-04',
updateTime: '2025-12-04',
iconType: 'blue',
iconClass: 'icon-bug'
},
{
title: 'WordPress Plugin CSSIgniter Shortcodes 跨站脚本漏洞',
cnnvd: 'CNNVD-202512-422',
level: '中危',
createTime: '2025-12-03',
updateTime: '2025-12-04',
iconType: 'yellow',
iconClass: 'icon-bug'
},
{
title: 'WordPress Plugin Modula Image Gallery 路径遍历漏洞',
cnnvd: 'CNNVD-202512-421',
level: '高危',
createTime: '2025-12-03',
updateTime: '2025-12-04',
iconType: 'orange',
iconClass: 'icon-bug'
},
{
title: 'WordPress Plugin Modula Image Gallery 代码问题漏洞',
cnnvd: 'CNNVD-202512-420',
level: '高危',
createTime: '2025-12-03',
updateTime: '2025-12-04',
iconType: 'orange',
iconClass: 'icon-bug'
},
{
title: 'WordPress Plugin MXChat 信息泄露漏洞',
cnnvd: 'CNNVD-202512-419',
level: '中危',
createTime: '2025-12-03',
updateTime: '2025-12-04',
iconType: 'yellow',
iconClass: 'icon-bug'
},
]);
// 筛选表单数据 (保持不变)
@@ -150,9 +190,9 @@ const filter = ref({
dateType: '收录时间',
});
const levelOptions = [{ label: '高危', value: 'high' }, { label: '中危', value: 'medium' }, { label: '低危', value: 'low' }];
const typeOptions = [{ label: 'SQL注入', value: 'sql' }, { label: 'XSS', value: 'xss' }];
const dateTypeOptions = [{ label: '收录时间', value: 'create' }, { label: '更新时间', value: 'update' }];
const levelOptions = [{label: '高危', value: 'high'}, {label: '中危', value: 'medium'}, {label: '低危', value: 'low'}];
const typeOptions = [{label: 'SQL注入', value: 'sql'}, {label: 'XSS', value: 'xss'}];
const dateTypeOptions = [{label: '收录时间', value: 'create'}, {label: '更新时间', value: 'update'}];
// 辅助函数 (保持不变)
const getLevelClass = (level) => {
@@ -187,8 +227,9 @@ const highlightKeyword = (text) => {
position: relative;
overflow: hidden;
text-align: center;
background-image: url(@/assets/v3/louDong_back.4bfd0a5.png);
background-image: url(@/assets/v3/louDong_back.4bfd0a5.png);
}
.page-title {
color: #fff;
font-size: 36px;
@@ -196,14 +237,50 @@ const highlightKeyword = (text) => {
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; }
.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;
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;
pointer-events: none;
z-index: 1;
}
.main-container {
@@ -220,8 +297,14 @@ const highlightKeyword = (text) => {
align-items: flex-start;
}
.list-column { flex: 1; }
.sidebar-column { width: 320px; flex-shrink: 0; }
.list-column {
flex: 1;
}
.sidebar-column {
width: 320px;
flex-shrink: 0;
}
.vuln-card {
background-color: #fff;
@@ -232,35 +315,130 @@ const highlightKeyword = (text) => {
cursor: pointer;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.04);
}
.vuln-card:hover {
transform: translateY(-5px);
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
}
.vuln-card.border-low { border-left: 4px solid #3d7fff; }
.vuln-card.border-medium { border-left: 4px solid #feca57; }
.vuln-card.border-high { border-left: 4px solid #ff9f43; }
.card-top { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 10px; }
.vuln-title { font-size: 16px; font-weight: 600; color: #333; margin: 0; line-height: 1.4; }
.vuln-title:hover { color: #3d7fff; }
.vuln-icon-wrapper { width: 32px; height: 32px; border-radius: 50%; display: flex; align-items: center; justify-content: center; margin-left: 15px; flex-shrink: 0; }
.vuln-icon-wrapper.blue { background-color: #e6f7ff; color: #1890ff; }
.vuln-icon-wrapper.yellow { background-color: #fffbe6; color: #faad14; }
.vuln-icon-wrapper.orange { background-color: #fff2e8; color: #fa541c; }
.card-meta { display: flex; align-items: center; margin-bottom: 15px; }
.cnnvd-tag { background-color: #eff6ff; color: #3d7fff; font-size: 12px; padding: 4px 8px; border-radius: 2px; margin-right: 10px; }
.level-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; }
.card-footer { font-size: 12px; color: #999; }
.date-item { margin-right: 30px; }
.pagination-wrapper { margin-top: 20px; display: flex; justify-content: flex-end; }
.vuln-card.border-low {
border-left: 4px solid #3d7fff;
}
.vuln-card.border-medium {
border-left: 4px solid #feca57;
}
.vuln-card.border-high {
border-left: 4px solid #ff9f43;
}
.card-top {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 10px;
}
.vuln-title {
font-size: 16px;
font-weight: 600;
color: #333;
margin: 0;
line-height: 1.4;
}
.vuln-title:hover {
color: #3d7fff;
}
.vuln-icon-wrapper {
width: 32px;
height: 32px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-left: 15px;
flex-shrink: 0;
}
.vuln-icon-wrapper.blue {
background-color: #e6f7ff;
color: #1890ff;
}
.vuln-icon-wrapper.yellow {
background-color: #fffbe6;
color: #faad14;
}
.vuln-icon-wrapper.orange {
background-color: #fff2e8;
color: #fa541c;
}
.card-meta {
display: flex;
align-items: center;
margin-bottom: 15px;
}
.cnnvd-tag {
background-color: #eff6ff;
color: #3d7fff;
font-size: 12px;
padding: 4px 8px;
border-radius: 2px;
margin-right: 10px;
}
.level-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;
}
.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;
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;
font-size: 16px;
font-weight: 600;
margin-bottom: 20px; /* 展开时有间距 */
color: #333;
}
@@ -271,19 +449,55 @@ const highlightKeyword = (text) => {
overflow: hidden;
}
.filter-item { margin-bottom: 15px; }
.filter-item label { display: block; font-size: 13px; color: #666; margin-bottom: 8px; }
.filter-item {
margin-bottom: 15px;
}
.filter-item label {
display: block;
font-size: 13px;
color: #666;
margin-bottom: 8px;
}
/* DevUI 组件样式覆盖 */
: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%;
: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;
}
.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;
@@ -302,5 +516,11 @@ const highlightKeyword = (text) => {
}
}
.download-btn { width: 100%; background-color: #3d7fff !important; border-color: #3d7fff !important; height: 40px; font-size: 14px; }
.download-btn {
width: 100%;
background-color: #3d7fff !important;
border-color: #3d7fff !important;
height: 40px;
font-size: 14px;
}
</style>