可信代码库-代码质量检测接口对接

This commit is contained in:
付民康
2025-06-27 14:15:26 +08:00
parent c1f7cb9025
commit f664d855bf
4 changed files with 167 additions and 68 deletions

View File

@@ -452,3 +452,35 @@ export function fetchUpdateRecommendQuestions(data) {
data: data, data: data,
}); });
} }
export function qualityTaskOverview(data) {
const {softwareId} = data;
return axios.request({
url: `/gateway/quality/task-overview/software` + `/${softwareId}`,
method: 'GET',
// headers: {
// Authorization: 'Bearer ' + localStorage.getItem('access_token'),
// }
});
}
export function qualityDefectPage(data) {
const {pageNum,pageSize,softwareId} = data;
return axios.request({
url: `/gateway/quality/defect/page` + `?pageNum=${pageNum}&pageSize=${pageSize}&softwareId=${softwareId}`,
method: 'GET',
// headers: {
// Authorization: 'Bearer ' + localStorage.getItem('access_token'),
// }
});
}
export function loginAccess() {
return axios.request({
url: `/gateway/u-auth/login-access`,
method: 'POST',
data: {},
headers: {
Authorization: 'Bearer ' + localStorage.getItem('access_token'),
}
});
}

View File

@@ -446,7 +446,7 @@ const getQuestionHistory = async () => {
// Message.error(data.error||'接口异常!') // Message.error(data.error||'接口异常!')
} }
} else { } else {
Message.error('请先登录!') // Message.error('请先登录!')
} }
}; };
const getQuestionCollection = async () => { const getQuestionCollection = async () => {
@@ -473,7 +473,7 @@ const getQuestionCollection = async () => {
// Message.error(data.error||'接口异常!') // Message.error(data.error||'接口异常!')
} }
} else { } else {
Message.error('请先登录!') // Message.error('请先登录!')
} }
}; };

View File

