297 lines
8.8 KiB
Vue
297 lines
8.8 KiB
Vue
<template>
|
||
<div class="info-outside w-full">
|
||
<div class="info">
|
||
<div class="flex items-center justify-start w-full gap-1">
|
||
<img src="@/assets/imgs/jyh/aiIcon.png" />
|
||
<span class="text-base font-medium">AI修复建议:</span>
|
||
</div>
|
||
<div>
|
||
<br />通过AI技术精准诊断漏洞类型,智能匹配多维度定制化修复策略,实现从数据校验、代码加固到权限控制的全链路防御,助力漏洞修复效率提升,全方位保障开源软件使用安全。<br />
|
||
|
||
<!-- <ul>-->
|
||
<!-- <li v-for="info in infoList">{{ info }}</li>-->
|
||
<!-- </ul>-->
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="ai-container">
|
||
<template v-if="tableData.length > 0">
|
||
<div class="ai-container-card" style="width: 100%" v-for="(rowItem, index) in tableData" :key="index">
|
||
<Panel :expand="rowItem.expand">
|
||
<template #header>
|
||
<div class="ai-panel-header">
|
||
<div style="padding: 25px 8px 0px 20px">
|
||
<img style="width: 36px; height: 33px" src="@/assets/imgs/jyh/warning.png" />
|
||
</div>
|
||
<div style="width: 100%; padding: 20px 20px 0px 0">
|
||
<div class="ai-panel-header-title">
|
||
<div>
|
||
<d-tag color="red-w98" class="mr-1" size="sm">严重</d-tag>
|
||
<span>{{ rowItem.libraryName || '--' }}</span>
|
||
</div>
|
||
<div
|
||
style="cursor: pointer; display: flex; gap: 8px; align-items: center"
|
||
@click="rowItem.expand = !rowItem.expand"
|
||
>
|
||
<d-icon :name="rowItem.expand ? 'icon-expand-new' : 'icon-drag-new'"></d-icon>
|
||
<span>{{ rowItem.expand ? '收起' : '展开' }}</span>
|
||
</div>
|
||
</div>
|
||
<div class="ai-panel-header-sub-title">
|
||
<div>
|
||
<span class="weak-text">安全问题</span>
|
||
<span>{{ rowItem.vulnerabilities.length || '--' }}</span>
|
||
</div>
|
||
<!-- <div>-->
|
||
<!-- <span class="weak-text">修复兼容性</span>-->
|
||
<!-- <span>{{ rowItem.vulnerabilities.length || '--' }}</span>-->
|
||
<!-- <d-tooltip-->
|
||
<!-- position="bottom"-->
|
||
<!-- content="这个评分是在比较当前版本和推荐版本之间的差异,并建议修复此组件时的复杂程度。"-->
|
||
<!-- >-->
|
||
<!-- <img src="@/assets/imgs/jyh/help.png" class="icon-sm" />-->
|
||
<!-- </d-tooltip>-->
|
||
<!-- <d-tag class="ml-1" type="warning" size="sm">{{'--'}}</d-tag>-->
|
||
<!-- </div>-->
|
||
<div>
|
||
<span class="weak-text">升级版本</span>
|
||
<span>{{ rowItem.currentVersion || '--' }}</span>
|
||
<img src="@/assets/imgs/jyh/ic_digital_power_next_step_@2x.png" class="icon-sm" />
|
||
<span>{{ rowItem.recommendedVersion || '--' }}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<template #body>
|
||
<div style="padding: 8px 20px 20px 20px; width: 100%">
|
||
<Table class="jyh-table" :tableConfig="tableConfig" :dataSource="rowItem.vulnerabilities" :libraryName="rowItem.libraryName" :currentVersion="rowItem.currentVersion"/>
|
||
<div class="w-full flex items-center justify-end">
|
||
<span>共{{ rowItem.vulnerabilities.length }}条</span>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
</Panel>
|
||
</div>
|
||
<div class="mt-20 mb-20 flex justify-end" v-if="tableData.length > 0">
|
||
<d-pagination
|
||
size="md"
|
||
:page-size-options="[10, 20, 50]"
|
||
:total="pager.total"
|
||
v-model:pageSize="pager.pageSize"
|
||
v-model:pageIndex="pager.pageIndex"
|
||
:max-items="5"
|
||
:can-change-page-size="true"
|
||
:can-view-total="true"
|
||
total-item-text="总计"
|
||
@page-index-change="fetchVulnList()"
|
||
@page-size-change="fetchVulnList()"
|
||
/>
|
||
</div>
|
||
</template>
|
||
<NoData v-else :small="false"></NoData>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { defineProps, onMounted, ref } from 'vue';
|
||
import Panel from '@/components/AIRepair/Panel.vue';
|
||
import Table from '@/components/AIRepair/Table.vue';
|
||
import NoData from '@/components/NoData/NoData.vue';
|
||
import { getVulnList, remediationSearchRemediations } from '@/api/jyh';
|
||
|
||
const infoList = ref([
|
||
'当前代码主要风险为易受常见的注入攻击,包括命令注入、SQL注入、表达式注入,针对每种攻击,应提供相应的防范措施,如数据校验、使用安全函数和限制程序权限。',
|
||
'相对上一次检查,【提升点】在于代码基础编码问题少了47.8%,问题总数降低29.3%;'
|
||
]);
|
||
|
||
const tableConfig = ref([
|
||
{
|
||
field: 'vulnId',
|
||
header: '安全问题编号',
|
||
sortable: true,
|
||
sortMethod: null
|
||
},
|
||
{
|
||
field: 'vulnType',
|
||
header: '安全问题类型',
|
||
sortable: false,
|
||
sortMethod: null,
|
||
format: (val) => {
|
||
// val小写转大写
|
||
return (val || '').toUpperCase();
|
||
}
|
||
},
|
||
{
|
||
field: 'vulnId',
|
||
header: 'CWE编号',
|
||
sortable: false,
|
||
sortMethod: null
|
||
},
|
||
{
|
||
field: 'cvssScore',
|
||
header: '分值',
|
||
sortable: true,
|
||
sortMethod: null
|
||
}
|
||
]);
|
||
|
||
|
||
const pager = ref({
|
||
total: 10,
|
||
pageIndex: 1,
|
||
pageSize: 10
|
||
});
|
||
|
||
const propsData = defineProps(['versionId']);
|
||
|
||
const fetchVulnList = async () => {
|
||
const { data } = await remediationSearchRemediations({
|
||
// softwareId: 47,
|
||
softwareId: propsData.versionId,
|
||
current: pager.value.pageIndex,
|
||
size: pager.value.pageSize
|
||
// componentId: '',
|
||
});
|
||
|
||
if (data.data.code === 200) {
|
||
tableData.value = data?.data?.data?.records || [];
|
||
pager.value.total = data?.data?.data?.total || 0;
|
||
// pager.value.total = data?.data?.data?.total || [];
|
||
}
|
||
};
|
||
|
||
const tableData = ref([
|
||
// {
|
||
// "componentId": 1,
|
||
// "libraryName": "Spring Framework",
|
||
// "currentVersion": "5.3.26",
|
||
// "vulnerabilities": [
|
||
// {
|
||
// "vulnId": "CVE-2024-12345",
|
||
// "severity": "High",
|
||
// "vulnType": "Remote Code Execution",
|
||
// "cvssScore": 8.5,
|
||
// "remediation": {
|
||
// "recommendedFix": "Upgrade to version 5.3.27 or later.",
|
||
// "patchLink": "https://spring.io/security/advisory/CVE-2024-12345",
|
||
// "recommendedVersion": "5.3.27"
|
||
// }
|
||
// }
|
||
// ]
|
||
// },
|
||
// {
|
||
// "componentId": 2,
|
||
// "libraryName": "Log4j",
|
||
// "currentVersion": "2.14.0",
|
||
// "vulnerabilities": [
|
||
// {
|
||
// "vulnId": "CVE-2023-67890",
|
||
// "severity": "Critical",
|
||
// "vulnType": "Information Disclosure",
|
||
// "cvssScore": 9.8,
|
||
// "remediation": {
|
||
// "recommendedFix": "Apply security patch 2.14.1.",
|
||
// "patchLink": "https://logging.apache.org/log4j/2.x/security.html",
|
||
// "recommendedVersion": "2.14.1"
|
||
// }
|
||
// }
|
||
// ]
|
||
// }
|
||
]);
|
||
onMounted(() => {
|
||
fetchVulnList();
|
||
});
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
@import 'devui-theme/styles-var/devui-var.scss';
|
||
|
||
.ai-container {
|
||
width: 100%;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 20px;
|
||
justify-content: center;
|
||
&-card {
|
||
border-top: 2px solid $devui-danger;
|
||
background-color: $devui-base-bg;
|
||
border-radius: var(--devui-border-radius-card, 8px);
|
||
box-shadow: var(--devui-shadow-length-base, 0 2px 6px 0) var(--devui-light-shadow, rgba(37, 43, 58, 0.12));
|
||
}
|
||
}
|
||
|
||
.ai-panel-header {
|
||
display: flex;
|
||
flex-direction: row;
|
||
height: 80px;
|
||
&-title {
|
||
width: 100%;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
}
|
||
|
||
&-sub-title {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-top: 10px;
|
||
div {
|
||
display: flex;
|
||
gap: 8px;
|
||
align-items: center;
|
||
margin-right: 20px;
|
||
position: relative;
|
||
&:not(:last-child)::after {
|
||
content: '';
|
||
position: absolute;
|
||
right: -10px;
|
||
height: 100%;
|
||
width: 1px;
|
||
background-color: $devui-line;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.weak-text {
|
||
color: $devui-text-weak;
|
||
}
|
||
|
||
.icon-sm {
|
||
width: 14px;
|
||
height: 14px;
|
||
}
|
||
|
||
.info-outside {
|
||
margin: 20px 0;
|
||
padding: 1px;
|
||
border-radius: 8px;
|
||
background-image: linear-gradient(
|
||
134.79deg,
|
||
#a4f7df 0%,
|
||
#a0cefb 21%,
|
||
#5f9afe 43%,
|
||
#d9b9fc 62%,
|
||
#01efbb 73%,
|
||
#fbae46 100%
|
||
);
|
||
}
|
||
|
||
.info {
|
||
padding: 10px 20px;
|
||
border-radius: 8px;
|
||
background-color: #ffffff;
|
||
img {
|
||
width: 24px;
|
||
height: 24px;
|
||
}
|
||
ul {
|
||
list-style: disc;
|
||
padding-left: 18px;
|
||
line-height: 22px;
|
||
}
|
||
}
|
||
</style>
|