feat(工作台): 工作台测试计划概览联调

This commit is contained in:
xinxin.wu 2024-12-05 19:27:59 +08:00 committed by Craftsman
parent 95eedaa556
commit fdf4368320
5 changed files with 135 additions and 63 deletions

View File

@ -37,7 +37,7 @@
</div>
<!-- 概览图 -->
<div>
<MsChart ref="charRef" height="280px" :options="options" />
<MsChart ref="chartRef" height="280px" :options="options" />
</div>
</div>
</div>
@ -67,7 +67,7 @@
} from '@/models/workbench/homePage';
import { WorkCardEnum } from '@/enums/workbenchEnum';
import { getColorScheme, getSeriesData } from '../utils';
import { createCustomTooltip, getColorScheme, getSeriesData } from '../utils';
const { t } = useI18n();
@ -176,6 +176,7 @@
});
}
}
const chartRef = ref<InstanceType<typeof MsChart>>();
async function handleRefreshKeyChange() {
await nextTick(() => {
@ -187,8 +188,15 @@
}, 0);
}
onMounted(() => {
initOverViewDetail();
onMounted(async () => {
await initOverViewDetail();
setTimeout(() => {
const chartDom = chartRef.value?.chartRef;
if (chartDom && chartDom.chart) {
createCustomTooltip(chartDom);
}
}, 0);
});
watch(

View File

@ -37,7 +37,7 @@
</div>
<!-- 概览图 -->
<div class="mt-[16px]">
<MsChart height="300px" :options="options" />
<MsChart ref="chartRef" height="300px" :options="options" />
</div>
</div>
</div>
@ -60,7 +60,7 @@
import type { SelectedCardItem, TimeFormParams } from '@/models/workbench/homePage';
import { getColorScheme, getSeriesData } from '../utils';
import { createCustomTooltip, getColorScheme, getSeriesData } from '../utils';
const { t } = useI18n();
const appStore = useAppStore();
@ -132,6 +132,7 @@
value: e.id,
}));
}
const chartRef = ref<InstanceType<typeof MsChart>>();
async function handleProjectChange(isRefreshKey: boolean = false, setAll = false) {
await nextTick();
@ -146,7 +147,14 @@
}
}
await nextTick();
initOverViewMemberDetail();
await initOverViewMemberDetail();
setTimeout(() => {
const chartDom = chartRef.value?.chartRef;
if (chartDom && chartDom.chart) {
createCustomTooltip(chartDom);
}
}, 0);
}
async function changeProject() {

View File

@ -6,36 +6,41 @@
<a-tooltip :content="t(props.item.label)" position="tl" :mouse-enter-delay="300">
<div class="title one-line-text"> {{ t(props.item.label) }} </div>
</a-tooltip>
<div>
<!-- TODO 待处理 -->
<div class="cascader-wrapper-self relative flex justify-end">
<MsCascader
v-model:model-value="innerPlanId"
v-model:model-value="selectValue"
mode="native"
:default-value="innerPlanId"
allow-search
:allow-clear="false"
:default-value="defaultValue"
:options="projectOptions"
:prefix="t('workbench.homePage.plan')"
:placeholder="t('workbench.homePage.planOfPleaseSelect')"
:virtual-list-props="{ height: 200 }"
option-size="small"
class="test-plan-panel filter-item w-[240px]"
class="test-plan-panel w-[240px]"
label-path-mode
:panel-width="100"
path-mode
popup-container=".cascader-wrapper-self"
:search-option-only-label="true"
:load-more="loadMore"
@change="changeHandler"
>
<template v-if="labelPath" #label>
<a-tooltip :content="labelPath">
<div class="one-line-text inline-flex w-full items-center justify-between pr-[8px]" title="">
<template #label>
<a-tooltip :content="labelPath" :mouse-enter-delay="300">
<div class="one-line-text max-w-[200px] items-center justify-between pr-[8px]">
{{ labelPath }}
</div>
</a-tooltip>
</template>
<template #option="{ data }">
<a-tooltip :content="t(data.label)" :mouse-enter-delay="300">
<div class="one-line-text w-[120px]" title="">
<div :class="`flex ${data.isLeaf ? ' w-[130px]' : 'w-[120px]'} items-center`" title="">
<a-tooltip :mouse-enter-delay="300" :content="t(data.label)">
<div :class="`one-line-text ${data.isLeaf ? 'max-w-[85%]' : ''}`" title="">
{{ t(data.label) }}
</div>
</a-tooltip>
</div>
</template>
</MsCascader>
</div>
@ -81,7 +86,7 @@
</div>
</div>
<div>
<MsChart ref="charRef" height="280px" :options="options" />
<MsChart ref="chartRef" height="280px" :options="options" />
</div>
</div>
</div>
@ -110,7 +115,7 @@
import { TestPlanStatusEnum } from '@/enums/testPlanEnum';
import { WorkOverviewEnum, WorkOverviewIconEnum } from '@/enums/workbenchEnum';
import { getSeriesData } from '../utils';
import { createCustomTooltip, getSeriesData } from '../utils';
const { t } = useI18n();
@ -152,6 +157,7 @@
const options = ref<Record<string, any>>({});
const hasPermission = ref<boolean>(false);
const chartRef = ref<InstanceType<typeof MsChart>>();
const contentTabList: ModuleCardItem[] = [
{
@ -205,7 +211,10 @@
},
];
const selectValue = ref<string[]>([]);
const detail = ref();
const execOptions = ref<Record<string, any>>({
...commonRatePieOptions,
title: {
@ -241,7 +250,6 @@
const totalCount = detail.value?.caseCountMap?.totalCount ?? 0;
const executeCount = detail.value?.caseCountMap?.executeCount ?? 0;
const executeData = [
{
name: t('common.executed'),
@ -312,32 +320,36 @@
}
});
const labelPath = ref<string>('');
const labelPath = ref<string>();
const projectOptions = ref<{ value: string; label: string }[]>([]);
const childrenData = ref<Record<string, CascaderOption[]>>({});
function getLabelPath(id: string) {
const modules = findNodePathByKey(projectOptions.value, id, undefined, 'value');
const [newProjectId] = innerProjectIds.value;
const projectName = projectOptions.value.find((e) => e.value === newProjectId)?.label;
const treeList = childrenData.value[newProjectId];
const modules = findNodePathByKey(treeList, id, undefined, 'value');
if (modules) {
const moduleName = (modules || [])?.treePath.map((item: any) => item.label);
if (moduleName.length === 1) {
return moduleName[0];
return `${projectName}/${moduleName[0]}`;
}
return `${moduleName.join(' / ')}`;
return `${projectName}/${moduleName.join(' / ')}`;
}
}
async function changeHandler(value: string) {
innerPlanId.value = value;
innerPlanId.value = value[value.length - 1];
innerProjectIds.value = [value[0]];
await nextTick();
labelPath.value = getLabelPath(innerPlanId.value);
initOverViewDetail();
emit('change');
}
onMounted(() => {
initOverViewDetail();
});
async function loadMore(option: CascaderOption, done: (children?: CascaderOption[]) => void) {
try {
let testPlanOptionsNode = await getWorkTestPlanListUrl(option.value as string);
@ -350,36 +362,38 @@
});
done(testPlanOptionsNode);
projectOptions.value = projectOptions.value.map((item) => {
return {
...item,
children: testPlanOptionsNode,
};
});
childrenData.value[option.value as string] = testPlanOptionsNode;
labelPath.value = getLabelPath(innerPlanId.value);
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
}
}
let loadingProjectId: string | null = null;
function refreshHandler(newProjectId: string) {
async function refreshHandler(newProjectId: string) {
const cascaderOption = projectOptions.value.find((e) => e.value === newProjectId);
if (cascaderOption) {
loadMore(cascaderOption, (children) => {
loadMore(cascaderOption, (_children) => {
childrenData.value[cascaderOption.value as string] = _children?.length ? _children : [];
projectOptions.value = projectOptions.value.map((item) => {
return {
...item,
children: cascaderOption.value === item.value ? children : [],
children: childrenData.value[item.value]?.length ? childrenData.value[item.value] : null,
isLeaf: false,
};
});
labelPath.value = getLabelPath(innerPlanId.value);
});
}
initOverViewDetail();
await initOverViewDetail();
setTimeout(() => {
const chartDom = chartRef.value?.chartRef;
if (chartDom && chartDom.chart) {
createCustomTooltip(chartDom);
}
}, 0);
}
async function handleRefreshKeyChange() {
@ -392,21 +406,17 @@
labelPath.value = getLabelPath(innerPlanId.value);
}
watch(
() => props.item.projectIds,
async (val) => {
if (val) {
const [newProjectId] = val;
projectOptions.value = appStore.projectList.map((e) => ({ value: e.id, label: e.name }));
const defaultValue = computed(() => {
const [newProjectId] = innerProjectIds.value;
return [newProjectId, innerPlanId.value];
});
if (loadingProjectId !== newProjectId) {
loadingProjectId = newProjectId;
onMounted(() => {
projectOptions.value = appStore.projectList.map((e) => ({ value: e.id, label: e.name }));
const [newProjectId] = props.item.projectIds;
selectValue.value = [newProjectId, props.item.planId];
refreshHandler(newProjectId);
}
}
},
{ immediate: true }
);
});
watch(
() => timeForm.value,
@ -457,6 +467,11 @@
@apply flex flex-col justify-center;
}
}
.cascader-wrapper-self {
:deep(.arco-trigger-position-bl) {
transform: translateX(-8%);
}
}
</style>
<style lang="less">

View File

@ -61,7 +61,7 @@
}
.popover-trigger-content {
padding: 8px 16px;
width: 120px;
width: 140px;
border-radius: var(--border-radius-small);
background-color: var(--color-text-fff);
box-shadow: 0 4px 10px -1px rgb(100 100 102 / 15%);

View File

@ -9,6 +9,8 @@ import type { ModuleCardItem, OverViewOfProject } from '@/models/workbench/homeP
import { RouteEnum } from '@/enums/routeEnum';
import { WorkCardEnum, WorkNavValueEnum } from '@/enums/workbenchEnum';
import VCharts from 'vue-echarts';
const { t } = useI18n();
// TODO 通用颜色配置注: 目前柱状图只用到了7种色阶其他色阶暂时保留
const commonColorConfig: Record<number, string[]> = {
@ -152,6 +154,7 @@ export function getCommonBarOptions(hasRoom: boolean, color: string[], isTestPla
boundaryGap: true,
type: 'category',
data: [],
triggerEvent: true,
axisLabel: {
show: true,
color: '#646466',
@ -162,13 +165,16 @@ export function getCommonBarOptions(hasRoom: boolean, color: string[], isTestPla
showMaxLabel: true,
// TOTO 等待优化
interval: 0,
triggerEvent: true,
},
axisPointer: {
type: 'shadow',
},
axisTick: {
show: true,
alignWithLabel: true,
lineStyle: {
color: 'transparent',
},
},
axisLine: {
lineStyle: {
@ -722,3 +728,38 @@ export function getSeriesData(
return options;
}
export function createCustomTooltip(chartDom: InstanceType<typeof VCharts>) {
if (chartDom && chartDom.chart) {
const customTooltip = document.createElement('div');
customTooltip.style.position = 'absolute';
customTooltip.style.maxWidth = '300px';
customTooltip.style.padding = '5px';
customTooltip.style.background = 'rgba(0, 0, 0, 0.75)';
customTooltip.style.color = 'var(--color-text-fff)';
customTooltip.style.borderRadius = '4px';
customTooltip.style.display = 'none';
document.body.appendChild(customTooltip);
// 针对x轴 监听鼠标悬浮事件
chartDom.chart.on('mouseover', 'xAxis', (params) => {
const event = params.event?.event as unknown as MouseEvent;
if (params.componentType === 'xAxis') {
const { clientX, clientY } = event;
customTooltip.textContent = `${params.value}`;
customTooltip.style.display = 'block';
customTooltip.style.left = `${clientX - 20}px`;
customTooltip.style.top = `${clientY + 10}px`;
}
});
// 针对x轴 监听鼠标离开事件
chartDom.chart.on('mouseout', 'xAxis', () => {
customTooltip.style.display = 'none';
});
}
}