2025-03-15 12:37:16 +08:00
|
|
|
<template>
|
|
|
|
|
<div class="flex align-center justify-start">
|
2025-03-18 17:37:09 +08:00
|
|
|
<d-search icon-position="left" style="width: 380px" placeholder="请输入搜索软件名称"></d-search>
|
|
|
|
|
<d-checkbox class="ml-10" label="只显示有漏洞的软件" :isShowTitle="false" v-model="checked" />
|
2025-03-15 12:37:16 +08:00
|
|
|
</div>
|
|
|
|
|
<Card simple class="jyh-card mt-3">
|
|
|
|
|
<div class="clear-padding">
|
2025-03-21 12:11:57 +08:00
|
|
|
<d-table
|
|
|
|
|
class="jyh-table"
|
|
|
|
|
v-if="tableData.length > 0"
|
|
|
|
|
:indent="32"
|
|
|
|
|
@check-change="treeCheckChange"
|
|
|
|
|
:data="tableData"
|
|
|
|
|
row-key="id"
|
|
|
|
|
>
|
2025-03-21 09:49:58 +08:00
|
|
|
<d-column field="libraryName" header="组件名称" show-overflow-tooltip>
|
2025-03-15 17:33:05 +08:00
|
|
|
<template #default="scope">
|
2025-03-21 02:21:14 +08:00
|
|
|
<a class="devui-link" @click="setSelectRow(scope.row)">{{ scope.row.libraryName }}</a>
|
2025-03-15 17:33:05 +08:00
|
|
|
</template>
|
|
|
|
|
</d-column>
|
2025-03-19 21:47:34 +08:00
|
|
|
<d-column field="latestVersion" header="版本"></d-column>
|
2025-03-15 12:37:16 +08:00
|
|
|
</d-table>
|
2025-03-19 19:07:42 +08:00
|
|
|
<NoData v-else :small="false"></NoData>
|
2025-03-15 12:37:16 +08:00
|
|
|
</div>
|
|
|
|
|
</Card>
|
2025-03-15 17:33:05 +08:00
|
|
|
<d-drawer v-model="showDetail" style="width: 800px; padding: 20px">
|
2025-03-19 21:47:34 +08:00
|
|
|
<SBOMDetail :selectRow="selectRow" @close="showDetail = false" />
|
2025-03-15 17:33:05 +08:00
|
|
|
</d-drawer>
|
2025-03-15 12:37:16 +08:00
|
|
|
</template>
|
|
|
|
|
<script setup lang="ts">
|
2025-03-19 21:47:34 +08:00
|
|
|
import { ref, reactive, onMounted, defineProps } from 'vue';
|
2025-03-15 17:33:05 +08:00
|
|
|
import SBOMDetail from './SBOMDetail.vue';
|
2025-03-19 19:07:42 +08:00
|
|
|
import NoData from '@/components/NoData/NoData.vue';
|
2025-03-19 21:47:34 +08:00
|
|
|
import { dependencyTree, getVulnList } from '@/api/jyh';
|
2025-03-19 13:04:13 +08:00
|
|
|
import { useRoute } from 'vue-router';
|
2025-03-19 21:47:34 +08:00
|
|
|
const propsData = defineProps(['versionId']);
|
2025-03-15 12:37:16 +08:00
|
|
|
const checked = ref(false);
|
2025-03-19 13:04:13 +08:00
|
|
|
const route = useRoute(); // 获取路由对象
|
2025-03-15 17:33:05 +08:00
|
|
|
const showDetail = ref(false);
|
2025-03-21 02:21:14 +08:00
|
|
|
const selectRow = ref({});
|
2025-03-15 12:37:16 +08:00
|
|
|
|
2025-03-19 21:47:34 +08:00
|
|
|
const tableData = ref([]);
|
|
|
|
|
|
2025-03-21 02:21:14 +08:00
|
|
|
const setSelectRow = (row) => {
|
|
|
|
|
selectRow.value = row;
|
|
|
|
|
showDetail.value = true;
|
2025-03-21 12:11:57 +08:00
|
|
|
};
|
2025-03-21 02:21:14 +08:00
|
|
|
|
2025-03-19 21:47:34 +08:00
|
|
|
const renameComponentsToChildren = (obj) => {
|
|
|
|
|
// 如果传入的不是对象,直接返回
|
|
|
|
|
if (typeof obj !== 'object' || obj === null) {
|
|
|
|
|
return obj;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果对象有 `components` 属性,将其改为 `children`
|
2025-03-21 02:21:14 +08:00
|
|
|
if (obj.hasOwnProperty('component')) {
|
2025-03-24 18:16:52 +08:00
|
|
|
// 生成随机 UUID 并赋值给 id
|
|
|
|
|
obj.id = crypto.randomUUID(); // 使用浏览器/Node.js 原生 API
|
|
|
|
|
// obj.id = obj.component.id; // 将 components 改为 children
|
2025-03-21 02:21:14 +08:00
|
|
|
obj.libraryName = obj.component.libraryName; // 将 components 改为 children
|
|
|
|
|
obj.latestVersion = obj.component.latestVersion; // 将 components 改为 children
|
|
|
|
|
// delete obj.components; // 删除原来的 components 属性
|
2025-03-19 21:47:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 递归处理对象的子元素
|
|
|
|
|
for (let key in obj) {
|
|
|
|
|
if (obj.hasOwnProperty(key)) {
|
|
|
|
|
obj[key] = renameComponentsToChildren(obj[key]); // 递归处理子对象
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return obj;
|
2025-03-21 12:11:57 +08:00
|
|
|
};
|
2025-03-19 21:47:34 +08:00
|
|
|
|
2025-03-15 12:37:16 +08:00
|
|
|
const treeCheckChange = (val, row, selection) => {
|
|
|
|
|
console.log('treeCheckChange', selection);
|
|
|
|
|
};
|
2025-03-19 13:04:13 +08:00
|
|
|
|
2025-03-19 21:47:34 +08:00
|
|
|
const fetchDependencyTree = async () => {
|
|
|
|
|
const { data } = await dependencyTree({
|
|
|
|
|
// softwareId: 47,
|
|
|
|
|
softwareId: propsData.versionId,
|
|
|
|
|
componentId: '',
|
|
|
|
|
current: 1,
|
|
|
|
|
size: 10
|
|
|
|
|
});
|
2025-03-21 12:11:57 +08:00
|
|
|
if (data.data.code === 200 && data?.data?.data?.components) {
|
2025-03-21 02:21:14 +08:00
|
|
|
tableData.value = renameComponentsToChildren(data?.data?.data?.components);
|
2025-03-19 21:47:34 +08:00
|
|
|
// pager.value.total = data?.data?.data?.total || [];
|
|
|
|
|
} else {
|
|
|
|
|
// tableData.value = baseTreeTableData1.value
|
|
|
|
|
}
|
2025-03-21 12:11:57 +08:00
|
|
|
};
|
2025-03-19 21:47:34 +08:00
|
|
|
|
2025-03-21 12:11:57 +08:00
|
|
|
onMounted(() => {
|
|
|
|
|
fetchDependencyTree();
|
2025-03-19 13:04:13 +08:00
|
|
|
});
|
2025-03-15 12:37:16 +08:00
|
|
|
</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>
|