update
This commit is contained in:
parent
aa509ef613
commit
5c15094344
|
|
@ -1,10 +1,11 @@
|
|||
import fetch from './fetch';
|
||||
|
||||
// 获取列表
|
||||
export function getList(facets) {
|
||||
export function getList(params) {
|
||||
return fetch({
|
||||
url: `/api/issues/search?components=kingchanx-fluid-cloudnative_fluid&s=FILE_LINE&issueStatuses=CONFIRMED%2COPEN&ps=100&facets=${ facets }&additionalFields=_all&timeZone=Asia%2FShanghai`,
|
||||
url: `/api/issues/search?components=kingchanx-fluid-cloudnative_fluid&s=FILE_LINE&issueStatuses=CONFIRMED%2COPEN&ps=100&&additionalFields=_all&timeZone=Asia%2FShanghai`,
|
||||
method: 'get',
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -178,6 +178,7 @@
|
|||
display: flex;
|
||||
.left-content {
|
||||
width: 218px;
|
||||
flex-shrink: 0;
|
||||
.filter-title {
|
||||
font-weight: bold;
|
||||
font-size: 17px;
|
||||
|
|
@ -186,15 +187,19 @@
|
|||
}
|
||||
.filter-item {
|
||||
padding: 0 20px;
|
||||
margin: 2px 0;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
height: 54px;
|
||||
height: 50px;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background: #466bff0c;
|
||||
}
|
||||
}
|
||||
.selected-item {
|
||||
background: #466bff17;
|
||||
}
|
||||
.ant-divider {
|
||||
margin: 20px;
|
||||
width: auto;
|
||||
|
|
@ -239,6 +244,7 @@
|
|||
font-weight: bold;
|
||||
font-size: 15px;
|
||||
color: #111010;
|
||||
word-break: break-word;
|
||||
span:nth-of-type(1) {
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
|
|
@ -255,5 +261,44 @@
|
|||
}
|
||||
.total-info {
|
||||
padding: 20px;
|
||||
.info-list {
|
||||
display: flex;
|
||||
.total-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 53px;
|
||||
font-weight: 400;
|
||||
font-size: 15px;
|
||||
color: #525151;
|
||||
> span:nth-child(2) {
|
||||
font-weight: bold;
|
||||
font-size: 18px;
|
||||
color: #111010;
|
||||
}
|
||||
.item-more {
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
color: #525151;
|
||||
span {
|
||||
color: #466AFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
.total-item:not(:last-child) {
|
||||
margin-right: 40px;
|
||||
}
|
||||
.total-item:nth-child(n + 2) {
|
||||
margin-left: 64px;
|
||||
position: relative;
|
||||
&::after {
|
||||
position: absolute;
|
||||
left: -40px;
|
||||
content: '';
|
||||
width: 0px;
|
||||
height: 53px;
|
||||
border-left: 1px solid rgba(187,189,197,0.61);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import './detail.scss';
|
|||
import ProblemDetail from "./component/ProblemDetail";
|
||||
import { issueType, issueTypeKeys, maintainability } from "../constants/quality"
|
||||
import { Divider } from 'antd';
|
||||
import { formatNumber } from '../../Utils/utils'
|
||||
|
||||
function issueList(props){
|
||||
const [ issues, setIssues ] = useState({});
|
||||
|
|
@ -12,7 +13,10 @@ function issueList(props){
|
|||
const [ listFilter, setListFilter ] = useState({});
|
||||
const [ selectedIssue, setSelectedIssue ] = useState(null);
|
||||
const [ detailVisible, setDetailVisible ] = useState(true);
|
||||
const [ issueInfo, setIssueInfo ] = useState(null);
|
||||
const [ issueInfo, setIssueInfo ] = useState({});
|
||||
const [ selectedType, setSelectedType ] = useState([]);
|
||||
const [ selectedSeverity, setSelectedSeverity ] = useState([]);
|
||||
const [ selectedTag, setSelectedTag ] = useState([]);
|
||||
const { projectDetail } = props;
|
||||
const metricKeys = 'lines,coverage,lines_to_cover,duplicated_lines_density,maintainability_issues,vulnerabilities,bugs,code_smells'
|
||||
const facets = 'impactSeverities,tags,types'
|
||||
|
|
@ -38,7 +42,17 @@ function issueList(props){
|
|||
});
|
||||
setBaseData(result)
|
||||
})
|
||||
getList(facets).then(res => {
|
||||
getIssueList()
|
||||
}, [projectDetail])
|
||||
|
||||
function getIssueList() {
|
||||
let params = {
|
||||
facets: facets,
|
||||
types: selectedType.join(','),
|
||||
impactSeverities: selectedSeverity.join(','),
|
||||
tags: selectedTag.join(','),
|
||||
}
|
||||
getList(params).then(res => {
|
||||
let issues = res.issues
|
||||
let issuesHandled = {}
|
||||
issues.forEach(e => {
|
||||
|
|
@ -52,12 +66,15 @@ function issueList(props){
|
|||
res.facets.forEach(e => {
|
||||
filter[e.property] = e.values
|
||||
})
|
||||
console.log(filter);
|
||||
setListFilter(filter)
|
||||
setBaseInfo(res)
|
||||
setIssues(issuesHandled)
|
||||
})
|
||||
}, [projectDetail])
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getIssueList()
|
||||
},[selectedType, selectedSeverity, selectedTag])
|
||||
|
||||
function detail(e) {
|
||||
setSelectedIssue(e)
|
||||
|
|
@ -66,13 +83,66 @@ function issueList(props){
|
|||
setDetailVisible(true)
|
||||
})
|
||||
}
|
||||
|
||||
function selectType(e) {
|
||||
let index = selectedType.indexOf(e)
|
||||
if (index > -1) {
|
||||
selectedType.splice(index, 1)
|
||||
setSelectedType([...selectedType])
|
||||
} else {
|
||||
setSelectedType([...selectedType, e])
|
||||
}
|
||||
}
|
||||
|
||||
function selectSeverity(e) {
|
||||
let index = selectedSeverity.indexOf(e)
|
||||
if (index > -1) {
|
||||
selectedSeverity.splice(index, 1)
|
||||
setSelectedSeverity([...selectedSeverity])
|
||||
} else {
|
||||
setSelectedSeverity([...selectedSeverity, e])
|
||||
}
|
||||
}
|
||||
|
||||
function selectTags(e) {
|
||||
let index = selectedTag.indexOf(e)
|
||||
if (index > -1) {
|
||||
selectedTag.splice(index, 1)
|
||||
setSelectedTag([...selectedTag])
|
||||
} else {
|
||||
setSelectedTag([...selectedTag, e])
|
||||
}
|
||||
}
|
||||
|
||||
return <div className="issue-total">
|
||||
<ProblemDetail visible={detailVisible} issue={selectedIssue} issueDetail={issueInfo} onClose={() => setDetailVisible(false)}></ProblemDetail>
|
||||
<div className="container total-info">
|
||||
<p>代码分析结果</p>
|
||||
<div>
|
||||
|
||||
<div className="info-list">
|
||||
<div className="total-item">
|
||||
<span>Bugs</span>
|
||||
<span>{ baseData.bugs }</span>
|
||||
</div>
|
||||
<div className="total-item">
|
||||
<span>漏洞</span>
|
||||
<span>{ formatNumber(baseData.vulnerabilities) }</span>
|
||||
</div>
|
||||
<div className="total-item">
|
||||
<span>异味</span>
|
||||
<span>{ formatNumber(baseData.code_smells) }</span>
|
||||
</div>
|
||||
<div className="total-item">
|
||||
<span>重复率</span>
|
||||
<span>{ baseData.duplicated_lines_density }% <span className="item-more">代码<span>{ formatNumber(baseData.lines) }</span>行</span></span>
|
||||
</div>
|
||||
<div className="total-item">
|
||||
<span>覆盖率</span>
|
||||
<span>{ baseData.coverage }% <span className="item-more">代码<span>{ formatNumber(baseData.lines_to_cover) }</span>行</span></span>
|
||||
</div>
|
||||
<div className="total-item">
|
||||
<span>代码行数</span>
|
||||
<span>{ baseData.lines && baseData.lines.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") }</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{issues && <p>发现{ baseInfo.total }个问题</p>}
|
||||
|
|
@ -80,11 +150,11 @@ function issueList(props){
|
|||
<div className="container left-content">
|
||||
<div className="type">
|
||||
<div className="filter-title">
|
||||
<span>问题类型</span>
|
||||
<span>问题类型 {}</span>
|
||||
</div>
|
||||
{
|
||||
listFilter.types && listFilter.types.map(e => (
|
||||
<div className="filter-item" key={e.val}>
|
||||
<div className={`filter-item${ selectedType.includes(e.val) ? ' selected-item' : '' }`} key={e.val} onClick={() => selectType(e.val)}>
|
||||
<span>{ issueType[e.val] }</span>
|
||||
<span>{ e.count }</span>
|
||||
</div>))
|
||||
|
|
@ -97,7 +167,7 @@ function issueList(props){
|
|||
</div>
|
||||
{
|
||||
listFilter.impactSeverities && listFilter.impactSeverities.map(e => (
|
||||
<div className="filter-item" key={e.val}>
|
||||
<div className={`filter-item${ selectedSeverity.includes(e.val) ? ' selected-item' : '' }`} key={e.val} onClick={() => selectSeverity(e.val)}>
|
||||
<span>{ maintainability[e.val] }</span>
|
||||
<span>{ e.count }</span>
|
||||
</div>))
|
||||
|
|
@ -110,7 +180,7 @@ function issueList(props){
|
|||
</div>
|
||||
{
|
||||
listFilter.tags && listFilter.tags.map(e => (
|
||||
<div className="filter-item" key={e.val}>
|
||||
<div className={`filter-item${ selectedTag.includes(e.val) ? ' selected-item' : '' }`} key={e.val} onClick={() => selectTags(e.val)}>
|
||||
<span>{ e.val }</span>
|
||||
<span>{ e.count }</span>
|
||||
</div>))
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
export function formatNumber(num) {
|
||||
if (num === undefined || num === null) return
|
||||
if (num >= 1e9) {
|
||||
return (num / 1e9).toFixed(1) + 'B'; // 十亿
|
||||
} else if (num >= 1e6) {
|
||||
return (num / 1e6).toFixed(1) + 'M'; // 百万
|
||||
} else if (num >= 1e3) {
|
||||
return (num / 1e3).toFixed(1) + 'K'; // 千
|
||||
} else {
|
||||
return num.toString(); // 小于 1000 的数字原样返回
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue