feat(接口测试): 批量执行场景前后端联调
This commit is contained in:
parent
364d8c9a18
commit
96b0df3330
|
@ -7,6 +7,7 @@ import {
|
||||||
BatchMoveScenarioUrl,
|
BatchMoveScenarioUrl,
|
||||||
BatchRecoverScenarioUrl,
|
BatchRecoverScenarioUrl,
|
||||||
BatchRecycleScenarioUrl,
|
BatchRecycleScenarioUrl,
|
||||||
|
BatchRunScenarioUrl,
|
||||||
DeleteModuleUrl,
|
DeleteModuleUrl,
|
||||||
DeleteScenarioUrl,
|
DeleteScenarioUrl,
|
||||||
ExecuteHistoryUrl,
|
ExecuteHistoryUrl,
|
||||||
|
@ -27,6 +28,7 @@ import {
|
||||||
import {
|
import {
|
||||||
ApiScenarioBatchDeleteParams,
|
ApiScenarioBatchDeleteParams,
|
||||||
ApiScenarioBatchEditParams,
|
ApiScenarioBatchEditParams,
|
||||||
|
ApiScenarioBatchRunParams,
|
||||||
ApiScenarioGetModuleParams,
|
ApiScenarioGetModuleParams,
|
||||||
ApiScenarioModuleUpdateParams,
|
ApiScenarioModuleUpdateParams,
|
||||||
ApiScenarioPageParams,
|
ApiScenarioPageParams,
|
||||||
|
@ -130,6 +132,11 @@ export function batchEditScenario(params: ApiScenarioBatchEditParams) {
|
||||||
return MSR.post({ url: BatchEditScenarioUrl, params });
|
return MSR.post({ url: BatchEditScenarioUrl, params });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 批量编辑场景
|
||||||
|
export function batchRunScenario(params: ApiScenarioBatchRunParams) {
|
||||||
|
return MSR.post({ url: BatchRunScenarioUrl, params });
|
||||||
|
}
|
||||||
|
|
||||||
// 场景执行历史接口
|
// 场景执行历史接口
|
||||||
export function getExecuteHistory(data: ExecutePageParams) {
|
export function getExecuteHistory(data: ExecutePageParams) {
|
||||||
return MSR.post<CommonList<ExecuteHistoryItem>>({ url: ExecuteHistoryUrl, data });
|
return MSR.post<CommonList<ExecuteHistoryItem>>({ url: ExecuteHistoryUrl, data });
|
||||||
|
|
|
@ -40,7 +40,7 @@ export const DefinitionReferenceUrl = '/api/definition/get-reference'; // 获取
|
||||||
* Mock
|
* Mock
|
||||||
*/
|
*/
|
||||||
export const DefinitionMockPageUrl = '/api/definition/mock/page'; // mock列表
|
export const DefinitionMockPageUrl = '/api/definition/mock/page'; // mock列表
|
||||||
export const UpdateMockStatusUrl = '/api/definition/mock/enable/'; // 更新mock状态
|
export const UpdateMockStatusUrl = '/api/definition/mock/enable'; // 更新mock状态
|
||||||
export const DeleteMockUrl = '/api/definition/mock/delete'; // 刪除mock
|
export const DeleteMockUrl = '/api/definition/mock/delete'; // 刪除mock
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -11,6 +11,7 @@ export const BatchRecycleScenarioUrl = '/api/scenario/batch-operation/delete-gc'
|
||||||
export const BatchMoveScenarioUrl = '/api/scenario/batch-operation/move'; // 批量移动接口场景
|
export const BatchMoveScenarioUrl = '/api/scenario/batch-operation/move'; // 批量移动接口场景
|
||||||
export const BatchCopyScenarioUrl = '/api/scenario/batch-operation/copy'; // 批量复制接口场景
|
export const BatchCopyScenarioUrl = '/api/scenario/batch-operation/copy'; // 批量复制接口场景
|
||||||
export const BatchEditScenarioUrl = '/api/scenario/batch-operation/edit'; // 批量编辑接口场景
|
export const BatchEditScenarioUrl = '/api/scenario/batch-operation/edit'; // 批量编辑接口场景
|
||||||
|
export const BatchRunScenarioUrl = '/api/scenario/batch-operation/run'; // 批量执行接口场景
|
||||||
|
|
||||||
// 回收站相关
|
// 回收站相关
|
||||||
export const GetTrashModuleTreeUrl = '/api/scenario/module/trash/tree';
|
export const GetTrashModuleTreeUrl = '/api/scenario/module/trash/tree';
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import type { CaseLevel } from '@/components/business/ms-case-associate/types';
|
import type { CaseLevel } from '@/components/business/ms-case-associate/types';
|
||||||
import { ScenarioStepInfo } from '@/views/api-test/scenario/components/step/index.vue';
|
import { ScenarioStepInfo } from '@/views/api-test/scenario/components/step/index.vue';
|
||||||
|
|
||||||
import { ApiDefinitionCustomField } from '@/models/apiTest/management';
|
import { ApiDefinitionCustomField, ApiRunModeRequest } from '@/models/apiTest/management';
|
||||||
import { ApiScenarioStatus, RequestComposition, RequestDefinitionStatus } from '@/enums/apiEnum';
|
import { ApiScenarioStatus, RequestComposition, RequestDefinitionStatus } from '@/enums/apiEnum';
|
||||||
|
|
||||||
import { BatchApiParams, TableQueryParams } from '../common';
|
import { BatchApiParams, TableQueryParams } from '../common';
|
||||||
|
@ -104,13 +104,22 @@ export interface BatchOptionParams extends BatchApiParams {
|
||||||
refId?: string;
|
refId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 场景批量编辑参数
|
||||||
|
export interface ApiScenarioBatchParams extends BatchApiParams {
|
||||||
|
projectId?: string;
|
||||||
|
moduleIds?: string[];
|
||||||
|
apiScenarioId?: string;
|
||||||
|
versionId?: string;
|
||||||
|
refId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
// 批量移动场景参数
|
// 批量移动场景参数
|
||||||
export interface ApiScenarioBatchMoveParams extends BatchOptionParams {
|
export interface ApiScenarioBatchMoveParams extends ApiScenarioBatchParams {
|
||||||
targetModuleId: string | number;
|
targetModuleId: string | number;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 批量编辑场景参数
|
// 批量编辑场景参数
|
||||||
export interface ApiScenarioBatchEditParams extends BatchOptionParams {
|
export interface ApiScenarioBatchEditParams extends ApiScenarioBatchParams {
|
||||||
// 修改操作的类型
|
// 修改操作的类型
|
||||||
type?: string;
|
type?: string;
|
||||||
|
|
||||||
|
@ -130,8 +139,14 @@ export interface ApiScenarioBatchEditParams extends BatchOptionParams {
|
||||||
priority?: string;
|
priority?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 批量编辑场景参数
|
||||||
|
export interface ApiScenarioBatchRunParams extends ApiScenarioBatchParams {
|
||||||
|
// 运行模式配置
|
||||||
|
runModeConfig?: ApiRunModeRequest;
|
||||||
|
}
|
||||||
|
|
||||||
// 批量删除场景参数
|
// 批量删除场景参数
|
||||||
export interface ApiScenarioBatchDeleteParams extends BatchApiParams {
|
export interface ApiScenarioBatchDeleteParams extends ApiScenarioBatchParams {
|
||||||
deleteAll: boolean;
|
deleteAll: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,232 @@
|
||||||
|
<template>
|
||||||
|
<a-modal v-model:visible="showBatchExecute" title-align="start" class="ms-modal-upload ms-modal-medium" :width="480">
|
||||||
|
<template #title>
|
||||||
|
{{ t('report.trigger.batch.execution') }}
|
||||||
|
<div class="text-[var(--color-text-4)]">
|
||||||
|
{{
|
||||||
|
t('case.batchModalSubTitle', {
|
||||||
|
count: props.batchParams?.currentSelectCount || tableSelected.length,
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<a-form ref="batchExecuteFormRef" class="rounded-[4px]" :model="batchExecuteForm" layout="vertical">
|
||||||
|
<a-form-item field="defaultEnv" :label="t('case.execute.selectEnv')">
|
||||||
|
<a-radio-group v-model="batchExecuteForm.defaultEnv">
|
||||||
|
<a-radio value="true"
|
||||||
|
>{{ t('case.execute.defaultEnv') }}
|
||||||
|
<a-tooltip :content="t('case.execute.defaultEnvTip')" position="top">
|
||||||
|
<icon-question-circle
|
||||||
|
class="text-[var(--color-text-brand)] hover:text-[rgb(var(--primary-5))]"
|
||||||
|
size="16"
|
||||||
|
/>
|
||||||
|
</a-tooltip>
|
||||||
|
</a-radio>
|
||||||
|
<a-radio value="false">{{ t('case.execute.newEnv') }}</a-radio>
|
||||||
|
</a-radio-group>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
v-if="batchExecuteForm.defaultEnv == 'false'"
|
||||||
|
field="environmentId"
|
||||||
|
:label="t('case.execute.newEnv')"
|
||||||
|
:rules="[{ required: true, message: t('apiTestManagement.valueRequired') }]"
|
||||||
|
asterisk-position="end"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<a-select v-model="batchExecuteForm.environmentId" :placeholder="t('common.pleaseSelect')">
|
||||||
|
<a-option v-for="item of environmentList" :key="item.id" :value="item.id">
|
||||||
|
{{ t(item.name) }}
|
||||||
|
</a-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item field="runMode" :label="t('case.execute.model')">
|
||||||
|
<a-radio-group v-model="batchExecuteForm.runMode">
|
||||||
|
<a-radio value="SERIAL">{{ t('case.execute.serial') }}</a-radio>
|
||||||
|
<a-radio value="PARALLEL">{{ t('case.execute.parallel') }}</a-radio>
|
||||||
|
</a-radio-group>
|
||||||
|
</a-form-item>
|
||||||
|
<div v-if="batchExecuteForm.runMode == 'SERIAL'" class="ms-switch">
|
||||||
|
<a-switch
|
||||||
|
v-model="batchExecuteForm.stopOnFailure"
|
||||||
|
type="line"
|
||||||
|
class="ms-form-table-input-switch execute-form-table-input-switch"
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
|
<span class="ml-3 font-normal text-[var(--color-text-1)]">{{ t('case.execute.StopOnFailure') }}</span>
|
||||||
|
</div>
|
||||||
|
<a-form-item field="integratedReport" :label="t('case.execute.reportSetting')">
|
||||||
|
<a-radio-group v-model="batchExecuteForm.integratedReport" type="button">
|
||||||
|
<a-radio value="false">{{ t('case.execute.independentReporting') }}</a-radio>
|
||||||
|
<a-radio value="true">{{ t('case.execute.CollectionReport') }}</a-radio>
|
||||||
|
</a-radio-group>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
v-if="batchExecuteForm.integratedReport == 'true'"
|
||||||
|
field="integratedReport"
|
||||||
|
:label="t('case.execute.reportName')"
|
||||||
|
:rules="[{ required: true, message: t('apiTestManagement.valueRequired') }]"
|
||||||
|
:validate-trigger="['blur', 'input']"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
v-model="batchExecuteForm.integratedReportName"
|
||||||
|
:max-length="255"
|
||||||
|
:placeholder="t('formCreate.PleaseEnter')"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item field="poolId" :label="t('case.execute.pool')">
|
||||||
|
<a-select v-model="batchExecuteForm.poolId" :placeholder="t('common.pleaseSelect')">
|
||||||
|
<a-option v-for="item of resourcePoolList" :key="item.id" :value="item.id">
|
||||||
|
{{ t(item.name) }}
|
||||||
|
</a-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
<template #footer>
|
||||||
|
<a-button type="secondary" :disabled="batchExecuteLoading" @click="cancelBatchExecute">
|
||||||
|
{{ t('common.cancel') }}
|
||||||
|
</a-button>
|
||||||
|
<a-button type="primary" :loading="batchExecuteLoading" @click="handleBatchExecuteCase">
|
||||||
|
{{ t('system.log.operateType.execute') }}
|
||||||
|
</a-button>
|
||||||
|
</template>
|
||||||
|
</a-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, watch } from 'vue';
|
||||||
|
import { FormInstance, Message } from '@arco-design/web-vue';
|
||||||
|
|
||||||
|
import { BatchActionQueryParams } from '@/components/pure/ms-table/type';
|
||||||
|
|
||||||
|
import { getEnvList, getPoolId, getPoolOption } from '@/api/modules/api-test/management';
|
||||||
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
import useAppStore from '@/store/modules/app';
|
||||||
|
|
||||||
|
import { Environment } from '@/models/apiTest/management';
|
||||||
|
import { ResourcePoolItem } from '@/models/setting/resourcePool';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const batchExecuteFormRef = ref<FormInstance>();
|
||||||
|
const batchExecuteForm = ref({
|
||||||
|
defaultEnv: 'true',
|
||||||
|
runMode: 'SERIAL',
|
||||||
|
integratedReport: 'false',
|
||||||
|
integratedReportName: '',
|
||||||
|
stopOnFailure: false,
|
||||||
|
poolId: '',
|
||||||
|
grouped: false,
|
||||||
|
environmentId: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
const environmentList = ref<Environment[]>();
|
||||||
|
const resourcePoolList = ref<ResourcePoolItem[]>();
|
||||||
|
const defaultPoolId = ref<string>();
|
||||||
|
const appStore = useAppStore();
|
||||||
|
const showBatchExecute = ref(false);
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
tableSelected: (string | number)[];
|
||||||
|
visible: boolean;
|
||||||
|
batchParams?: BatchActionQueryParams;
|
||||||
|
batchConditionParams: any;
|
||||||
|
batchRunFunc: (a: any) => Promise<any>;
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
visible: false,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// 初始化资源池列表
|
||||||
|
async function initPoolList() {
|
||||||
|
resourcePoolList.value = await getPoolOption(appStore.currentProjectId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取项目配置的默认资源池
|
||||||
|
async function getDefaultPoolId() {
|
||||||
|
try {
|
||||||
|
defaultPoolId.value = await getPoolId(appStore.currentProjectId);
|
||||||
|
batchExecuteForm.value.poolId = defaultPoolId.value || '';
|
||||||
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化环境列表
|
||||||
|
async function initEnvList() {
|
||||||
|
environmentList.value = await getEnvList(appStore.currentProjectId);
|
||||||
|
}
|
||||||
|
|
||||||
|
const batchExecuteLoading = ref(false);
|
||||||
|
|
||||||
|
const emit = defineEmits(['update:visible', 'finished']);
|
||||||
|
|
||||||
|
function cancelBatchExecute() {
|
||||||
|
showBatchExecute.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleBatchExecuteCase() {
|
||||||
|
batchExecuteFormRef.value?.validate(async (errors) => {
|
||||||
|
const { batchParams } = props;
|
||||||
|
const { batchConditionParams } = props;
|
||||||
|
if (!errors) {
|
||||||
|
try {
|
||||||
|
batchExecuteLoading.value = true;
|
||||||
|
await props?.batchRunFunc({
|
||||||
|
selectIds: batchParams?.selectedIds || [],
|
||||||
|
selectAll: !!batchParams?.selectAll,
|
||||||
|
excludeIds: batchParams?.excludeIds || [],
|
||||||
|
projectId: appStore.currentProjectId,
|
||||||
|
...batchConditionParams,
|
||||||
|
runModeConfig: {
|
||||||
|
runMode: batchExecuteForm.value.runMode,
|
||||||
|
integratedReport: batchExecuteForm.value.integratedReport === 'true',
|
||||||
|
integratedReportName: batchExecuteForm.value.integratedReportName,
|
||||||
|
stopOnFailure: batchExecuteForm.value.stopOnFailure,
|
||||||
|
poolId: batchExecuteForm.value.poolId,
|
||||||
|
grouped: batchExecuteForm.value.grouped,
|
||||||
|
environmentId: batchExecuteForm.value.environmentId,
|
||||||
|
},
|
||||||
|
apiDefinitionId: '',
|
||||||
|
versionId: '',
|
||||||
|
refId: '',
|
||||||
|
});
|
||||||
|
Message.success(t('case.detail.execute.success'));
|
||||||
|
cancelBatchExecute();
|
||||||
|
emit('finished');
|
||||||
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(error);
|
||||||
|
} finally {
|
||||||
|
batchExecuteLoading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.visible,
|
||||||
|
(val) => {
|
||||||
|
if (val) {
|
||||||
|
showBatchExecute.value = true;
|
||||||
|
initEnvList();
|
||||||
|
initPoolList();
|
||||||
|
getDefaultPoolId();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => showBatchExecute.value,
|
||||||
|
(val) => {
|
||||||
|
emit('update:visible', val);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less"></style>
|
|
@ -270,97 +270,14 @@
|
||||||
@load-case="(id: string) => loadCase(id)"
|
@load-case="(id: string) => loadCase(id)"
|
||||||
@delete-case="deleteCaseByDetail"
|
@delete-case="deleteCaseByDetail"
|
||||||
/>
|
/>
|
||||||
<a-modal v-model:visible="showBatchExecute" title-align="start" class="ms-modal-upload ms-modal-medium" :width="480">
|
<batchRunModal
|
||||||
<template #title>
|
v-model:visible="showBatchExecute"
|
||||||
{{ t('report.trigger.batch.execution') }}
|
:batch-condition-params="batchConditionParams"
|
||||||
<div class="text-[var(--color-text-4)]">
|
:batch-params="batchParams"
|
||||||
{{
|
:table-selected="tableSelected"
|
||||||
t('case.batchModalSubTitle', {
|
:batch-run-func="batchExecuteCase"
|
||||||
count: batchParams.currentSelectCount || tableSelected.length,
|
@finished="loadCaseListAndResetSelector"
|
||||||
})
|
/>
|
||||||
}}
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<a-form ref="batchExecuteFormRef" class="rounded-[4px]" :model="batchExecuteForm" layout="vertical">
|
|
||||||
<a-form-item field="defaultEnv" :label="t('case.execute.selectEnv')">
|
|
||||||
<a-radio-group v-model="batchExecuteForm.defaultEnv">
|
|
||||||
<a-radio value="true"
|
|
||||||
>{{ t('case.execute.defaultEnv') }}
|
|
||||||
<a-tooltip :content="t('case.execute.defaultEnvTip')" position="top">
|
|
||||||
<icon-question-circle
|
|
||||||
class="text-[var(--color-text-brand)] hover:text-[rgb(var(--primary-5))]"
|
|
||||||
size="16"
|
|
||||||
/> </a-tooltip
|
|
||||||
></a-radio>
|
|
||||||
<a-radio value="false">{{ t('case.execute.newEnv') }}</a-radio>
|
|
||||||
</a-radio-group>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item
|
|
||||||
v-if="batchExecuteForm.defaultEnv == 'false'"
|
|
||||||
field="environmentId"
|
|
||||||
:label="t('case.execute.newEnv')"
|
|
||||||
:rules="[{ required: true, message: t('apiTestManagement.valueRequired') }]"
|
|
||||||
asterisk-position="end"
|
|
||||||
required
|
|
||||||
>
|
|
||||||
<a-select v-model="batchExecuteForm.environmentId" :placeholder="t('common.pleaseSelect')">
|
|
||||||
<a-option v-for="item of environmentList" :key="item.id" :value="item.id">
|
|
||||||
{{ t(item.name) }}
|
|
||||||
</a-option>
|
|
||||||
</a-select>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item field="runMode" :label="t('case.execute.model')">
|
|
||||||
<a-radio-group v-model="batchExecuteForm.runMode">
|
|
||||||
<a-radio value="SERIAL">{{ t('case.execute.serial') }}</a-radio>
|
|
||||||
<a-radio value="PARALLEL">{{ t('case.execute.parallel') }}</a-radio>
|
|
||||||
</a-radio-group>
|
|
||||||
</a-form-item>
|
|
||||||
<div v-if="batchExecuteForm.runMode == 'SERIAL'" class="ms-switch">
|
|
||||||
<a-switch
|
|
||||||
v-model="batchExecuteForm.stopOnFailure"
|
|
||||||
type="line"
|
|
||||||
class="ms-form-table-input-switch execute-form-table-input-switch"
|
|
||||||
size="small"
|
|
||||||
/>
|
|
||||||
<span class="ml-3 font-normal text-[var(--color-text-1)]">{{ t('case.execute.StopOnFailure') }}</span>
|
|
||||||
</div>
|
|
||||||
<a-form-item field="integratedReport" :label="t('case.execute.reportSetting')">
|
|
||||||
<a-radio-group v-model="batchExecuteForm.integratedReport" type="button">
|
|
||||||
<a-radio value="false">{{ t('case.execute.independentReporting') }}</a-radio>
|
|
||||||
<a-radio value="true">{{ t('case.execute.CollectionReport') }}</a-radio>
|
|
||||||
</a-radio-group>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item
|
|
||||||
v-if="batchExecuteForm.integratedReport == 'true'"
|
|
||||||
field="integratedReport"
|
|
||||||
:label="t('case.execute.reportName')"
|
|
||||||
:rules="[{ required: true, message: t('apiTestManagement.valueRequired') }]"
|
|
||||||
:validate-trigger="['blur', 'input']"
|
|
||||||
>
|
|
||||||
<a-input
|
|
||||||
v-model="batchExecuteForm.integratedReportName"
|
|
||||||
:max-length="255"
|
|
||||||
:placeholder="t('formCreate.PleaseEnter')"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item field="poolId" :label="t('case.execute.pool')">
|
|
||||||
<a-select v-model="batchExecuteForm.poolId" :placeholder="t('common.pleaseSelect')">
|
|
||||||
<a-option v-for="item of resourcePoolList" :key="item.id" :value="item.id">
|
|
||||||
{{ t(item.name) }}
|
|
||||||
</a-option>
|
|
||||||
</a-select>
|
|
||||||
</a-form-item>
|
|
||||||
</a-form>
|
|
||||||
<template #footer>
|
|
||||||
<a-button type="secondary" :disabled="batchExecuteLoading" @click="cancelBatchExecute">
|
|
||||||
{{ t('common.cancel') }}
|
|
||||||
</a-button>
|
|
||||||
<a-button type="primary" :loading="batchExecuteLoading" @click="handleBatchExecuteCase">
|
|
||||||
{{ t('system.log.operateType.execute') }}
|
|
||||||
</a-button>
|
|
||||||
</template>
|
|
||||||
</a-modal>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
@ -379,6 +296,7 @@
|
||||||
import caseDetailDrawer from './caseDetailDrawer.vue';
|
import caseDetailDrawer from './caseDetailDrawer.vue';
|
||||||
import createAndEditCaseDrawer from './createAndEditCaseDrawer.vue';
|
import createAndEditCaseDrawer from './createAndEditCaseDrawer.vue';
|
||||||
import apiStatus from '@/views/api-test/components/apiStatus.vue';
|
import apiStatus from '@/views/api-test/components/apiStatus.vue';
|
||||||
|
import BatchRunModal from '@/views/api-test/components/batchRunModal.vue';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
batchDeleteCase,
|
batchDeleteCase,
|
||||||
|
@ -389,9 +307,6 @@
|
||||||
executeCase,
|
executeCase,
|
||||||
getCaseDetail,
|
getCaseDetail,
|
||||||
getCasePage,
|
getCasePage,
|
||||||
getEnvList,
|
|
||||||
getPoolId,
|
|
||||||
getPoolOption,
|
|
||||||
updateCasePriority,
|
updateCasePriority,
|
||||||
updateCaseStatus,
|
updateCaseStatus,
|
||||||
} from '@/api/modules/api-test/management';
|
} from '@/api/modules/api-test/management';
|
||||||
|
@ -402,9 +317,8 @@
|
||||||
import useAppStore from '@/store/modules/app';
|
import useAppStore from '@/store/modules/app';
|
||||||
import { hasAnyPermission } from '@/utils/permission';
|
import { hasAnyPermission } from '@/utils/permission';
|
||||||
|
|
||||||
import { ApiCaseDetail, Environment } from '@/models/apiTest/management';
|
import { ApiCaseDetail } from '@/models/apiTest/management';
|
||||||
import { DragSortParams } from '@/models/common';
|
import { DragSortParams } from '@/models/common';
|
||||||
import { ResourcePoolItem } from '@/models/setting/resourcePool';
|
|
||||||
import { RequestDefinitionStatus } from '@/enums/apiEnum';
|
import { RequestDefinitionStatus } from '@/enums/apiEnum';
|
||||||
import { TableKeyEnum } from '@/enums/tableEnum';
|
import { TableKeyEnum } from '@/enums/tableEnum';
|
||||||
|
|
||||||
|
@ -615,11 +529,6 @@
|
||||||
const lastReportStatusList = ['error', 'FakeError', 'success'];
|
const lastReportStatusList = ['error', 'FakeError', 'success'];
|
||||||
const lastReportStatusFilters = ref<string[]>([...lastReportStatusList]);
|
const lastReportStatusFilters = ref<string[]>([...lastReportStatusList]);
|
||||||
|
|
||||||
const environmentList = ref<Environment[]>();
|
|
||||||
|
|
||||||
const resourcePoolList = ref<ResourcePoolItem[]>();
|
|
||||||
const defaultPoolId = ref<string>();
|
|
||||||
|
|
||||||
async function getModuleIds() {
|
async function getModuleIds() {
|
||||||
let moduleIds: string[] = [];
|
let moduleIds: string[] = [];
|
||||||
if (props.activeModule !== 'all') {
|
if (props.activeModule !== 'all') {
|
||||||
|
@ -661,30 +570,9 @@
|
||||||
caseFilters.value = caseLevelFields.value?.options.map((item: any) => item.text);
|
caseFilters.value = caseLevelFields.value?.options.map((item: any) => item.text);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化环境列表
|
|
||||||
async function initEnvList() {
|
|
||||||
environmentList.value = await getEnvList(appStore.currentProjectId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化资源池列表
|
|
||||||
async function initPoolList() {
|
|
||||||
resourcePoolList.value = await getPoolOption(appStore.getCurrentProjectId);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getDefaultPoolId() {
|
|
||||||
try {
|
|
||||||
defaultPoolId.value = await getPoolId(appStore.getCurrentProjectId);
|
|
||||||
} catch (error) {
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
loadCaseList();
|
loadCaseList();
|
||||||
initPoolList();
|
|
||||||
getCaseLevelFields();
|
getCaseLevelFields();
|
||||||
getDefaultPoolId();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function handleFilterHidden(val: boolean) {
|
function handleFilterHidden(val: boolean) {
|
||||||
|
@ -830,24 +718,13 @@
|
||||||
// 用例执行
|
// 用例执行
|
||||||
const showBatchExecute = ref(false);
|
const showBatchExecute = ref(false);
|
||||||
const batchEditLoading = ref(false);
|
const batchEditLoading = ref(false);
|
||||||
const batchExecuteLoading = ref(false);
|
|
||||||
const batchFormRef = ref<FormInstance>();
|
const batchFormRef = ref<FormInstance>();
|
||||||
const batchForm = ref({
|
const batchForm = ref({
|
||||||
attr: '',
|
attr: '',
|
||||||
value: '',
|
value: '',
|
||||||
values: [],
|
values: [],
|
||||||
});
|
});
|
||||||
const batchExecuteFormRef = ref<FormInstance>();
|
|
||||||
const batchExecuteForm = ref({
|
|
||||||
defaultEnv: 'true',
|
|
||||||
runMode: 'SERIAL',
|
|
||||||
integratedReport: 'false',
|
|
||||||
integratedReportName: '',
|
|
||||||
stopOnFailure: false,
|
|
||||||
poolId: '',
|
|
||||||
grouped: false,
|
|
||||||
environmentId: '',
|
|
||||||
});
|
|
||||||
const attrOptions = [
|
const attrOptions = [
|
||||||
{
|
{
|
||||||
name: 'case.caseLevel',
|
name: 'case.caseLevel',
|
||||||
|
@ -937,51 +814,7 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function cancelBatchExecute() {
|
const batchConditionParams = ref<any>();
|
||||||
showBatchExecute.value = false;
|
|
||||||
batchFormRef.value?.resetFields();
|
|
||||||
batchForm.value = {
|
|
||||||
attr: '',
|
|
||||||
value: '',
|
|
||||||
values: [],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
function handleBatchExecuteCase() {
|
|
||||||
batchExecuteFormRef.value?.validate(async (errors) => {
|
|
||||||
if (!errors) {
|
|
||||||
try {
|
|
||||||
batchExecuteLoading.value = true;
|
|
||||||
const batchConditionParams = await genBatchConditionParams();
|
|
||||||
await batchExecuteCase({
|
|
||||||
selectIds: batchParams.value?.selectedIds || [],
|
|
||||||
selectAll: !!batchParams.value?.selectAll,
|
|
||||||
excludeIds: batchParams.value?.excludeIds || [],
|
|
||||||
...batchConditionParams,
|
|
||||||
runModeConfig: {
|
|
||||||
runMode: batchExecuteForm.value.runMode,
|
|
||||||
integratedReport: batchExecuteForm.value.integratedReport === 'true',
|
|
||||||
integratedReportName: batchExecuteForm.value.integratedReportName,
|
|
||||||
stopOnFailure: batchExecuteForm.value.stopOnFailure,
|
|
||||||
poolId: batchExecuteForm.value.poolId,
|
|
||||||
grouped: batchExecuteForm.value.grouped,
|
|
||||||
environmentId: batchExecuteForm.value.environmentId,
|
|
||||||
},
|
|
||||||
apiDefinitionId: '',
|
|
||||||
versionId: '',
|
|
||||||
refId: '',
|
|
||||||
});
|
|
||||||
Message.success(t('case.detail.execute.success'));
|
|
||||||
cancelBatchExecute();
|
|
||||||
loadCaseListAndResetSelector();
|
|
||||||
} catch (error) {
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.log(error);
|
|
||||||
} finally {
|
|
||||||
batchExecuteLoading.value = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理表格选中后批量操作
|
// 处理表格选中后批量操作
|
||||||
function handleTableBatch(event: BatchActionParams, params: BatchActionQueryParams) {
|
function handleTableBatch(event: BatchActionParams, params: BatchActionQueryParams) {
|
||||||
|
@ -995,9 +828,10 @@
|
||||||
showBatchEditModal.value = true;
|
showBatchEditModal.value = true;
|
||||||
break;
|
break;
|
||||||
case 'execute':
|
case 'execute':
|
||||||
showBatchExecute.value = true;
|
genBatchConditionParams().then((data) => {
|
||||||
batchExecuteForm.value.poolId = defaultPoolId.value || '';
|
batchConditionParams.value = data;
|
||||||
initEnvList();
|
showBatchExecute.value = true;
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -275,6 +275,14 @@
|
||||||
@folder-node-select="folderNodeSelect"
|
@folder-node-select="folderNodeSelect"
|
||||||
/>
|
/>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
|
<batchRunModal
|
||||||
|
v-model:visible="showBatchExecute"
|
||||||
|
:batch-condition-params="batchConditionParams"
|
||||||
|
:batch-params="batchParams"
|
||||||
|
:table-selected="tableSelected"
|
||||||
|
:batch-run-func="batchRunScenario"
|
||||||
|
@finished="loadScenarioList"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
@ -289,10 +297,10 @@
|
||||||
import MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
|
import MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
|
||||||
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
||||||
import MsTagsInput from '@/components/pure/ms-tags-input/index.vue';
|
import MsTagsInput from '@/components/pure/ms-tags-input/index.vue';
|
||||||
import caseLevel from '@/components/business/ms-case-associate/caseLevel.vue';
|
|
||||||
import type { CaseLevel } from '@/components/business/ms-case-associate/types';
|
import type { CaseLevel } from '@/components/business/ms-case-associate/types';
|
||||||
import type { MsTreeNodeData } from '@/components/business/ms-tree/types';
|
import type { MsTreeNodeData } from '@/components/business/ms-tree/types';
|
||||||
import apiStatus from '@/views/api-test/components/apiStatus.vue';
|
import apiStatus from '@/views/api-test/components/apiStatus.vue';
|
||||||
|
import BatchRunModal from '@/views/api-test/components/batchRunModal.vue';
|
||||||
import ExecutionStatus from '@/views/api-test/report/component/reportStatus.vue';
|
import ExecutionStatus from '@/views/api-test/report/component/reportStatus.vue';
|
||||||
import operationScenarioModuleTree from '@/views/api-test/scenario/components/operationScenarioModuleTree.vue';
|
import operationScenarioModuleTree from '@/views/api-test/scenario/components/operationScenarioModuleTree.vue';
|
||||||
|
|
||||||
|
@ -300,6 +308,7 @@
|
||||||
batchEditScenario,
|
batchEditScenario,
|
||||||
batchOptionScenario,
|
batchOptionScenario,
|
||||||
batchRecycleScenario,
|
batchRecycleScenario,
|
||||||
|
batchRunScenario,
|
||||||
getScenarioPage,
|
getScenarioPage,
|
||||||
recycleScenario,
|
recycleScenario,
|
||||||
updateScenario,
|
updateScenario,
|
||||||
|
@ -351,6 +360,7 @@
|
||||||
const moveModalVisible = ref(false);
|
const moveModalVisible = ref(false);
|
||||||
const isBatchMove = ref(false); // 是否批量移动场景
|
const isBatchMove = ref(false); // 是否批量移动场景
|
||||||
const isBatchCopy = ref(false); // 是否批量复制场景
|
const isBatchCopy = ref(false); // 是否批量复制场景
|
||||||
|
const showBatchExecute = ref(false);
|
||||||
|
|
||||||
let columns: MsTableColumn = [
|
let columns: MsTableColumn = [
|
||||||
{
|
{
|
||||||
|
@ -540,6 +550,23 @@
|
||||||
const statusFilters = ref(Object.keys(ApiScenarioStatus));
|
const statusFilters = ref(Object.keys(ApiScenarioStatus));
|
||||||
const tableStore = useTableStore();
|
const tableStore = useTableStore();
|
||||||
|
|
||||||
|
const activeModules = computed(() => {
|
||||||
|
return props.activeModule === 'all' ? [] : [props.activeModule];
|
||||||
|
});
|
||||||
|
|
||||||
|
const batchConditionParams = computed(() => {
|
||||||
|
return {
|
||||||
|
condition: {
|
||||||
|
keyword: keyword.value,
|
||||||
|
filter: {
|
||||||
|
status: statusFilters.value,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
projectId: appStore.currentProjectId,
|
||||||
|
moduleIds: activeModules.value,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
async function loadScenarioList(refreshTreeCount?: boolean) {
|
async function loadScenarioList(refreshTreeCount?: boolean) {
|
||||||
let moduleIds: string[] = [];
|
let moduleIds: string[] = [];
|
||||||
if (props.activeModule && props.activeModule !== 'all') {
|
if (props.activeModule && props.activeModule !== 'all') {
|
||||||
|
@ -873,7 +900,7 @@
|
||||||
moveModalVisible.value = true;
|
moveModalVisible.value = true;
|
||||||
break;
|
break;
|
||||||
case 'execute':
|
case 'execute':
|
||||||
Message.info('// todo @ba1q1');
|
showBatchExecute.value = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue