Tcode平台改造升级-漏洞数据库页面开发

This commit is contained in:
fmk1023
2025-12-05 16:08:59 +08:00
parent 28ea0cc27f
commit 5550b0fb7f
6 changed files with 366 additions and 13 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 KiB

View File

@@ -249,7 +249,7 @@
</a>
<ul>
<li><a href="/" class="LNK router-link-exact-active router-link-active">首页</a></li>
<li><router-link to="/" class="LNK router-link-exact-active router-link-active">首页</router-link></li>
<li>
<a href="javascript:;" rel="noopener noreferrer" class="LNK">产品服务</a>
@@ -339,7 +339,7 @@
<!---->
</li>
<li><a href="/solutions" class="LNK">解决方案 <i class="ico-arrow-down"></i></a>
<li><router-link to="/solutions" class="LNK">解决方案 <i class="ico-arrow-down"></i></router-link>
<!-- <div class="nav-hover">-->
<!-- <ul class="hover-child">-->
<!-- <li class="child-item"><a href="/solutions/industry1" class="LNK">行业解决方案 1</a></li>-->
@@ -349,11 +349,43 @@
</li>
<li><a href="javascript:;" class="LNK">数据服务 <i class="ico-arrow-down"></i></a>
<div class="nav-hover">
<div class="nav-hover hover-product hover-product2 EN" style="left: 200px;">
<div data-v-bc7d8fb8="" class="menu-row-title">核心安全数据要素服务</div>
<div class="product-list">
<div class="plist">
<div class="list-item">
<ul>
<!-- 漏洞数据库 -->
<li class="hover-item">
<router-link to="/VulnerabilityDatabase" rel="noopener noreferrer" class="LNK">🗄 漏洞数据库</router-link>
<h4 class="item-tit">标准化漏洞查询</h4>
<ul class="hover-child">
<li class="child-item"><a href="/data/api" class="LNK">API 数据服务</a></li>
<li class="child-item"><a href="/data/report" class="LNK">定制数据报告</a></li>
<li class="child-item"><a href="javascript:;" target="_blank" class="LNK">聚合 NVD/CNNVD/OSV 数据提供标准化漏洞详情查询</a></li>
<li class="child-item child-item-2"><router-link to="/VulnerabilityDatabase" target="_blank" class="LNK"><i class="ico-dp"></i> [ 查询漏洞 > ]</router-link></li>
</ul>
</li>
<!-- 威胁情报库 -->
<li class="hover-item">
<a href="javascript:;" rel="noopener noreferrer" class="LNK">🧠 威胁情报库</a>
<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>
</ul>
</li>
<!-- 安全事件中心 -->
<li class="hover-item">
<a href="javascript:;" rel="noopener noreferrer" class="LNK">🚨 安全事件中心</a>
<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>
</ul>
</li>
</ul>
</div>
</div>
</div>
</div>
</li>
@@ -365,7 +397,7 @@
</div>
</li>
<li><a href="/pricing" class="LNK">定价</a></li>
<li><router-link to="/pricing" class="LNK">定价</router-link></li>
<li><a href="javascript:;" class="LNK">开源服务专区 <i class="ico-arrow-down"></i></a>
<div class="nav-hover hover-product hover-product2 EN" style="left: 400px;">
@@ -417,7 +449,7 @@
</div>
</li>
<li><a href="/intro" class="LNK">关于我们 <i class="ico-arrow-down"></i></a>
<li><router-link to="/intro" class="LNK">关于我们 <i class="ico-arrow-down"></i></router-link>
<!-- <div class="nav-hover">-->
<!-- <ul class="hover-child">-->
<!-- <li class="child-item"><a href="/about/intro" class="LNK">公司介绍</a></li>-->
@@ -1421,7 +1453,7 @@ const handleLogin = (type) => {
.hover-product2 {
.menu-row-title {
color: #fff;
font-size: 13px;
font-size: 18px;
padding: 20px 0;
/*writing-mode: vertical-rl;*/
align-items: center;
@@ -1431,7 +1463,8 @@ const handleLogin = (type) => {
justify-content: center;
letter-spacing: 8px;
padding: 10px;
margin: 0 16px
margin: 0 16px;
text-align: center;
/*width: 60px;*/
}
}

View File

@@ -38,7 +38,7 @@
</div>
<Aside :asideDefaultWidth="240" @on-select="handleClickMenu" style="height: calc(100% - 60px);padding-top: 0px;"></Aside>
</d-drawer>
<d-layout :style="{ marginLeft: mainMarginLeftWidth + 'px', transition: 'margin-left ease 0.1s' }">
<d-layout :style="{ marginLeft: mainMarginLeftWidth + 'px', transition: 'margin-left ease 0.1s', marginTop: '23px' }">
<d-layout :class="responsiveClass">
<!-- sidebar -->
<d-aside class="d-aside mr-[32px] pt-24" v-if="route?.meta?.sidebarType">

View File

@@ -197,6 +197,20 @@ export default [
hiddenFooter: true,
hasMobile: true,
asideMenu: 'drawer' // 左侧菜单抽屉模式
}
},
{
path: '/VulnerabilityDatabase',
name: 'VulnerabilityDatabase',
component: () => import('@/views/Jyh/VulnerabilityDatabase/index.vue'),
meta: {
title: '漏洞数据库',
reportTitle: '漏洞数据库',
className: 'w-full min-w-full',
hiddenFooter: true,
hasMobile: true,
asideMenu: 'drawer' // 左侧菜单抽屉模式
}
},
{

View File

@@ -205,7 +205,7 @@ const comparisonData = ref<FeatureSection[]>([
.comparison-table-container {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
max-width: 1200px;
margin: 0 auto;
margin: 60px auto;
padding: 40px 20px;
background-color: #fff;
color: #000;

View File

@@ -0,0 +1,306 @@
<template>
<div class="vuln-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="搜索关键字CNNVD编号 CVE编号"
class="main-search-input"
/>
<button class="search-icon-btn">
<i class="icon-search d-icon d-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="vuln-list">
<div
v-for="(item, index) in vulnList"
:key="index"
class="vuln-card"
:class="getCardBorderClass(item.level)"
>
<div class="card-top">
<h3 class="vuln-title" v-html="highlightKeyword(item.title)"></h3>
<div class="vuln-icon-wrapper" :class="item.iconType">
<i class="d-icon" :class="item.iconClass"></i>
</div>
</div>
<div class="card-meta">
<span class="cnnvd-tag">CNNVD编号{{ item.cnnvd }}</span>
<span
v-if="item.level"
class="level-tag"
:class="getLevelClass(item.level)"
>
{{ item.level }}
</span>
</div>
<div class="card-footer">
<span class="date-item">收录时间{{ item.createTime }}</span>
<span class="date-item">更新时间{{ item.updateTime }}</span>
</div>
</div>
</div>
<div class="pagination-wrapper">
<d-pagination
:total="317483"
: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.level" placeholder="请选择" :options="levelOptions"></d-select>
</div>
<div class="filter-item">
<label>漏洞类型</label>
<d-select v-model="filter.type" placeholder="请选择" :options="typeOptions"></d-select>
</div>
<div v-if="!isFilterCollapsed" class="filter-item">
<label>厂商</label>
<d-input v-model="filter.vendor" placeholder="请输入厂商"></d-input>
</div>
<div v-if="!isFilterCollapsed" class="filter-item">
<label>时间类型</label>
<d-select v-model="filter.dateType" placeholder="时间类型" :options="dateTypeOptions"></d-select>
</div>
<div 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 icon="search" variant="solid" color="primary" class="confirm-btn">确认</d-button>
<d-button icon="refresh" class="reset-btn">取消</d-button>
</div>
</div>
<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>
</a>
</div>
</div>
<d-button class="download-btn" variant="solid" color="primary" icon="icon-download">
<i class="d-icon d-icon-download"></i> 下载漏洞数据
</d-button>
</div>
</div>
</main>
</div>
</template>
<script setup>
import { ref } from 'vue';
// 假设已安装 vue-devui部分组件需要按需引入或全局注册
// import { DButton, DSelect, DInput, DPagination } from 'vue-devui';
const mainKeyword = ref('');
const isFilterCollapsed = ref(false); // 【新增:控制高级搜索的展开/收起】
// 模拟漏洞数据 (保持不变)
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' },
]);
// 筛选表单数据 (保持不变)
const filter = ref({
level: '',
type: '',
vendor: '',
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 getLevelClass = (level) => {
if (level === '高危') return 'tag-high';
if (level === '中危') return 'tag-medium';
return 'tag-low';
};
const getCardBorderClass = (level) => {
if (level === '高危') return 'border-high';
if (level === '中危') return 'border-medium';
return 'border-low';
};
const highlightKeyword = (text) => {
return text;
};
</script>
<style lang="scss" scoped>
/* 全局重置 */
.vuln-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; }
.vuln-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);
}
.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; }
.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; }
/* 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%;
}
.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;
.d-icon {
margin-left: 5px;
}
}
.download-btn { width: 100%; background-color: #3d7fff !important; border-color: #3d7fff !important; height: 40px; font-size: 14px; }
</style>