可信代码库-软件详情数据修改

This commit is contained in:
付民康
2025-04-22 14:52:34 +08:00
parent bdedb15589
commit 898f353bde
7 changed files with 371 additions and 66 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 689 B

View File

@@ -0,0 +1,102 @@
<template>
<d-row class="mt-3" v-if="inited">
<d-col :span="12">
<d-chart :option="optionConChart" style="width: 100%; height: 400px"></d-chart>
<p class="text-center mt-translate-y">国家/地球分布</p>
</d-col>
<d-col :span="12">
<d-chart :option="optionOrgChart" style="width: 100%; height: 400px"></d-chart>
<p class="text-center mt-translate-y">组织/公司分布</p>
</d-col>
</d-row>
</template>
<script setup lang="ts">
import { ref, reactive, computed } from 'vue';
import { DChart } from 'vue-devui/echarts';
const inited = ref(false);
const props = withDefaults(
defineProps<{
companyGraph: Array<any>;
countryGraph: Array<any>;
}>(),
{
companyGraph: () => [],
countryGraph: () => []
}
);
const options = (x: any, y: any, color = '#2070F3') => {
return {
tooltip: {
show: true,
trigger: 'item'
},
xAxis: {
type: 'category',
data: x,
axisLabel: {
interval: 0, // 强制显示所有标签
// rotate: 45, // 如果标签过长,可以旋转标签
fontSize: 12 // 调整字体大小
}
},
yAxis: {
// 给y轴添加单位后缀
axisLabel: {
formatter: '{value}%'
},
name: '单位',
type: 'value'
},
series: [
{
data: y,
type: 'bar',
barWidth: '30',
// 给label添加单位后缀
label: {
show: true,
position: 'top',
formatter: '{c}%'
},
itemStyle: {
color,
borderRadius: [5, 5, 0, 0]
}
}
]
};
};
const optionConChart = computed(() => {
return options(
props.countryGraph.map((d) => d.name),
props.countryGraph.map((d) => d.value),
'#2070F3'
);
});
const optionOrgChart = computed(() => {
return options(
props.companyGraph.map((d) => d.name),
props.companyGraph.map((d) => d.value),
'#2CB8C9'
);
});
const onInited = () => {
setTimeout(() => {
inited.value = true;
}, 100);
};
// 向外暴露onInited方法
defineExpose({ onInited });
</script>
<style scoped lang="scss">
.mt-translate-y {
transform: translateY(-30px);
}
</style>

View File

@@ -156,7 +156,7 @@ const fetchVulnList = async () => {
});
if (data.data.code === 200) {
tableData.value = data?.data?.data?.components || [];
tableData.value = data?.data?.data?.records || [];
pager.value.total = data?.data?.data?.total || 0;
// pager.value.total = data?.data?.data?.total || [];
}

View File

