Files
Situation-Awareness-Platfor…/src/views/Jyh/Version/Detail/SBOM.vue
2025-06-18 17:38:37 +08:00

163 lines
4.8 KiB
Vue

<template>
<div class="flex align-center justify-start">
<d-search icon-position="left" style="width: 380px" placeholder="请输入搜索软件名称" v-model="searchText" @change="handleSearch"></d-search>
<d-checkbox class="ml-10" label="只显示有漏洞的软件" :isShowTitle="false" v-model="checked" />
</div>
<Card simple class="jyh-card mt-3">
<div class="clear-padding">
<d-table
class="jyh-table"
v-if="filteredTableData.length > 0"
:indent="32"
@check-change="treeCheckChange"
:data="filteredTableData"
row-key="id"
>
<d-column field="libraryName" header="组件名称" show-overflow-tooltip>
<template #default="scope">
<a class="devui-link" @click="setSelectRow(scope.row)">{{ scope.row.libraryName }}</a>
</template>
</d-column>
<d-column field="latestVersion" header="版本"></d-column>
</d-table>
<NoData v-else :small="false"></NoData>
</div>
<!-- 分页组件 -->
<div class="mt-8 flex justify-end">
<d-pagination
v-if="pager.total > 0"
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="fetchDependencyTree"
@page-size-change="fetchDependencyTree"
/>
</div>
</Card>
<d-drawer v-model="showDetail" style="width: 800px; padding: 20px">
<SBOMDetail :selectRow="selectRow" @close="showDetail = false" />
</d-drawer>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted, defineProps, computed } from 'vue';
import SBOMDetail from './SBOMDetail.vue';
import NoData from '@/components/NoData/NoData.vue';
import { dependencyTree, getVulnList } from '@/api/jyh';
import { useRoute } from 'vue-router';
const propsData = defineProps(['versionId']);
const checked = ref(false);
const route = useRoute(); // 获取路由对象
const showDetail = ref(false);
const selectRow = ref({});
const tableData = ref([]);
const searchText = ref(''); // 搜索关键词
// 分页状态
const pager = ref({
total: 0,
pageIndex: 1,
pageSize: 10
});
const setSelectRow = (row) => {
selectRow.value = row;
showDetail.value = true;
};
const filteredTableData = computed(() => {
if (!searchText.value) return tableData.value; // 无关键词时返回全部数据
return tableData.value.filter(item =>
item.libraryName.toLowerCase().includes(searchText.value.toLowerCase())
);
});
function generateUUID() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
const r = Math.random() * 16 | 0;
const v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
const renameComponentsToChildren = (obj) => {
// 如果传入的不是对象,直接返回
if (typeof obj !== 'object' || obj === null) {
return obj;
}
// 如果对象有 `components` 属性,将其改为 `children`
if (obj.hasOwnProperty('component')) {
// 生成随机 UUID 并赋值给 id
obj.id = generateUUID(); // 使用浏览器/Node.js 原生 API
// obj.id = obj.component.id; // 将 components 改为 children
obj.libraryName = obj.component.libraryName; // 将 components 改为 children
obj.latestVersion = obj.component.latestVersion; // 将 components 改为 children
// delete obj.components; // 删除原来的 components 属性
}
// 递归处理对象的子元素
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
obj[key] = renameComponentsToChildren(obj[key]); // 递归处理子对象
}
}
return obj;
};
const treeCheckChange = (val, row, selection) => {
console.log('treeCheckChange', selection);
};
const fetchDependencyTree = async () => {
const { data } = await dependencyTree({
// softwareId: 47,
softwareId: propsData.versionId,
componentId: '',
current: pager.value.pageIndex,
size: pager.value.pageSize
});
if (data.data.code === 200 && data?.data?.data?.components) {
tableData.value = renameComponentsToChildren(data?.data?.data?.components);
pager.value.total = data?.data.data.total || 0;
// pager.value.total = data?.data?.data?.total || [];
} else {
// tableData.value = baseTreeTableData1.value
}
};
// 搜索处理
const handleSearch = () => {
pager.value.pageIndex = 1; // 搜索后重置到第一页
fetchDependencyTree();
};
onMounted(() => {
fetchDependencyTree();
});
</script>
<style scoped lang="scss">
.clear-padding {
margin: -16px -20px;
}
:deep(.devui-table__cell) {
display: flex;
align-items: center;
.devui-table__tree-operate {
transform: translateY(-3px);
}
}
</style>