feat(接口测试): 接口测试diff对比同步以及状态接口联调部分
This commit is contained in:
parent
5bdbb92b14
commit
a7a50d1516
|
@ -20,7 +20,9 @@ import {
|
||||||
BatchRecoverCaseUrl,
|
BatchRecoverCaseUrl,
|
||||||
BatchUpdateDefinitionUrl,
|
BatchUpdateDefinitionUrl,
|
||||||
CasePageUrl,
|
CasePageUrl,
|
||||||
|
caseTableBatchSyncUrl,
|
||||||
CheckDefinitionScheduleUrl,
|
CheckDefinitionScheduleUrl,
|
||||||
|
clearThisChangeUrl,
|
||||||
ConvertJsonSchemaToJsonUrl,
|
ConvertJsonSchemaToJsonUrl,
|
||||||
CopyMockUrl,
|
CopyMockUrl,
|
||||||
DebugCaseUrl,
|
DebugCaseUrl,
|
||||||
|
@ -35,6 +37,7 @@ import {
|
||||||
DeleteModuleUrl,
|
DeleteModuleUrl,
|
||||||
DeleteRecycleApiUrl,
|
DeleteRecycleApiUrl,
|
||||||
DeleteRecycleCaseUrl,
|
DeleteRecycleCaseUrl,
|
||||||
|
diffDataUrl,
|
||||||
ExecuteCaseUrl,
|
ExecuteCaseUrl,
|
||||||
ExportDefinitionUrl,
|
ExportDefinitionUrl,
|
||||||
GetCaseDetailUrl,
|
GetCaseDetailUrl,
|
||||||
|
@ -54,6 +57,7 @@ import {
|
||||||
GetPoolOptionUrl,
|
GetPoolOptionUrl,
|
||||||
GetTrashModuleCountUrl,
|
GetTrashModuleCountUrl,
|
||||||
GetTrashModuleTreeUrl,
|
GetTrashModuleTreeUrl,
|
||||||
|
ignoreEveryTimeApiChangeUrl,
|
||||||
ImportDefinitionUrl,
|
ImportDefinitionUrl,
|
||||||
JsonSchemaAutoGenerateUrl,
|
JsonSchemaAutoGenerateUrl,
|
||||||
MockDetailUrl,
|
MockDetailUrl,
|
||||||
|
@ -137,6 +141,7 @@ import {
|
||||||
MoveModules,
|
MoveModules,
|
||||||
TransferFileParams,
|
TransferFileParams,
|
||||||
} from '@/models/common';
|
} from '@/models/common';
|
||||||
|
import { TableQueryParams } from '@/models/common';
|
||||||
import { ResourcePoolItem } from '@/models/setting/resourcePool';
|
import { ResourcePoolItem } from '@/models/setting/resourcePool';
|
||||||
|
|
||||||
// 更新模块
|
// 更新模块
|
||||||
|
@ -313,6 +318,22 @@ export function convertJsonSchemaToJson(data: JsonSchema) {
|
||||||
export function jsonSchemaAutoGenerate(data: JsonSchema) {
|
export function jsonSchemaAutoGenerate(data: JsonSchema) {
|
||||||
return MSR.post({ url: JsonSchemaAutoGenerateUrl, data });
|
return MSR.post({ url: JsonSchemaAutoGenerateUrl, data });
|
||||||
}
|
}
|
||||||
|
// 接口定义-用例接口对比-清除本次变更
|
||||||
|
export function clearThisChange(id: string) {
|
||||||
|
return MSR.get({ url: `${clearThisChangeUrl}/${id}` });
|
||||||
|
}
|
||||||
|
// 接口定义-用例接口对比-忽略每次变更
|
||||||
|
export function ignoreEveryTimeChange(id: string, ignore: boolean) {
|
||||||
|
return MSR.get({ url: `${ignoreEveryTimeApiChangeUrl}/${id}`, params: { ignore } });
|
||||||
|
}
|
||||||
|
// 接口测试-接口管理-接口用例-批量同步编辑
|
||||||
|
export function caseTableBatchSync(data: TableQueryParams) {
|
||||||
|
return MSR.post({ url: caseTableBatchSyncUrl, data });
|
||||||
|
}
|
||||||
|
// // 接口测试-接口用例-定义对比用例
|
||||||
|
export function diffDataRequest(id: string) {
|
||||||
|
return MSR.get({ url: `${diffDataUrl}/${id}` });
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mock
|
* Mock
|
||||||
|
|
|
@ -38,6 +38,10 @@ export const RecoverOperationHistoryUrl = '/api/definition/operation-history/rec
|
||||||
export const DefinitionReferenceUrl = '/api/definition/get-reference'; // 获取接口引用关系
|
export const DefinitionReferenceUrl = '/api/definition/get-reference'; // 获取接口引用关系
|
||||||
export const ConvertJsonSchemaToJsonUrl = '/api/definition/json-schema/preview'; // 将json-schema转换为 json 数据
|
export const ConvertJsonSchemaToJsonUrl = '/api/definition/json-schema/preview'; // 将json-schema转换为 json 数据
|
||||||
export const JsonSchemaAutoGenerateUrl = '/api/definition/json-schema/auto-generate'; // 将json-schema转换为 json 数据
|
export const JsonSchemaAutoGenerateUrl = '/api/definition/json-schema/auto-generate'; // 将json-schema转换为 json 数据
|
||||||
|
export const clearThisChangeUrl = '/api/case/api-change/clear'; // 接口定义-变更对比-清除本次变更
|
||||||
|
export const caseTableBatchSyncUrl = '/api/case/batch/api-change/sync'; // 接口测试-接口管理-接口用例-批量同步
|
||||||
|
export const ignoreEveryTimeApiChangeUrl = '/api/case/api-change/ignore'; // 接口测试-接口用例-忽略每次接口变更
|
||||||
|
export const diffDataUrl = '/api/case/api/compare'; // 接口测试-接口用例-定义对比用例
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mock
|
* Mock
|
||||||
|
|
|
@ -549,7 +549,7 @@
|
||||||
return totalWidth + tablePadding;
|
return totalWidth + tablePadding;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 求总和里边最大宽度作为标签列宽
|
// TODO 求总和里边最大宽度作为标签列宽 这里需要考虑一下性能优化
|
||||||
const getMaxRowTagWidth = (rows: TableData[], dataIndex: string) => {
|
const getMaxRowTagWidth = (rows: TableData[], dataIndex: string) => {
|
||||||
const allTags = ((rows as TableData) || []).map((row: TableData) => row[dataIndex] || []);
|
const allTags = ((rows as TableData) || []).map((row: TableData) => row[dataIndex] || []);
|
||||||
|
|
||||||
|
|
|
@ -328,6 +328,8 @@ export interface ApiCaseDetail extends ExecuteRequestParams {
|
||||||
deleteTime: number;
|
deleteTime: number;
|
||||||
deleteUser: string;
|
deleteUser: string;
|
||||||
deleteName: string;
|
deleteName: string;
|
||||||
|
apiChange: boolean; // 接口定义参数变更标识
|
||||||
|
inconsistentWithApi: boolean; // 与接口定义不一致
|
||||||
}
|
}
|
||||||
// 批量操作参数
|
// 批量操作参数
|
||||||
export interface ApiCaseBatchParams extends BatchApiParams {
|
export interface ApiCaseBatchParams extends BatchApiParams {
|
||||||
|
@ -401,3 +403,19 @@ export interface ApiCaseExecuteHistoryItem {
|
||||||
triggerMode: string;
|
triggerMode: string;
|
||||||
deleted: boolean;
|
deleted: boolean;
|
||||||
}
|
}
|
||||||
|
export interface syncItem {
|
||||||
|
header: boolean;
|
||||||
|
body: boolean;
|
||||||
|
query: boolean;
|
||||||
|
rest: boolean;
|
||||||
|
}
|
||||||
|
// 批量同步
|
||||||
|
export interface batchSyncForm {
|
||||||
|
notificationConfig: {
|
||||||
|
apiCreator: boolean;
|
||||||
|
scenarioCreator: boolean;
|
||||||
|
};
|
||||||
|
// 同步项目
|
||||||
|
syncItems: syncItem;
|
||||||
|
deleteRedundantParam: boolean;
|
||||||
|
}
|
||||||
|
|
|
@ -1002,7 +1002,6 @@
|
||||||
() => requestMethodsOptions.value,
|
() => requestMethodsOptions.value,
|
||||||
() => {
|
() => {
|
||||||
initFilterColumn();
|
initFilterColumn();
|
||||||
apiTableRef.value.initColumn(columns);
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -12,19 +12,12 @@
|
||||||
<icon-right :size="10" class="block" />
|
<icon-right :size="10" class="block" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<MsTag
|
<ApiChangeTag
|
||||||
v-if="props.detail.inconsistentWithApi"
|
:ignore-api-change="props.detail.ignoreApiChange"
|
||||||
class="cursor-pointer"
|
:ignore-api-diff="props.detail.ignoreApiDiff"
|
||||||
type="warning"
|
:inconsistent-with-api="props.detail.inconsistentWithApi"
|
||||||
theme="light"
|
@show-diff="showDiffDrawer"
|
||||||
:tooltip-disabled="true"
|
/>
|
||||||
@click.stop="showDiffDrawer"
|
|
||||||
>
|
|
||||||
<template #icon>
|
|
||||||
<MsIcon type="icon-icon_warning_colorful" size="16" />
|
|
||||||
</template>
|
|
||||||
<span class="ml-[8px]"> {{ statusText }}</span>
|
|
||||||
</MsTag>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<div class="detail-collapse-item">
|
<div class="detail-collapse-item">
|
||||||
|
@ -435,10 +428,10 @@
|
||||||
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
|
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
|
||||||
import MsJsonSchema from '@/components/pure/ms-json-schema/index.vue';
|
import MsJsonSchema from '@/components/pure/ms-json-schema/index.vue';
|
||||||
import { parseSchemaToJsonSchemaTableData } from '@/components/pure/ms-json-schema/utils';
|
import { parseSchemaToJsonSchemaTableData } from '@/components/pure/ms-json-schema/utils';
|
||||||
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
|
||||||
import { ResponseItem } from '@/views/api-test/components/requestComposition/response/edit.vue';
|
import { ResponseItem } from '@/views/api-test/components/requestComposition/response/edit.vue';
|
||||||
import responseCodeTimeSize from '@/views/api-test/components/requestComposition/response/responseCodeTimeSize.vue';
|
import responseCodeTimeSize from '@/views/api-test/components/requestComposition/response/responseCodeTimeSize.vue';
|
||||||
import Result from '@/views/api-test/components/requestComposition/response/result.vue';
|
import Result from '@/views/api-test/components/requestComposition/response/result.vue';
|
||||||
|
import ApiChangeTag from '@/views/api-test/management/components/management/case/apiChangeTag.vue';
|
||||||
|
|
||||||
import { getPluginScript } from '@/api/modules/api-test/common';
|
import { getPluginScript } from '@/api/modules/api-test/common';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
@ -898,13 +891,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const statusText = computed(() => {
|
|
||||||
if (props.detail.inconsistentWithApi) {
|
|
||||||
return t('case.definitionInconsistent');
|
|
||||||
}
|
|
||||||
// TODO 这里的交互参数等待协调
|
|
||||||
});
|
|
||||||
|
|
||||||
// 查看diff对比
|
// 查看diff对比
|
||||||
function showDiffDrawer() {
|
function showDiffDrawer() {
|
||||||
emit('showDiff');
|
emit('showDiff');
|
||||||
|
|
|
@ -87,6 +87,8 @@
|
||||||
:active-api-case-id="activeApiCaseId"
|
:active-api-case-id="activeApiCaseId"
|
||||||
:active-defined-id="activeDefinedId"
|
:active-defined-id="activeDefinedId"
|
||||||
@close="closeDifferent"
|
@close="closeDifferent"
|
||||||
|
@clear-this-change="clearThisChangeHandler"
|
||||||
|
@sync="syncHandler"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<tab-case-dependency v-else-if="activeKey === 'reference'" :source-id="caseDetail.id" />
|
<tab-case-dependency v-else-if="activeKey === 'reference'" :source-id="caseDetail.id" />
|
||||||
|
@ -396,11 +398,20 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
const isPriorityLocalExec = computed(() => executeRef.value?.isPriorityLocalExec ?? false);
|
const isPriorityLocalExec = computed(() => executeRef.value?.isPriorityLocalExec ?? false);
|
||||||
|
const caseId = ref<string>(route.query.id as string);
|
||||||
|
// 忽略本次变更
|
||||||
|
async function clearThisChangeHandler() {
|
||||||
|
getCaseDetailInfo(caseId.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function syncHandler(id: string) {
|
||||||
|
// TODO 这里需要调用同步合并后的详情接口回显详情
|
||||||
|
createAndEditCaseDrawerRef.value?.open(id, caseDetail.value, false);
|
||||||
|
}
|
||||||
|
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
initProtocolList();
|
initProtocolList();
|
||||||
const caseId = route.query.id;
|
getCaseDetailInfo(caseId.value);
|
||||||
getCaseDetailInfo(caseId as string);
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
<template>
|
||||||
|
<MsTag
|
||||||
|
v-if="props.inconsistentWithApi"
|
||||||
|
class="cursor-pointer font-normal"
|
||||||
|
:type="props.ignoreApiDiff ? 'default' : 'warning'"
|
||||||
|
theme="light"
|
||||||
|
:tooltip-disabled="true"
|
||||||
|
max-width="160px"
|
||||||
|
@click.stop="showDiffDrawer"
|
||||||
|
>
|
||||||
|
<template #icon>
|
||||||
|
<div class="!text-[var(--color-text-4)]">
|
||||||
|
<MsIcon v-if="props.ignoreApiDiff" type="icon-icon_warning_filled" size="16" />
|
||||||
|
<MsIcon v-else class="!text-[var(--color-text-4)]" type="icon-icon_warning_colorful" size="16" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<span class="ml-[4px]"> {{ statusText }}</span>
|
||||||
|
</MsTag>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
||||||
|
|
||||||
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
inconsistentWithApi?: boolean;
|
||||||
|
ignoreApiDiff?: boolean;
|
||||||
|
ignoreApiChange?: boolean;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'showDiff'): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
function showDiffDrawer() {
|
||||||
|
emit('showDiff');
|
||||||
|
}
|
||||||
|
|
||||||
|
const statusText = computed(() => {
|
||||||
|
// 忽略每次变更
|
||||||
|
if (props.ignoreApiChange) {
|
||||||
|
return t('case.eachHasBeenIgnored');
|
||||||
|
}
|
||||||
|
// 忽略本次变更
|
||||||
|
if (props.ignoreApiDiff) {
|
||||||
|
return t('case.haveIgnoredTheChange');
|
||||||
|
}
|
||||||
|
// 与接口定义不一致
|
||||||
|
if (props.inconsistentWithApi) {
|
||||||
|
return t('case.definitionInconsistent');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
|
@ -73,6 +73,8 @@
|
||||||
:active-api-case-id="activeApiCaseId"
|
:active-api-case-id="activeApiCaseId"
|
||||||
:active-defined-id="activeDefinedId"
|
:active-defined-id="activeDefinedId"
|
||||||
@close="closeDifferent"
|
@close="closeDifferent"
|
||||||
|
@clear-this-change="clearThisChangeHandler"
|
||||||
|
@sync="syncHandler"
|
||||||
/>
|
/>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="reference" :title="t('apiTestManagement.reference')" class="px-[18px] py-[16px]">
|
<a-tab-pane key="reference" :title="t('apiTestManagement.reference')" class="px-[18px] py-[16px]">
|
||||||
|
@ -132,9 +134,11 @@
|
||||||
isDrawer?: boolean; // 抽屉
|
isDrawer?: boolean; // 抽屉
|
||||||
detail: RequestParam;
|
detail: RequestParam;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'updateFollow'): void;
|
(e: 'updateFollow'): void;
|
||||||
(e: 'deleteCase', id: string): void;
|
(e: 'deleteCase', id: string): void;
|
||||||
|
(e: 'loadCase', id: string): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
|
@ -342,6 +346,16 @@
|
||||||
activeDefinedId.value = '';
|
activeDefinedId.value = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 忽略本次变更
|
||||||
|
async function clearThisChangeHandler() {
|
||||||
|
emit('loadCase', props.detail.id as string);
|
||||||
|
}
|
||||||
|
|
||||||
|
function syncHandler(id: string) {
|
||||||
|
// TODO 这里需要调用同步合并后的详情接口回显详情
|
||||||
|
createAndEditCaseDrawerRef.value?.open(id, caseDetail.value, false);
|
||||||
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.detail,
|
() => props.detail,
|
||||||
() => {
|
() => {
|
||||||
|
|
|
@ -275,6 +275,7 @@
|
||||||
</a-modal>
|
</a-modal>
|
||||||
<createAndEditCaseDrawer
|
<createAndEditCaseDrawer
|
||||||
ref="createAndEditCaseDrawerRef"
|
ref="createAndEditCaseDrawerRef"
|
||||||
|
v-model:visible="showCaseVisible"
|
||||||
:api-detail="apiDetail"
|
:api-detail="apiDetail"
|
||||||
@load-case="loadCaseListAndResetSelector()"
|
@load-case="loadCaseListAndResetSelector()"
|
||||||
@show-diff="showDifferences"
|
@show-diff="showDifferences"
|
||||||
|
@ -300,13 +301,21 @@
|
||||||
<!-- 执行结果抽屉 -->
|
<!-- 执行结果抽屉 -->
|
||||||
<caseAndScenarioReportDrawer v-model:visible="showExecuteResult" :report-id="activeReportId" />
|
<caseAndScenarioReportDrawer v-model:visible="showExecuteResult" :report-id="activeReportId" />
|
||||||
<!-- 同步抽屉 -->
|
<!-- 同步抽屉 -->
|
||||||
<SyncModal v-model:visible="showSyncModal" :batch-params="batchParams" />
|
<SyncModal
|
||||||
|
ref="syncModalRef"
|
||||||
|
v-model:visible="showSyncModal"
|
||||||
|
:loading="syncLoading"
|
||||||
|
:batch-params="batchParams"
|
||||||
|
@batch-sync="handleBatchSync"
|
||||||
|
/>
|
||||||
<!-- diff对比抽屉 -->
|
<!-- diff对比抽屉 -->
|
||||||
<DifferentDrawer
|
<DifferentDrawer
|
||||||
v-model:visible="showDifferentDrawer"
|
v-model:visible="showDifferentDrawer"
|
||||||
:active-api-case-id="activeApiCaseId"
|
:active-api-case-id="activeApiCaseId"
|
||||||
:active-defined-id="activeDefinedId"
|
:active-defined-id="activeDefinedId"
|
||||||
@close="closeDifferent"
|
@close="closeDifferent"
|
||||||
|
@clear-this-change="handleClearThisChange"
|
||||||
|
@sync="syncHandler"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -339,6 +348,7 @@
|
||||||
batchDeleteCase,
|
batchDeleteCase,
|
||||||
batchEditCase,
|
batchEditCase,
|
||||||
batchExecuteCase,
|
batchExecuteCase,
|
||||||
|
caseTableBatchSync,
|
||||||
deleteCase,
|
deleteCase,
|
||||||
dragSort,
|
dragSort,
|
||||||
getCaseDetail,
|
getCaseDetail,
|
||||||
|
@ -353,6 +363,7 @@
|
||||||
import { characterLimit, operationWidth } from '@/utils';
|
import { characterLimit, operationWidth } from '@/utils';
|
||||||
import { hasAnyPermission } from '@/utils/permission';
|
import { hasAnyPermission } from '@/utils/permission';
|
||||||
|
|
||||||
|
import type { batchSyncForm } from '@/models/apiTest/management';
|
||||||
import { ApiCaseDetail } from '@/models/apiTest/management';
|
import { ApiCaseDetail } from '@/models/apiTest/management';
|
||||||
import { DragSortParams } from '@/models/common';
|
import { DragSortParams } from '@/models/common';
|
||||||
import { RequestCaseStatus } from '@/enums/apiEnum';
|
import { RequestCaseStatus } from '@/enums/apiEnum';
|
||||||
|
@ -860,7 +871,6 @@
|
||||||
const batchConditionParams = ref<any>();
|
const batchConditionParams = ref<any>();
|
||||||
|
|
||||||
const showSyncModal = ref<boolean>(false);
|
const showSyncModal = ref<boolean>(false);
|
||||||
// 同步 TODO 等待联调
|
|
||||||
function syncParams() {
|
function syncParams() {
|
||||||
showSyncModal.value = true;
|
showSyncModal.value = true;
|
||||||
}
|
}
|
||||||
|
@ -975,7 +985,6 @@
|
||||||
const activeDefinedId = ref<string>('');
|
const activeDefinedId = ref<string>('');
|
||||||
const showDifferentDrawer = ref<boolean>(false);
|
const showDifferentDrawer = ref<boolean>(false);
|
||||||
|
|
||||||
// 查看对比 TODO 等待联调
|
|
||||||
async function showDifferences(record: ApiCaseDetail) {
|
async function showDifferences(record: ApiCaseDetail) {
|
||||||
activeApiCaseId.value = record.id;
|
activeApiCaseId.value = record.id;
|
||||||
activeDefinedId.value = record.apiDefinitionId;
|
activeDefinedId.value = record.apiDefinitionId;
|
||||||
|
@ -987,6 +996,48 @@
|
||||||
activeDefinedId.value = '';
|
activeDefinedId.value = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const syncLoading = ref<boolean>(false);
|
||||||
|
const syncModalRef = ref<InstanceType<typeof SyncModal>>();
|
||||||
|
// 批量同步
|
||||||
|
async function handleBatchSync(syncForm: batchSyncForm) {
|
||||||
|
try {
|
||||||
|
syncLoading.value = true;
|
||||||
|
const selectModules = await getModuleIds();
|
||||||
|
const params = await genBatchConditionParams();
|
||||||
|
await caseTableBatchSync({
|
||||||
|
selectIds: batchParams.value?.selectedIds || [],
|
||||||
|
selectAll: !!batchParams.value?.selectAll,
|
||||||
|
excludeIds: batchParams.value?.excludeIds || [],
|
||||||
|
...params,
|
||||||
|
...syncForm,
|
||||||
|
moduleIds: selectModules,
|
||||||
|
});
|
||||||
|
Message.success(t('bugManagement.syncSuccess'));
|
||||||
|
syncModalRef.value?.resetForm();
|
||||||
|
resetSelector();
|
||||||
|
loadCaseListAndResetSelector();
|
||||||
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(error);
|
||||||
|
} finally {
|
||||||
|
syncLoading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const showCaseVisible = ref(false);
|
||||||
|
// 清除本次变更
|
||||||
|
async function handleClearThisChange() {
|
||||||
|
await loadCaseList();
|
||||||
|
await getCaseDetailInfo(activeApiCaseId.value);
|
||||||
|
if (showCaseVisible.value) {
|
||||||
|
createAndEditCaseDrawerRef.value?.open(caseDetail.value.apiDefinitionId, caseDetail.value as RequestParam, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 对比抽屉同步成功打开编辑
|
||||||
|
function syncHandler(definedId: string) {
|
||||||
|
// TODO 这里调用同步后的最新的合并后的详情,打开编辑抽屉用户手动保存更新即可生效
|
||||||
|
createAndEditCaseDrawerRef.value?.open(definedId, caseDetail.value as RequestParam, false);
|
||||||
|
}
|
||||||
defineExpose({
|
defineExpose({
|
||||||
loadCaseList,
|
loadCaseList,
|
||||||
});
|
});
|
||||||
|
|
|
@ -71,20 +71,12 @@
|
||||||
</a-form>
|
</a-form>
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<div class="px-[16px] font-medium">{{ t('apiTestManagement.requestParams') }}</div>
|
<div class="px-[16px] font-medium">{{ t('apiTestManagement.requestParams') }}</div>
|
||||||
<!-- 与定义不一致 TODO 等待联调 -->
|
<ApiChangeTag
|
||||||
<MsTag
|
:ignore-api-change="detailForm.ignoreApiChange"
|
||||||
v-if="detailForm.inconsistentWithApi"
|
:ignore-api-diff="detailForm.ignoreApiDiff"
|
||||||
class="cursor-pointer"
|
:inconsistent-with-api="detailForm.inconsistentWithApi"
|
||||||
type="warning"
|
@show-diff="showDiffDrawer"
|
||||||
theme="light"
|
/>
|
||||||
:tooltip-disabled="true"
|
|
||||||
@click="showDiffDrawer"
|
|
||||||
>
|
|
||||||
<template #icon>
|
|
||||||
<MsIcon type="icon-icon_warning_colorful" size="16" />
|
|
||||||
</template>
|
|
||||||
<span class="ml-[8px]"> {{ t('case.definitionInconsistent') }}</span>
|
|
||||||
</MsTag>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<requestComposition
|
<requestComposition
|
||||||
|
@ -111,7 +103,6 @@
|
||||||
|
|
||||||
import MsDetailCard, { type Description } from '@/components/pure/ms-detail-card/index.vue';
|
import MsDetailCard, { type Description } from '@/components/pure/ms-detail-card/index.vue';
|
||||||
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
|
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
|
||||||
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
|
||||||
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 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';
|
||||||
|
@ -120,6 +111,7 @@
|
||||||
import apiStatus from '@/views/api-test/components/apiStatus.vue';
|
import apiStatus from '@/views/api-test/components/apiStatus.vue';
|
||||||
import executeButton from '@/views/api-test/components/executeButton.vue';
|
import executeButton from '@/views/api-test/components/executeButton.vue';
|
||||||
import requestComposition, { RequestParam } from '@/views/api-test/components/requestComposition/index.vue';
|
import requestComposition, { RequestParam } from '@/views/api-test/components/requestComposition/index.vue';
|
||||||
|
import ApiChangeTag from '@/views/api-test/management/components/management/case/apiChangeTag.vue';
|
||||||
|
|
||||||
import { localExecuteApiDebug } from '@/api/modules/api-test/common';
|
import { localExecuteApiDebug } from '@/api/modules/api-test/common';
|
||||||
import {
|
import {
|
||||||
|
@ -153,7 +145,10 @@
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
|
|
||||||
const innerVisible = ref(false);
|
const innerVisible = defineModel<boolean>('visible', {
|
||||||
|
default: false,
|
||||||
|
});
|
||||||
|
|
||||||
const drawerLoading = ref(false);
|
const drawerLoading = ref(false);
|
||||||
|
|
||||||
const apiDefinitionId = ref('');
|
const apiDefinitionId = ref('');
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
<div>{{ t('case.apiAndCaseDiff') }}</div>
|
<div>{{ t('case.apiAndCaseDiff') }}</div>
|
||||||
<div class="flex items-center text-[14px]">
|
<div class="flex items-center text-[14px]">
|
||||||
<div class="-mt-[2px] mr-[8px]"> {{ t('case.syncItem') }}</div>
|
<div class="-mt-[2px] mr-[8px]"> {{ t('case.syncItem') }}</div>
|
||||||
<a-checkbox-group v-model="form.checkType">
|
<a-checkbox-group v-model="checkType">
|
||||||
<a-checkbox v-for="item of checkList" :key="item.value" :value="item.value">
|
<a-checkbox v-for="item of checkList" :key="item.value" :value="item.value">
|
||||||
<div class="flex items-center"
|
<div class="flex items-center"
|
||||||
>{{ item.label }}
|
>{{ item.label }}
|
||||||
|
@ -31,17 +31,21 @@
|
||||||
</a-checkbox>
|
</a-checkbox>
|
||||||
</a-checkbox-group>
|
</a-checkbox-group>
|
||||||
<a-divider direction="vertical" :margin="0" class="!mr-[8px]"></a-divider>
|
<a-divider direction="vertical" :margin="0" class="!mr-[8px]"></a-divider>
|
||||||
<a-switch v-model:model-value="form.ignoreUpdate" size="small" />
|
<a-switch
|
||||||
|
v-model:model-value="form.ignoreApiChange"
|
||||||
|
:before-change="(val) => changeIgnore(val)"
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
<div class="ml-[8px]">{{ t('case.ignoreAllChange') }}</div>
|
<div class="ml-[8px]">{{ t('case.ignoreAllChange') }}</div>
|
||||||
<a-divider direction="vertical" :margin="8"></a-divider>
|
<a-divider direction="vertical" :margin="8"></a-divider>
|
||||||
<a-switch v-model:model-value="form.deleteParams" size="small" />
|
<a-switch v-model:model-value="form.deleteRedundantParam" size="small" />
|
||||||
<div class="ml-[8px] font-normal text-[var(--color-text-1)]">{{ t('case.deleteNotCorrespondValue') }}</div>
|
<div class="ml-[8px] font-normal text-[var(--color-text-1)]">{{ t('case.deleteNotCorrespondValue') }}</div>
|
||||||
<a-divider direction="vertical" :margin="0" class="!ml-[8px]"></a-divider>
|
<a-divider direction="vertical" :margin="0" class="!ml-[8px]"></a-divider>
|
||||||
<a-button class="mx-[12px]" type="secondary" @click="cancel">{{ t('common.cancel') }}</a-button>
|
<a-button class="mx-[12px]" type="secondary" @click="cancel">{{ t('common.cancel') }}</a-button>
|
||||||
<a-button class="mr-[12px]" type="outline">
|
<a-button class="mr-[12px]" type="outline" @click="clearThisChangeHandler">
|
||||||
{{ t('case.ignoreAllChange') }}
|
{{ t('case.ignoreThisChange') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
<a-button type="primary" :loading="syncLoading" :disabled="!form.checkType.length" @click="confirmBatchSync">
|
<a-button type="primary" :loading="syncLoading" :disabled="!checkType.length" @click="confirmSync">
|
||||||
{{ t('case.apiSyncChange') }}
|
{{ t('case.apiSyncChange') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -87,6 +91,7 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
import { Message } from '@arco-design/web-vue';
|
||||||
import { cloneDeep } from 'lodash-es';
|
import { cloneDeep } from 'lodash-es';
|
||||||
|
|
||||||
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
|
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
|
||||||
|
@ -94,10 +99,17 @@
|
||||||
import DiffItem from './diffItem.vue';
|
import DiffItem from './diffItem.vue';
|
||||||
import DiffRequestBody from './diffRequestBody.vue';
|
import DiffRequestBody from './diffRequestBody.vue';
|
||||||
|
|
||||||
import { getCaseDetail, getDefinitionDetail } from '@/api/modules/api-test/management';
|
import {
|
||||||
|
clearThisChange,
|
||||||
|
diffDataRequest,
|
||||||
|
getCaseDetail,
|
||||||
|
getDefinitionDetail,
|
||||||
|
ignoreEveryTimeChange,
|
||||||
|
} from '@/api/modules/api-test/management';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
|
||||||
import { EnableKeyValueParam, ExecuteRequestCommonParam } from '@/models/apiTest/common';
|
import { EnableKeyValueParam, ExecuteRequestCommonParam } from '@/models/apiTest/common';
|
||||||
|
import type { syncItem } from '@/models/apiTest/management';
|
||||||
import { ApiDefinitionDetail } from '@/models/apiTest/management';
|
import { ApiDefinitionDetail } from '@/models/apiTest/management';
|
||||||
import { RequestBodyFormat, RequestComposition } from '@/enums/apiEnum';
|
import { RequestBodyFormat, RequestComposition } from '@/enums/apiEnum';
|
||||||
|
|
||||||
|
@ -113,6 +125,8 @@
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'close'): void;
|
(e: 'close'): void;
|
||||||
|
(e: 'clearThisChange'): void;
|
||||||
|
(e: 'sync', activeDefinedId: string): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const showDiffVisible = defineModel<boolean>('visible', {
|
const showDiffVisible = defineModel<boolean>('visible', {
|
||||||
|
@ -140,18 +154,21 @@
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const initForm = {
|
const initForm = {
|
||||||
deleteParams: false,
|
deleteRedundantParam: false,
|
||||||
checkType: [],
|
syncItems: {
|
||||||
|
header: false,
|
||||||
|
body: false,
|
||||||
|
query: false,
|
||||||
|
rest: false,
|
||||||
|
},
|
||||||
noticeApiCaseCreator: true,
|
noticeApiCaseCreator: true,
|
||||||
noticeApiScenarioCreator: true,
|
noticeApiScenarioCreator: true,
|
||||||
ignoreUpdate: false,
|
ignoreApiChange: false,
|
||||||
ignoreUpdateType: ['THIS_TIME'],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const form = ref({ ...initForm });
|
const checkType = ref([]);
|
||||||
|
|
||||||
// 忽略更新
|
const form = ref({ ...initForm });
|
||||||
function changeIgnoreType() {}
|
|
||||||
|
|
||||||
function cancel() {
|
function cancel() {
|
||||||
showDiffVisible.value = false;
|
showDiffVisible.value = false;
|
||||||
|
@ -159,7 +176,16 @@
|
||||||
}
|
}
|
||||||
const syncLoading = ref<boolean>(false);
|
const syncLoading = ref<boolean>(false);
|
||||||
// 同步
|
// 同步
|
||||||
function confirmBatchSync() {}
|
function confirmSync() {
|
||||||
|
// 处理同步类型参数
|
||||||
|
checkType.value.forEach((e: any) => {
|
||||||
|
const key = e.toLowerCase() as keyof syncItem;
|
||||||
|
form.value.syncItems[key] = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
emit('sync', props.activeDefinedId);
|
||||||
|
showDiffVisible.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
const defaultCaseParams = inject<RequestParam>('defaultCaseParams');
|
const defaultCaseParams = inject<RequestParam>('defaultCaseParams');
|
||||||
const caseDetail = ref<Record<string, any>>({});
|
const caseDetail = ref<Record<string, any>>({});
|
||||||
|
@ -297,12 +323,12 @@
|
||||||
caseDetail.value = {
|
caseDetail.value = {
|
||||||
...cloneDeep(defaultCaseParams as RequestParam),
|
...cloneDeep(defaultCaseParams as RequestParam),
|
||||||
...({
|
...({
|
||||||
...res.request,
|
|
||||||
...res,
|
...res,
|
||||||
url: res.path,
|
url: res.path,
|
||||||
...parseRequestBodyResult,
|
...parseRequestBodyResult,
|
||||||
} as Partial<TabItem>),
|
} as Partial<TabItem>),
|
||||||
};
|
};
|
||||||
|
form.value.ignoreApiChange = caseDetail.value.ignoreApiChange;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log(error);
|
console.log(error);
|
||||||
|
@ -313,24 +339,68 @@
|
||||||
try {
|
try {
|
||||||
const detail = await getDefinitionDetail(apiDefinitionId);
|
const detail = await getDefinitionDetail(apiDefinitionId);
|
||||||
apiDetailInfo.value = detail as ApiDefinitionDetail;
|
apiDetailInfo.value = detail as ApiDefinitionDetail;
|
||||||
apiDefinedRequest.value = detail.request as unknown as RequestParam;
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getDiffDataRequest(activeApiCaseId: string) {
|
||||||
|
try {
|
||||||
|
const result = await diffDataRequest(activeApiCaseId);
|
||||||
|
const { caseRequest, apiRequest } = result;
|
||||||
|
caseDetail.value = {
|
||||||
|
...caseDetail.value,
|
||||||
|
...caseRequest,
|
||||||
|
num: caseDetail.value.num,
|
||||||
|
};
|
||||||
|
apiDefinedRequest.value = apiRequest;
|
||||||
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const loading = ref<boolean>(false);
|
const loading = ref<boolean>(false);
|
||||||
async function getRequestDetail(definedId: string, apiCaseId: string) {
|
async function getRequestDetail(definedId: string, apiCaseId: string) {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
try {
|
try {
|
||||||
await Promise.all([getApiDetail(definedId), getCaseDetailInfo(apiCaseId)]);
|
await Promise.all([getApiDetail(definedId), getCaseDetailInfo(apiCaseId)]);
|
||||||
|
await getDiffDataRequest(props.activeApiCaseId);
|
||||||
processData();
|
processData();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
console.error(error);
|
console.error(error);
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 忽略并清除本次变更
|
||||||
|
async function clearThisChangeHandler() {
|
||||||
|
if (props.activeApiCaseId) {
|
||||||
|
try {
|
||||||
|
await clearThisChange(props.activeApiCaseId);
|
||||||
|
getRequestDetail(props.activeDefinedId, props.activeApiCaseId);
|
||||||
|
emit('clearThisChange');
|
||||||
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 忽略每次变更
|
||||||
|
async function changeIgnore(newValue: string | number | boolean) {
|
||||||
|
try {
|
||||||
|
await ignoreEveryTimeChange(props.activeApiCaseId, newValue as boolean);
|
||||||
|
Message.success(newValue ? t('case.eachHasBeenIgnored') : t('case.eachHasBeenIgnoredClosed'));
|
||||||
|
getRequestDetail(props.activeDefinedId, props.activeApiCaseId);
|
||||||
|
emit('clearThisChange');
|
||||||
|
return false;
|
||||||
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
if (props.activeDefinedId && props.activeApiCaseId) {
|
if (props.activeDefinedId && props.activeApiCaseId) {
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
title-align="start"
|
title-align="start"
|
||||||
class="ms-modal-upload ms-modal-medium"
|
class="ms-modal-upload ms-modal-medium"
|
||||||
:width="600"
|
:width="600"
|
||||||
@close="cancel"
|
@close="resetForm"
|
||||||
>
|
>
|
||||||
<template #title>
|
<template #title>
|
||||||
{{ t('case.apiSyncChange') }}
|
{{ t('case.apiSyncChange') }}
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
<div class="mb-[8px]">
|
<div class="mb-[8px]">
|
||||||
{{ t('case.syncItem') }}
|
{{ t('case.syncItem') }}
|
||||||
</div>
|
</div>
|
||||||
<a-checkbox-group v-model="form.checkType">
|
<a-checkbox-group v-model="checkType">
|
||||||
<a-checkbox v-for="item of checkList" :key="item.value" :value="item.value">
|
<a-checkbox v-for="item of checkList" :key="item.value" :value="item.value">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
{{ item.label }}
|
{{ item.label }}
|
||||||
|
@ -37,7 +37,7 @@
|
||||||
</a-checkbox>
|
</a-checkbox>
|
||||||
</a-checkbox-group>
|
</a-checkbox-group>
|
||||||
<div class="my-[16px] flex items-center">
|
<div class="my-[16px] flex items-center">
|
||||||
<a-switch v-model:model-value="form.deleteParams" size="small" />
|
<a-switch v-model:model-value="form.deleteRedundantParam" size="small" />
|
||||||
<div class="ml-[8px] text-[var(--color-text-1)]">{{ t('case.deleteNotCorrespondValue') }}</div>
|
<div class="ml-[8px] text-[var(--color-text-1)]">{{ t('case.deleteNotCorrespondValue') }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -53,17 +53,17 @@
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</div>
|
</div>
|
||||||
<div class="my-[16px] flex items-center">
|
<div class="my-[16px] flex items-center">
|
||||||
<a-switch v-model:model-value="form.noticeApiCaseCreator" size="small" />
|
<a-switch v-model:model-value="form.notificationConfig.apiCreator" size="small" />
|
||||||
<div class="ml-[8px] text-[var(--color-text-1)]">{{ t('case.NoticeApiCaseCreator') }}</div>
|
<div class="ml-[8px] text-[var(--color-text-1)]">{{ t('case.NoticeApiCaseCreator') }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="my-[16px] flex items-center">
|
<div class="my-[16px] flex items-center">
|
||||||
<a-switch v-model:model-value="form.noticeApiScenarioCreator" size="small" />
|
<a-switch v-model:model-value="form.notificationConfig.scenarioCreator" size="small" />
|
||||||
<div class="ml-[8px] text-[var(--color-text-1)]">{{ t('case.NoticeApiScenarioCreator') }}</div>
|
<div class="ml-[8px] text-[var(--color-text-1)]">{{ t('case.NoticeApiScenarioCreator') }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<a-button type="secondary" @click="cancel">{{ t('common.cancel') }}</a-button>
|
<a-button type="secondary" @click="resetForm">{{ t('common.cancel') }}</a-button>
|
||||||
<a-button type="primary" :loading="syncLoading" :disabled="!form.checkType.length" @click="confirmBatchSync">
|
<a-button type="primary" :loading="props.loading" :disabled="!checkType.length" @click="confirmBatchSync">
|
||||||
{{ t('case.apiSyncChange') }}
|
{{ t('case.apiSyncChange') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
</template>
|
</template>
|
||||||
|
@ -72,31 +72,47 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
import { cloneDeep } from 'lodash-es';
|
||||||
|
|
||||||
import type { BatchActionQueryParams } from '@/components/pure/ms-table/type';
|
import type { BatchActionQueryParams } from '@/components/pure/ms-table/type';
|
||||||
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
|
||||||
|
import type { batchSyncForm, syncItem } from '@/models/apiTest/management';
|
||||||
import { RequestComposition } from '@/enums/apiEnum';
|
import { RequestComposition } from '@/enums/apiEnum';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
batchParams: BatchActionQueryParams;
|
batchParams: BatchActionQueryParams;
|
||||||
|
loading: boolean;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'batchSync', form: batchSyncForm): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const showBatchSyncModal = defineModel<boolean>('visible', {
|
const showBatchSyncModal = defineModel<boolean>('visible', {
|
||||||
required: true,
|
required: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const initForm = {
|
const initForm: batchSyncForm = {
|
||||||
deleteParams: false,
|
notificationConfig: {
|
||||||
checkType: [],
|
apiCreator: false,
|
||||||
noticeApiCaseCreator: true,
|
scenarioCreator: false,
|
||||||
noticeApiScenarioCreator: true,
|
},
|
||||||
|
// 同步项目
|
||||||
|
syncItems: {
|
||||||
|
header: false,
|
||||||
|
body: false,
|
||||||
|
query: false,
|
||||||
|
rest: false,
|
||||||
|
},
|
||||||
|
deleteRedundantParam: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
const form = ref({ ...initForm });
|
const form = ref<batchSyncForm>(cloneDeep(initForm));
|
||||||
|
const checkType = ref([]);
|
||||||
|
|
||||||
const checkList = ref([
|
const checkList = ref([
|
||||||
{
|
{
|
||||||
|
@ -118,13 +134,24 @@
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const syncLoading = ref<boolean>(false);
|
function resetForm() {
|
||||||
|
form.value = cloneDeep(initForm);
|
||||||
function cancel() {
|
checkType.value = [];
|
||||||
showBatchSyncModal.value = false;
|
showBatchSyncModal.value = false;
|
||||||
}
|
}
|
||||||
// 同步 TODO 等待联调
|
|
||||||
function confirmBatchSync() {}
|
function confirmBatchSync() {
|
||||||
|
checkType.value.forEach((e: string) => {
|
||||||
|
const key = e.toLowerCase() as keyof syncItem;
|
||||||
|
form.value.syncItems[key] = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
emit('batchSync', form.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
resetForm,
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
|
|
@ -228,6 +228,7 @@ export default {
|
||||||
'case.definitionInconsistent': 'Inconsistent with the definition',
|
'case.definitionInconsistent': 'Inconsistent with the definition',
|
||||||
'case.haveIgnoredTheChange': 'Have ignored the change',
|
'case.haveIgnoredTheChange': 'Have ignored the change',
|
||||||
'case.eachHasBeenIgnored': 'Each change difference has been ignored',
|
'case.eachHasBeenIgnored': 'Each change difference has been ignored',
|
||||||
|
'case.eachHasBeenIgnoredClosed': 'Closed Ignore each change difference',
|
||||||
'case.apiCaseList': 'List',
|
'case.apiCaseList': 'List',
|
||||||
'case.apiCaseDetail': 'Use case details',
|
'case.apiCaseDetail': 'Use case details',
|
||||||
'case.belongingApi': 'Belonging interface',
|
'case.belongingApi': 'Belonging interface',
|
||||||
|
|
|
@ -215,6 +215,7 @@ export default {
|
||||||
'case.definitionInconsistent': '与定义不一致',
|
'case.definitionInconsistent': '与定义不一致',
|
||||||
'case.haveIgnoredTheChange': '已忽略本次变更差异',
|
'case.haveIgnoredTheChange': '已忽略本次变更差异',
|
||||||
'case.eachHasBeenIgnored': '已忽略每次变更差异',
|
'case.eachHasBeenIgnored': '已忽略每次变更差异',
|
||||||
|
'case.eachHasBeenIgnoredClosed': '已关闭忽略每次变更差异',
|
||||||
'case.apiCaseList': '列表',
|
'case.apiCaseList': '列表',
|
||||||
'case.apiCaseDetail': '用例详情',
|
'case.apiCaseDetail': '用例详情',
|
||||||
'case.belongingApi': '所属接口',
|
'case.belongingApi': '所属接口',
|
||||||
|
|
|
@ -52,7 +52,7 @@
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
<template #name="{ record }">
|
<template #name="{ record }">
|
||||||
<div class="one-line-text">{{ characterLimit(record.name) }}</div>
|
<div class="one-line-text">{{ record.name }}</div>
|
||||||
</template>
|
</template>
|
||||||
<template #caseLevel="{ record }">
|
<template #caseLevel="{ record }">
|
||||||
<a-select
|
<a-select
|
||||||
|
|
|
@ -29,8 +29,6 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useVModel } from '@vueuse/core';
|
|
||||||
|
|
||||||
import MsRichText from '@/components/pure/ms-rich-text/MsRichText.vue';
|
import MsRichText from '@/components/pure/ms-rich-text/MsRichText.vue';
|
||||||
import MsFormItemSub from '@/components/business/ms-form-item-sub/index.vue';
|
import MsFormItemSub from '@/components/business/ms-form-item-sub/index.vue';
|
||||||
|
|
||||||
|
@ -61,7 +59,7 @@
|
||||||
(e: 'handleSummary', content: string): void;
|
(e: 'handleSummary', content: string): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const innerSummary = useVModel(props, 'richText', emit);
|
const innerSummary = ref(props.richText);
|
||||||
|
|
||||||
function handleCancel() {
|
function handleCancel() {
|
||||||
emit('cancel');
|
emit('cancel');
|
||||||
|
@ -135,6 +133,18 @@
|
||||||
emit('handleClick');
|
emit('handleClick');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.richText,
|
||||||
|
(val) => {
|
||||||
|
if (val) {
|
||||||
|
innerSummary.value = { ...val };
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
deep: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
|
|
@ -173,7 +173,7 @@
|
||||||
:is-preview="props.isPreview"
|
:is-preview="props.isPreview"
|
||||||
/>
|
/>
|
||||||
<Summary
|
<Summary
|
||||||
v-else-if="item.value === ReportCardTypeEnum.SUMMARY"
|
v-if="item.value === ReportCardTypeEnum.SUMMARY"
|
||||||
:rich-text="getContent(item)"
|
:rich-text="getContent(item)"
|
||||||
:share-id="shareId"
|
:share-id="shareId"
|
||||||
:is-preview="props.isPreview"
|
:is-preview="props.isPreview"
|
||||||
|
|
|
@ -89,9 +89,9 @@ export default {
|
||||||
'testPlan.planForm.repeatCaseTip1': 'Enable: Repeatedly associate the same case',
|
'testPlan.planForm.repeatCaseTip1': 'Enable: Repeatedly associate the same case',
|
||||||
'testPlan.planForm.repeatCaseTip2': 'Close: Cannot be associated with the same case repeatedly',
|
'testPlan.planForm.repeatCaseTip2': 'Close: Cannot be associated with the same case repeatedly',
|
||||||
'testPlan.planForm.enableAutomaticStatusTip':
|
'testPlan.planForm.enableAutomaticStatusTip':
|
||||||
'Enable: function cases associated interface/UI/case execution successful performance, function of the use case status automatically updated to success',
|
'Enable: function case execution successful cases associated interface, function of the use case status automatically updated to success',
|
||||||
'testPlan.planForm.closeAutomaticStatusTip':
|
'testPlan.planForm.closeAutomaticStatusTip':
|
||||||
'Close: the function of use case execution result is not affected by the interface/UI/performance',
|
'Close: The result of execution of a functional use case is not affected by the interface',
|
||||||
'testPlan.planForm.passThresholdTip': 'If the pass rate reaches the specified pass threshold, the result is passed',
|
'testPlan.planForm.passThresholdTip': 'If the pass rate reaches the specified pass threshold, the result is passed',
|
||||||
'testPlan.planForm.pickCases': 'Select cases',
|
'testPlan.planForm.pickCases': 'Select cases',
|
||||||
'testPlan.testPlanDetail.executed': 'Executed',
|
'testPlan.testPlanDetail.executed': 'Executed',
|
||||||
|
|
|
@ -85,9 +85,8 @@ export default {
|
||||||
'testPlan.planForm.selectPlanGroup': '选择计划组',
|
'testPlan.planForm.selectPlanGroup': '选择计划组',
|
||||||
'testPlan.planForm.repeatCaseTip1': '开启:可重复关联同一个用例',
|
'testPlan.planForm.repeatCaseTip1': '开启:可重复关联同一个用例',
|
||||||
'testPlan.planForm.repeatCaseTip2': '关闭:不可重复关联同一用例',
|
'testPlan.planForm.repeatCaseTip2': '关闭:不可重复关联同一用例',
|
||||||
'testPlan.planForm.enableAutomaticStatusTip':
|
'testPlan.planForm.enableAutomaticStatusTip': '开启:功能用例关联的接口用例执行成功,功能用例的状态自动更新为成功',
|
||||||
'开启:功能用例关联的接口/UI/性能用例执行成功,功能用例的状态自动更新为成功',
|
'testPlan.planForm.closeAutomaticStatusTip': '关闭:功能用例的执行结果不受接口的影响',
|
||||||
'testPlan.planForm.closeAutomaticStatusTip': '关闭:功能用例的执行结果不受接口/UI/性能的影响',
|
|
||||||
'testPlan.planForm.passThresholdTip': '通过率达到设置的通过阈值时,报告结果为通过',
|
'testPlan.planForm.passThresholdTip': '通过率达到设置的通过阈值时,报告结果为通过',
|
||||||
'testPlan.planForm.pickCases': '选择用例',
|
'testPlan.planForm.pickCases': '选择用例',
|
||||||
'testPlan.testPlanDetail.executed': '已执行',
|
'testPlan.testPlanDetail.executed': '已执行',
|
||||||
|
|
Loading…
Reference in New Issue