@@ -134,6 +134,9 @@
<template v-else-if="column.key === 'programmingLanguage'">
<d-tag type="success">{{ scope.row.programmingLanguage }}</d-tag>
</template>
<template v-else-if="column.key === 'primaryLanguage'">
<d-tag type="primary">{{ scope.row.primaryLanguage }}</d-tag>
</template>
<template v-else-if="column.key === 'contributorCountries'">
<!-- <div style="cursor: pointer" @click="openCountryModal(column)">-->
<!-- <span class="mr-2">美国 3.57%</span>-->
@@ -282,7 +285,7 @@ const defultColumns = ref([
{ key: 'softwareName', label: '软件名称', visible: true, filterable: true, sortable: false },
{ key: 'softwareVersion', label: '软件版本', visible: true, filterable: true, sortable: false },
{ key: 'securityScore', label: '软件评分', visible: true, filterable: false, sortable: true },
{ key: 'licenseNum', label: 'License数量', visible: true, filterable: false, sortable: false,width: 140 },
// { key: 'licenseNum', label: 'License数量', visible: true, filterable: false, sortable: false,width: 140 },
{ key: 'industryCategory', label: '行业类型', visible: true, filterable: true, sortable: false },
{ key: 'primaryLanguage', label: '编程语言', visible: true, filterable: true, sortable: false },
{ key: 'codeLines', label: '代码量', visible: true, filterable: false, sortable: false },
@@ -312,7 +315,7 @@ const columns = ref([
{ key: 'softwareName', label: '软件名称', visible: true, filterable: true, sortable: false },
{ key: 'softwareVersion', label: '软件版本', visible: true, filterable: true, sortable: false },
{ key: 'securityScore', label: '软件评分', visible: true, filterable: false, sortable: true },
{ key: 'licenseNum', label: 'License数量', visible: true, filterable: false, sortable: false,width: 140 },
// { key: 'licenseNum', label: 'License数量', visible: true, filterable: false, sortable: false,width: 140 },
{ key: 'industryCategory', label: '行业类型', visible: true, filterable: true, sortable: false },
{ key: 'primaryLanguage', label: '编程语言', visible: true, filterable: true, sortable: false },
{ key: 'codeLines', label: '代码量', visible: true, filterable: false, sortable: false },

View File

@@ -1,55 +1,118 @@
<template>
<div class="version-info">
<Card simple class="jyh-card mb-4">
<div class="card-title">基本信息</div>
<div class="card-title">
<d-tooltip position="left" content="此内容由AI辅助生成">
<img
style="width: 14px; height: 14px;display: inline-block"
src="@/assets/imgs/jyh/aiLogo.png"
/>
</d-tooltip>
基本信息
<!-- <span style="color: #3b82f6;font-size: 12px;font-weight: normal">(该数据由AI生成)</span>-->
</div>
<d-row class="mb-3">
<d-col :span="8">
<d-tooltip position="left" content="此内容由AI辅助生成">
<img
style="width: 14px; height: 14px;display: inline-block"
src="@/assets/imgs/jyh/aiLogo.png"
/>
</d-tooltip>
<span class="card-key width-90">社区名称</span>
<span class="card-val">{{ infos.communityName }}</span>
<span class="card-val">{{propsData.ReleaseInfo?.basicInfo?.communityName || propsData.ReleaseInfo?.criticalSoftwareAIGenerateInfo?.communityName || '--'}}</span>
</d-col>
<d-col :span="8">
<d-tooltip position="left" content="此内容由AI辅助生成">
<img
style="width: 14px; height: 14px;display: inline-block"
src="@/assets/imgs/jyh/aiLogo.png"
/>
</d-tooltip>
<span class="card-key width-90">官网地址</span>
<a :href="infos.communityWebsite" class="card-url">{{ infos.communityWebsite }}</a>
<a :href="propsData.ReleaseInfo?.basicInfo?.communityWebsite || propsData.ReleaseInfo?.criticalSoftwareAIGenerateInfo?.communityName" class="card-url">{{
propsData.ReleaseInfo?.basicInfo?.communityWebsite || propsData.ReleaseInfo?.criticalSoftwareAIGenerateInfo?.communityName ||'--' }}</a>
</d-col>
<d-col :span="8">
<d-tooltip position="left" content="此内容由AI辅助生成">
<img
style="width: 14px; height: 14px;display: inline-block"
src="@/assets/imgs/jyh/aiLogo.png"
/>
</d-tooltip>
<span class="card-key width-90">联系方式</span>
<span class="card-val">{{ infos.communityContact }}</span>
<span class="card-val">{{
propsData.ReleaseInfo?.basicInfo?.communityContact || propsData.ReleaseInfo?.criticalSoftwareAIGenerateInfo?.communityContact ||'--' }}</span>
</d-col>
</d-row>
<d-row class="mb-3">
<d-col :span="24">
<div class="flex">
<d-tooltip position="left" content="此内容由AI辅助生成">
<img
style="width: 14px; height: 14px;display: inline-block"
src="@/assets/imgs/jyh/aiLogo.png"
/>
</d-tooltip>
<span class="card-key width-90 flex-shrink-0">社区描述</span>
<span class="card-val flex-grow-1">{{ infos.communityDescription }}</span>
<span class="card-val flex-grow-1">{{
propsData.ReleaseInfo?.basicInfo?.communityDescription || propsData.ReleaseInfo?.criticalSoftwareAIGenerateInfo?.communityDescription ||'--' }}</span>
</div>
</d-col>
</d-row>
</Card>
<Card simple class="jyh-card mb-4">
<div class="card-title">贡献者分布</div>
<div class="card-title">
<d-tooltip position="left" content="此内容由AI辅助生成">
<img
style="width: 14px; height: 14px;display: inline-block"
src="@/assets/imgs/jyh/aiLogo.png"
/>
</d-tooltip>
贡献者分布
</div>
<p class="card-desc">有关Pull Request创建者的公司信息和地区分布(使用公共GitHub信息进行分析)</p>
<div class="mt-3">
<chart-line ref="chartLine" :companyGraph="infos.companyGraph" :countryGraph="infos.countryGraph" />
<chart-bar ref="chartBarRef" :companyGraph="companyGraph" :countryGraph="countryGraph" />
</div>
</Card>
</div>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue';
import SBOMDetail from './SBOMDetail.vue';
import { communityInfo } from '@/api/jyh';
import { useRoute } from 'vue-router';
import ChartLine from '@/components/ChartLine/index.vue';
<script setup lang="ts">
import ChartBar from '@/components/ChartBar/index.vue';
import { computed, defineProps, onMounted, ref } from 'vue';
const route = useRoute(); // 获取路由对象
const propsData = defineProps(['versionId','ReleaseInfo']);
const chartLine = ref();
const infos = ref({});
onMounted(async () => {
const { data } = await communityInfo(Number(route.params.versionId));
infos.value = data?.data?.data || {};
chartLine.value.onInited();
const chartBarRef = ref();
const countryGraph = computed(() => {
if(propsData.ReleaseInfo.criticalSoftwareAIGenerateInfo&&propsData.ReleaseInfo.criticalSoftwareAIGenerateInfo.contributorCountries) {
let countriesObj = JSON.parse(propsData.ReleaseInfo.criticalSoftwareAIGenerateInfo.contributorCountries);
return Object.entries(countriesObj).map(([name, value]) => ({
name,
value
}));
} else {
return []
}
});
const companyGraph = computed(() => {
if(propsData.ReleaseInfo.criticalSoftwareAIGenerateInfo&&propsData.ReleaseInfo.criticalSoftwareAIGenerateInfo.organizationDistribution) {
let countriesObj = JSON.parse(propsData.ReleaseInfo.criticalSoftwareAIGenerateInfo.organizationDistribution);
return Object.entries(countriesObj).map(([name, value]) => ({
name,
value
}));
} else {
return []
}
});
onMounted(() => {
chartBarRef.value.onInited();
});
</script>

View File

@@ -54,9 +54,15 @@
</d-row>
<d-row class="mb-3">
<d-col :span="8">
<d-tooltip position="left" content="此内容由AI辅助生成">
<img
style="width: 14px; height: 14px;display: inline-block"
src="@/assets/imgs/jyh/aiLogo.png"
/>
</d-tooltip>
<span class="card-key width-110">社区EOL日期</span>
<span class="card-val">
{{ ReleaseInfo.referenceInfo.communityEolDate?dayjs(ReleaseInfo.referenceInfo.communityEolDate).format('YYYY-MM-DD') :'--' }}</span>
{{ ReleaseInfo.criticalSoftwareAIGenerateInfo.communityEolDate?dayjs(ReleaseInfo.criticalSoftwareAIGenerateInfo.communityEolDate).format('YYYY-MM-DD') :'--' }}</span>
</d-col>
<d-col :span="8">
<span class="card-key width-110">所属领域/产业</span>
@@ -79,18 +85,29 @@
<a class="card-url" :href="ReleaseInfo.referenceInfo.sourceCodeCommunityUrl || '--'">{{ ReleaseInfo.referenceInfo.sourceCodeCommunityUrl || ReleaseInfo.basicInfo.communityWebsite || '--' }}</a>
</d-col>
</d-row>
<d-row>
<d-col :span="24">
<span class="card-key width-140">社区EOL披露地址</span>
<a class="card-url" :href="ReleaseInfo.referenceInfo.communityEolDisclosureUrl || '--'">{{ ReleaseInfo.referenceInfo.communityEolDisclosureUrl || ReleaseInfo.basicInfo.eolNoticeUrl || '--' }}</a>
</d-col>
</d-row>
<!-- <d-row>-->
<!-- <d-col :span="24">-->
<!-- <span class="card-key width-140">社区EOL披露地址</span>-->
<!-- <a class="card-url" :href="ReleaseInfo.referenceInfo.communityEolDisclosureUrl || '&#45;&#45;'">{{ ReleaseInfo.referenceInfo.communityEolDisclosureUrl || ReleaseInfo.basicInfo.eolNoticeUrl || '&#45;&#45;' }}</a>-->
<!-- </d-col>-->
<!-- </d-row>-->
</Card>
<Card simple class="jyh-card mb-4">
<div class="card-title">开源主License信息</div>
<div class="card-title">
<d-tooltip position="left" content="此内容由AI辅助生成">
<img
style="width: 14px; height: 14px;display: inline-block"
src="@/assets/imgs/jyh/aiLogo.png"
/>
</d-tooltip>
开源主License信息</div>
<div class="mb-3">
<d-table class="jyh-table jyh-table-2" :header-bg="true" :data="ReleaseInfo.openSourceLicenseList">
<d-table class="jyh-table jyh-table-2" :header-bg="true"
:data="[
{ name: ReleaseInfo.basicInfo.mainLicenseName || ReleaseInfo.criticalSoftwareAIGenerateInfo.mainLicenseName,
description: ReleaseInfo.basicInfo.mainLicenseDescription || ReleaseInfo.criticalSoftwareAIGenerateInfo.mainLicenseDescription}
]">
<d-column type="index" header="序号" width="80"></d-column>
<!-- <d-column field="id" header="编号"></d-column>-->
<d-column field="name" header="名称"></d-column>
@@ -106,21 +123,29 @@
<!-- </d-row>-->
</Card>
<Card simple class="jyh-card mb-4">
<div class="card-title">Copyright报告</div>
<div class="card-title">
<d-tooltip position="left" content="此内容由AI辅助生成">
<img
style="width: 14px; height: 14px;display: inline-block"
src="@/assets/imgs/jyh/aiLogo.png"
/>
</d-tooltip>
Copyright报告</div>
<div class="mb-3">
<d-table
class="jyh-table jyh-table-2"
:header-bg="true"
:data="[
{
reportName: 'Copyright (c) Isaac Z. Schlueter and Contributors',
entryTime: '2025-03-20'
reportName: ReleaseInfo.basicInfo.copyrightReportName || ReleaseInfo.criticalSoftwareAIGenerateInfo.copyrightReportName,
reportUrl: ReleaseInfo.basicInfo.copyrightReportUrl || ReleaseInfo.criticalSoftwareAIGenerateInfo.copyrightReportUrl,
entryTime: ReleaseInfo.basicInfo.copyrightEntryTime || ReleaseInfo.criticalSoftwareAIGenerateInfo.copyrightEntryTime
}
]"
>
<d-column field="reportName" header="Copyright报告">
<template #default="scope">
{{ scope.row.reportName }}
<a :href="scope.row.reportUrl">{{ scope.row.reportName }}</a>
</template>
</d-column>
<d-column field="entryTime" header="录入时间"></d-column>
@@ -140,27 +165,119 @@
<d-table
class="jyh-table jyh-table-2"
:header-bg="true"
:data="[
{
type: '二进制包',
entityPackageDownloadUrl: 'https://raw.gitcode.com/file/inherits/inherits.tar',
fileName: 'inherits.tar',
entryTime: '2025-03-20'
}
]"
:data="ReleaseInfo.entityInfoList"
>
<d-column field="type" header="类型"></d-column>
<d-column field="entityPackageDownloadUrl" header="实体包下载地址">
<d-column field="entityType" header="类型"></d-column>
<d-column field="entityDownloadUrl" header="实体包下载地址">
<template #default="scope">
<a class="card-url" :href="scope.row.entityPackageDownloadUrl || '--'">{{ scope.row.entityPackageDownloadUrl || '--' }}</a>
<a :href="scope.row.entityDownloadUrl" target="_blank">{{ scope.row.entityDownloadUrl }}</a>
</template>
</d-column>
<d-column field="fileName" header="文件名称"></d-column>
<d-column field="entityFilename" header="文件名称"></d-column>
<d-column field="entryTime" header="录入时间"></d-column>
<d-column field="integrityCheckResult" header="完整性结果">
<template #default="scope">
<a @click="visible = true">{{ scope.row.integrityCheckResult }}</a>
</template>
</d-column>
</d-table>
</div>
</Card>
<Card simple class="jyh-card mb-4">
<div class="card-title">
<d-tooltip position="left" content="此内容由AI辅助生成">
<img
style="width: 14px; height: 14px;display: inline-block"
src="@/assets/imgs/jyh/aiLogo.png"
/>
</d-tooltip>
网络安全
<!-- <span style="color: #3b82f6;font-size: 12px;font-weight: normal">(该数据由AI生成)</span>-->
</div>
<!-- <d-row class="mb-3">-->
<!-- <d-col :span="24">-->
<!-- <span class="card-key width-160">软件评分</span>-->
<!-- <span class="card-val">{{ ReleaseInfo.networkSecurity.softwareRating || '&#45;&#45;' }}</span>-->
<!-- </d-col>-->
<!-- </d-row>-->
<d-row class="mb-3">
<d-col :span="24">
<d-tooltip position="left" content="此内容由AI辅助生成">
<img
style="width: 14px; height: 14px;display: inline-block"
src="@/assets/imgs/jyh/aiLogo.png"
/>
</d-tooltip>
<span class="card-key width-160">社区安全问题求助</span>
<a class="card-url" :href="ReleaseInfo.basicInfo.securityHelpChannel || ReleaseInfo.criticalSoftwareAIGenerateInfo.securityHelpChannel || ''" target="_blank">{{
ReleaseInfo.basicInfo.securityHelpChannel || ReleaseInfo.criticalSoftwareAIGenerateInfo.securityHelpChannel || '--'
}}</a>
</d-col>
</d-row>
<div class="mb-3 flex">
<d-tooltip position="left" content="此内容由AI辅助生成">
<img
style="width: 14px; height: 14px;display: inline-block"
src="@/assets/imgs/jyh/aiLogo.png"
/>
</d-tooltip>
<span class="card-key width-160">官网漏洞披露地址</span>
<d-table style="display: contents" class="jyh-table jyh-table-2" :header-bg="true" :data="vulnDisclosureUrl">
<!-- <d-column field="id" header="编号"></d-column> -->
<d-column field="厂商" header="厂商"></d-column>
<d-column field="软件名称" header="软件名称"></d-column>
<!-- <d-column field="source" header="来源"></d-column> -->
<d-column field="软件地址" header="来源url"> </d-column>
</d-table>
</div>
<div class="mb-3 flex">
<d-tooltip position="left" content="此内容由AI辅助生成">
<img
style="width: 14px; height: 14px;display: inline-block"
src="@/assets/imgs/jyh/aiLogo.png"
/>
</d-tooltip>
<span class="card-key width-160">外部漏洞源的软件名称</span>
<d-table
style="display: contents"
class="jyh-table jyh-table-2"
:header-bg="true"
:data="externalVulnSourceInfo"
>
<!-- <d-column field="id" header="编号"></d-column> -->
<d-column field="厂商" header="厂商"></d-column>
<d-column field="软件名称" header="软件名称"></d-column>
<!-- <d-column field="source" header="来源"></d-column> -->
<d-column field="软件地址" header="来源url"> </d-column>
</d-table>
</div>
<d-row class="mb-3">
<d-col :span="24">
<d-tooltip position="left" content="此内容由AI辅助生成">
<img
style="width: 14px; height: 14px;display: inline-block"
src="@/assets/imgs/jyh/aiLogo.png"
/>
</d-tooltip>
<span class="card-key width-160">是否涉及用户登录</span>
<span class="card-val">{{ securityInfoList.involvesUserLogin ? '是' : '否' }}</span>
</d-col>
</d-row>
<d-row>
<d-col :span="24">
<d-tooltip position="left" content="此内容由AI辅助生成">
<img
style="width: 14px; height: 14px;display: inline-block"
src="@/assets/imgs/jyh/aiLogo.png"
/>
</d-tooltip>
<span class="card-key width-160">是否安卓类APP组件</span>
<span class="card-val">{{ securityInfoList.isAndroidComponent ? '是' : '否' }}</span>
</d-col>
</d-row>
</Card>
<d-modal
title="完整性结果详情"
v-model="visible"
@@ -226,7 +343,7 @@
</template>
<script setup lang="ts">
import { ref, defineEmits, onMounted, reactive } from 'vue';
import { ref, defineEmits, onMounted, reactive,computed,defineProps,toRef } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { discussDetailType, userInfoType } from '@/api/discussion/types';
import { Message } from 'vue-devui/message';
@@ -236,23 +353,15 @@ import { useGlobalInfoStore } from '@/stores/Global';
import dayjs from 'dayjs';
const route = useRoute();
const emits = defineEmits(['changeTabs']);
const props = defineProps(['ReleaseInfo']);
// 触发事件的方法
const handleTabChange = (tabName) => {
emits('changeTabs', tabName); // 触发 changeTabs 事件,并传递参数
};
const jcfxList = ['','低','中','高'];
const licenseTableData = ref([{ code: '05822156', name: 'MIT License', detail: 'integer' }]);
const CopyrightTableData = ref([{ code: '05822156', detail: 'integer' }]);
const visible = ref(false);
const ReleaseInfo = ref({
basicInfo: {},
copyRightReportList: [],
entityList: [],
networkSecurity: {},
openSourceLicenseList: [],
referenceInfo: {}
});
// 将 props.ReleaseInfo 转换为响应式引用
const ReleaseInfo = toRef(props, 'ReleaseInfo');
const globalInfo = useGlobalInfoStore();
const industryList = ref(globalInfo.industryList);
const getIndustryName = (value) => {
@@ -260,6 +369,34 @@ const getIndustryName = (value) => {
return industry ? industry.name : '未知行业'; // 如果找不到,返回默认值
};
const securityInfoList = computed(() => {
if(ReleaseInfo.value.securityInfoList&&ReleaseInfo.value.securityInfoList.length>0) {
return ReleaseInfo.value.securityInfoList[0]
} else if(ReleaseInfo.value.softwareSecurityAIGenerateInfo&&ReleaseInfo.value.softwareSecurityAIGenerateInfo.length>0) {
return ReleaseInfo.value.softwareSecurityAIGenerateInfo[0]
} else {
return {}
}
});
const vulnDisclosureUrl = computed(() => {
if(ReleaseInfo.value.softwareSecurityAIGenerateInfo) {
debugger
const _vulnDisclosureUrl: any = JSON.parse(ReleaseInfo?.value.softwareSecurityAIGenerateInfo[0]?.vulnDisclosureUrl || '[]');
return _vulnDisclosureUrl || [];
} else {
return []
}
});
const externalVulnSourceInfo = computed(() => {
if(props.ReleaseInfo) {
const _vulnDisclosureUrl: any = JSON.parse(props.ReleaseInfo?.softwareSecurityAIGenerateInfo[0]?.externalVulnSourceInfo || '[]');
return _vulnDisclosureUrl || [];
} else {
return []
}
});
const router = useRouter();
// 跳转
@@ -292,10 +429,10 @@ const getReleaseInfo = async (versionId) => {
};
onMounted(() => {
const versionId = route.params.versionId; // 获取路由参数 versionId
if (versionId) {
getReleaseInfo(versionId); // 调用接口获取数据
}
// const versionId = route.params.versionId; // 获取路由参数 versionId
// if (versionId) {
// getReleaseInfo(versionId); // 调用接口获取数据
// }
});
</script>

View File

@@ -55,9 +55,9 @@
</d-tabs>
</div>
<div class="version-detail-content">
<version-info :versionId="versionId" v-if="selectTab === 'bbxx'" @changeTabs="changeTabs"></version-info>
<version-info :ReleaseInfo="ReleaseInfo" v-if="selectTab === 'bbxx'" @changeTabs="changeTabs"></version-info>
<vulnerabilities-list :versionId="versionId" v-else-if="selectTab === 'ldxx'"></vulnerabilities-list>
<community-info :versionId="versionId" v-else-if="selectTab === 'communityInfo'"></community-info>
<community-info :versionId="versionId" :ReleaseInfo="ReleaseInfo" v-else-if="selectTab === 'communityInfo'"></community-info>
<Dependence :versionId="versionId" v-else-if="selectTab === 'ylgx'"></Dependence>
<SBOM :versionId="versionId" v-else-if="selectTab === 'SBOM'" />
<AIRepair :versionId="versionId" v-else-if="selectTab === 'ai'"></AIRepair>