@@ -1,6 +1,6 @@
<template> <template>
<div> <div class="code">
<pre class="pre-code"><code :data-ln-start-from="1"> <pre class="pre-code"><code :class="[codeIndex]" :data-ln-start-from="lineNumber">
<span v-html="renderCode(fixed_code)"></span> <span v-html="renderCode(fixed_code)"></span>
</code></pre> </code></pre>
</div> </div>
@@ -11,16 +11,24 @@
import hljs from 'highlight.js'; import hljs from 'highlight.js';
import 'highlight.js/styles/rainbow.css'; // 引入样式 import 'highlight.js/styles/rainbow.css'; // 引入样式
import {lineNumbersBlock} from "@/utils/highlightjs-line-numbers"; import {lineNumbersBlock} from "@/utils/highlightjs-line-numbers";
import { onMounted, defineProps, nextTick,watch } from 'vue';
const fixed_code = '/*' const props = defineProps(['lineNumber','content'])
const codeIndex = `code${props.content.id}`
const fixed_code = props.content.defectContent + '\t\t'
debugger
const lineNumber = props.content.lineNumber? props.content.lineNumber -1 : 0
const renderCode = (code, num = 1) => { const renderCode = (code, num = 1) => {
return hljs.highlightAuto(code).value; return hljs.highlightAuto(code).value;
}; };
// 显示代码行数 // 显示代码行数
const updateLineNumbers = () => { const updateLineNumbers = () => {
debugger
// 搜索pre、code元素进行高亮和行号添加 // 搜索pre、code元素进行高亮和行号添加
let blocks = document.querySelectorAll('pre code'); let blocks = document.querySelectorAll('.' + codeIndex);
console.log(blocks) console.log(blocks)
blocks.forEach((block) => { blocks.forEach((block) => {
//高亮 //高亮
@@ -30,6 +38,21 @@ const updateLineNumbers = () => {
}) })
} }
watch(() => props.content, (newVal) => {
if (newVal && newVal.id) {
nextTick(updateLineNumbers);
}
}, { immediate: true, deep: true });
onMounted(() => {
nextTick(() => {
updateLineNumbers()
})
});
</script> </script>

View File

@@ -1,32 +1,32 @@
<template> <template>
<Card simple class="jyh-card mb-4"> <Card simple class="jyh-card mb-4">
<d-row class="mb-3"> <d-row class="mb-3">
<d-col :span="8"> <d-col :span="16">
<span class="card-key width-140">问题数<d-icon style="color: grey" name="icon-info-o" size="12px" /> <span class="card-key width-140">问题数<d-icon style="color: grey; margin-left: 4px" name="icon-info-o" size="12px" />
</span> </span>
<span class="card-val">{{ ReleaseInfo?.basicInfo?.softwareName || '--' }}</span> <span class="card-val">{{ QualityTaskOverview?.issueCount || '--' }}</span>
</d-col> </d-col>
<d-col :span="8"> <d-col :span="16">
<span class="card-key width-140">未解决问题<d-icon style="color: grey; margin-left: 4px" name="icon-info-o" size="12px" /></span> <span class="card-key width-140">代码总行<d-icon style="color: grey; margin-left: 4px" name="icon-info-o" size="12px" /></span>
<span class="card-val">{{ ReleaseInfo?.basicInfo?.softwareVersion || '--' }}</span> <span class="card-val">{{ QualityTaskOverview?.codeLineTotal || '--' }}</span>
</d-col>
<d-col :span="8">
<span class="card-key width-140">已解决问题数<d-icon style="color: grey; margin-left: 4px" name="icon-info-o" size="12px" /></span>
<span class="card-val">{{ ReleaseInfo?.basicInfo?.mainLanguageType || '--' }}</span>
</d-col> </d-col>
<!-- <d-col :span="8">-->
<!-- <span class="card-key width-140">已忽略问题数<d-icon style="color: grey; margin-left: 4px" name="icon-info-o" size="12px" /></span>-->
<!-- <span class="card-val">{{ QualityTaskOverview?.dismissedCount || '&#45;&#45;' }}</span>-->
<!-- </d-col>-->
<!-- <d-col :span="8">-->
<!-- <span class="card-key width-140">已解决问题数<d-icon style="color: grey; margin-left: 4px" name="icon-info-o" size="12px" /></span>-->
<!-- <span class="card-val">{{ QualityTaskOverview?.solveCount || '&#45;&#45;' }}</span>-->
<!-- </d-col>-->
</d-row> </d-row>
<d-row> <d-row>
<d-col :span="8"> <d-col :span="16">
<span class="card-key width-140">代码平均复杂度<d-icon style="color: grey; margin-left: 4px" name="icon-info-o" size="12px" /></span>
<span class="card-val">{{ ReleaseInfo?.basicInfo?.developer || '--' }}</span>
</d-col>
<d-col :span="8">
<span class="card-key width-140">代码重复率<d-icon style="color: grey; margin-left: 4px" name="icon-info-o" size="12px" /></span> <span class="card-key width-140">代码重复率<d-icon style="color: grey; margin-left: 4px" name="icon-info-o" size="12px" /></span>
<span class="card-val">{{ ReleaseInfo?.basicInfo?.developer || '--' }}</span> <span class="card-val">{{ QualityTaskOverview?.duplicationRatio || '--' }}</span>
</d-col> </d-col>
<d-col :span="8"> <d-col :span="16">
<span class="card-key width-140">代码总行数<d-icon style="color: grey; margin-left: 4px" name="icon-info-o" size="12px" /></span> <span class="card-key width-140">代码平均复杂度<d-icon style="color: grey; margin-left: 4px" name="icon-info-o" size="12px" /></span>
<span class="card-val">{{ ReleaseInfo?.basicInfo?.developer || '--' }}</span> <span class="card-val">{{ QualityTaskOverview?.cyclomaticComplexityPerMethod || '--' }}</span>
</d-col> </d-col>
</d-row> </d-row>
</Card> </Card>
@@ -42,8 +42,8 @@
<div style="width: 100%; padding: 20px 20px 0px 0"> <div style="width: 100%; padding: 20px 20px 0px 0">
<div class="ai-panel-header-title"> <div class="ai-panel-header-title">
<div> <div>
<d-tag color="red-w98" class="mr-1" size="sm">--</d-tag> <!-- <d-tag color="red-w98" class="mr-1" size="sm">&#45;&#45;</d-tag>-->
<span>{{ rowItem.libraryName || '--' }}</span> <span>{{ rowItem.defectCheckerName || '--' }}</span>
</div> </div>
<div <div
style="cursor: pointer; display: flex; gap: 8px; align-items: center" style="cursor: pointer; display: flex; gap: 8px; align-items: center"
@@ -51,20 +51,30 @@
> >
<div style="margin-right: 8px"> <div style="margin-right: 8px">
<span style="margin-right: 4px" class="weak-text">问题发现时间</span> <span style="margin-right: 4px" class="weak-text">问题发现时间</span>
<span>{{ rowItem.vulnerabilities.length || '--' }}</span> <span>{{ dayjs(new Date(rowItem.createdAt)).format('YYYY-MM-DD HH:mm:ss') || '--' }}</span>
</div> </div>
<div style="margin-right: 8px"> <div style="margin-right: 8px">
<span style="margin-right: 4px" class="weak-text">修改点个数</span> <span style="margin-right: 4px" class="weak-text">缺陷级别</span>
<span>{{ rowItem.vulnerabilities.length || '--' }}</span> <d-tag :color="levelMap[rowItem.defectLevel]?.color" size="sm">{{
levelMap[rowItem.defectLevel]?.text || '--'
}}</d-tag>
<!-- <span>{{ defectLevelMap[rowItem.defectLevel] || '&#45;&#45;' }}</span>-->
</div>
<div style="margin-right: 8px">
<span style="margin-right: 4px" class="weak-text">缺陷状态</span>
<d-tag :color="statusMap[rowItem.defectStatus]?.color" size="sm">{{
levelMap[rowItem.defectStatus]?.text || '--'
}}</d-tag>
<!-- <span>{{ defectStatusMap[rowItem.defectStatus] || '&#45;&#45;' }}</span>-->
</div> </div>
<d-icon :name="rowItem.expand ? 'icon-expand-new' : 'icon-drag-new'"></d-icon> <d-icon :name="rowItem.expand ? 'icon-expand-new' : 'icon-drag-new'"></d-icon>
<span>{{ rowItem.expand ? '收起' : '展开' }}</span> <span>{{ rowItem.expand ? '收起' : '展开' }}</span>
</div> </div>
</div> </div>
<div class="ai-panel-header-sub-title"> <div style="margin-top: 6px" class="ai-panel-header-sub-title">
<div> <div>
<span class="weak-text">待处理 </span> <span class="weak-text">文件路径 </span>
<span>{{ rowItem.vulnerabilities.length || '--' }}</span> <a class="devui-link">{{ rowItem.filePath || '--' }}</a>
</div> </div>
<!-- <div>--> <!-- <div>-->
<!-- <span class="weak-text">修复兼容性</span>--> <!-- <span class="weak-text">修复兼容性</span>-->
@@ -77,12 +87,12 @@
<!-- </d-tooltip>--> <!-- </d-tooltip>-->
<!-- <d-tag class="ml-1" type="warning" size="sm">{{'&#45;&#45;'}}</d-tag>--> <!-- <d-tag class="ml-1" type="warning" size="sm">{{'&#45;&#45;'}}</d-tag>-->
<!-- </div>--> <!-- </div>-->
<div> <!-- <div>-->
<span class="weak-text">负责人</span> <!-- <span class="weak-text">负责人</span>-->
<span>{{ rowItem.currentVersion || '--' }}</span> <!-- <span>{{ rowItem.currentVersion || '&#45;&#45;' }}</span>-->
<!-- <img src="@/assets/imgs/jyh/ic_digital_power_next_step_@2x.png" class="icon-sm" />--> <!--&lt;!&ndash; <img src="@/assets/imgs/jyh/ic_digital_power_next_step_@2x.png" class="icon-sm" />&ndash;&gt;-->
<!-- <span>{{ rowItem.recommendedVersion || '&#45;&#45;' }}</span>--> <!--&lt;!&ndash; <span>{{ rowItem.recommendedVersion || '&#45;&#45;' }}</span>&ndash;&gt;-->
</div> <!-- </div>-->
</div> </div>
</div> </div>
</div> </div>
@@ -90,7 +100,7 @@
<template #body> <template #body>
<div style="padding: 8px 20px 20px 20px; width: 100%"> <div style="padding: 8px 20px 20px 20px; width: 100%">
<Code /> <Code v-if="rowItem.expand" :content="rowItem" :lineNumber="rowItem.lineNumber" />
<!-- <Table class="jyh-table" :tableConfig="tableConfig" :dataSource="rowItem.vulnerabilities" :libraryName="rowItem.libraryName" :currentVersion="rowItem.currentVersion"/>--> <!-- <Table class="jyh-table" :tableConfig="tableConfig" :dataSource="rowItem.vulnerabilities" :libraryName="rowItem.libraryName" :currentVersion="rowItem.currentVersion"/>-->
<!-- <div class="w-full flex items-center justify-end">--> <!-- <div class="w-full flex items-center justify-end">-->
<!-- <span>{{ rowItem.vulnerabilities.length }}</span>--> <!-- <span>{{ rowItem.vulnerabilities.length }}</span>-->
@@ -102,7 +112,7 @@
<div class="mt-20 mb-20 flex justify-end" v-if="tableData.length > 0"> <div class="mt-20 mb-20 flex justify-end" v-if="tableData.length > 0">
<d-pagination <d-pagination
size="md" size="md"
:page-size-options="[10, 20, 50]" :page-size-options="[5, 10, 20]"
:total="pager.total" :total="pager.total"
v-model:pageSize="pager.pageSize" v-model:pageSize="pager.pageSize"
v-model:pageIndex="pager.pageIndex" v-model:pageIndex="pager.pageIndex"
@@ -110,8 +120,8 @@
:can-change-page-size="true" :can-change-page-size="true"
:can-view-total="true" :can-view-total="true"
total-item-text="总计" total-item-text="总计"
@page-index-change="fetchVulnList()" @page-index-change="fetchQualityDefectPage()"
@page-size-change="fetchVulnList()" @page-size-change="fetchQualityDefectPage()"
/> />
</div> </div>
</template> </template>
@@ -124,8 +134,25 @@ import { defineProps, onMounted, ref } from 'vue';
import Panel from '@/components/AIRepair/Panel.vue'; import Panel from '@/components/AIRepair/Panel.vue';
import Table from '@/components/AIRepair/Table.vue'; import Table from '@/components/AIRepair/Table.vue';
import NoData from '@/components/NoData/NoData.vue'; import NoData from '@/components/NoData/NoData.vue';
import dayjs from 'dayjs';
import Code from './Code.vue'; import Code from './Code.vue';
import { getVulnList, remediationSearchRemediations } from '@/api/jyh'; import { getVulnList, qualityDefectPage, qualityTaskOverview, remediationSearchRemediations } from '@/api/jyh';
import { Message } from 'vue-devui';
// 缺陷级别映射
const levelMap = {
'0': { text: '致命', color: '#ef4444' }, // 红色
'1': { text: '严重', color: '#f97316' }, // 橙色
'2': { text: '一般', color: '#eab308' }, // 黄色
'3': { text: '提示', color: '#10b981' } // 绿色
}
// 缺陷状态映射
const statusMap = {
'0': { text: '未解决', color: '#ef4444' }, // 红色
'1': { text: '已解决', color: '#10b981' }, // 绿色
'2': { text: '已忽略', color: '#9ca3af' } // 灰色
}
const infoList = ref([ const infoList = ref([
'当前代码主要风险为易受常见的注入攻击包括命令注入、SQL注入、表达式注入针对每种攻击应提供相应的防范措施如数据校验、使用安全函数和限制程序权限。', '当前代码主要风险为易受常见的注入攻击包括命令注入、SQL注入、表达式注入针对每种攻击应提供相应的防范措施如数据校验、使用安全函数和限制程序权限。',
@@ -167,39 +194,56 @@ const tableConfig = ref([
const pager = ref({ const pager = ref({
total: 0, total: 0,
pageIndex: 1, pageIndex: 1,
pageSize: 10 pageSize: 5
}); });
const propsData = defineProps(['versionId']); const propsData = defineProps(['versionId']);
const fetchVulnList = async () => {
const { data } = await remediationSearchRemediations({ const QualityTaskOverview = ref({});
const fetchQualityTaskOverview = async () => {
const { data } = await qualityTaskOverview({
// softwareId: 47, // softwareId: 47,
softwareId: propsData.versionId, softwareId: propsData.versionId,
current: pager.value.pageIndex, pageNum: pager.value.pageIndex,
size: pager.value.pageSize pageSize: pager.value.pageSize
// componentId: '', // componentId: '',
}); });
debugger
if (data.data.code === 200) { if (data.code === 200) {
tableData.value = data?.data?.data?.records || []; QualityTaskOverview.value = data?.data;
pager.value.total = data?.data?.data?.total || 0;
// pager.value.total = data?.data?.data?.total || []; // pager.value.total = data?.data?.data?.total || [];
} else {
// Message.error(data.msg);
}
};
const fetchQualityDefectPage= async () => {
const { data } = await qualityDefectPage({
// softwareId: 47,
softwareId: propsData.versionId,
pageNum: pager.value.pageIndex,
pageSize: pager.value.pageSize
// componentId: '',
});
debugger
if (data.code === 200) {
tableData.value = data?.data?.records.map(i=>{
return {
...i,
expand:true
}
}) || [];
pager.value.total = data?.data?.total || 0;
// pager.value.total = data?.data?.data?.total || [];
} else {
// Message.error(data.msg);
} }
}; };
const tableData = ref([ const tableData = ref([]);
{
"componentId": 1,
"libraryName": "",
"currentVersion": "",
expand: true,
"vulnerabilities": [ ]
}
]);
onMounted(() => { onMounted(() => {
// fetchVulnList(); fetchQualityTaskOverview();
fetchQualityDefectPage();
}); });
</script> </script>