feat(接口测试): 报告样式调整&导入同步 mock

This commit is contained in:
baiqi 2024-09-11 18:20:43 +08:00 committed by Craftsman
parent 3c5d0c3d51
commit 0e882485b7
9 changed files with 176 additions and 146 deletions

View File

@ -229,6 +229,7 @@ export interface ImportApiDefinitionRequest {
coverModule: boolean; // 是否覆盖子目录
coverData: boolean; // 是否覆盖数据
syncCase: boolean; // 是否同步导入用例
syncMock: boolean; // 是否同步导入mock
protocol: string;
authSwitch?: boolean;
authUsername?: string;

View File

@ -100,6 +100,13 @@
<a-switch v-model:model-value="importForm.syncCase" size="small" />
{{ t('apiTestManagement.syncImportCase') }}
</div>
<div
v-if="importForm.platform === RequestImportFormat.MeterSphere"
class="mb-[16px] flex items-center gap-[4px]"
>
<a-switch v-model:model-value="importForm.syncMock" size="small" />
{{ t('apiTestManagement.syncImportMock') }}
</div>
<a-form-item
v-if="importForm.platform === RequestImportFormat.SWAGGER"
:label="t('apiTestManagement.importMethod')"
@ -395,6 +402,7 @@
moduleId: '',
coverData: false,
syncCase: true,
syncMock: true,
coverModule: false,
swaggerUrl: '',
authSwitch: false,
@ -480,6 +488,7 @@
coverModule: importForm.value.coverModule,
coverData: importForm.value.coverData,
syncCase: importForm.value.syncCase,
syncMock: importForm.value.syncMock,
protocol: importForm.value.protocol,
moduleId: importForm.value.moduleId,
authSwitch: importForm.value.authSwitch,
@ -496,6 +505,7 @@
coverModule: importForm.value.coverModule,
coverData: importForm.value.coverData,
syncCase: importForm.value.syncCase,
syncMock: importForm.value.syncMock,
protocol: importForm.value.protocol,
moduleId: importForm.value.moduleId,
swaggerUrl: importForm.value.swaggerUrl,
@ -528,6 +538,7 @@
coverModule: importForm.value.coverModule,
coverData: importForm.value.coverData,
syncCase: importForm.value.syncCase,
syncMock: importForm.value.syncMock,
protocol: importForm.value.protocol,
moduleId: importForm.value.moduleId,
swaggerUrl: importForm.value.swaggerUrl,

View File

@ -84,6 +84,7 @@ export default {
'apiTestManagement.exportCase': 'Synchronous export use case',
'apiTestManagement.exportMock': 'Export Mock Synchronously',
'apiTestManagement.syncImportCase': 'Sync Import API Cases',
'apiTestManagement.syncImportMock': 'Sync Import API Mock',
'apiTestManagement.syncUpdateDirectory': 'Sync Update API Directory',
'apiTestManagement.importSwaggerFileTip1': 'Supports Swagger 3.0 version JSON files,',
'apiTestManagement.importSwaggerFileTip2': '2.0 files can be converted to 3.0 on the official website',

View File

@ -80,6 +80,7 @@ export default {
'apiTestManagement.exportCase': '同步导出用例',
'apiTestManagement.exportMock': '同步导出 Mock',
'apiTestManagement.syncImportCase': '同步导入接口用例',
'apiTestManagement.syncImportMock': '同步导入 Mock',
'apiTestManagement.syncUpdateDirectory': '同步更新接口所在目录',
'apiTestManagement.importSwaggerFileTip1': '支持 Swagger 3.0 版本的 json 文件,',
'apiTestManagement.importSwaggerFileTip2': '2.0 文件可以在官网一键转换 3.0',

View File

@ -34,7 +34,7 @@
<!-- </a-popover> -->
</div>
<div class="chart-legend grid flex-1 gap-y-3">
<div class="chart-legend grid flex-1 gap-y-[12px]">
<!-- 图例开始 -->
<div v-for="item of legendData" :key="item.value" class="grid grid-cols-3">
<div class="flex flex-nowrap items-center">

View File

@ -4,151 +4,155 @@
<ReportDetailHeader :detail="detail" show-type="CASE" />
<!-- 报告参数结束 -->
<!-- 报告分析开始 -->
<div class="analyze mb-1">
<div class="analyze">
<!-- 请求分析 -->
<div class="request-analyze min-h-[110px]">
<div class="block-title mb-4">{{ t('report.detail.api.requestAnalysis') }}</div>
<SetReportChart
:legend-data="legendData"
:options="charOptions"
:request-total="getIndicators(detail.total) || 0"
/>
</div>
<!-- 耗时分析 -->
<div class="time-analyze">
<div class="time-card mb-2 mt-[16px] h-[40px] flex-1 gap-4">
<div class="time-card-item flex h-full">
<MsIcon type="icon-icon_time_outlined" class="mr-[4px] text-[var(--color-text-4)]" size="16" />
<span class="time-card-item-title">{{ t('report.detail.api.totalTime') }}</span>
<a-popover position="bottom" content-class="response-popover-content">
<span class="count">{{ getTotalTime.split('-')[0] }}</span
><span class="time-card-item-title">{{ getTotalTime.split('-')[1] || 'ms' }}</span>
<template #content>
<div class="min-w-[140px] max-w-[400px] p-4 text-[14px]">
<div class="text-[var(--color-text-4)]">{{ t('report.detail.api.totalTime') }}</div>
<div class="mt-2 text-[var(--color-text-1)]">
<span class="text-[18px] font-medium">{{ getTotalTime.split('-')[0] }}</span
>{{ getTotalTime.split('-')[1] || 'ms' }}</div
>
<div class="block-title">{{ t('report.detail.api.requestAnalysis') }}</div>
<div class="flex justify-between">
<div class="request-analyze">
<SetReportChart
:legend-data="legendData"
:options="charOptions"
:request-total="getIndicators(detail.total) || 0"
/>
</div>
<!-- 耗时分析 -->
<div class="time-analyze gap-[12px]">
<div class="time-card flex-1 gap-[12px]">
<div class="time-card-item">
<MsIcon type="icon-icon_time_outlined" class="mr-[4px] text-[var(--color-text-4)]" size="16" />
<span class="time-card-item-title">{{ t('report.detail.api.totalTime') }}</span>
<a-popover position="bottom" content-class="response-popover-content">
<span class="count">{{ getTotalTime.split('-')[0] }}</span
><span class="time-card-item-title">{{ getTotalTime.split('-')[1] || 'ms' }}</span>
<template #content>
<div class="min-w-[140px] max-w-[400px] p-4 text-[14px]">
<div class="text-[var(--color-text-4)]">{{ t('report.detail.api.totalTime') }}</div>
<div class="mt-2 text-[var(--color-text-1)]">
<span class="text-[18px] font-medium">{{ getTotalTime.split('-')[0] }}</span
>{{ getTotalTime.split('-')[1] || 'ms' }}</div
>
</div>
</template>
</a-popover>
</div>
<div class="time-card-item h-full">
<MsIcon type="icon-icon_time_outlined" class="mr-[4px] text-[var(--color-text-4)]" size="16" />
<span class="time-card-item-title"> {{ t('report.detail.api.requestTotalTime') }}</span>
<a-popover position="bottom" content-class="response-popover-content">
<div class="flex items-end">
<div class="count">
{{ detail.requestDuration !== null ? formatDuration(detail.requestDuration).split('-')[0] : '0' }}
</div>
<div class="time-card-item-title">
{{ detail.requestDuration !== null ? formatDuration(detail.requestDuration).split('-')[1] : 'ms' }}
</div>
</div>
</template>
</a-popover>
<template #content>
<div class="min-w-[140px] max-w-[400px] p-4 text-[14px]">
<div class="text-[var(--color-text-4)]">{{ t('report.detail.api.requestTotalTime') }}</div>
<div class="mt-2 text-[var(--color-text-1)]">
<span class="text-[18px] font-medium">{{
detail.requestDuration !== null ? formatDuration(detail.requestDuration).split('-')[0] : '0'
}}</span
>{{
detail.requestDuration !== null ? formatDuration(detail.requestDuration).split('-')[1] : 'ms'
}}</div
>
</div>
</template>
</a-popover>
</div>
</div>
<div class="time-card-item h-full">
<MsIcon type="icon-icon_time_outlined" class="mr-[4px] text-[var(--color-text-4)]" size="16" />
<span class="time-card-item-title"> {{ t('report.detail.api.requestTotalTime') }}</span>
<a-popover position="bottom" content-class="response-popover-content">
<div class="time-card flex-1 gap-4">
<!-- 执行率 -->
<div v-if="detail.integrated" class="time-card-item-rote">
<div class="time-card-item-rote-title">
<MsIcon type="icon-icon_yes_outlined" class="mr-[4px] text-[var(--color-text-4)]" size="16" />
{{ t('report.detail.api.executionRate') }}
</div>
<div class="flex items-center">
<div class="count">{{
detail.requestDuration !== null ? formatDuration(detail.requestDuration).split('-')[0] : '0'
}}</div
><div class="time-card-item-title">{{
detail.requestDuration !== null ? formatDuration(detail.requestDuration).split('-')[1] : 'ms'
}}</div>
<a-popover position="bottom" content-class="response-popover-content">
<div class="count one-line-text max-w-[80px]"> {{ getExcuteRate() }} </div
><span v-show="getExcuteRate() !== 'Calculating'">%</span>
<a-divider direction="vertical" class="!h-[16px]" :margin="8"></a-divider>
<span>{{ getIndicators(getRequestEacuteCount) }}</span>
<span class="mx-1 text-[var(--color-text-4)]">/ {{ getIndicators(getRequestTotalCount) }}</span>
<template #content>
<div class="min-w-[190px] max-w-[400px] p-4 text-[14px]">
<div class="text-[var(--color-text-4)]">{{ t('report.detail.api.executionRate') }}</div>
<div class="mt-2 flex items-center justify-between">
<div class="count text-[18px] font-medium">
{{ getExcuteRate() }} <span v-show="getExcuteRate() !== 'Calculating'">%</span>
</div>
<div>
<span>{{ getIndicators(getRequestEacuteCount) }}</span>
<span class="mx-1 text-[var(--color-text-4)]"
>/ {{ getIndicators(getRequestTotalCount) }}</span
>
</div>
</div>
</div>
</template>
</a-popover>
</div>
</div>
<div class="time-card-item-rote">
<div class="time-card-item-rote-title">
<MsIcon type="icon-icon_yes_outlined" class="mr-[4px] text-[var(--color-text-4)]" size="16" />
{{ t('report.detail.api.assertPass') }}
</div>
<template #content>
<div class="min-w-[140px] max-w-[400px] p-4 text-[14px]">
<div class="text-[var(--color-text-4)]">{{ t('report.detail.api.requestTotalTime') }}</div>
<div class="mt-2 text-[var(--color-text-1)]">
<span class="text-[18px] font-medium">{{
detail.requestDuration !== null ? formatDuration(detail.requestDuration).split('-')[0] : '0'
}}</span
>{{
detail.requestDuration !== null ? formatDuration(detail.requestDuration).split('-')[1] : 'ms'
}}</div
>
</div>
</template>
</a-popover>
</div>
</div>
<div class="time-card flex-1 gap-4">
<!-- 执行率 -->
<div v-if="detail.integrated" class="time-card-item-rote">
<div class="time-card-item-rote-title">
<MsIcon type="icon-icon_yes_outlined" class="mr-[4px] text-[var(--color-text-4)]" size="16" />
{{ t('report.detail.api.executionRate') }}
</div>
<div class="flex items-center">
<a-popover position="bottom" content-class="response-popover-content">
<div class="count one-line-text max-w-[80px]"> {{ getExcuteRate() }} </div
><span v-show="getExcuteRate() !== 'Calculating'">%</span>
<a-divider direction="vertical" class="!h-[16px]" :margin="8"></a-divider>
<span>{{ getIndicators(getRequestEacuteCount) }}</span>
<span class="mx-1 text-[var(--color-text-4)]">/ {{ getIndicators(getRequestTotalCount) }}</span>
<template #content>
<div class="min-w-[190px] max-w-[400px] p-4 text-[14px]">
<div class="text-[var(--color-text-4)]">{{ t('report.detail.api.executionRate') }}</div>
<div class="mt-2 flex items-center justify-between">
<div class="count text-[18px] font-medium">
{{ getExcuteRate() }} <span v-show="getExcuteRate() !== 'Calculating'">%</span>
</div>
<div>
<span>{{ getIndicators(getRequestEacuteCount) }}</span>
<span class="mx-1 text-[var(--color-text-4)]">/ {{ getIndicators(getRequestTotalCount) }}</span>
</div>
</div>
<div class="flex items-center">
<a-popover position="bottom" content-class="response-popover-content">
<div class="flex items-center">
<div class="count one-line-text max-w-[80px]">{{ detail.assertionPassRate || '0.00' }}</div
><span v-show="detail.assertionPassRate !== 'Calculating'" class="ml-1">%</span>
<a-divider direction="vertical" class="!h-[16px]" :margin="8"></a-divider>
<div class="one-line-text max-w-[80px]">{{
getIndicators(detail.assertionSuccessCount) !== 'Calculating'
? addCommasToNumber(detail.assertionSuccessCount || 0)
: getIndicators(detail.assertionSuccessCount)
}}</div>
<span class="mx-1 text-[var(--color-text-4)]">/</span>
<div class="one-line-text max-w-[80px]">
{{
getIndicators(detail.assertionCount) !== 'Calculating'
? addCommasToNumber(detail.assertionCount)
: getIndicators(detail.assertionCount)
}}</div
>
</div>
</template>
</a-popover>
</div>
</div>
<div class="time-card-item-rote">
<div class="time-card-item-rote-title">
<MsIcon type="icon-icon_yes_outlined" class="mr-[4px] text-[var(--color-text-4)]" size="16" />
{{ t('report.detail.api.assertPass') }}
</div>
<div class="flex items-center">
<a-popover position="bottom" content-class="response-popover-content">
<div class="flex items-center">
<div class="count one-line-text max-w-[80px]">{{ detail.assertionPassRate || '0.00' }}</div
><span v-show="detail.assertionPassRate !== 'Calculating'" class="ml-1">%</span>
<a-divider direction="vertical" class="!h-[16px]" :margin="8"></a-divider>
<div class="one-line-text max-w-[80px]">{{
getIndicators(detail.assertionSuccessCount) !== 'Calculating'
? addCommasToNumber(detail.assertionSuccessCount || 0)
: getIndicators(detail.assertionSuccessCount)
}}</div>
<span class="mx-1 text-[var(--color-text-4)]">/</span>
<div class="one-line-text max-w-[80px]">
{{
getIndicators(detail.assertionCount) !== 'Calculating'
? addCommasToNumber(detail.assertionCount)
: getIndicators(detail.assertionCount)
}}</div
>
</div>
<template #content>
<div class="min-w-[190px] max-w-[400px] p-4 text-[14px]">
<div class="text-[var(--color-text-4)]">{{ t('report.detail.api.assertPass') }}</div>
<div class="mt-2 flex items-center justify-between">
<div class="text-[18px] font-medium text-[var(--color-text-1)]"
>{{ getIndicators(detail.assertionPassRate) }}
<span v-show="detail.assertionPassRate !== 'Calculating'">%</span></div
>
<div>
<span class="text-[var(--color-text-1)]">{{
getIndicators(detail.assertionSuccessCount) !== 'Calculating'
? addCommasToNumber(detail.assertionSuccessCount || 0)
: getIndicators(detail.assertionSuccessCount)
}}</span>
<span class="text-[var(--color-text-4)]"
><span class="mx-1">/</span>
{{
getIndicators(detail.assertionCount) !== 'Calculating'
? addCommasToNumber(detail.assertionCount)
: getIndicators(detail.assertionCount)
}}</span
<template #content>
<div class="min-w-[190px] max-w-[400px] p-4 text-[14px]">
<div class="text-[var(--color-text-4)]">{{ t('report.detail.api.assertPass') }}</div>
<div class="mt-2 flex items-center justify-between">
<div class="text-[18px] font-medium text-[var(--color-text-1)]"
>{{ getIndicators(detail.assertionPassRate) }}
<span v-show="detail.assertionPassRate !== 'Calculating'">%</span></div
>
<div>
<span class="text-[var(--color-text-1)]">{{
getIndicators(detail.assertionSuccessCount) !== 'Calculating'
? addCommasToNumber(detail.assertionSuccessCount || 0)
: getIndicators(detail.assertionSuccessCount)
}}</span>
<span class="text-[var(--color-text-4)]"
><span class="mx-1">/</span>
{{
getIndicators(detail.assertionCount) !== 'Calculating'
? addCommasToNumber(detail.assertionCount)
: getIndicators(detail.assertionCount)
}}</span
>
</div>
</div>
</div>
</div>
</template>
</a-popover>
</template>
</a-popover>
</div>
</div>
</div>
</div>
@ -417,11 +421,12 @@
@apply mb-4 bg-white;
}
.analyze {
height: 196px;
@apply mb-4 bg-white;
padding: 16px;
border-radius: 4px;
@apply mb-4 flex justify-between bg-white;
.request-analyze {
@apply flex h-full flex-1 flex-col p-4;
@apply flex h-full flex-1 flex-col;
.chart-legend {
.chart-legend-item {
@apply grid grid-cols-3 gap-2;
@ -435,28 +440,36 @@
}
}
.time-analyze {
@apply flex h-full flex-1 flex-col p-4;
@apply flex h-full flex-1 flex-col px-4;
.time-card {
@apply flex items-center justify-between;
.time-card-item {
@apply flex flex-1 flex-grow items-end;
padding: 9px 12px;
border-radius: 6px;
background: var(--color-text-n9);
@apply mt-4 flex flex-1 flex-grow items-center px-4;
.time-card-item-title {
color: var(--color-text-4);
line-height: 16px;
}
.count {
font-size: 18px;
@apply mx-2 font-medium;
line-height: 22px;
font-size: 18px;
}
}
.time-card-item-rote {
@apply flex flex-1 flex-grow flex-col;
padding: 9px 12px;
border-radius: 6px;
background: var(--color-text-n9);
@apply mt-4 flex flex-1 flex-grow flex-col p-4;
.time-card-item-rote-title {
@apply mb-2 flex items-center;
color: var(--color-text-4);
@apply mb-2;
}
.count {
font-size: 18px;
@ -473,7 +486,9 @@
}
}
.block-title {
font-size: 14px;
@apply font-medium;
margin-bottom: 16px;
font-size: 14px;
}
</style>

View File

@ -48,6 +48,7 @@
:active-type="activeTab"
:report-detail="detail || []"
:is-export="props.isExport"
class="p-[16px]"
/>
</div>
<!-- 报告明细结束 -->

View File

@ -382,7 +382,7 @@
.arco-tree-node-title {
@apply !cursor-pointer bg-white;
padding: 12px 4px;
padding: 8px 4px;
&:hover {
background-color: white !important;
}

View File

@ -1,6 +1,6 @@
<template>
<div
class="tiled-wrap p-4"
class="tiled-wrap"
:class="{
'border border-solid border-[var(--color-text-n8)]': props.showType === 'API',
'!max-h-max': props.isExport,