feat(测试计划): 测试计划-报告-详情-缺陷和功能用例tab

This commit is contained in:
teukkk 2024-05-20 19:01:57 +08:00 committed by Craftsman
parent 553ebde094
commit c3f576d544
9 changed files with 329 additions and 3 deletions

View File

@ -1,7 +1,8 @@
import MSR from '@/api/http'; import MSR from '@/api/http';
import * as reportUrl from '@/api/requrls/test-plan/report'; import * as reportUrl from '@/api/requrls/test-plan/report';
import type { TableQueryParams } from '@/models/common'; import { CommonList, TableQueryParams } from '@/models/common';
import { FeatureCaseItem, ReportBugItem, UpdateReportDetailParams } from '@/models/testPlan/report';
// 报告列表 // 报告列表
export function reportList(data: TableQueryParams) { export function reportList(data: TableQueryParams) {
@ -23,4 +24,19 @@ export function reportBathDelete(data: TableQueryParams) {
return MSR.post({ url: reportUrl.PlanBatchDeleteUrl, data }); return MSR.post({ url: reportUrl.PlanBatchDeleteUrl, data });
} }
// 测试计划-报告-详情-缺陷分页查询
export function getReportBugList(data: TableQueryParams) {
return MSR.post<CommonList<ReportBugItem>>({ url: reportUrl.ReportBugListUrl, data });
}
// 测试计划-报告-详情-功能用例分页查询
export function getReportFeatureCaseList(data: TableQueryParams) {
return MSR.post<CommonList<FeatureCaseItem>>({ url: reportUrl.ReportFeatureCaseListUrl, data });
}
// 测试计划-报告-详情-报告内容更新
export function updateReportDetail(data: UpdateReportDetailParams) {
return MSR.post({ url: reportUrl.UpdateReportDetailUrl, data });
}
export default {}; export default {};

View File

@ -6,3 +6,9 @@ export const PlanReportRenameUrl = '/test-plan/report/rename';
export const PlanDeleteUrl = '/test-plan/report/delete'; export const PlanDeleteUrl = '/test-plan/report/delete';
// 批量删除报告 // 批量删除报告
export const PlanBatchDeleteUrl = '/test-plan/report/batch-delete'; export const PlanBatchDeleteUrl = '/test-plan/report/batch-delete';
// 测试计划-报告-详情-缺陷分页查询
export const ReportBugListUrl = '/test-plan/report/detail/bug/page';
// 测试计划-报告-详情-功能用例分页查询
export const ReportFeatureCaseListUrl = '/test-plan/report/detail/functional/case/page';
// 测试计划-报告-详情-报告内容更新
export const UpdateReportDetailUrl = '/test-plan/report/detail/edit';

View File

@ -67,6 +67,8 @@ export enum TableKeyEnum {
TEST_PLAN_DETAIL_FEATURE_CASE_TABLE = 'testPlanDetailFeatureCaseTable', TEST_PLAN_DETAIL_FEATURE_CASE_TABLE = 'testPlanDetailFeatureCaseTable',
TEST_PLAN_DETAIL_BUG_TABLE_CASE_COUNT = 'testPlanDetailBugCaseCount', TEST_PLAN_DETAIL_BUG_TABLE_CASE_COUNT = 'testPlanDetailBugCaseCount',
TEST_PLAN_REPORT_TABLE = 'testPlanReportTable', TEST_PLAN_REPORT_TABLE = 'testPlanReportTable',
TEST_PLAN_REPORT_DETAIL_BUG = 'testPlanReportDetailBug',
TEST_PLAN_REPORT_DETAIL_FEATURE_CASE = 'testPlanReportDetailFeatureCase',
TASK_API_CASE_SYSTEM = 'taskCenterApiCaseSystem', TASK_API_CASE_SYSTEM = 'taskCenterApiCaseSystem',
TASK_API_CASE_ORGANIZATION = 'taskCenterApiCaseOrganization', TASK_API_CASE_ORGANIZATION = 'taskCenterApiCaseOrganization',
TASK_API_CASE_PROJECT = 'taskCenterApiCaseProject', TASK_API_CASE_PROJECT = 'taskCenterApiCaseProject',

View File

@ -0,0 +1,25 @@
export interface ReportBugItem {
id: string;
num: number;
title: string;
status: string;
handleUserName: string;
relationCaseCount: number;
}
export interface FeatureCaseItem {
id: string;
num: number;
name: string;
moduleName: string;
priority: string;
executeResult: string;
executeUserName: string;
bugCount: number;
}
export interface UpdateReportDetailParams {
id: string;
summary: string;
richTextTmpFileIds: string[];
}

View File

@ -0,0 +1,85 @@
<template>
<MsBaseTable v-bind="propsRes" v-on="propsEvent"> </MsBaseTable>
</template>
<script setup lang="ts">
import { onBeforeMount } from 'vue';
import { useRoute } from 'vue-router';
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
import type { MsTableColumn } from '@/components/pure/ms-table/type';
import useTable from '@/components/pure/ms-table/useTable';
import { getReportBugList } from '@/api/modules/test-plan/report';
import { useTableStore } from '@/store';
import { TableKeyEnum } from '@/enums/tableEnum';
const props = defineProps<{
reportId: string;
}>();
const tableStore = useTableStore();
const route = useRoute();
const columns: MsTableColumn = [
{
title: 'ID',
dataIndex: 'num',
slotName: 'num',
sortIndex: 1,
sortable: {
sortDirections: ['ascend', 'descend'],
sorter: true,
},
fixed: 'left',
width: 100,
ellipsis: true,
showTooltip: true,
},
{
title: 'bugManagement.bugName',
dataIndex: 'title',
width: 150,
showTooltip: true,
sortable: {
sortDirections: ['ascend', 'descend'],
sorter: true,
},
},
{
title: 'bugManagement.status',
dataIndex: 'status',
width: 100,
showTooltip: true,
},
{
title: 'bugManagement.handleMan',
dataIndex: 'handleUserName',
showTooltip: true,
width: 125,
},
{
title: 'bugManagement.numberOfCase',
dataIndex: 'relationCaseCount',
width: 80,
},
];
const { propsRes, propsEvent, loadList, setLoadListParams } = useTable(getReportBugList, {
scroll: { x: '100%' },
columns,
tableKey: TableKeyEnum.TEST_PLAN_REPORT_DETAIL_BUG,
showSelectorAll: false,
});
async function loadCaseList() {
setLoadListParams({ reportId: props.reportId, shareId: route.query.shareId as string | undefined });
loadList();
}
onBeforeMount(() => {
loadCaseList();
});
await tableStore.initColumn(TableKeyEnum.TEST_PLAN_REPORT_DETAIL_BUG, columns, 'drawer');
</script>

View File

@ -0,0 +1,120 @@
<template>
<MsBaseTable v-bind="propsRes" v-on="propsEvent">
<template #caseLevel="{ record }">
<CaseLevel :case-level="record.priority" />
</template>
<template #[FilterSlotNameEnum.CASE_MANAGEMENT_EXECUTE_RESULT]="{ filterContent }">
<ExecuteResult :execute-result="filterContent.key" />
</template>
<template #lastExecResult="{ record }">
<ExecuteResult :execute-result="record.executeResult" />
</template>
</MsBaseTable>
</template>
<script setup lang="ts">
import { onBeforeMount } from 'vue';
import { useRoute } from 'vue-router';
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
import type { MsTableColumn } from '@/components/pure/ms-table/type';
import useTable from '@/components/pure/ms-table/useTable';
import CaseLevel from '@/components/business/ms-case-associate/caseLevel.vue';
import ExecuteResult from '@/components/business/ms-case-associate/executeResult.vue';
import { getReportFeatureCaseList } from '@/api/modules/test-plan/report';
import { useTableStore } from '@/store';
import { TableKeyEnum } from '@/enums/tableEnum';
import { FilterSlotNameEnum } from '@/enums/tableFilterEnum';
import { executionResultMap } from '@/views/case-management/caseManagementFeature/components/utils';
const props = defineProps<{
reportId: string;
}>();
const tableStore = useTableStore();
const route = useRoute();
const columns: MsTableColumn = [
{
title: 'ID',
dataIndex: 'num',
slotName: 'num',
sortIndex: 1,
sortable: {
sortDirections: ['ascend', 'descend'],
sorter: true,
},
fixed: 'left',
width: 100,
ellipsis: true,
showTooltip: true,
},
{
title: 'case.caseName',
dataIndex: 'name',
showTooltip: true,
sortable: {
sortDirections: ['ascend', 'descend'],
sorter: true,
},
width: 180,
},
{
title: 'case.caseLevel',
dataIndex: 'priority',
slotName: 'caseLevel',
width: 150,
},
{
title: 'common.executionResult',
dataIndex: 'executeResult',
slotName: 'lastExecResult',
filterConfig: {
valueKey: 'key',
labelKey: 'statusText',
options: Object.values(executionResultMap),
filterSlotName: FilterSlotNameEnum.CASE_MANAGEMENT_EXECUTE_RESULT,
},
width: 150,
},
{
title: 'common.belongModule',
dataIndex: 'moduleName',
ellipsis: true,
showTooltip: true,
width: 200,
},
{
title: 'testPlan.featureCase.bugCount',
dataIndex: 'bugCount',
width: 100,
},
{
title: 'testPlan.featureCase.executor',
dataIndex: 'executeUserName',
showTooltip: true,
width: 150,
},
];
const { propsRes, propsEvent, loadList, setLoadListParams } = useTable(getReportFeatureCaseList, {
scroll: { x: '100%' },
columns,
tableKey: TableKeyEnum.TEST_PLAN_REPORT_DETAIL_FEATURE_CASE,
heightUsed: 20,
showSelectorAll: false,
});
async function loadCaseList() {
setLoadListParams({ reportId: props.reportId, shareId: route.query.shareId as string | undefined });
loadList();
}
onBeforeMount(() => {
loadCaseList();
});
await tableStore.initColumn(TableKeyEnum.TEST_PLAN_REPORT_DETAIL_FEATURE_CASE, columns, 'drawer');
</script>

View File

@ -1,13 +1,79 @@
<template> <template>
<MsCard class="mb-[16px]" hide-back hide-footer auto-height no-content-padding hide-divider> </MsCard> <MsCard class="mb-[16px]" hide-back hide-footer auto-height no-content-padding hide-divider> </MsCard>
<MsCard class="mb-[16px]" hide-back hide-footer auto-height no-content-padding hide-divider> </MsCard> <MsCard class="mb-[16px]" simple auto-height>
<MsCard class="mb-[16px]" hide-back hide-footer auto-height no-content-padding hide-divider> </MsCard> <div class="font-medium">{{ t('report.detail.reportSummary') }}</div>
<MsRichText
v-model:raw="richText.summary"
v-model:filedIds="richText.richTextTmpFileIds"
:upload-image="handleUploadImage"
:preview-url="PreviewEditorImageUrl"
class="mt-[8px] w-full"
/>
<div class="mt-[16px] flex items-center gap-[12px]">
<a-button type="primary" @click="handleUpdateReportDetail">{{ t('common.save') }}</a-button>
<a-button type="secondary" @click="handleCancel">{{ t('common.cancel') }}</a-button>
</div>
</MsCard>
<MsCard simple auto-height>
<MsTab
v-model:active-key="activeTab"
:show-badge="false"
:content-tab-list="contentTabList"
no-content
class="relative mb-[16px] border-b"
/>
<BugTable v-if="activeTab === 'bug'" :report-id="reportId" />
<FeatureCaseTable v-if="activeTab === 'featureCase'" :report-id="reportId" />
</MsCard>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue'; import { ref } from 'vue';
import { useRoute } from 'vue-router';
import MsCard from '@/components/pure/ms-card/index.vue'; import MsCard from '@/components/pure/ms-card/index.vue';
import MsRichText from '@/components/pure/ms-rich-text/MsRichText.vue';
import MsTab from '@/components/pure/ms-tab/index.vue';
import BugTable from './component/bugTable.vue';
import FeatureCaseTable from './component/featureCaseTable.vue';
import { editorUploadFile } from '@/api/modules/case-management/featureCase';
import { PreviewEditorImageUrl } from '@/api/requrls/case-management/featureCase';
import { useI18n } from '@/hooks/useI18n';
const { t } = useI18n();
const route = useRoute();
const reportId = ref(route.query.id as string);
const activeTab = ref('bug');
const contentTabList = ref([
{
value: 'bug',
label: t('report.detail.bugDetails'),
},
{
value: 'featureCase',
label: t('report.detail.featureCaseDetails'),
},
]);
// TODO
const richText = ref({
summary: '',
richTextTmpFileIds: [],
});
async function handleUploadImage(file: File) {
const { data } = await editorUploadFile({
fileList: [file],
});
return data;
}
function handleUpdateReportDetail() {
// TODO:
}
function handleCancel() {
// TODO:
}
</script> </script>
<style scoped></style> <style scoped></style>

View File

@ -33,4 +33,7 @@ export default {
'report.passRate': 'Pass rate', 'report.passRate': 'Pass rate',
'report.completed': 'Completed', 'report.completed': 'Completed',
'report.passRateTip': 'Pass rate: successful cases in the plan / cases in the plan * 100%', 'report.passRateTip': 'Pass rate: successful cases in the plan / cases in the plan * 100%',
'report.detail.reportSummary': 'Report summary',
'report.detail.bugDetails': 'Bug details',
'report.detail.featureCaseDetails': 'Feature case details',
}; };

View File

@ -33,4 +33,7 @@ export default {
'report.passRate': '通过率', 'report.passRate': '通过率',
'report.passRateTip': '通过率:执行成功的用例/计划内用例 * 100%', 'report.passRateTip': '通过率:执行成功的用例/计划内用例 * 100%',
'report.completed': '已完成', 'report.completed': '已完成',
'report.detail.reportSummary': '报告总结',
'report.detail.bugDetails': '缺陷明细',
'report.detail.featureCaseDetails': '功能用例明细',
}; };