feat(工作台): 调整优化工作台饼图
This commit is contained in:
parent
efa4a1f319
commit
8dc9e2b022
|
@ -243,8 +243,8 @@ export const commonRatePieOptions = {
|
||||||
title: {
|
title: {
|
||||||
show: true,
|
show: true,
|
||||||
text: '',
|
text: '',
|
||||||
left: 26,
|
left: 40,
|
||||||
top: '20%',
|
top: '26%',
|
||||||
textStyle: {
|
textStyle: {
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: 'normal',
|
fontWeight: 'normal',
|
||||||
|
@ -276,16 +276,14 @@ export const commonRatePieOptions = {
|
||||||
name: '',
|
name: '',
|
||||||
type: 'pie',
|
type: 'pie',
|
||||||
color: [],
|
color: [],
|
||||||
padAngle: 2,
|
radius: ['65%', '80%'],
|
||||||
radius: ['85%', '100%'],
|
center: [44, '50%'],
|
||||||
center: [30, '50%'],
|
|
||||||
avoidLabelOverlap: false,
|
avoidLabelOverlap: false,
|
||||||
label: {
|
label: {
|
||||||
show: false,
|
show: false,
|
||||||
position: 'center',
|
position: 'center',
|
||||||
},
|
},
|
||||||
emphasis: {
|
emphasis: {
|
||||||
scale: false, // 禁用放大效果
|
|
||||||
label: {
|
label: {
|
||||||
show: false,
|
show: false,
|
||||||
fontSize: 40,
|
fontSize: 40,
|
||||||
|
|
|
@ -173,7 +173,7 @@
|
||||||
const coverTitleConfig = computed(() => {
|
const coverTitleConfig = computed(() => {
|
||||||
return {
|
return {
|
||||||
name: t('workbench.homePage.apiCoverage'),
|
name: t('workbench.homePage.apiCoverage'),
|
||||||
color: ['#EDEDF1', '#00C261'],
|
color: ['#D4D4D8', '#00C261'],
|
||||||
tooltipText:
|
tooltipText:
|
||||||
props.item.key === WorkCardEnum.API_CASE_COUNT
|
props.item.key === WorkCardEnum.API_CASE_COUNT
|
||||||
? t('workbench.homePage.apiCaseCountCoverRateTooltip')
|
? t('workbench.homePage.apiCaseCountCoverRateTooltip')
|
||||||
|
@ -185,12 +185,12 @@
|
||||||
return props.item.key === WorkCardEnum.API_CASE_COUNT
|
return props.item.key === WorkCardEnum.API_CASE_COUNT
|
||||||
? {
|
? {
|
||||||
name: t('workbench.homePage.caseExecutionRate'),
|
name: t('workbench.homePage.caseExecutionRate'),
|
||||||
color: ['#EDEDF1', '#00C261'],
|
color: ['#D4D4D8', '#00C261'],
|
||||||
tooltipText: t('workbench.homePage.apiCaseCountExecuteRateTooltip'),
|
tooltipText: t('workbench.homePage.apiCaseCountExecuteRateTooltip'),
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
name: t('workbench.homePage.sceneExecutionRate'),
|
name: t('workbench.homePage.sceneExecutionRate'),
|
||||||
color: ['#EDEDF1', '#00C261'],
|
color: ['#D4D4D8', '#00C261'],
|
||||||
tooltipText: t('workbench.homePage.scenarioCaseCountExecuteRateTooltip'),
|
tooltipText: t('workbench.homePage.scenarioCaseCountExecuteRateTooltip'),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
<PassRatePie
|
<PassRatePie
|
||||||
:tooltip-text="tabItem.tooltip"
|
:tooltip-text="tabItem.tooltip"
|
||||||
:options="tabItem.options"
|
:options="tabItem.options"
|
||||||
:size="60"
|
|
||||||
:loading="tabItem.value === 'cover' ? loading : undefined"
|
:loading="tabItem.value === 'cover' ? loading : undefined"
|
||||||
:has-permission="hasPermission"
|
:has-permission="hasPermission"
|
||||||
:value-list="tabItem.valueList"
|
:value-list="tabItem.valueList"
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
<PassRatePie
|
<PassRatePie
|
||||||
:options="tabItem.options"
|
:options="tabItem.options"
|
||||||
:tooltip-text="tabItem.tooltip"
|
:tooltip-text="tabItem.tooltip"
|
||||||
:size="60"
|
|
||||||
:value-list="tabItem.valueList"
|
:value-list="tabItem.valueList"
|
||||||
:has-permission="hasPermission"
|
:has-permission="hasPermission"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
<PassRatePie
|
<PassRatePie
|
||||||
:options="options"
|
:options="options"
|
||||||
tooltip-text="workbench.homePage.caseReviewCoverRateTooltip"
|
tooltip-text="workbench.homePage.caseReviewCoverRateTooltip"
|
||||||
:size="60"
|
|
||||||
:value-list="coverValueList"
|
:value-list="coverValueList"
|
||||||
:has-permission="hasPermission"
|
:has-permission="hasPermission"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -28,7 +28,6 @@
|
||||||
:has-permission="hasPermission"
|
:has-permission="hasPermission"
|
||||||
:tooltip-text="tooltip"
|
:tooltip-text="tooltip"
|
||||||
:options="legacyOptions"
|
:options="legacyOptions"
|
||||||
:size="60"
|
|
||||||
:value-list="legacyValueList"
|
:value-list="legacyValueList"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
<div class="flex w-full flex-col gap-4">
|
<div class="flex w-full flex-col gap-4">
|
||||||
<div
|
<div
|
||||||
v-for="(ele, i) of currentData"
|
v-for="(ele, i) of currentData"
|
||||||
:key="`ele.status-${i}`"
|
:key="`${ele.status}-${i}`"
|
||||||
class="grid flex-1 grid-cols-3 gap-4"
|
class="grid flex-1 grid-cols-3 gap-4"
|
||||||
@mouseover="handleMouseOver(ele.status)"
|
@mouseover="handleMouseOver(ele.status)"
|
||||||
@mouseout="handleMouseOut(ele.status)"
|
@mouseout="handleMouseOut(ele.status)"
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
>
|
>
|
||||||
<div class="tooltip-rate h-[50px] w-[50px]"></div>
|
<div class="tooltip-rate h-[50px] w-[50px]"></div>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<MsChart :height="`${props.size}px`" :width="`${props.size}px`" :options="props.options" />
|
<MsChart height="92px" width="92px" :options="props.options" />
|
||||||
</div>
|
</div>
|
||||||
<div class="pass-rate-title flex-1">
|
<div class="pass-rate-title flex-1">
|
||||||
<div v-for="item of props.valueList" :key="item.label" class="flex-1">
|
<div v-for="item of props.valueList" :key="item.label" class="flex-1">
|
||||||
|
@ -30,7 +30,6 @@
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
options: Record<string, any>;
|
options: Record<string, any>;
|
||||||
size: number;
|
|
||||||
tooltipText?: string;
|
tooltipText?: string;
|
||||||
hasPermission: boolean;
|
hasPermission: boolean;
|
||||||
loading?: boolean;
|
loading?: boolean;
|
||||||
|
@ -43,8 +42,9 @@
|
||||||
|
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
.pass-rate-content {
|
.pass-rate-content {
|
||||||
padding: 16px;
|
padding: 0 16px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
height: 92px;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
background: var(--color-text-n9);
|
background: var(--color-text-n9);
|
||||||
@apply flex items-center;
|
@apply flex items-center;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<a-spin class="w-full" :loading="props.loading">
|
<a-spin class="w-full" :loading="props.loading">
|
||||||
<div class="rate-content relative">
|
<div class="rate-content relative flex flex-col items-center">
|
||||||
<div class="relative flex h-full w-full items-center justify-center">
|
<div class="relative flex h-full w-full items-center justify-center">
|
||||||
<a-tooltip
|
<a-tooltip
|
||||||
v-if="props.rateConfig.tooltipText"
|
v-if="props.rateConfig.tooltipText"
|
||||||
|
@ -10,7 +10,38 @@
|
||||||
>
|
>
|
||||||
<div class="tooltip-rate-tooltip"></div>
|
<div class="tooltip-rate-tooltip"></div>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<MsChart :options="options" width="146px" />
|
<MsChart ref="chartRef" :options="options" width="100px" height="100px" />
|
||||||
|
</div>
|
||||||
|
<div class="flex w-full items-center justify-center">
|
||||||
|
<div class="flex w-[80%] flex-col gap-[8px]">
|
||||||
|
<template v-if="props.hasPermission">
|
||||||
|
<div
|
||||||
|
v-for="(ele, i) of legend"
|
||||||
|
:key="`${ele.name}-${i}`"
|
||||||
|
class="flex justify-between"
|
||||||
|
@mouseover="handleMouseOver(ele.name)"
|
||||||
|
@mouseout="handleMouseOut(ele.name)"
|
||||||
|
>
|
||||||
|
<div class="flex items-center text-left text-[var(--color-text-3)]">
|
||||||
|
<div
|
||||||
|
:style="{
|
||||||
|
background: ele.selected ? `${ele.color}` : '#D4D4D8',
|
||||||
|
}"
|
||||||
|
class="mr-[8px] h-[8px] w-[8px] cursor-pointer rounded-lg"
|
||||||
|
@click="toggleLegend(ele.name, i)"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
{{ ele.name }}
|
||||||
|
</div>
|
||||||
|
<div class="text-[16px] text-[rgb(var(--primary-5))]">{{ addCommasToNumber(ele.value) }}</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div v-else class="mt-[16px] flex h-full flex-1 items-center justify-center">
|
||||||
|
<div class="rounded bg-[var(--color-text-n9)] px-[16px] py-[4px] text-[var(--color-text-4)]">
|
||||||
|
{{ t('workbench.homePage.notHasResPermission') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a-spin>
|
</a-spin>
|
||||||
|
@ -43,7 +74,7 @@
|
||||||
show: true,
|
show: true,
|
||||||
text: '',
|
text: '',
|
||||||
left: 'center',
|
left: 'center',
|
||||||
top: 32,
|
top: 30,
|
||||||
textStyle: {
|
textStyle: {
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: 'normal',
|
fontWeight: 'normal',
|
||||||
|
@ -65,7 +96,9 @@
|
||||||
tooltip: {
|
tooltip: {
|
||||||
show: true,
|
show: true,
|
||||||
},
|
},
|
||||||
|
color: [],
|
||||||
legend: {
|
legend: {
|
||||||
|
show: false,
|
||||||
orient: 'vertical',
|
orient: 'vertical',
|
||||||
itemWidth: 8, // 图例标记的宽度
|
itemWidth: 8, // 图例标记的宽度
|
||||||
itemHeight: 8, // 图例标记的高度
|
itemHeight: 8, // 图例标记的高度
|
||||||
|
@ -102,8 +135,8 @@
|
||||||
series: {
|
series: {
|
||||||
name: '',
|
name: '',
|
||||||
type: 'pie',
|
type: 'pie',
|
||||||
radius: ['50%', '58%'],
|
radius: ['75%', '90%'],
|
||||||
center: ['50%', '32%'],
|
center: ['50%', '50%'],
|
||||||
color: [],
|
color: [],
|
||||||
avoidLabelOverlap: false,
|
avoidLabelOverlap: false,
|
||||||
label: {
|
label: {
|
||||||
|
@ -122,31 +155,52 @@
|
||||||
},
|
},
|
||||||
data: [],
|
data: [],
|
||||||
},
|
},
|
||||||
graphic: {
|
// graphic: {
|
||||||
type: 'text',
|
// type: 'text',
|
||||||
left: 'center',
|
// left: 'center',
|
||||||
bottom: 10,
|
// bottom: 10,
|
||||||
style: {
|
// style: {
|
||||||
text: t('workbench.homePage.notHasResPermission'),
|
// text: t('workbench.homePage.notHasResPermission'),
|
||||||
fontSize: 14,
|
// fontSize: 14,
|
||||||
fill: '#959598',
|
// fill: '#959598',
|
||||||
backgroundColor: '#F9F9FE',
|
// backgroundColor: '#F9F9FE',
|
||||||
padding: [6, 16, 6, 16],
|
// padding: [6, 16, 6, 16],
|
||||||
borderRadius: 4,
|
// borderRadius: 4,
|
||||||
},
|
// },
|
||||||
invisible: false,
|
// invisible: false,
|
||||||
},
|
// },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const legend = ref<{ name: string; value: number; color: string; selected: boolean }[]>([]);
|
||||||
|
|
||||||
function initOptions() {
|
function initOptions() {
|
||||||
const { name, color } = props.rateConfig;
|
const { name, color } = props.rateConfig;
|
||||||
options.value.series.data = [...props.data.slice(1)].map((e) => {
|
const temData = [...props.data.slice(1)];
|
||||||
|
const hasDataLength = temData.filter((e) => Number(e.value) > 0).length;
|
||||||
|
|
||||||
|
const pieBorderWidth = hasDataLength === 1 ? 0 : 1;
|
||||||
|
|
||||||
|
options.value.series.data =
|
||||||
|
hasDataLength > 0
|
||||||
|
? temData.map((e) => {
|
||||||
|
return {
|
||||||
|
...e,
|
||||||
|
tooltip: {
|
||||||
|
...toolTipConfig,
|
||||||
|
show: !!props.hasPermission,
|
||||||
|
},
|
||||||
|
itemStyle: {
|
||||||
|
borderWidth: pieBorderWidth,
|
||||||
|
borderColor: '#ffffff',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
})
|
||||||
|
: [];
|
||||||
|
legend.value = [...props.data.slice(1)].map((e, i) => {
|
||||||
return {
|
return {
|
||||||
...e,
|
...e,
|
||||||
tooltip: {
|
selected: true,
|
||||||
...toolTipConfig,
|
color: color[i],
|
||||||
show: !!props.hasPermission,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -162,13 +216,48 @@
|
||||||
options.value.title.subtext = `-%`;
|
options.value.title.subtext = `-%`;
|
||||||
}
|
}
|
||||||
|
|
||||||
options.value.graphic.invisible = !!props.hasPermission;
|
|
||||||
options.value.tooltip.show = !!props.hasPermission;
|
options.value.tooltip.show = !!props.hasPermission;
|
||||||
options.value.title.text = name;
|
options.value.title.text = name;
|
||||||
|
|
||||||
options.value.series.color = color;
|
options.value.series.color = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const chartRef = ref<InstanceType<typeof MsChart>>();
|
||||||
|
function toggleLegend(name: string, index: number) {
|
||||||
|
const chart = chartRef.value?.chartRef;
|
||||||
|
if (chart) {
|
||||||
|
chart.dispatchAction({
|
||||||
|
type: 'legendToggleSelect',
|
||||||
|
name,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (legend.value) {
|
||||||
|
legend.value[index].selected = !legend.value[index].selected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 悬浮放大交互效果
|
||||||
|
function handleMouseOver(name: string) {
|
||||||
|
const chart = chartRef.value?.chartRef;
|
||||||
|
if (chart) {
|
||||||
|
chart.dispatchAction({
|
||||||
|
type: 'highlight',
|
||||||
|
name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 移除放大交互效果
|
||||||
|
function handleMouseOut(name: string) {
|
||||||
|
const chart = chartRef.value?.chartRef;
|
||||||
|
if (chart) {
|
||||||
|
chart.dispatchAction({
|
||||||
|
type: 'downplay',
|
||||||
|
name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.data,
|
() => props.data,
|
||||||
(val) => {
|
(val) => {
|
||||||
|
@ -191,15 +280,12 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
.rate-content {
|
|
||||||
height: 158px;
|
|
||||||
}
|
|
||||||
.tooltip-rate-tooltip {
|
.tooltip-rate-tooltip {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 10px;
|
top: 20px;
|
||||||
z-index: 9;
|
z-index: 9;
|
||||||
width: 78px;
|
width: 60px;
|
||||||
height: 78px;
|
height: 60px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
:options="relatedOptions"
|
:options="relatedOptions"
|
||||||
:has-permission="hasPermission"
|
:has-permission="hasPermission"
|
||||||
tooltip-text="workbench.homePage.associateCaseCoverRateTooltip"
|
tooltip-text="workbench.homePage.associateCaseCoverRateTooltip"
|
||||||
:size="60"
|
|
||||||
:value-list="coverRateValueList"
|
:value-list="coverRateValueList"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -24,12 +24,7 @@
|
||||||
<div class="mt-[16px]">
|
<div class="mt-[16px]">
|
||||||
<div class="flex gap-[16px]">
|
<div class="flex gap-[16px]">
|
||||||
<div v-for="tabItem of testPlanTabList" :key="tabItem.label" class="flex-1">
|
<div v-for="tabItem of testPlanTabList" :key="tabItem.label" class="flex-1">
|
||||||
<PassRatePie
|
<PassRatePie :has-permission="hasPermission" :options="tabItem.options" :value-list="tabItem.valueList" />
|
||||||
:has-permission="hasPermission"
|
|
||||||
:options="tabItem.options"
|
|
||||||
:size="60"
|
|
||||||
:value-list="tabItem.valueList"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-[16px] h-[148px]">
|
<div class="mt-[16px] h-[148px]">
|
||||||
|
|
|
@ -364,15 +364,25 @@ export function handlePieData(
|
||||||
) {
|
) {
|
||||||
const options: Record<string, any> = getPieCharOptions(key);
|
const options: Record<string, any> = getPieCharOptions(key);
|
||||||
const lastStatusPercentList = statusPercentList ?? [];
|
const lastStatusPercentList = statusPercentList ?? [];
|
||||||
options.series.data = lastStatusPercentList.map((item) => ({
|
const hasDataLength = lastStatusPercentList.filter((e) => Number(e.count) > 0).length;
|
||||||
name: item.status,
|
const pieBorderWidth = hasDataLength === 1 ? 0 : 2;
|
||||||
value: item.count,
|
|
||||||
tooltip: {
|
options.series.data =
|
||||||
...toolTipConfig,
|
hasDataLength > 0
|
||||||
position: 'right',
|
? lastStatusPercentList.map((item) => ({
|
||||||
show: !!hasPermission,
|
name: item.status,
|
||||||
},
|
value: item.count,
|
||||||
}));
|
tooltip: {
|
||||||
|
...toolTipConfig,
|
||||||
|
position: 'right',
|
||||||
|
show: !!hasPermission,
|
||||||
|
},
|
||||||
|
itemStyle: {
|
||||||
|
borderWidth: pieBorderWidth,
|
||||||
|
borderColor: '#ffffff',
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
: [];
|
||||||
|
|
||||||
// 计算总数和图例格式
|
// 计算总数和图例格式
|
||||||
const tempObject: Record<string, any> = {};
|
const tempObject: Record<string, any> = {};
|
||||||
|
@ -407,13 +417,20 @@ export function handleUpdateTabPie(
|
||||||
const countList = list || [];
|
const countList = list || [];
|
||||||
let lastCountList: { value: number | string; label: string; name: string }[] = [];
|
let lastCountList: { value: number | string; label: string; name: string }[] = [];
|
||||||
if (hasPermission) {
|
if (hasPermission) {
|
||||||
|
const pieBorderWidth = countList.slice(1).filter((e) => Number(e.count) > 0).length === 1 ? 0 : 1;
|
||||||
|
|
||||||
lastCountList = countList.slice(1).map((item) => {
|
lastCountList = countList.slice(1).map((item) => {
|
||||||
return {
|
return {
|
||||||
value: item.count,
|
value: item.count,
|
||||||
label: item.name,
|
label: item.name,
|
||||||
name: item.name,
|
name: item.name,
|
||||||
|
itemStyle: {
|
||||||
|
borderWidth: pieBorderWidth,
|
||||||
|
borderColor: '#ffffff',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
options.series.data = lastCountList.every((e) => e.value === 0) ? [] : lastCountList;
|
options.series.data = lastCountList.every((e) => e.value === 0) ? [] : lastCountList;
|
||||||
|
|
||||||
options.title.text = countList[0].name ?? '';
|
options.title.text = countList[0].name ?? '';
|
||||||
|
|
Loading…
Reference in New Issue