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

297 lines
8.8 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="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 || '&#45;&#45;' }}</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">{{'&#45;&#45;'}}</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>