feat(测试计划): 测试计划报告优化测试集接口联调

This commit is contained in:
xinxin.wu 2024-09-14 12:22:03 +08:00 committed by Craftsman
parent 2217d40ce1
commit 4436083f8c
11 changed files with 430 additions and 167 deletions

View File

@ -11,7 +11,7 @@ import {
UpdateReportDetailParams,
} from '@/models/testPlan/report';
import type { ExecuteHistoryItem } from '@/models/testPlan/testPlan';
import { manualReportGenParams, PlanReportDetail } from '@/models/testPlan/testPlanReport';
import { manualReportGenParams, PlanReportDetail, testPlanSetItem } from '@/models/testPlan/testPlanReport';
// 报告列表
export function reportList(data: TableQueryParams) {
@ -187,3 +187,26 @@ export function logTestPlanReportBatchExport(data: BatchApiParams) {
export function testPlanBatchReportExportGetIds(data: BatchApiParams) {
return MSR.post<string[]>({ url: reportUrl.TestPlanBatchReportExportGetIdsUrl, data });
}
// 报告-详情-用例明细测试点
export function getCollectFunctionalPage(data: TableQueryParams) {
if (data.shareId) {
return MSR.post<CommonList<testPlanSetItem>>({ url: `${reportUrl.getShareCollectFunctionalUrl}`, data });
}
return MSR.post<CommonList<testPlanSetItem>>({ url: `${reportUrl.getCollectFunctionalUrl}`, data });
}
// 报告-详情-接口明细测试点
export function getCollectApiPage(data: TableQueryParams) {
if (data.shareId) {
return MSR.post<CommonList<testPlanSetItem>>({ url: `${reportUrl.getShareCollectionApiUrl}`, data });
}
return MSR.post<CommonList<testPlanSetItem>>({ url: `${reportUrl.getCollectApiUrl}`, data });
}
// 报告-详情-场景明细测试点
export function getCollectScenarioPage(data: TableQueryParams) {
if (data.shareId) {
return MSR.post<CommonList<testPlanSetItem>>({ url: `${reportUrl.getShareCollectScenarioUrl}`, data });
}
return MSR.post<CommonList<testPlanSetItem>>({ url: `${reportUrl.getCollectScenarioUrl}`, data });
}
export default {};

View File

@ -74,3 +74,15 @@ export const TestPlanReportExportUrl = '/test-plan/report/export';
export const TestPlanBatchReportExportUrl = '/test-plan/report/batch-export';
// 测试计划-报告-批量导出获取报告 ID 集合
export const TestPlanBatchReportExportGetIdsUrl = '/test-plan/report/batch-param';
// 测试计划-报告-详情-报告-用例明细-测试点
export const getCollectFunctionalUrl = '/test-plan/report/detail/functional/collection/page';
// 测试计划-报告-详情-报告-接口明细-测试点
export const getCollectApiUrl = '/test-plan/report/detail/api/collection/page';
// 测试计划-报告-详情-报告-场景明细-测试点
export const getCollectScenarioUrl = '/test-plan/report/detail/scenario/collection/page';
// 测试计划-报告-详情-分享-报告-用例明细-测试点
export const getShareCollectFunctionalUrl = '/test-plan/report/share/detail/functional/collection/page';
// 测试计划-报告-详情-分享-报告-接口明细-测试点
export const getShareCollectionApiUrl = '/test-plan/report/share/detail/api/collection/page';
// 测试计划-报告-详情-分享-报告-场景明细-测试点
export const getShareCollectScenarioUrl = '/test-plan/report/share/detail/scenario/collection/page';

View File

@ -98,3 +98,11 @@ export type SelectedReportCardTypes =
| ReportCardTypeEnum.FUNCTIONAL_DETAIL
| ReportCardTypeEnum.API_CASE_DETAIL
| ReportCardTypeEnum.SCENARIO_CASE_DETAIL;
// 测试集列表
export interface testPlanSetItem {
id: string;
name: string; // 测试集名称
count: number;
planName: string; // 计划名称
}

View File

@ -0,0 +1,40 @@
import { defineStore } from 'pinia';
import { ReportCardTypeEnum } from '@/enums/testPlanReportEnum';
export interface testSetConfigType {
TEST_PLAN: Record<keyof typeof ReportCardTypeEnum, boolean>;
GROUP: Record<keyof typeof ReportCardTypeEnum, boolean>;
}
const useTestPlanReportStore = defineStore('testPlanReport', {
persist: true,
state: (): {
testSetConfig: Record<string, Record<string, boolean>>;
} => ({
testSetConfig: {
TEST_PLAN: {
[ReportCardTypeEnum.FUNCTIONAL_DETAIL]: false,
[ReportCardTypeEnum.API_CASE_DETAIL]: false,
[ReportCardTypeEnum.SCENARIO_CASE_DETAIL]: false,
},
GROUP: {
[ReportCardTypeEnum.FUNCTIONAL_DETAIL]: false,
[ReportCardTypeEnum.API_CASE_DETAIL]: false,
[ReportCardTypeEnum.SCENARIO_CASE_DETAIL]: false,
},
},
}),
actions: {
setTestStatus(isGroup: boolean, enable: boolean, cardType: ReportCardTypeEnum) {
const testSetKey: 'TEST_PLAN' | 'GROUP' = isGroup ? 'GROUP' : 'TEST_PLAN';
this.testSetConfig[testSetKey][cardType as keyof typeof ReportCardTypeEnum] = enable;
},
getTestStatus(isGroup: boolean, cardType: ReportCardTypeEnum) {
const testSetKey: 'TEST_PLAN' | 'GROUP' = isGroup ? 'GROUP' : 'TEST_PLAN';
return this.testSetConfig[testSetKey][cardType as keyof typeof ReportCardTypeEnum];
},
},
});
export default useTestPlanReportStore;

View File

@ -1,5 +1,5 @@
<template>
<div :class="`${props.enabledTestSet ? 'test-set-wrapper test-set-cell' : ''}`">
<div :class="`${props.enabledTestSet ? 'test-set-wrapper' : ''}`">
<MsBaseTable v-bind="currentCaseTable.propsRes.value" v-on="currentCaseTable.propsEvent.value">
<template #num="{ record }">
<MsButton type="text" @click="toDetail(record)">{{ record.num }}</MsButton>
@ -38,7 +38,7 @@
</div>
</template>
<script setup lang="ts" async>
<script setup lang="ts">
import MsButton from '@/components/pure/ms-button/index.vue';
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
import type { MsTableColumn } from '@/components/pure/ms-table/type';
@ -76,15 +76,16 @@
const props = defineProps<{
reportId: string;
enabledTestSet: boolean;
testSetId?: string; // id
shareId?: string;
activeType: ReportCardTypeEnum;
isPreview?: boolean;
isGroup?: boolean;
}>();
const innerKeyword = defineModel<string>('keyword', {
required: true,
});
const isGroup = inject<Ref<boolean>>('isPlanGroup', ref(false));
const staticColumns: MsTableColumn = [
{
@ -137,7 +138,8 @@
showTooltip: true,
width: 200,
showInTable: true,
showDrag: true,
showDrag: false,
columnSelectorDisabled: true,
},
];
const lastStaticColumns: MsTableColumn = [
@ -174,7 +176,7 @@
];
const columns = computed(() => {
if (props.isGroup) {
if (isGroup.value) {
return [...staticColumns, ...testPlanNameColumns, ...lastStaticColumns];
}
return [...staticColumns, ...lastStaticColumns];
@ -192,7 +194,7 @@
};
const tableKey = computed(() => {
if (props.isGroup) {
if (isGroup.value) {
return keyMap.GROUP[props.activeType];
}
return keyMap.TEST_PLAN[props.activeType];
@ -229,6 +231,7 @@
reportId: props.reportId,
shareId: props.shareId ?? undefined,
keyword: innerKeyword.value,
collectionId: props.testSetId,
});
currentCaseTable.value.loadList();
}
@ -259,13 +262,27 @@
}
}
onMounted(() => {
if (props.reportId) {
currentCaseTable.value.resetPagination();
loadCaseList();
}
});
watch(
[() => props.reportId, () => props.isPreview],
() => {
if (props.reportId && props.isPreview) {
() => props.reportId,
(val) => {
if (val) {
currentCaseTable.value.resetPagination();
loadCaseList();
} else {
}
}
);
watch(
() => props.isPreview,
(val) => {
if (!val) {
currentCaseTable.value.propsRes.value.data = detailTableExample[props.activeType];
}
},

View File

@ -1,4 +1,18 @@
<template>
<div class="mb-[8px] flex items-center justify-between">
<div class="font-medium"> {{ props.label }} </div>
<div v-if="props.isPreview" class="flex items-center">
<a-input-search
v-model:model-value="keyword"
:placeholder="t('common.searchByIdName')"
allow-clear
class="w-[240px]"
@search="loadCaseList"
@press-enter="loadCaseList"
@clear="loadCaseList"
/>
</div>
</div>
<MsBaseTable v-bind="propsRes" v-on="propsEvent">
<template #num="{ record }">
<MsButton :disabled="!props.isPreview" type="text" @click="toDetail(record)">{{ record.num }}</MsButton>
@ -16,6 +30,7 @@
import useTable from '@/components/pure/ms-table/useTable';
import { getReportBugList, getReportShareBugList } from '@/api/modules/test-plan/report';
import { useI18n } from '@/hooks/useI18n';
import useOpenNewPage from '@/hooks/useOpenNewPage';
import { ReportBugItem } from '@/models/testPlan/report';
@ -24,14 +39,19 @@
import { detailTableExample } from '@/views/test-plan/report/detail/component/reportConfig';
const { t } = useI18n();
const { openNewPage } = useOpenNewPage();
const props = defineProps<{
reportId: string;
shareId?: string;
isPreview?: boolean;
label: string;
}>();
const keyword = ref<string>('');
const sortableConfig = computed<TableSortable | undefined>(() => {
return props.isPreview
? {
@ -86,8 +106,8 @@
showSelectorAll: false,
});
async function loadCaseList() {
setLoadListParams({ reportId: props.reportId, shareId: props.shareId ?? undefined });
function loadCaseList() {
setLoadListParams({ reportId: props.reportId, shareId: props.shareId ?? undefined, keyword: keyword.value });
loadList();
}
@ -98,12 +118,25 @@
});
}
onMounted(() => {
if (props.reportId) {
loadCaseList();
}
});
watch(
[() => props.reportId, () => props.isPreview],
() => {
if (props.reportId && props.isPreview) {
() => props.reportId,
(val) => {
if (val) {
loadCaseList();
} else {
}
}
);
watch(
() => props.isPreview,
(val) => {
if (!val) {
propsRes.value.data = detailTableExample[ReportCardTypeEnum.BUG_DETAIL];
}
},

View File

@ -1,5 +1,5 @@
<template>
<div :class="`${props.enabledTestSet ? 'test-set-wrapper test-set-cell' : ''}`">
<div :class="`${props.enabledTestSet ? 'test-set-wrapper' : ''}`">
<MsBaseTable v-bind="propsRes" v-on="propsEvent">
<template #num="{ record }">
<MsButton :disabled="!props.isPreview" type="text" @click="toDetail(record)">{{ record.num }}</MsButton>
@ -17,7 +17,6 @@
</MsButton>
</template>
<template #expand-icon="{ record, expanded }">
<!-- TODO 待联调 -->
<div
class="flex items-end gap-[2px] text-[var(--color-text-4)]"
:class="[
@ -84,9 +83,9 @@
const props = defineProps<{
enabledTestSet: boolean; //
reportId: string;
testSetId?: string; // id
shareId?: string;
isPreview?: boolean;
isGroup?: boolean;
}>();
const { t } = useI18n();
@ -102,6 +101,7 @@
}
: undefined;
});
const isGroup = inject<Ref<boolean>>('isPlanGroup', ref(false));
const staticColumns: MsTableColumn = [
{
@ -186,13 +186,14 @@
dataIndex: 'planName',
showTooltip: true,
showInTable: true,
showDrag: true,
showDrag: false,
columnSelectorDisabled: true,
width: 200,
},
];
const columns = computed(() => {
if (props.isGroup) {
if (isGroup.value) {
return [...staticColumns, ...testPlanNameColumns, ...lastStaticColumns];
}
return [...staticColumns, ...lastStaticColumns];
@ -203,7 +204,7 @@
};
const tableKey = computed(() =>
props.isGroup
isGroup.value
? TableKeyEnum.TEST_PLAN_REPORT_FUNCTIONAL_TABLE_GROUP
: TableKeyEnum.TEST_PLAN_REPORT_FUNCTIONAL_TABLE
);
@ -219,7 +220,12 @@
});
async function loadCaseList() {
setLoadListParams({ reportId: props.reportId, keyword: innerKeyword.value, shareId: props.shareId ?? undefined });
setLoadListParams({
reportId: props.reportId,
keyword: innerKeyword.value,
shareId: props.shareId ?? undefined,
collectionId: props.testSetId,
});
loadList();
}
//
@ -231,19 +237,20 @@
}
watch(
[() => props.reportId, () => props.isPreview],
() => {
if (props.reportId && props.isPreview) {
() => props.reportId,
(val) => {
if (val) {
loadCaseList();
} else {
propsRes.value.data = detailTableExample[ReportCardTypeEnum.FUNCTIONAL_DETAIL];
}
},
{
immediate: true,
}
);
onMounted(() => {
if (props.isPreview && props.reportId) {
loadCaseList();
}
});
const showDetailVisible = ref<boolean>(false);
const executeReportId = ref<string>('');
@ -272,6 +279,18 @@
getExecuteStep();
}
watch(
() => props.isPreview,
(val) => {
if (!val) {
propsRes.value.data = detailTableExample[ReportCardTypeEnum.FUNCTIONAL_DETAIL];
}
},
{
immediate: true,
}
);
defineExpose({
loadCaseList,
});

View File

@ -1,4 +1,38 @@
<template>
<div class="mb-[8px] flex items-center justify-between">
<div class="font-medium"> {{ props.label }} </div>
<div v-if="props.isPreview" class="flex items-center">
<a-input-search
v-model:model-value="keyword"
:placeholder="t('common.searchByIdName')"
allow-clear
class="mr-[8px] w-[240px]"
@search="loadReportDetailList"
@press-enter="loadReportDetailList"
@clear="loadReportDetailList"
/>
<a-radio-group
v-if="props.isPreview"
v-model:model-value="currentMode"
type="button"
size="medium"
@change="handleModeChange"
>
<a-radio value="drawer">
<div class="mode-button">
<MsIcon :class="{ 'active-color': currentMode === 'drawer' }" type="icon-icon_drawer" />
<span class="mode-button-title">{{ t('msTable.columnSetting.drawer') }}</span>
</div>
</a-radio>
<a-radio value="new_window">
<div class="mode-button">
<MsIcon :class="{ 'active-color': currentMode === 'new_window' }" type="icon-icon_into-item_outlined" />
<span class="mode-button-title">{{ t('msTable.columnSetting.newWindow') }}</span>
</div>
</a-radio>
</a-radio-group>
</div>
</div>
<MsBaseTable v-bind="propsRes" no-disable filter-icon-align-left v-on="propsEvent">
<template #passRateTitle="{ columnConfig }">
<div class="flex items-center text-[var(--color-text-3)]">
@ -66,11 +100,10 @@
reportId: string;
shareId?: string;
isPreview?: boolean;
label?: string;
}>();
const innerCurrentMode = defineModel<string>('currentMode', {
default: 'drawer',
});
const keyword = ref<string>('');
const statusResultOptions = computed(() => {
return Object.keys(PlanReportStatus).map((key) => {
@ -149,16 +182,14 @@
);
function loadReportDetailList() {
setLoadListParams({ reportId: props.reportId, shareId: props.shareId ?? undefined });
setLoadListParams({ reportId: props.reportId, shareId: props.shareId ?? undefined, keyword: keyword.value });
loadList();
}
watch(
[() => props.reportId, () => props.isPreview],
() => {
if (props.reportId && props.isPreview) {
loadReportDetailList();
} else {
() => props.isPreview,
(val) => {
if (!val) {
propsRes.value.data = detailTableExample[ReportCardTypeEnum.SUB_PLAN_DETAIL];
}
},
@ -167,13 +198,29 @@
}
);
onMounted(() => {
if (props.reportId) {
loadReportDetailList();
}
});
watch(
() => props.reportId,
(val) => {
if (val) {
loadReportDetailList();
}
}
);
const reportVisible = ref(false);
const independentReportId = ref<string>('');
const currentMode = ref<string>('drawer');
function openReport(record: PlanReportDetail) {
independentReportId.value = record.id;
if (innerCurrentMode.value === 'drawer') {
if (currentMode.value === 'drawer') {
reportVisible.value = true;
} else {
openNewPage(RouteEnum.TEST_PLAN_REPORT_DETAIL, {
@ -181,6 +228,10 @@
});
}
}
function handleModeChange(value: string | number | boolean, ev: Event) {
currentMode.value = value as string;
}
</script>
<style scoped></style>

View File

@ -4,21 +4,25 @@
v-bind="propsRes"
:expanded-keys="expandedKeys"
:expandable="expandable"
row-class="test-set-expand-tr"
v-on="propsEvent"
@expand="(record) => handleExpand(record.id as string)"
>
<template #expand-icon="{ record, expanded }">
<div
class="flex items-end gap-[2px] text-[var(--color-text-4)]"
:class="[
expanded ? '!text-[rgb(var(--primary-5))]' : '',
record.testSetCount === 0 ? 'cursor-not-allowed' : '',
]"
:class="[expanded ? '!text-[rgb(var(--primary-5))]' : '', record.count === 0 ? 'cursor-not-allowed' : '']"
>
<MsIcon type="icon-icon_split_turn-down_arrow" />
<div v-if="record.testSetCount" class="break-keep">{{ record.testSetCount }}</div>
<div v-if="record.count" class="break-keep">{{ record.count }}</div>
</div>
</template>
<template #other>
<span></span>
</template>
<template #empty>
<span></span>
</template>
</MsBaseTable>
</template>
@ -29,12 +33,11 @@
import ApiAndScenarioTable from '@/views/test-plan/report/detail/component/system-card/apiAndScenarioTable.vue';
import FeatureCaseTable from '@/views/test-plan/report/detail/component/system-card/featureCaseTable.vue';
import { getReportFeatureCaseList, getReportShareFeatureCaseList } from '@/api/modules/test-plan/report';
import { getCollectApiPage, getCollectFunctionalPage, getCollectScenarioPage } from '@/api/modules/test-plan/report';
import type { SelectedReportCardTypes } from '@/models/testPlan/testPlanReport';
import { ReportCardTypeEnum } from '@/enums/testPlanReportEnum';
import { detailTableExample } from '@/views/test-plan/report/detail/component/reportConfig';
const props = defineProps<{
enabledTestSet: boolean;
activeType: ReportCardTypeEnum; //
@ -42,24 +45,25 @@
reportId: string;
shareId?: string;
isPreview?: boolean;
isGroup?: boolean;
}>();
const expandedKeys = ref<string[]>([]);
const isGroup = inject<Ref<boolean>>('isPlanGroup', ref(false));
const expandable = reactive({
title: '',
width: 30,
expandedRowRender: (record: Record<string, any>) => {
if (record.testSetCount) {
if (record.count) {
if (props.activeType === ReportCardTypeEnum.FUNCTIONAL_DETAIL) {
return h(FeatureCaseTable, {
keyword: props.keyword,
reportId: props.reportId,
shareId: props.shareId,
isPreview: props.isPreview,
isGroup: props.isGroup,
isGroup: isGroup.value,
enabledTestSet: props.enabledTestSet,
testSetId: record.id,
});
}
if (
@ -72,8 +76,9 @@
reportId: props.reportId,
shareId: props.shareId,
isPreview: props.isPreview,
isGroup: props.isGroup,
isGroup: isGroup.value,
enabledTestSet: props.enabledTestSet,
testSetId: record.id,
});
}
}
@ -89,53 +94,98 @@
}
};
const testSetColumns: MsTableColumn = [
{
title: 'ms.case.associate.testSet',
dataIndex: 'testSetName',
showInTable: true,
showDrag: true,
width: 200,
},
{
title: 'report.plan.name',
dataIndex: 'planName',
showInTable: true,
showDrag: true,
width: 300,
},
];
const columns = computed<MsTableColumn>(() => {
if (isGroup.value) {
return [
{
title: 'ms.case.associate.testSet',
dataIndex: 'name',
showInTable: true,
showDrag: true,
width: 200,
},
{
title: 'report.plan.name',
dataIndex: 'planName',
showInTable: true,
showDrag: true,
width: 300,
},
{
title: '',
dataIndex: 'other',
slotName: 'other',
showInTable: true,
showDrag: true,
width: 300,
},
];
}
return [
{
title: 'ms.case.associate.testSet',
dataIndex: 'name',
showInTable: true,
showDrag: true,
width: 200,
},
//
{
title: '',
dataIndex: 'other',
slotName: 'other',
showInTable: true,
showDrag: true,
width: 300,
},
{
title: '',
dataIndex: 'empty',
slotName: 'empty',
showInTable: true,
showDrag: true,
width: 300,
},
];
});
const reportFeatureCaseList = () => {
return !props.shareId ? getReportFeatureCaseList : getReportShareFeatureCaseList;
const apiMap: Record<SelectedReportCardTypes, any> = {
[ReportCardTypeEnum.FUNCTIONAL_DETAIL]: getCollectFunctionalPage,
[ReportCardTypeEnum.API_CASE_DETAIL]: getCollectApiPage,
[ReportCardTypeEnum.SCENARIO_CASE_DETAIL]: getCollectScenarioPage,
};
const { propsRes, propsEvent, loadList, setLoadListParams } = useTable(reportFeatureCaseList(), {
columns: testSetColumns,
const getReportTestSetList = () => {
return apiMap[props.activeType as SelectedReportCardTypes];
};
const { propsRes, propsEvent, loadList, setLoadListParams } = useTable(getReportTestSetList(), {
columns: columns.value,
scroll: { x: '100%' },
heightUsed: 320,
showSelectorAll: false,
});
// TODO
async function loadCaseList() {
function loadCaseList() {
if (props.enabledTestSet) {
expandedKeys.value = [];
}
// setLoadListParams({ reportId: props.reportId, keyword: props.keyword, shareId: props.shareId ?? undefined });
// loadList();
setLoadListParams({ reportId: props.reportId, keyword: props.keyword, shareId: props.shareId });
loadList();
}
onMounted(() => {
if (props.reportId) {
loadCaseList();
}
});
watch(
[() => props.reportId, () => props.isPreview],
() => {
if (props.reportId && props.isPreview) {
// TODO
// loadCaseList();
} else {
propsRes.value.data = detailTableExample[ReportCardTypeEnum.FUNCTIONAL_DETAIL];
() => props.reportId,
(val) => {
if (val) {
loadCaseList();
}
},
{
immediate: true,
}
);
@ -174,8 +224,18 @@
}
}
}
:deep(.arco-table-tr-expand) {
> .arco-table-td {
> .arco-table-cell {
padding: 8px !important;
}
}
}
:deep(.arco-table-tr-expand .arco-table-cell) {
padding: 12px !important;
padding: 8px 16px !important;
}
:deep(.arco-table-cell-with-sorter) {
margin: 8px 0 !important;
}
:deep(.arco-table .arco-table-tr-expand .arco-table-td .arco-table) {
margin: 0 !important;
@ -196,4 +256,11 @@
:deep(.arco-table-tr-expand .arco-table-td .arco-table .arco-table-td) {
border-color: var(--color-text-n8) !important;
}
:deep(.arco-table-tr.test-set-expand-tr) {
&:hover {
> .arco-table-td {
background: white !important;
}
}
}
</style>

View File

@ -2,8 +2,8 @@
<div class="mb-[8px] flex items-center justify-between">
<div class="font-medium"> {{ props.label }} </div>
<div v-if="props.isPreview" class="flex items-center">
<a-switch v-model:model-value="enabledTestSet" size="small" />
<span class="mx-[8px]"> {{ t('ms.case.associate.testSet') }}</span>
<a-switch v-model:model-value="enabledTestSet" size="small" @change="(val)=>changeHandler(val as boolean)" />
<span class="mx-[16px]"> {{ t('ms.case.associate.testSet') }}</span>
<a-input-search
v-model:model-value="keyword"
:placeholder="t('common.searchByIdName')"
@ -17,41 +17,34 @@
</div>
<!-- 开启测试集 -->
<TestSetTable
v-if="enabledTestSet"
v-if="showSetTable"
ref="testSetTableRef"
v-model:keyword="keyword"
:active-type="props.activeType"
:report-id="props.reportId"
:share-id="props.shareId"
:is-preview="props.isPreview"
:is-group="props.isGroup"
:enabled-test-set="enabledTestSet"
/>
<!-- 功能用例明细 -->
<FeatureCaseTable
v-else-if="props.activeType === ReportCardTypeEnum.FUNCTIONAL_DETAIL && !enabledTestSet"
v-if="showFeatureTable"
ref="featureCaseTableRef"
v-model:keyword="keyword"
:report-id="props.reportId"
:share-id="props.shareId"
:is-preview="props.isPreview"
:is-group="props.isGroup"
:enabled-test-set="enabledTestSet"
/>
<!-- 接口用例明细和场景用例明细 -->
<ApiAndScenarioTable
v-else-if="
(props.activeType === ReportCardTypeEnum.API_CASE_DETAIL ||
props.activeType === ReportCardTypeEnum.SCENARIO_CASE_DETAIL) &&
!enabledTestSet
"
v-if="showApiAndScenario"
ref="apiAndScenarioTableRef"
v-model:keyword="keyword"
:active-type="props.activeType"
:report-id="props.reportId"
:share-id="props.shareId"
:is-preview="props.isPreview"
:is-group="props.isGroup"
:keyword="keyword"
:enabled-test-set="enabledTestSet"
/>
</template>
@ -62,6 +55,7 @@
import FeatureCaseTable from '@/views/test-plan/report/detail/component/system-card/featureCaseTable.vue';
import { useI18n } from '@/hooks/useI18n';
import useTestPlanReportStore from '@/store/modules/testPlan/testPlanReport';
import { ReportCardTypeEnum } from '@/enums/testPlanReportEnum';
@ -71,17 +65,25 @@
label: string;
shareId?: string;
isPreview?: boolean;
isGroup?: boolean;
}>();
const { t } = useI18n();
const enabledTestSet = ref<boolean>(false);
const testPlanReportStore = useTestPlanReportStore();
const keyword = ref<string>('');
const testSetTableRef = ref<InstanceType<typeof TestSetTable>>();
const featureCaseTableRef = ref<InstanceType<typeof TestSetTable>>();
const apiAndScenarioTableRef = ref<InstanceType<typeof TestSetTable>>();
const isGroup = inject<Ref<boolean>>('isPlanGroup', ref(false));
const enabledTestSet = computed({
set: (val) => {
testPlanReportStore.setTestStatus(isGroup.value, val, props.activeType);
},
get: () => {
return testPlanReportStore.getTestStatus(isGroup.value, props.activeType);
},
});
function searchList() {
if (enabledTestSet.value) {
@ -96,6 +98,33 @@
keyword.value = '';
searchList();
}
const showFeatureTable = computed(() => {
if (props.isPreview) {
return props.activeType === ReportCardTypeEnum.FUNCTIONAL_DETAIL && !enabledTestSet.value;
}
return props.activeType === ReportCardTypeEnum.FUNCTIONAL_DETAIL;
});
const showApiAndScenario = computed(() => {
if (props.isPreview) {
return (
(props.activeType === ReportCardTypeEnum.API_CASE_DETAIL ||
props.activeType === ReportCardTypeEnum.SCENARIO_CASE_DETAIL) &&
!enabledTestSet.value
);
}
return (
props.activeType === ReportCardTypeEnum.API_CASE_DETAIL ||
props.activeType === ReportCardTypeEnum.SCENARIO_CASE_DETAIL
);
});
const showSetTable = computed(() => (props.isPreview ? enabledTestSet.value : false));
function changeHandler(value: boolean) {
testPlanReportStore.setTestStatus(isGroup.value, value, props.activeType);
}
</script>
<style lang="less" scoped>
@ -105,9 +134,4 @@
@apply overflow-y-auto bg-white;
.ms-scroll-bar();
}
.test-set-cell {
:deep(.arco-table-cell) {
padding: 8px 16px !important;
}
}
</style>

View File

@ -140,39 +140,16 @@
</div>
<div class="wrapper-preview-card">
<div class="flex items-center justify-between">
<div v-if="!notShowLabel.includes(item.value)" class="mb-[8px] font-medium">
<div v-if="item.value === ReportCardTypeEnum.SUMMARY" class="mb-[8px] font-medium">
{{ t(item.label) }}
</div>
<a-radio-group
v-if="item.value === ReportCardTypeEnum.SUB_PLAN_DETAIL && props.isPreview"
class="mb-2"
:model-value="currentMode"
type="button"
@change="handleModeChange"
>
<a-radio value="drawer">
<div class="mode-button">
<MsIcon :class="{ 'active-color': currentMode === 'drawer' }" type="icon-icon_drawer" />
<span class="mode-button-title">{{ t('msTable.columnSetting.drawer') }}</span>
</div>
</a-radio>
<a-radio value="new_window">
<div class="mode-button">
<MsIcon
:class="{ 'active-color': currentMode === 'new_window' }"
type="icon-icon_into-item_outlined"
/>
<span class="mode-button-title">{{ t('msTable.columnSetting.newWindow') }}</span>
</div>
</a-radio>
</a-radio-group>
</div>
<ReportDetailTable
v-if="item.value === ReportCardTypeEnum.SUB_PLAN_DETAIL"
v-model:current-mode="currentMode"
:report-id="detail.id"
:share-id="shareId"
:is-preview="props.isPreview"
:label="t(item.label)"
/>
<Summary
v-if="item.value === ReportCardTypeEnum.SUMMARY"
@ -193,14 +170,14 @@
:report-id="detail.id"
:share-id="shareId"
:is-preview="props.isPreview"
:label="t(item.label)"
/>
<TestSetTable
<TestSetTableIndex
v-else-if="hasTestSet.includes(item.value)"
:report-id="detail.id"
:share-id="shareId"
:active-type="item.value"
:is-preview="props.isPreview"
:is-group="props.isGroup"
:label="t(item.label)"
/>
<CustomRichText
@ -240,7 +217,7 @@
import ReportMetricsItem from '@/views/test-plan/report/detail/component/system-card/ReportMetricsItem.vue';
import Summary from '@/views/test-plan/report/detail/component/system-card/summary.vue';
import SystemTrigger from '@/views/test-plan/report/detail/component/system-card/systemTrigger.vue';
import TestSetTable from '@/views/test-plan/report/detail/component/system-card/testTableIndex.vue';
import TestSetTableIndex from '@/views/test-plan/report/detail/component/system-card/testTableIndex.vue';
import { getReportLayout, updateReportDetail } from '@/api/modules/test-plan/report';
import {
@ -306,19 +283,13 @@
const getAnalysisHover = computed(() => (props.isPreview ? '' : 'hover-analysis cursor-not-allowed'));
const notShowLabel = [
ReportCardTypeEnum.CUSTOM_CARD,
ReportCardTypeEnum.FUNCTIONAL_DETAIL,
ReportCardTypeEnum.API_CASE_DETAIL,
ReportCardTypeEnum.SCENARIO_CASE_DETAIL,
];
const isPlanGroup = ref(props.isGroup);
provide('isPlanGroup', isPlanGroup);
const hasTestSet = [
ReportCardTypeEnum.FUNCTIONAL_DETAIL,
ReportCardTypeEnum.API_CASE_DETAIL,
ReportCardTypeEnum.SCENARIO_CASE_DETAIL,
];
/**
* 分享share
*/
@ -543,23 +514,27 @@
const isDefaultLayout = ref<boolean>(false);
watchEffect(() => {
if (props.detailInfo) {
detail.value = cloneDeep(props.detailInfo);
const { defaultLayout, id, name, summary } = detail.value;
isDefaultLayout.value = defaultLayout;
richText.value.summary = summary;
reportForm.value.reportName = name;
initOptionsData();
if (props.isPreview) {
if (!defaultLayout && id) {
getDefaultLayout();
} else {
innerCardList.value = props.isGroup ? cloneDeep(defaultGroupConfig) : cloneDeep(defaultSingleConfig);
watch(
() => props.detailInfo,
(val) => {
if (val) {
detail.value = cloneDeep(props.detailInfo);
const { defaultLayout, id, name, summary } = detail.value;
isDefaultLayout.value = defaultLayout;
richText.value.summary = summary;
reportForm.value.reportName = name;
initOptionsData();
if (props.isPreview) {
if (!defaultLayout && id) {
getDefaultLayout();
} else {
innerCardList.value = props.isGroup ? cloneDeep(defaultGroupConfig) : cloneDeep(defaultSingleConfig);
}
}
}
}
});
},
{ deep: true }
);
//
function getContent(item: configItem): customValueForm {
@ -601,12 +576,6 @@
}
}
const currentMode = ref<string>('drawer');
function handleModeChange(value: string | number | boolean, ev: Event) {
currentMode.value = value as string;
}
function getColor(index: number, type: string) {
if (type === 'top' && index === 0) {
return ['text-[rgb(var(--primary-3))]'];