feat(测试计划&接口测试): 测试计划部分接口调整&接口测试报告展示布局优化调整
This commit is contained in:
parent
d4bd63ca04
commit
1a58e75e4c
|
@ -2,7 +2,11 @@ import MSR from '@/api/http/index';
|
||||||
import {
|
import {
|
||||||
addTestPlanModuleUrl,
|
addTestPlanModuleUrl,
|
||||||
AddTestPlanUrl,
|
AddTestPlanUrl,
|
||||||
|
archivedPlanUrl,
|
||||||
|
batchDeletePlanUrl,
|
||||||
|
deletePlanUrl,
|
||||||
DeleteTestPlanModuleUrl,
|
DeleteTestPlanModuleUrl,
|
||||||
|
getStatisticalCountUrl,
|
||||||
GetTestPlanListUrl,
|
GetTestPlanListUrl,
|
||||||
GetTestPlanModuleCountUrl,
|
GetTestPlanModuleCountUrl,
|
||||||
GetTestPlanModuleUrl,
|
GetTestPlanModuleUrl,
|
||||||
|
@ -13,7 +17,7 @@ import {
|
||||||
import type { CreateOrUpdateModule, UpdateModule } from '@/models/caseManagement/featureCase';
|
import type { CreateOrUpdateModule, UpdateModule } from '@/models/caseManagement/featureCase';
|
||||||
import type { CommonList, MoveModules, TableQueryParams } from '@/models/common';
|
import type { CommonList, MoveModules, TableQueryParams } from '@/models/common';
|
||||||
import { ModuleTreeNode } from '@/models/common';
|
import { ModuleTreeNode } from '@/models/common';
|
||||||
import type { AddTestPlanParams, TestPlanItem } from '@/models/testPlan/testPlan';
|
import type { AddTestPlanParams, TestPlanItem, UseCountType } from '@/models/testPlan/testPlan';
|
||||||
|
|
||||||
// 获取模块树
|
// 获取模块树
|
||||||
export function getTestPlanModule(params: TableQueryParams) {
|
export function getTestPlanModule(params: TableQueryParams) {
|
||||||
|
@ -41,7 +45,7 @@ export function deletePlanModuleTree(id: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取模块数量
|
// 获取模块数量
|
||||||
export function getPlanModulesCounts(data: TableQueryParams) {
|
export function getPlanModulesCount(data: TableQueryParams) {
|
||||||
return MSR.post({ url: GetTestPlanModuleCountUrl, data });
|
return MSR.post({ url: GetTestPlanModuleCountUrl, data });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,3 +58,19 @@ export function getTestPlanList(data: TableQueryParams) {
|
||||||
export function addTestPlan(data: AddTestPlanParams) {
|
export function addTestPlan(data: AddTestPlanParams) {
|
||||||
return MSR.post({ url: AddTestPlanUrl, data });
|
return MSR.post({ url: AddTestPlanUrl, data });
|
||||||
}
|
}
|
||||||
|
// 批量删除测试计划
|
||||||
|
export function batchDeletePlan(data: TableQueryParams) {
|
||||||
|
return MSR.post({ url: batchDeletePlanUrl, data });
|
||||||
|
}
|
||||||
|
// 删除测试计划
|
||||||
|
export function deletePlan(id: string | undefined) {
|
||||||
|
return MSR.get({ url: `${deletePlanUrl}/${id}` });
|
||||||
|
}
|
||||||
|
// 获取统计数量
|
||||||
|
export function getStatisticalCount(id: string) {
|
||||||
|
return MSR.get<UseCountType>({ url: `${getStatisticalCountUrl}/${id}` });
|
||||||
|
}
|
||||||
|
// 归档
|
||||||
|
export function archivedPlan(id: string | undefined) {
|
||||||
|
return MSR.get({ url: `${archivedPlanUrl}/${id}` });
|
||||||
|
}
|
||||||
|
|
|
@ -14,3 +14,11 @@ export const GetTestPlanModuleCountUrl = '/test-plan/module/count';
|
||||||
export const GetTestPlanListUrl = '/test-plan/page';
|
export const GetTestPlanListUrl = '/test-plan/page';
|
||||||
// 创建测试计划
|
// 创建测试计划
|
||||||
export const AddTestPlanUrl = '/test-plan/add';
|
export const AddTestPlanUrl = '/test-plan/add';
|
||||||
|
// 批量删除测试计划
|
||||||
|
export const batchDeletePlanUrl = '/test-plan/batch-delete';
|
||||||
|
// 删除测试计划
|
||||||
|
export const deletePlanUrl = '/test-plan/delete';
|
||||||
|
// 获取统计数量
|
||||||
|
export const getStatisticalCountUrl = '/test-plan/getCount';
|
||||||
|
// 归档
|
||||||
|
export const archivedPlanUrl = '/test-plan/archived';
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div ref="fullRef" class="flex flex-col rounded-[var(--border-radius-small)] bg-[var(--color-fill-1)] p-[12px]">
|
||||||
ref="fullRef"
|
|
||||||
class="flex h-full flex-col rounded-[var(--border-radius-small)] bg-[var(--color-fill-1)] p-[12px]"
|
|
||||||
>
|
|
||||||
<div v-if="showTitleLine" class="mb-[8px] flex items-center justify-between">
|
<div v-if="showTitleLine" class="mb-[8px] flex items-center justify-between">
|
||||||
<div class="flex flex-wrap gap-[4px]">
|
<div class="flex flex-wrap gap-[4px]">
|
||||||
<a-select
|
<a-select
|
||||||
|
@ -257,6 +254,32 @@
|
||||||
return editor.getValue();
|
return editor.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const innerHeight = ref<string | number>();
|
||||||
|
|
||||||
|
function handleEditorMount() {
|
||||||
|
if (!props.isAdaptive) {
|
||||||
|
innerHeight.value = props.height;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const editorElement = editor.getDomNode();
|
||||||
|
|
||||||
|
if (!editorElement) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取代码编辑器文本行高
|
||||||
|
const lineHeight = editor.getOption(monaco.editor.EditorOption.lineHeight);
|
||||||
|
// 获取代码的行数
|
||||||
|
const lineCount = editor.getModel()?.getLineCount() || 10;
|
||||||
|
// 计算高度 @desc 原本行数差3行完全展示文本 24为上下的边距为12px
|
||||||
|
const height = (lineCount + 3) * lineHeight;
|
||||||
|
innerHeight.value = height > 300 ? `${height + 24}px` : '300px';
|
||||||
|
if (height > 1000) {
|
||||||
|
innerHeight.value = `1000px`;
|
||||||
|
}
|
||||||
|
editor.layout();
|
||||||
|
}
|
||||||
|
|
||||||
const init = () => {
|
const init = () => {
|
||||||
// 注册自定义主题 TODO:自定义主题高亮色还没配置
|
// 注册自定义主题 TODO:自定义主题高亮色还没配置
|
||||||
// Object.keys(MsCodeEditorTheme).forEach((e) => {
|
// Object.keys(MsCodeEditorTheme).forEach((e) => {
|
||||||
|
@ -276,6 +299,7 @@
|
||||||
...props,
|
...props,
|
||||||
language: props.language.toLowerCase(),
|
language: props.language.toLowerCase(),
|
||||||
theme: currentTheme.value,
|
theme: currentTheme.value,
|
||||||
|
selectOnLineNumbers: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
// 监听值的变化
|
// 监听值的变化
|
||||||
|
@ -284,6 +308,8 @@
|
||||||
emit('update:modelValue', value);
|
emit('update:modelValue', value);
|
||||||
emit('change', value);
|
emit('change', value);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
handleEditorMount();
|
||||||
};
|
};
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
|
@ -294,6 +320,7 @@
|
||||||
if (newValue !== value) {
|
if (newValue !== value) {
|
||||||
editor.setValue(newValue);
|
editor.setValue(newValue);
|
||||||
}
|
}
|
||||||
|
handleEditorMount();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ immediate: true }
|
{ immediate: true }
|
||||||
|
@ -356,6 +383,8 @@
|
||||||
redo,
|
redo,
|
||||||
format,
|
format,
|
||||||
getEncodingCode,
|
getEncodingCode,
|
||||||
|
innerHeight,
|
||||||
|
handleEditorMount,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -363,11 +392,12 @@
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.ms-code-editor {
|
.ms-code-editor {
|
||||||
|
width: 100%;
|
||||||
|
height: v-bind(innerheight);
|
||||||
|
|
||||||
@apply z-10;
|
@apply z-10;
|
||||||
// TODO: 高度改为自适应
|
// height: 100vh;
|
||||||
width: v-bind(width);
|
|
||||||
height: v-bind(height);
|
|
||||||
min-height: 200px;
|
|
||||||
// &.MS-text[data-mode-id='plaintext'] {
|
// &.MS-text[data-mode-id='plaintext'] {
|
||||||
// :deep(.mtk1) {
|
// :deep(.mtk1) {
|
||||||
// color: rgb(var(--primary-5));
|
// color: rgb(var(--primary-5));
|
||||||
|
|
|
@ -130,4 +130,9 @@ export const editorProps = {
|
||||||
type: String as PropType<string>,
|
type: String as PropType<string>,
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
|
// 是否自适应 开启后按照代码高度计算代码器高度最大1000px 未开启则按照外侧传入容器高度
|
||||||
|
isAdaptive: {
|
||||||
|
type: Boolean as PropType<boolean>,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -62,4 +62,15 @@ export interface SwitchListModel {
|
||||||
tooltipPosition: 'top' | 'tl' | 'tr' | 'bottom' | 'bl' | 'br' | 'left' | 'lt' | 'lb' | 'right' | 'rt' | 'rb';
|
tooltipPosition: 'top' | 'tl' | 'tr' | 'bottom' | 'bl' | 'br' | 'left' | 'lt' | 'lb' | 'right' | 'rt' | 'rb';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取统计数量
|
||||||
|
export interface UseCountType {
|
||||||
|
id: string;
|
||||||
|
passRate: string; // 通过率
|
||||||
|
functionalCaseCount: number; // 功能用例数
|
||||||
|
apiCaseCount: number; // 接口用例数
|
||||||
|
apiScenarioCount: number; // 接口场景数
|
||||||
|
bugCount: number; // Bug数量
|
||||||
|
testProgress: string; // 测试进度
|
||||||
|
}
|
||||||
|
|
||||||
export default {};
|
export default {};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="response flex min-w-[300px] flex-col">
|
<div class="response flex h-full min-w-[300px] flex-col">
|
||||||
<div :class="['response-head', activeLayout === 'vertical' ? 'border-t' : '']">
|
<div :class="['response-head', activeLayout === 'vertical' ? 'border-t' : '']">
|
||||||
<slot name="titleLeft">
|
<slot name="titleLeft">
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
|
|
|
@ -136,6 +136,7 @@
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.response-container {
|
.response-container {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
|
height: calc(100% - 48px);
|
||||||
}
|
}
|
||||||
:deep(.arco-table-th) {
|
:deep(.arco-table-th) {
|
||||||
background-color: var(--color-text-n9);
|
background-color: var(--color-text-n9);
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
show-language-change
|
show-language-change
|
||||||
show-charset-change
|
show-charset-change
|
||||||
read-only
|
read-only
|
||||||
|
is-adaptive
|
||||||
>
|
>
|
||||||
<template #rightTitle>
|
<template #rightTitle>
|
||||||
<a-button type="outline" class="arco-btn-outline--secondary p-[0_8px]" size="mini" @click="emits('copy')">
|
<a-button type="outline" class="arco-btn-outline--secondary p-[0_8px]" size="mini" @click="emits('copy')">
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
:show-language-change="false"
|
:show-language-change="false"
|
||||||
:show-charset-change="false"
|
:show-charset-change="false"
|
||||||
read-only
|
read-only
|
||||||
|
is-adaptive
|
||||||
>
|
>
|
||||||
</MsCodeEditor>
|
</MsCodeEditor>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,99 +1,101 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="flex h-[calc(100%-64px)] flex-col" @click.stop="() => {}">
|
<div class="flex flex-col" @click.stop="() => {}">
|
||||||
<div v-if="isShowLoopControl" class="my-4 flex items-center justify-start" @click.stop="() => {}">
|
<div class="response-header">
|
||||||
<a-pagination
|
<div v-if="isShowLoopControl" class="my-4 flex items-center justify-start" @click.stop="() => {}">
|
||||||
v-model:page-size="controlPageSize"
|
<a-pagination
|
||||||
v-model:current="controlCurrent"
|
v-model:page-size="controlPageSize"
|
||||||
:total="controlTotal"
|
v-model:current="controlCurrent"
|
||||||
size="mini"
|
:total="controlTotal"
|
||||||
show-total
|
size="mini"
|
||||||
:show-jumper="controlTotal > 5"
|
show-total
|
||||||
@change="loadControlLoop"
|
:show-jumper="controlTotal > 5"
|
||||||
/>
|
@change="loadControlLoop"
|
||||||
<!-- <loopPagination v-model:current-loop="controlCurrent" :loop-total="controlTotal" /> -->
|
/>
|
||||||
</div>
|
<!-- <loopPagination v-model:current-loop="controlCurrent" :loop-total="controlTotal" /> -->
|
||||||
<div class="mt-4 flex w-full items-center justify-between rounded bg-[var(--color-text-n9)] p-4">
|
|
||||||
<div class="font-medium">
|
|
||||||
<span
|
|
||||||
:class="{ 'text-[rgb(var(--primary-5))]': activeType === 'ResContent' }"
|
|
||||||
@click.stop="setActiveType('ResContent')"
|
|
||||||
>{{ t('report.detail.api.resContent') }}</span
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
v-if="total > 0"
|
|
||||||
:class="{ 'text-[rgb(var(--primary-5))]': activeType === 'SubRequest' }"
|
|
||||||
@click.stop="setActiveType('SubRequest')"
|
|
||||||
>
|
|
||||||
<a-divider direction="vertical" :margin="8"></a-divider>
|
|
||||||
{{ t('report.detail.api.subRequest') }}</span
|
|
||||||
>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-row gap-6 text-center">
|
<div class="flex w-full items-center justify-between rounded bg-[var(--color-text-n9)] p-4">
|
||||||
<a-popover position="left" content-class="response-popover-content">
|
<div class="font-medium">
|
||||||
<div
|
<span
|
||||||
v-if="activeStepDetailCopy?.content?.responseResult.responseCode"
|
:class="{ 'text-[rgb(var(--primary-5))]': activeType === 'ResContent' }"
|
||||||
class="one-line-text max-w-[200px]"
|
@click.stop="setActiveType('ResContent')"
|
||||||
:style="{ color: statusCodeColor }"
|
>{{ t('report.detail.api.resContent') }}</span
|
||||||
>
|
>
|
||||||
{{ activeStepDetailCopy?.content?.responseResult.responseCode || '-' }}
|
<span
|
||||||
</div>
|
v-if="total > 0"
|
||||||
<template #content>
|
:class="{ 'text-[rgb(var(--primary-5))]': activeType === 'SubRequest' }"
|
||||||
<div class="flex items-center gap-[8px] text-[14px]">
|
@click.stop="setActiveType('SubRequest')"
|
||||||
<div class="text-[var(--color-text-4)]">{{ t('apiTestDebug.statusCode') }}</div>
|
|
||||||
<div :style="{ color: statusCodeColor }">
|
|
||||||
{{ activeStepDetailCopy?.content?.responseResult.responseCode || '-' }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</a-popover>
|
|
||||||
<a-popover position="left" content-class="w-[400px]">
|
|
||||||
<div v-if="timingInfo?.responseTime" class="one-line-text text-[rgb(var(--success-7))]">
|
|
||||||
{{ timingInfo?.responseTime || 0 }} ms
|
|
||||||
</div>
|
|
||||||
<template #content>
|
|
||||||
<div class="mb-[8px] flex items-center gap-[8px] text-[14px]">
|
|
||||||
<div class="text-[var(--color-text-4)]">{{ t('apiTestDebug.responseTime') }}</div>
|
|
||||||
<div class="text-[rgb(var(--success-7))]"> {{ timingInfo?.responseTime }} ms </div>
|
|
||||||
</div>
|
|
||||||
<responseTimeLine v-if="timingInfo" :response-timing="timingInfo" />
|
|
||||||
</template>
|
|
||||||
</a-popover>
|
|
||||||
<a-popover position="left" content-class="response-popover-content">
|
|
||||||
<div
|
|
||||||
v-if="activeStepDetail?.content?.responseResult.responseSize"
|
|
||||||
class="one-line-text text-[rgb(var(--success-7))]"
|
|
||||||
>
|
>
|
||||||
{{ activeStepDetail?.content?.responseResult.responseSize || '-' }} bytes
|
<a-divider direction="vertical" :margin="8"></a-divider>
|
||||||
</div>
|
{{ t('report.detail.api.subRequest') }}</span
|
||||||
<template #content>
|
>
|
||||||
<div class="flex items-center gap-[8px] text-[14px]">
|
</div>
|
||||||
<div class="text-[var(--color-text-4)]">{{ t('apiTestDebug.responseSize') }}</div>
|
<div class="flex flex-row gap-6 text-center">
|
||||||
<div class="one-line-text text-[rgb(var(--success-7))]">
|
<a-popover position="left" content-class="response-popover-content">
|
||||||
{{ activeStepDetail?.content?.responseResult.responseSize }} bytes
|
<div
|
||||||
</div>
|
v-if="activeStepDetailCopy?.content?.responseResult.responseCode"
|
||||||
|
class="one-line-text max-w-[200px]"
|
||||||
|
:style="{ color: statusCodeColor }"
|
||||||
|
>
|
||||||
|
{{ activeStepDetailCopy?.content?.responseResult.responseCode || '-' }}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
<template #content>
|
||||||
</a-popover>
|
<div class="flex items-center gap-[8px] text-[14px]">
|
||||||
<a-popover position="left" content-class="response-popover-content">
|
<div class="text-[var(--color-text-4)]">{{ t('apiTestDebug.statusCode') }}</div>
|
||||||
<div v-if="props.showType && props.showType !== 'CASE'" class="one-line-text max-w-[150px]">{{
|
<div :style="{ color: statusCodeColor }">
|
||||||
props.environmentName
|
{{ activeStepDetailCopy?.content?.responseResult.responseCode || '-' }}
|
||||||
}}</div>
|
</div>
|
||||||
<template #content>
|
</div>
|
||||||
<div v-if="props.showType && props.showType !== 'CASE'" class="one-line-text">{{
|
</template>
|
||||||
|
</a-popover>
|
||||||
|
<a-popover position="left" content-class="w-[400px]">
|
||||||
|
<div v-if="timingInfo?.responseTime" class="one-line-text text-[rgb(var(--success-7))]">
|
||||||
|
{{ timingInfo?.responseTime || 0 }} ms
|
||||||
|
</div>
|
||||||
|
<template #content>
|
||||||
|
<div class="mb-[8px] flex items-center gap-[8px] text-[14px]">
|
||||||
|
<div class="text-[var(--color-text-4)]">{{ t('apiTestDebug.responseTime') }}</div>
|
||||||
|
<div class="text-[rgb(var(--success-7))]"> {{ timingInfo?.responseTime }} ms </div>
|
||||||
|
</div>
|
||||||
|
<responseTimeLine v-if="timingInfo" :response-timing="timingInfo" />
|
||||||
|
</template>
|
||||||
|
</a-popover>
|
||||||
|
<a-popover position="left" content-class="response-popover-content">
|
||||||
|
<div
|
||||||
|
v-if="activeStepDetail?.content?.responseResult.responseSize"
|
||||||
|
class="one-line-text text-[rgb(var(--success-7))]"
|
||||||
|
>
|
||||||
|
{{ activeStepDetail?.content?.responseResult.responseSize || '-' }} bytes
|
||||||
|
</div>
|
||||||
|
<template #content>
|
||||||
|
<div class="flex items-center gap-[8px] text-[14px]">
|
||||||
|
<div class="text-[var(--color-text-4)]">{{ t('apiTestDebug.responseSize') }}</div>
|
||||||
|
<div class="one-line-text text-[rgb(var(--success-7))]">
|
||||||
|
{{ activeStepDetail?.content?.responseResult.responseSize }} bytes
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-popover>
|
||||||
|
<a-popover position="left" content-class="response-popover-content">
|
||||||
|
<div v-if="props.showType && props.showType !== 'CASE'" class="one-line-text max-w-[150px]">{{
|
||||||
props.environmentName
|
props.environmentName
|
||||||
}}</div>
|
}}</div>
|
||||||
</template>
|
<template #content>
|
||||||
</a-popover>
|
<div v-if="props.showType && props.showType !== 'CASE'" class="one-line-text">{{
|
||||||
|
props.environmentName
|
||||||
|
}}</div>
|
||||||
|
</template>
|
||||||
|
</a-popover>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="activeType === 'SubRequest'" class="my-4 flex justify-start">
|
||||||
|
<MsPagination
|
||||||
|
v-model:page-size="pageSize"
|
||||||
|
v-model:current="current"
|
||||||
|
:total="total"
|
||||||
|
size="mini"
|
||||||
|
@change="loadLoop"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div v-if="activeType === 'SubRequest'" class="my-4 flex justify-start">
|
|
||||||
<MsPagination
|
|
||||||
v-model:page-size="pageSize"
|
|
||||||
v-model:current="current"
|
|
||||||
:total="total"
|
|
||||||
size="mini"
|
|
||||||
@change="loadLoop"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<!-- 平铺 -->
|
<!-- 平铺 -->
|
||||||
<a-spin v-if="props.mode === 'tiled'" class="w-full" :loading="loading">
|
<a-spin v-if="props.mode === 'tiled'" class="w-full" :loading="loading">
|
||||||
|
@ -108,8 +110,8 @@
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</a-spin>
|
</a-spin>
|
||||||
<!-- 响应内容tab -->
|
<!-- 响应内容tab -->
|
||||||
<div v-else class="h-full">
|
<div v-else>
|
||||||
<a-spin :loading="loading" class="h-full w-full pb-1">
|
<a-spin :loading="loading" class="w-full pb-1">
|
||||||
<result
|
<result
|
||||||
v-model:active-tab="activeTab"
|
v-model:active-tab="activeTab"
|
||||||
:request-result="activeStepDetailCopy?.content"
|
:request-result="activeStepDetailCopy?.content"
|
||||||
|
@ -371,4 +373,10 @@
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="less"></style>
|
<style scoped lang="less">
|
||||||
|
.response-header {
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 9999999;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -29,10 +29,10 @@
|
||||||
</div>
|
</div>
|
||||||
<transition name="fade">
|
<transition name="fade">
|
||||||
<div v-show="!expandIds.includes(item.value) && isShowContent(item.value)" class="expandContent">
|
<div v-show="!expandIds.includes(item.value) && isShowContent(item.value)" class="expandContent">
|
||||||
<div v-if="item.value === ResponseComposition.BODY" class="res-item">
|
<div v-if="item.value === ResponseComposition.BODY">
|
||||||
<ResBody ref="resBodyRef" :request-result="props.requestResult" @copy="copyScript" />
|
<ResBody ref="resBodyRef" :request-result="props.requestResult" @copy="copyScript" />
|
||||||
</div>
|
</div>
|
||||||
<div v-if="!expandIds.includes(item.value) && item.value === ResponseComposition.CONSOLE" class="res-item">
|
<div v-if="!expandIds.includes(item.value) && item.value === ResponseComposition.CONSOLE">
|
||||||
<ResConsole :console="props.console?.trim()" />
|
<ResConsole :console="props.console?.trim()" />
|
||||||
</div>
|
</div>
|
||||||
<div v-if="!expandIds.includes(item.value) && item.value === ResponseComposition.HEADER" class="">
|
<div v-if="!expandIds.includes(item.value) && item.value === ResponseComposition.HEADER" class="">
|
||||||
|
@ -49,7 +49,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
<a-divider v-if="isShowContent(item.value)" type="dashed" :margin="0" class="!mb-4"></a-divider>
|
<a-divider v-if="isShowContent(item.value)" type="dashed" :margin="0"></a-divider>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -155,10 +155,13 @@
|
||||||
.tiledList {
|
.tiledList {
|
||||||
@apply px-4;
|
@apply px-4;
|
||||||
.menu-list-wrapper {
|
.menu-list-wrapper {
|
||||||
@apply mt-4;
|
|
||||||
.menu-list {
|
.menu-list {
|
||||||
height: 32px;
|
position: sticky;
|
||||||
// border-bottom: 1px dashed var(--color-text-n8);
|
top: 50px;
|
||||||
|
z-index: 999999;
|
||||||
|
height: 40px;
|
||||||
|
line-height: 40px;
|
||||||
|
background: white;
|
||||||
@apply flex items-start justify-between px-4;
|
@apply flex items-start justify-between px-4;
|
||||||
.menu-title {
|
.menu-title {
|
||||||
@apply font-medium;
|
@apply font-medium;
|
||||||
|
@ -166,9 +169,6 @@
|
||||||
}
|
}
|
||||||
.expandContent {
|
.expandContent {
|
||||||
background: var(--color-text-n9);
|
background: var(--color-text-n9);
|
||||||
.res-item {
|
|
||||||
height: 210px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
:title="props.scenarioDetail?.name"
|
:title="props.scenarioDetail?.name"
|
||||||
show-full-screen
|
show-full-screen
|
||||||
:unmount-on-close="true"
|
:unmount-on-close="true"
|
||||||
|
no-content-padding
|
||||||
>
|
>
|
||||||
<template #headerLeft>
|
<template #headerLeft>
|
||||||
<ConditionStatus
|
<ConditionStatus
|
||||||
|
@ -15,7 +16,7 @@
|
||||||
:status="props.scenarioDetail?.stepType"
|
:status="props.scenarioDetail?.stepType"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<div>
|
<div class="px-[12px]">
|
||||||
<StepDetailContent
|
<StepDetailContent
|
||||||
mode="tiled"
|
mode="tiled"
|
||||||
:show-type="props.showType"
|
:show-type="props.showType"
|
||||||
|
@ -102,4 +103,7 @@
|
||||||
padding-left: 0 !important;
|
padding-left: 0 !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
:deep(.arco-drawer-body) {
|
||||||
|
padding: 0 16px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -499,10 +499,6 @@
|
||||||
height: 1px;
|
height: 1px;
|
||||||
background: var(--color-text-n8);
|
background: var(--color-text-n8);
|
||||||
}
|
}
|
||||||
.foldContent {
|
|
||||||
height: 100%;
|
|
||||||
height: 1000px;
|
|
||||||
}
|
|
||||||
:deep(.step-tree-node-title) {
|
:deep(.step-tree-node-title) {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
import { useVModel } from '@vueuse/core';
|
import { useVModel } from '@vueuse/core';
|
||||||
import { Message } from '@arco-design/web-vue';
|
import { Message } from '@arco-design/web-vue';
|
||||||
|
|
||||||
|
import { archivedPlan, deletePlan } from '@/api/modules/test-plan/testPlan';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import { characterLimit } from '@/utils';
|
import { characterLimit } from '@/utils';
|
||||||
|
|
||||||
|
@ -59,6 +60,7 @@
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'update:visible', val: boolean): void;
|
(e: 'update:visible', val: boolean): void;
|
||||||
|
(e: 'success'): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const showModalVisible = useVModel(props, 'visible', emit);
|
const showModalVisible = useVModel(props, 'visible', emit);
|
||||||
|
@ -68,11 +70,21 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
const confirmLoading = ref<boolean>(false);
|
const confirmLoading = ref<boolean>(false);
|
||||||
function confirmHandler(isDelete: boolean) {
|
|
||||||
|
async function confirmHandler(isDelete: boolean) {
|
||||||
try {
|
try {
|
||||||
|
confirmLoading.value = true;
|
||||||
|
if (isDelete) {
|
||||||
|
await deletePlan(props.record?.id);
|
||||||
|
} else {
|
||||||
|
await archivedPlan(props.record?.id);
|
||||||
|
}
|
||||||
Message.success(isDelete ? t('common.deleteSuccess') : t('common.batchArchiveSuccess'));
|
Message.success(isDelete ? t('common.deleteSuccess') : t('common.batchArchiveSuccess'));
|
||||||
|
emit('success');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
|
} finally {
|
||||||
|
confirmLoading.value = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,7 @@
|
||||||
>
|
>
|
||||||
</template>
|
</template>
|
||||||
<template #statusFilter="{ columnConfig }">
|
<template #statusFilter="{ columnConfig }">
|
||||||
<a-trigger v-model:popup-visible="statusFilterVisible" @popup-visible-change="handleFilterHidden">
|
<a-trigger v-model:popup-visible="statusFilterVisible" trigger="click" @popup-visible-change="handleFilterHidden">
|
||||||
<a-button type="text" class="arco-btn-text--secondary" @click="statusFilterVisible = true">
|
<a-button type="text" class="arco-btn-text--secondary" @click="statusFilterVisible = true">
|
||||||
{{ t(columnConfig.title as string) }}
|
{{ t(columnConfig.title as string) }}
|
||||||
<icon-down :class="statusFilterVisible ? 'text-[rgb(var(--primary-5))]' : ''" />
|
<icon-down :class="statusFilterVisible ? 'text-[rgb(var(--primary-5))]' : ''" />
|
||||||
|
@ -242,7 +242,7 @@
|
||||||
@save="handleMoveOrCopy"
|
@save="handleMoveOrCopy"
|
||||||
/>
|
/>
|
||||||
<ScheduledModal v-model:visible="showScheduledTaskModal" />
|
<ScheduledModal v-model:visible="showScheduledTaskModal" />
|
||||||
<ActionModal v-model:visible="showStatusDeleteModal" :record="activeRecord" />
|
<ActionModal v-model:visible="showStatusDeleteModal" :record="activeRecord" @success="fetchData()" />
|
||||||
<BatchEditModal
|
<BatchEditModal
|
||||||
v-model:visible="showEditModel"
|
v-model:visible="showEditModel"
|
||||||
:batch-params="batchParams"
|
:batch-params="batchParams"
|
||||||
|
@ -274,13 +274,12 @@
|
||||||
import StatusProgress from './statusProgress.vue';
|
import StatusProgress from './statusProgress.vue';
|
||||||
import statusTag from '@/views/case-management/caseReview/components/statusTag.vue';
|
import statusTag from '@/views/case-management/caseReview/components/statusTag.vue';
|
||||||
|
|
||||||
import { getTestPlanList, getTestPlanModule } from '@/api/modules/test-plan/testPlan';
|
import { archivedPlan, batchDeletePlan, getTestPlanList, getTestPlanModule } from '@/api/modules/test-plan/testPlan';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useModal from '@/hooks/useModal';
|
import useModal from '@/hooks/useModal';
|
||||||
import { useAppStore, useTableStore } from '@/store';
|
import { useAppStore, useTableStore } from '@/store';
|
||||||
import { characterLimit } from '@/utils';
|
import { characterLimit } from '@/utils';
|
||||||
|
|
||||||
import { ReviewStatus } from '@/models/caseManagement/caseReview';
|
|
||||||
import type { planStatusType, TestPlanItem } from '@/models/testPlan/testPlan';
|
import type { planStatusType, TestPlanItem } from '@/models/testPlan/testPlan';
|
||||||
import { ColumnEditTypeEnum, TableKeyEnum } from '@/enums/tableEnum';
|
import { ColumnEditTypeEnum, TableKeyEnum } from '@/enums/tableEnum';
|
||||||
import { testPlanTypeEnum } from '@/enums/testPlanEnum';
|
import { testPlanTypeEnum } from '@/enums/testPlanEnum';
|
||||||
|
@ -537,110 +536,8 @@
|
||||||
eventTag: 'delete',
|
eventTag: 'delete',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
// TODO 临时数据
|
|
||||||
const data = [
|
|
||||||
{
|
|
||||||
id: '100944',
|
|
||||||
projectId: 'string',
|
|
||||||
num: '100944',
|
|
||||||
name: '系统示例',
|
|
||||||
status: 'COMPLETED',
|
|
||||||
tags: ['string'],
|
|
||||||
schedule: 'string',
|
|
||||||
createUser: 'string',
|
|
||||||
createTime: 'string',
|
|
||||||
moduleName: 'string',
|
|
||||||
moduleId: 'string',
|
|
||||||
passCount: 0,
|
|
||||||
unPassCount: 0,
|
|
||||||
reviewedCount: 0,
|
|
||||||
underReviewedCount: 0,
|
|
||||||
childrenCount: 2,
|
|
||||||
statusDetail: {
|
|
||||||
tolerance: 100,
|
|
||||||
UNPENDING: 100,
|
|
||||||
RUNNING: 30,
|
|
||||||
SUCCESS: 30,
|
|
||||||
ERROR: 30,
|
|
||||||
executionProgress: '100%',
|
|
||||||
},
|
|
||||||
useCaseCount: {
|
|
||||||
caseCount: 3,
|
|
||||||
apiCount: 3,
|
|
||||||
scenarioCount: 3,
|
|
||||||
},
|
|
||||||
// children: [
|
|
||||||
// {
|
|
||||||
// id: '100945',
|
|
||||||
// projectId: 'string',
|
|
||||||
// num: '100945',
|
|
||||||
// name: '系统示例',
|
|
||||||
// status: 'COMPLETED',
|
|
||||||
// tags: ['string'],
|
|
||||||
// schedule: 'string',
|
|
||||||
// createUser: 'string',
|
|
||||||
// createTime: 'string',
|
|
||||||
// moduleName: 'string',
|
|
||||||
// moduleId: 'string',
|
|
||||||
// testPlanItem: [],
|
|
||||||
// testPlanGroupId: 'string',
|
|
||||||
// passCount: 0,
|
|
||||||
// unPassCount: 0,
|
|
||||||
// reviewedCount: 0,
|
|
||||||
// underReviewedCount: 0,
|
|
||||||
// childrenCount: 0,
|
|
||||||
// useCaseCount: {
|
|
||||||
// caseCount: 3,
|
|
||||||
// apiCount: 3,
|
|
||||||
// scenarioCount: 3,
|
|
||||||
// },
|
|
||||||
// statusDetail: {
|
|
||||||
// tolerance: 100,
|
|
||||||
// UNPENDING: 100,
|
|
||||||
// RUNNING: 30,
|
|
||||||
// SUCCESS: 30,
|
|
||||||
// ERROR: 30,
|
|
||||||
// executionProgress: '100%',
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// id: '100955',
|
|
||||||
// projectId: 'string',
|
|
||||||
// num: '100955',
|
|
||||||
// name: '系统示例',
|
|
||||||
// status: 'COMPLETED',
|
|
||||||
// tags: ['string'],
|
|
||||||
// schedule: 'string',
|
|
||||||
// createUser: 'string',
|
|
||||||
// createTime: 'string',
|
|
||||||
// moduleName: 'string',
|
|
||||||
// moduleId: 'string',
|
|
||||||
// testPlanItem: [],
|
|
||||||
// testPlanGroupId: 'string',
|
|
||||||
// passCount: 0,
|
|
||||||
// unPassCount: 0,
|
|
||||||
// reviewedCount: 0,
|
|
||||||
// underReviewedCount: 0,
|
|
||||||
// childrenCount: 0,
|
|
||||||
// useCaseCount: {
|
|
||||||
// caseCount: 3,
|
|
||||||
// apiCount: 3,
|
|
||||||
// scenarioCount: 3,
|
|
||||||
// },
|
|
||||||
// statusDetail: {
|
|
||||||
// tolerance: 100,
|
|
||||||
// UNPENDING: 100,
|
|
||||||
// RUNNING: 30,
|
|
||||||
// SUCCESS: 30,
|
|
||||||
// ERROR: 30,
|
|
||||||
// executionProgress: '100%',
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// ],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector, setProps } = useTable(
|
const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector } = useTable(
|
||||||
getTestPlanList,
|
getTestPlanList,
|
||||||
{
|
{
|
||||||
tableKey: TableKeyEnum.TEST_PLAN_ALL_TABLE,
|
tableKey: TableKeyEnum.TEST_PLAN_ALL_TABLE,
|
||||||
|
@ -821,6 +718,19 @@
|
||||||
onBeforeOk: async () => {
|
onBeforeOk: async () => {
|
||||||
try {
|
try {
|
||||||
const { selectedIds, selectAll, excludeIds } = batchParams.value;
|
const { selectedIds, selectAll, excludeIds } = batchParams.value;
|
||||||
|
await batchDeletePlan({
|
||||||
|
projectId: appStore.currentProjectId,
|
||||||
|
selectIds: selectedIds || [],
|
||||||
|
excludeIds: excludeIds || [],
|
||||||
|
moduleIds: props.activeFolder === 'all' ? [] : [props.activeFolder, ...props.offspringIds],
|
||||||
|
condition: {
|
||||||
|
keyword: keyword.value,
|
||||||
|
filter: {},
|
||||||
|
combine: batchParams.value.condition,
|
||||||
|
},
|
||||||
|
selectAll: !!selectAll,
|
||||||
|
type: showType.value,
|
||||||
|
});
|
||||||
Message.success(t('common.deleteSuccess'));
|
Message.success(t('common.deleteSuccess'));
|
||||||
fetchData();
|
fetchData();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -908,6 +818,7 @@
|
||||||
},
|
},
|
||||||
onBeforeOk: async () => {
|
onBeforeOk: async () => {
|
||||||
try {
|
try {
|
||||||
|
await archivedPlan(record.id);
|
||||||
Message.success(t('common.batchArchiveSuccess'));
|
Message.success(t('common.batchArchiveSuccess'));
|
||||||
fetchData();
|
fetchData();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
@ -105,12 +105,12 @@
|
||||||
import TestPlanTree from './components/testPlanTree.vue';
|
import TestPlanTree from './components/testPlanTree.vue';
|
||||||
import CreateAndEditPlanDrawer from './createAndEditPlanDrawer.vue';
|
import CreateAndEditPlanDrawer from './createAndEditPlanDrawer.vue';
|
||||||
|
|
||||||
import { createPlanModuleTree } from '@/api/modules/test-plan/testPlan';
|
import { createPlanModuleTree, getPlanModulesCount } from '@/api/modules/test-plan/testPlan';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useAppStore from '@/store/modules/app';
|
import useAppStore from '@/store/modules/app';
|
||||||
|
|
||||||
import type { CaseModuleQueryParams, CreateOrUpdateModule, ValidateInfo } from '@/models/caseManagement/featureCase';
|
import type { CreateOrUpdateModule } from '@/models/caseManagement/featureCase';
|
||||||
import type { ModuleTreeNode } from '@/models/common';
|
import { ModuleTreeNode, TableQueryParams } from '@/models/common';
|
||||||
|
|
||||||
import Message from '@arco-design/web-vue/es/message';
|
import Message from '@arco-design/web-vue/es/message';
|
||||||
|
|
||||||
|
@ -202,7 +202,13 @@
|
||||||
/**
|
/**
|
||||||
* 刷新模块树的统计数量
|
* 刷新模块树的统计数量
|
||||||
*/
|
*/
|
||||||
function initModulesCount(params: any) {}
|
async function initModulesCount(params: TableQueryParams) {
|
||||||
|
try {
|
||||||
|
modulesCount.value = await getPlanModulesCount(params);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const showPlanDrawer = ref(false);
|
const showPlanDrawer = ref(false);
|
||||||
function handleSelect(value: string | number | Record<string, any> | undefined) {
|
function handleSelect(value: string | number | Record<string, any> | undefined) {
|
||||||
|
|
Loading…
Reference in New Issue