fix(工作台): 修复个工作台测试计划概览&缺陷饼图bug

This commit is contained in:
xinxin.wu 2024-12-10 18:59:17 +08:00 committed by 刘瑞斌
parent 0e2894eea6
commit 0a7787a0cd
7 changed files with 62 additions and 57 deletions

View File

@ -230,7 +230,7 @@ export function workbenchTodoTestPlanList(data: TableQueryParams) {
} }
// 待办-测试计划列表 // 待办-测试计划列表
export function getWorkTestPlanListUrl(projectId: string) { export function getWorkTestPlanListUrl(projectId: string) {
return MSR.get<CascaderOption[]>({ url: `${WorkTestPlanListUrl}/${projectId}` }); return MSR.get<CascaderOption[]>({ url: `${WorkTestPlanListUrl}/${projectId}` }, { ignoreCancelToken: true });
} }
// 工作台-测试计划概览 // 工作台-测试计划概览

View File

@ -9,7 +9,7 @@ export default function bindDataZoomEvent(
const chartDom = chartRef.value?.chartRef; const chartDom = chartRef.value?.chartRef;
const handleDataZoom = (params: any) => { const handleDataZoom = (params: any) => {
const containerWidth = chartDom.getDom().offsetWidth; const containerWidth = chartDom.getDom()?.offsetWidth;
// 计算缩放百分比 // 计算缩放百分比
const percent = (params.end - params.start) / 100; const percent = (params.end - params.start) / 100;
// 计算单组条形图的宽度(包括间隔和最小宽度) // 计算单组条形图的宽度(包括间隔和最小宽度)
@ -52,8 +52,9 @@ export default function bindDataZoomEvent(
const handleResize = () => { const handleResize = () => {
if (chartDom) { if (chartDom) {
const currentOptions = chartDom.chart.getOption(); const currentOptions = chartDom.chart?.getOption();
if (currentOptions.dataZoom.length) {
if (currentOptions && currentOptions?.dataZoom.length) {
handleDataZoom({ start: currentOptions.dataZoom[0].start, end: currentOptions.dataZoom[0].end }); handleDataZoom({ start: currentOptions.dataZoom[0].start, end: currentOptions.dataZoom[0].end });
} }
} }

View File

@ -65,7 +65,7 @@
border-radius: 4px; border-radius: 4px;
color: var(--color-text-4); color: var(--color-text-4);
background-color: var(--color-text-fff); background-color: var(--color-text-fff);
@apply flex items-center justify-center; @apply flex w-full items-center justify-center;
} }
.no-config-svg { .no-config-svg {
margin: 0 auto 24px; margin: 0 auto 24px;

View File

@ -97,21 +97,15 @@
const hasPermission = ref<boolean>(false); const hasPermission = ref<boolean>(false);
function handleData(detail: OverViewOfProject) { function handleData(detail: OverViewOfProject) {
const labelCount: Record<string, any> = {}; const data = detail.projectCountList.map((e) => {
const uniqueData = detail.projectCountList.map((e) => { return {
const { name } = e; value: '',
if (!labelCount[name]) { label: e.name,
labelCount[name] = 1; };
return { value: '', label: name };
}
labelCount[name] += 1;
//
return { value: '', label: `${name} (${labelCount[name]})` };
}); });
options.value = getSeriesData( options.value = getSeriesData(
uniqueData, data,
detail, detail,
[...defectStatusColor, ...getColorScheme(13)], [...defectStatusColor, ...getColorScheme(13)],
false, false,

View File

@ -161,12 +161,20 @@
showSkeleton.value = false; showSkeleton.value = false;
} }
} }
const chartRef = ref<InstanceType<typeof MsChart>>();
async function handleProjectChange(shouldEmit = false) { async function handleProjectChange(shouldEmit = false) {
await nextTick(); await nextTick();
innerSelectAll.value = appStore.projectList.length === innerProjectIds.value.length; innerSelectAll.value = appStore.projectList.length === innerProjectIds.value.length;
await nextTick(); await nextTick();
initOverViewDetail(); await initOverViewDetail();
const chartDom = chartRef.value?.chartRef;
if (chartDom && chartDom.chart) {
createCustomTooltip(chartDom);
bindDataZoomEvent(chartRef, options);
}
if (shouldEmit) emit('change'); if (shouldEmit) emit('change');
} }
@ -177,7 +185,6 @@
}); });
} }
} }
const chartRef = ref<InstanceType<typeof MsChart>>();
async function handleRefreshKeyChange() { async function handleRefreshKeyChange() {
await nextTick(() => { await nextTick(() => {
@ -191,7 +198,6 @@
onMounted(async () => { onMounted(async () => {
await initOverViewDetail(); await initOverViewDetail();
nextTick(() => { nextTick(() => {
const chartDom = chartRef.value?.chartRef; const chartDom = chartRef.value?.chartRef;

View File

@ -71,7 +71,9 @@
<MsChart height="76px" width="76px" :options="execOptions" /> <MsChart height="76px" width="76px" :options="execOptions" />
</div> </div>
</div> </div>
<HeaderCard :content-tab-list="cardModuleList" /> <div class="flex-1">
<HeaderCard :content-tab-list="cardModuleList" />
</div>
</div> </div>
<div> <div>
<MsChart ref="chartRef" height="280px" :options="options" /> <MsChart ref="chartRef" height="280px" :options="options" />
@ -318,16 +320,18 @@
const [newProjectId] = innerProjectIds.value; const [newProjectId] = innerProjectIds.value;
const projectName = projectOptions.value.find((e) => e.value === newProjectId)?.label; const projectName = projectOptions.value.find((e) => e.value === newProjectId)?.label;
const treeList = childrenData.value[newProjectId]; const treeList = childrenData.value[newProjectId] || [];
const modules = findNodePathByKey(treeList, id, undefined, 'value'); if (treeList.length) {
const modules = findNodePathByKey(treeList, id, undefined, 'value');
if (modules) { if (modules) {
const moduleName = (modules || [])?.treePath.map((item: any) => item.label); const moduleName = (modules || [])?.treePath.map((item: any) => item.label);
if (moduleName.length === 1) { if (moduleName.length === 1) {
return `${projectName}/${moduleName[0]}`; return `${projectName}/${moduleName[0]}`;
}
return `${projectName}/${moduleName.join(' / ')}`;
} }
return `${projectName}/${moduleName.join(' / ')}`;
} }
} }
@ -403,7 +407,9 @@
onMounted(() => { onMounted(() => {
projectOptions.value = appStore.projectList.map((e) => ({ value: e.id, label: e.name })); projectOptions.value = appStore.projectList.map((e) => ({ value: e.id, label: e.name }));
const [newProjectId] = props.item.projectIds; const [newProjectId] = props.item.projectIds;
selectValue.value = [newProjectId, props.item.planId]; if (props.item.planId) {
selectValue.value = [newProjectId, props.item.planId];
}
refreshHandler(newProjectId); refreshHandler(newProjectId);
}); });

View File

@ -132,10 +132,7 @@ export function getCommonBarOptions(
<div class="flex h-[18px] items-center justify-between"> <div class="flex h-[18px] items-center justify-between">
<div class="flex items-center"> <div class="flex items-center">
<div class="mb-[2px] mr-[8px] h-[8px] w-[8px] rounded-sm" style="background:${item.color}"></div> <div class="mb-[2px] mr-[8px] h-[8px] w-[8px] rounded-sm" style="background:${item.color}"></div>
<div class="one-line-text max-w-[100px] text-[var(--color-text-2)]">${item.seriesName.replace( <div class="one-line-text max-w-[100px] text-[var(--color-text-2)]">${item.seriesName}</div>
/\s\(\d+\)$/,
''
)}</div>
</div> </div>
<div class="text-[var(--color-text-1)] font-semibold">${addCommasToNumber(item.data.originValue || 0)}</div> <div class="text-[var(--color-text-1)] font-semibold">${addCommasToNumber(item.data.originValue || 0)}</div>
</div> </div>
@ -256,7 +253,7 @@ export function getCommonBarOptions(
ellipsis: '...', ellipsis: '...',
}, },
formatter(name: string) { formatter(name: string) {
return name.replace(/\s\(\d+\)$/, ''); // 去掉后缀 "(数字) 确保seriesName 重复也可以展示为正常" return name;
}, },
tooltip: { tooltip: {
show: true, show: true,
@ -320,7 +317,7 @@ export function getCommonBarOptions(
} }
// 下方饼图配置 // 下方饼图配置
export function getPieCharOptions(key: WorkCardEnum) { export function getPieCharOptions() {
return { return {
title: { title: {
show: true, show: true,
@ -341,7 +338,7 @@ export function getPieCharOptions(key: WorkCardEnum) {
}, },
textAlign: 'center', // 确保副标题居中 textAlign: 'center', // 确保副标题居中
}, },
color: colorMapConfig[key],
tooltip: { show: true }, tooltip: { show: true },
legend: { legend: {
show: false, show: false,
@ -351,6 +348,8 @@ export function getPieCharOptions(key: WorkCardEnum) {
type: 'pie', type: 'pie',
radius: ['75%', '90%'], radius: ['75%', '90%'],
center: [90, '48%'], center: [90, '48%'],
minAngle: 5, // 设置扇区的最小角度
minShowLabelAngle: 10, // 设置标签显示的最小角度
avoidLabelOverlap: false, avoidLabelOverlap: false,
label: { label: {
show: false, show: false,
@ -404,27 +403,29 @@ export function handlePieData(
}[] }[]
| null = [] | null = []
) { ) {
const options: Record<string, any> = getPieCharOptions(key); const options: Record<string, any> = getPieCharOptions();
const lastStatusPercentList = statusPercentList ?? []; const lastStatusPercentList = statusPercentList ?? [];
const hasDataLength = lastStatusPercentList.filter((e) => Number(e.count) > 0).length; const hasDataLength = lastStatusPercentList.filter((e) => Number(e.count) > 0).length;
const pieBorderWidth = hasDataLength === 1 ? 0 : 2; const pieBorderWidth = hasDataLength === 1 ? 0 : 2;
options.series.data = const lastData = lastStatusPercentList
hasDataLength > 0 .map((item, color) => ({
? lastStatusPercentList.map((item) => ({ name: item.status,
name: item.status, value: item.count,
value: item.count, tooltip: {
tooltip: { ...toolTipConfig,
...toolTipConfig, position: 'right',
position: 'right', show: !!hasPermission,
show: !!hasPermission, },
}, itemStyle: {
itemStyle: { color: colorMapConfig[key][color],
borderWidth: pieBorderWidth, borderWidth: pieBorderWidth,
borderColor: '#ffffff', borderColor: '#ffffff',
}, },
})) }))
: []; .filter((e) => e.value !== 0);
options.series.data = hasDataLength > 0 ? lastData : [];
// 计算总数和图例格式 // 计算总数和图例格式
const tempObject: Record<string, any> = {}; const tempObject: Record<string, any> = {};
@ -677,10 +678,7 @@ export function getSeriesData(
<div class="mb-[2px] mr-[8px] h-[8px] w-[8px] rounded-sm bg-[${params.color}]" style="background:${ <div class="mb-[2px] mr-[8px] h-[8px] w-[8px] rounded-sm bg-[${params.color}]" style="background:${
params.color params.color
}"></div> }"></div>
<div class="one-line-text max-w-[100px]"" style="color:#959598">${params.name.replace( <div class="one-line-text max-w-[100px]"" style="color:#959598">${params.name}</div>
/\s\(\d+\)$/,
''
)}</div>
</div> </div>
<div class="text-[var(--color-text-1)] font-semibold">${addCommasToNumber(params.value)}</div> <div class="text-[var(--color-text-1)] font-semibold">${addCommasToNumber(params.value)}</div>
</div> </div>