feat(接口管理): 新增用例详情的引用执行变更记录的列表

This commit is contained in:
guoyuqi 2024-03-18 15:21:46 +08:00 committed by Craftsman
parent 10fb5fead9
commit ae34ffe61f
11 changed files with 571 additions and 271 deletions

View File

@ -81,6 +81,7 @@ import {
ApiCaseChangeHistoryParams,
ApiCaseDependencyParams,
ApiCaseDetail,
ApiCaseExecuteHistoryItem,
ApiCaseExecuteHistoryParams,
ApiCasePageParams,
ApiDefinitionBatchDeleteParams,
@ -115,7 +116,6 @@ import {
DragSortParams,
ModuleTreeNode,
MoveModules,
TableQueryParams,
TransferFileParams,
} from '@/models/common';
import { ResourcePoolItem } from '@/models/setting/resourcePool';
@ -457,7 +457,7 @@ export function getEnvList(projectId: string) {
// 获取接口用例-执行历史
export function getApiCaseExecuteHistory(data: ApiCaseExecuteHistoryParams) {
return MSR.post({ url: GetExecuteHistoryUrl, data });
return MSR.post<CommonList<ApiCaseExecuteHistoryItem>>({ url: GetExecuteHistoryUrl, data });
}
// 获取接口用例-变更历史

View File

@ -70,7 +70,7 @@ export const GetCaseDetailUrl = '/api/case/get-detail'; // 获取接口用例详
export const GetEnvListUrl = '/api/test/env-list'; // 接口测试-环境列表
export const BatchExecuteCaseUrl = '/api/case/batch/run'; // 批量执行接口用例
export const ExecuteCaseUrl = '/api/case/run/'; // 单独执行接口用例
export const GetExecuteHistoryUrl = 'api/case/execute/page'; // 获取用的执行历史
export const GetExecuteHistoryUrl = '/api/case/execute/page'; // 获取用的执行历史
export const GetDependencyUrl = '/api/case/get-reference'; // 获取用例的依赖关系
export const GetChangeHistoryUrl = '/api/case/operation-history/page'; // 获取用例的依赖关系
export const ToggleFollowCaseUrl = '/api/case/follow'; // 接口定义-关注/取消关注

View File

@ -278,3 +278,11 @@ export enum ExecuteStatusFilters {
FAKE_ERROR = 'FAKE_ERROR',
STOPPED = 'STOPPED',
}
// 变更历史类型
export enum ChangeHistoryStatusFilters {
ADD = 'ADD',
UPDATE = 'UPDATE',
IMPORT = 'IMPORT',
DELETE = 'DELETE',
}

View File

@ -383,3 +383,15 @@ export interface ApiCaseChangeHistoryParams extends TableQueryParams {
export interface ApiCaseDependencyParams extends TableQueryParams {
resourceId: string;
}
// 用例-执行历史-请求参数
export interface ApiCaseExecuteHistoryItem {
id: string;
num: string;
name: string;
operationUser: string;
createUser: string;
startTime: number;
status: string;
triggerMode: string;
}

View File

@ -50,12 +50,15 @@
<detailTab :detail="caseDetail" :protocols="protocols" is-case />
</a-tab-pane>
<a-tab-pane key="reference" :title="t('apiTestManagement.reference')" class="px-[18px] py-[16px]">
<quote :source-id="caseDetail.id" />
<tab-case-dependency :source-id="caseDetail.id" />
</a-tab-pane>
<a-tab-pane key="executeHistory" :title="t('apiTestManagement.executeHistory')" class="px-[18px] py-[16px]">
<tab-case-execute-history :source-id="caseDetail.id" module-type="API_REPORT" />
</a-tab-pane>
<!-- <a-tab-pane key="dependencies" :title="t('apiTestManagement.dependencies')" class="px-[18px] py-[16px]">
</a-tab-pane> -->
<a-tab-pane key="changeHistory" :title="t('apiTestManagement.changeHistory')" class="px-[18px] py-[16px]">
<history :source-id="caseDetail.id" />
<tab-case-change-history :source-id="caseDetail.id" />
</a-tab-pane>
</a-tabs>
</div>
@ -72,11 +75,12 @@
import caseLevel from '@/components/business/ms-case-associate/caseLevel.vue';
import type { CaseLevel } from '@/components/business/ms-case-associate/types';
import detailTab from '../api/preview/detail.vue';
import history from '../api/preview/history.vue';
import quote from '../api/preview/quote.vue';
import createAndEditCaseDrawer from './createAndEditCaseDrawer.vue';
import apiMethodName from '@/views/api-test/components/apiMethodName.vue';
import { RequestParam } from '@/views/api-test/components/requestComposition/index.vue';
import TabCaseChangeHistory from '@/views/api-test/management/components/management/case/tabContent/tabCaseChangeHistory.vue';
import TabCaseDependency from '@/views/api-test/management/components/management/case/tabContent/tabCaseDependency.vue';
import TabCaseExecuteHistory from '@/views/api-test/management/components/management/case/tabContent/tabCaseExecuteHistory.vue';
import { getProtocolList } from '@/api/modules/api-test/common';
import { toggleFollowCase } from '@/api/modules/api-test/management';

View File

@ -1,264 +0,0 @@
<template>
<div>
<a-alert v-if="isShowTip" class="mb-6" type="warning">
<div class="flex items-start justify-between">
<span class="w-[80%]">{{ t('case.detail.changeHistoryTip') }}</span>
<span class="cursor-pointer text-[var(--color-text-2)]" @click="noRemindHandler">{{
t('case.detail.noReminders')
}}</span>
</div>
</a-alert>
<ms-base-table v-bind="propsRes" v-on="propsEvent">
<template #name="{ record }">
<a-button type="text" class="px-0">{{ record.name }}</a-button>
</template>
<template #type="{ record }">
{{ t(typeOptions.find((e) => e.value === record.type)?.label || '') }}
</template>
<template #operation="{ record }">
<!-- TODO 这一版本不上 -->
<!-- <MsRemoveButton
position="br"
:title="
t('caseManagement.featureCase.confirmRecoverChangeHistoryTitle', { name: characterLimit(record.name) })
"
:sub-title-tip="
t('caseManagement.featureCase.recoverChangeHistoryTip', { name: characterLimit(record.name) })
"
:loading="recoverLoading"
@ok="recoverHandler(record)"
/> -->
<MsButton @click="saveAsHandler(record)">{{ t('caseManagement.featureCase.saveAsVersion') }}</MsButton>
</template>
</ms-base-table>
<a-modal
v-model:visible="showModal"
title-align="start"
class="ms-modal-form ms-modal-medium"
:ok-text="t('organization.member.Confirm')"
:cancel-text="t('organization.member.Cancel')"
unmount-on-close
@close="handleCancel"
>
<template #title> {{ t('caseManagement.featureCase.saveAsVersion') }} </template>
<div class="form">
<a-form ref="versionFormRef" :model="form" size="large" layout="vertical">
<a-form-item
field="versionId"
:label="t('caseManagement.featureCase.tableColumnVersion')"
asterisk-position="end"
:rules="[{ required: true, message: t('caseManagement.featureCase.saveAsVersionPlaceholder') }]"
>
<a-select
v-model="form.versionId"
multiple
allow-clear
:placeholder="t('organization.member.selectUserScope')"
>
<a-option v-for="item of versionOptions" :key="item.id" :value="item.id">{{ item.name }}</a-option>
</a-select>
<MsFormItemSub :text="t('caseManagement.featureCase.saveAsVersionTip')" :show-fill-icon="false" />
</a-form-item>
</a-form>
</div>
<template #footer>
<a-button type="secondary" @click="handleCancel">{{ t('common.cancel') }}</a-button>
<a-button class="ml-[12px]" type="primary" :loading="confirmLoading" @click="handleOK">
{{ t('common.save') }}
</a-button>
</template>
</a-modal>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { FormInstance, Message, ValidatedError } from '@arco-design/web-vue';
import MsButton from '@/components/pure/ms-button/index.vue';
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
import type { MsTableColumn } from '@/components/pure/ms-table/type';
import useTable from '@/components/pure/ms-table/useTable';
import MsFormItemSub from '@/components/business/ms-form-item-sub/index.vue';
import { getApiCaseChangeHistory } from '@/api/modules/api-test/management';
import { useI18n } from '@/hooks/useI18n';
import useVisit from '@/hooks/useVisit';
import { useAppStore } from '@/store';
import { TableKeyEnum } from '@/enums/tableEnum';
const { t } = useI18n();
const appStore = useAppStore();
const visitedKey = 'notRemindChangeHistoryTip';
const { addVisited } = useVisit(visitedKey);
const { getIsVisited } = useVisit(visitedKey);
const props = defineProps<{
caseId: string;
}>();
const columns: MsTableColumn = [
{
title: 'case.detail.changeNumber',
dataIndex: 'id',
showTooltip: true,
width: 90,
},
{
title: 'case.detail.changeType',
slotName: 'type',
dataIndex: 'type',
width: 200,
},
{
title: 'case.detail.operator',
dataIndex: 'createUserName',
slotName: 'createUserName',
width: 150,
},
{
title: 'case.detail.tableColumnUpdateTime',
slotName: 'createTime',
dataIndex: 'createTime',
width: 200,
},
// {
// title: 'caseManagement.featureCase.tableColumnActions',
// slotName: 'operation',
// dataIndex: 'operation',
// fixed: 'right',
// width: 140,
// showInTable: true,
// showDrag: false,
// },
];
const typeOptions = [
{
label: 'system.log.operateType.add',
value: 'ADD',
},
{
label: 'system.log.operateType.update',
value: 'UPDATE',
},
{
label: 'system.log.operateType.import',
value: 'IMPORT',
},
{
label: 'system.log.operateType.delete',
value: 'DELETE',
},
];
const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector } = useTable(getApiCaseChangeHistory, {
columns,
tableKey: TableKeyEnum.CASE_MANAGEMENT_TAB_CHANGE_HISTORY,
scroll: { x: '100%' },
selectable: false,
heightUsed: 340,
enableDrag: false,
});
const form = ref({
versionId: '',
});
const versionOptions = ref([
{
id: '1001',
name: 'v1.0',
},
{
id: '1002',
name: 'v1.1',
},
]);
const recoverLoading = ref<boolean>(false);
//
async function recoverHandler(record: any) {
recoverLoading.value = true;
try {
Message.success(t('caseManagement.featureCase.recoveredSuccessfully'));
resetSelector();
} catch (error) {
console.log(error);
} finally {
recoverLoading.value = false;
}
}
const showModal = ref<boolean>(false);
//
function saveAsHandler(record: any) {
showModal.value = true;
}
const handleCancel = () => {
showModal.value = false;
};
const confirmLoading = ref<boolean>(false);
const versionFormRef = ref<FormInstance | null>(null);
const handleOK = () => {
versionFormRef.value?.validate(async (errors: undefined | Record<string, ValidatedError>) => {
if (!errors) {
try {
confirmLoading.value = true;
Message.success(t('common.saveSuccess'));
handleCancel();
} catch (error) {
console.log(error);
} finally {
confirmLoading.value = false;
}
} else {
return false;
}
});
};
const isShowTip = ref<boolean>(true);
const noRemindHandler = () => {
isShowTip.value = false;
addVisited();
};
const doCheckIsTip = () => {
isShowTip.value = !getIsVisited();
};
async function initData() {
setLoadListParams({
projectId: appStore.currentProjectId,
sourceId: props.caseId,
types: ['IMPORT', 'ADD', 'UPDATE', 'DELETE'],
modules: ['API_TEST_MANAGEMENT_CASE'],
});
await loadList();
}
// watch(
// () => activeTab.value,
// (val) => {
// if (val === 'changeHistory') {
// doCheckIsTip();
// initData();
// }
// }
// );
onMounted(() => {
doCheckIsTip();
initData();
});
</script>
<style scoped></style>

View File

@ -0,0 +1,180 @@
<template>
<div class="history-container">
<a-alert v-if="!getIsVisited()" :show-icon="false" class="mb-[16px]" type="warning" closable @close="addVisited">
{{ t('apiTestManagement.historyListTip') }}
<template #close-element>
<span class="text-[14px]">{{ t('common.notRemind') }}</span>
</template>
</a-alert>
<ms-base-table v-bind="propsRes" no-disable v-on="propsEvent">
<template #typeFilter="{ columnConfig }">
<a-trigger
v-model:popup-visible="statusFilterVisible"
trigger="click"
@popup-visible-change="handleFilterHidden"
>
<MsButton type="text" class="arco-btn-text--secondary" @click="statusFilterVisible = true">
{{ t(columnConfig.title as string) }}
<icon-down :class="statusFilterVisible ? 'text-[rgb(var(--primary-5))]' : ''" />
</MsButton>
<template #content>
<div class="arco-table-filters-content">
<div class="flex items-center justify-center px-[6px] py-[2px]">
<a-checkbox-group v-model:model-value="typeFilter" direction="vertical" size="small">
<a-checkbox v-for="val of typeOptions" :key="val.value" :value="val.value">
<span>{{ t(val.label) }}</span>
</a-checkbox>
</a-checkbox-group>
</div>
</div>
</template>
</a-trigger>
</template>
</ms-base-table>
</div>
</template>
<script setup lang="ts">
import dayjs from 'dayjs';
import MsButton from '@/components/pure/ms-button/index.vue';
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
import { MsTableColumn } from '@/components/pure/ms-table/type';
import useTable from '@/components/pure/ms-table/useTable';
import { getApiCaseChangeHistory } from '@/api/modules/api-test/management';
import { operationTypeOptions } from '@/config/common';
import { useI18n } from '@/hooks/useI18n';
import useVisit from '@/hooks/useVisit';
import useAppStore from '@/store/modules/app';
import { hasAnyPermission } from '@/utils/permission';
import { ChangeHistoryStatusFilters } from '@/enums/apiEnum';
import { TableKeyEnum } from '@/enums/tableEnum';
const typeFilter = ref(Object.keys(ChangeHistoryStatusFilters));
const statusFilterVisible = ref(false);
const props = defineProps<{
sourceId: string | number;
}>();
const appStore = useAppStore();
const { t } = useI18n();
const visitedKey = 'messageManagementRobotListTip';
const { addVisited, getIsVisited } = useVisit(visitedKey);
const typeOptions = [
{
label: 'system.log.operateType.add',
value: 'ADD',
},
{
label: 'system.log.operateType.update',
value: 'UPDATE',
},
{
label: 'system.log.operateType.import',
value: 'IMPORT',
},
{
label: 'system.log.operateType.delete',
value: 'DELETE',
},
];
const columns: MsTableColumn = [
{
title: 'apiTestManagement.changeOrder',
dataIndex: 'id',
width: 200,
},
{
title: 'apiTestManagement.type',
dataIndex: 'type',
slotName: 'type',
titleSlotName: 'typeFilter',
width: 100,
},
{
title: 'mockManagement.operationUser',
dataIndex: 'createUserName',
showTooltip: true,
width: 150,
},
{
title: 'apiTestManagement.updateTime',
dataIndex: 'createTime',
sortable: {
sortDirections: ['ascend', 'descend'],
sorter: true,
},
width: 180,
},
// {
// title: 'common.operation',
// slotName: 'action',
// dataIndex: 'operation',
// width: 50,
// },
];
const { propsRes, propsEvent, loadList, setLoadListParams } = useTable(
getApiCaseChangeHistory,
{
columns,
tableKey: TableKeyEnum.CASE_MANAGEMENT_TAB_CHANGE_HISTORY,
scroll: { x: '100%' },
selectable: false,
heightUsed: 374,
},
(item) => ({
...item,
type: t(operationTypeOptions.find((e) => e.value === item.type)?.label || ''),
createTime: dayjs(item.createTime).format('YYYY-MM-DD HH:mm:ss'),
updateTime: dayjs(item.updateTime).format('YYYY-MM-DD HH:mm:ss'),
})
);
function loadHistory() {
setLoadListParams({
projectId: appStore.currentProjectId,
sourceId: props.sourceId,
modules: ['API_TEST_MANAGEMENT_CASE'],
types: typeFilter.value.length === Object.keys(ChangeHistoryStatusFilters).length ? undefined : typeFilter.value,
});
loadList();
}
function handleFilterHidden(val: boolean) {
if (!val) {
loadHistory();
}
}
onBeforeMount(() => {
if (hasAnyPermission(['PROJECT_API_DEFINITION_CASE:READ', 'PROJECT_API_DEFINITION_CASE:READ+UPDATE'])) {
loadHistory();
}
});
// async function recover(record: any) {
// try {
// await recovergetApiCaseChangeHistory({
// id: record.id,
// sourceId: props.sourceId,
// });
// } catch (error) {
// // eslint-disable-next-line no-console
// console.log(error);
// }
// }
</script>
<style lang="less" scoped>
.history-container {
@apply h-full overflow-y-auto;
.ms-scroll-bar();
}
</style>

View File

@ -0,0 +1,132 @@
<template>
<div class="history-container">
<div class="history-table-before">
<span class="text-[var(--color-text-1)]">{{ t('case.detail.dependency.list') }}</span>
<a-input-search
v-model:model-value="keyword"
:placeholder="t('apiTestManagement.quoteSearchPlaceholder')"
allow-clear
class="mr-[8px] w-[240px]"
@search="loadQuoteList"
@press-enter="loadQuoteList"
/>
</div>
<ms-base-table v-bind="propsRes" no-disable v-on="propsEvent">
<template #id="{ record }">
<MsButton type="text">{{ record.id }}</MsButton>
</template>
</ms-base-table>
</div>
</template>
<script setup lang="ts">
import MsButton from '@/components/pure/ms-button/index.vue';
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
import { MsTableColumn } from '@/components/pure/ms-table/type';
import useTable from '@/components/pure/ms-table/useTable';
import { getApiCaseDependency } from '@/api/modules/api-test/management';
import { useI18n } from '@/hooks/useI18n';
const props = defineProps<{
sourceId: string | number;
}>();
const { t } = useI18n();
const keyword = ref('');
const quoteLocaleMap = {
COPY: 'common.copy',
REF: 'apiTestManagement.quote',
};
const resourceLocaleMap = {
API: 'case.detail.resource.api',
};
const columns: MsTableColumn = [
{
title: 'ID',
dataIndex: 'num',
slotName: 'num',
sortIndex: 1,
sortable: {
sortDirections: ['ascend', 'descend'],
sorter: true,
},
width: 150,
},
{
title: 'apiTestManagement.resourceName',
dataIndex: 'resourceName',
sortable: {
sortDirections: ['ascend', 'descend'],
sorter: true,
},
showTooltip: true,
width: 150,
},
{
title: 'apiTestManagement.resourceType',
dataIndex: 'resourceType',
width: 100,
},
{
title: 'apiTestManagement.quoteType',
dataIndex: 'refType',
width: 100,
},
{
title: 'apiTestManagement.belongOrg',
dataIndex: 'organizationName',
showTooltip: true,
width: 150,
},
{
title: 'apiTestManagement.belongProject',
dataIndex: 'projectName',
showTooltip: true,
width: 150,
},
];
const { propsRes, propsEvent, loadList, setLoadListParams } = useTable(
getApiCaseDependency,
{
columns,
scroll: { x: '100%' },
selectable: false,
heightUsed: 374,
},
(item) => ({
...item,
refType: t(quoteLocaleMap[item.refType] || ''),
resourceType: t(resourceLocaleMap[item.resourceType] || ''),
})
);
function loadQuoteList() {
setLoadListParams({
keyword: keyword.value,
resourceId: props.sourceId,
});
loadList();
}
onBeforeMount(() => {
loadQuoteList();
});
</script>
<style lang="less" scoped>
.history-container {
@apply h-full overflow-y-auto;
.ms-scroll-bar();
}
.history-table-before {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
}
</style>

View File

@ -0,0 +1,216 @@
<template>
<div class="history-container">
<div class="history-table-before">
<span class="text-[var(--color-text-1)]">{{ t('case.detail.execute.history.list') }}</span>
<a-input-search
v-model:model-value="keyword"
:placeholder="t('apiTestManagement.quoteSearchPlaceholder')"
allow-clear
class="mr-[8px] w-[240px]"
@search="loadExecuteList"
@press-enter="loadExecuteList"
/>
</div>
<ms-base-table v-bind="propsRes" no-disable v-on="propsEvent">
<template #triggerModeFilter="{ columnConfig }">
<a-trigger
v-model:popup-visible="triggerModeFilterVisible"
trigger="click"
@popup-visible-change="handleFilterHidden"
>
<MsButton type="text" class="arco-btn-text--secondary" @click="triggerModeFilterVisible = true">
<div class="font-medium">
{{ t(columnConfig.title as string) }}
</div>
<icon-down :class="triggerModeFilterVisible ? 'text-[rgb(var(--primary-5))]' : ''" />
</MsButton>
<template #content>
<div class="arco-table-filters-content">
<div class="flex items-center justify-center px-[6px] py-[2px]">
<a-checkbox-group v-model:model-value="triggerModeListFilters" direction="vertical" size="small">
<a-checkbox v-for="(key, value) of TriggerModeLabel" :key="key" :value="value">
<div class="font-medium">{{ t(key) }}</div>
</a-checkbox>
</a-checkbox-group>
</div>
</div>
</template>
</a-trigger>
</template>
<template #statusFilter="{ columnConfig }">
<a-trigger
v-model:popup-visible="statusFilterVisible"
trigger="click"
@popup-visible-change="handleFilterHidden"
>
<MsButton type="text" class="arco-btn-text--secondary" @click="statusFilterVisible = true">
{{ t(columnConfig.title as string) }}
<icon-down :class="statusFilterVisible ? 'text-[rgb(var(--primary-5))]' : ''" />
</MsButton>
<template #content>
<div class="arco-table-filters-content">
<div class="flex items-center justify-center px-[6px] py-[2px]">
<a-checkbox-group v-model:model-value="statusFilters" direction="vertical" size="small">
<a-checkbox v-for="val of Object.values(ExecuteStatusFilters)" :key="val" :value="val">
<execute-status :status="val" />
</a-checkbox>
</a-checkbox-group>
</div>
</div>
</template>
</a-trigger>
</template>
<template #triggerMode="{ record }">
<span>{{ t(TriggerModeLabel[record.triggerMode]) }}</span>
</template>
<template #status="{ record }">
<execute-status :status="record.status" />
</template>
<template #operation="{ record }">
<MsButton class="!mr-0" @click="showResult(record)"
>{{ t('apiScenario.executeHistory.execution.operation') }}
</MsButton>
</template>
</ms-base-table>
</div>
</template>
<script setup lang="ts">
import dayjs from 'dayjs';
import MsButton from '@/components/pure/ms-button/index.vue';
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
import { MsTableColumn } from '@/components/pure/ms-table/type';
import useTable from '@/components/pure/ms-table/useTable';
import ExecuteStatus from '@/views/api-test/scenario/components/executeStatus.vue';
import { getApiCaseExecuteHistory } from '@/api/modules/api-test/management';
import { useI18n } from '@/hooks/useI18n';
import useAppStore from '@/store/modules/app';
import { ApiCaseExecuteHistoryItem } from '@/models/apiTest/management';
import { ExecuteStatusFilters } from '@/enums/apiEnum';
import { TriggerModeLabel } from '@/enums/reportEnum';
const triggerModeListFilters = ref<string[]>(Object.keys(TriggerModeLabel));
const triggerModeFilterVisible = ref(false);
const statusFilterVisible = ref(false);
const statusFilters = ref(Object.keys(ExecuteStatusFilters));
const props = defineProps<{
sourceId: string | number;
moduleType: string;
}>();
const appStore = useAppStore();
const { t } = useI18n();
const keyword = ref('');
const columns: MsTableColumn = [
{
title: 'apiTestManagement.order',
dataIndex: 'num',
slotName: 'num',
sortIndex: 1,
width: 150,
},
{
title: 'apiTestManagement.executeMethod',
dataIndex: 'triggerMode',
slotName: 'triggerMode',
titleSlotName: 'triggerModeFilter',
showTooltip: true,
sortable: {
sortDirections: ['ascend', 'descend'],
sorter: true,
},
width: 150,
},
{
title: 'apiTestManagement.executeResult',
dataIndex: 'status',
slotName: 'status',
titleSlotName: 'statusFilter',
sortable: {
sortDirections: ['ascend', 'descend'],
sorter: true,
},
width: 100,
},
{
title: 'apiTestManagement.taskOperator',
dataIndex: 'operationUser',
width: 100,
},
{
title: 'apiTestManagement.taskOperationTime',
dataIndex: 'startTime',
showTooltip: true,
sortable: {
sortDirections: ['ascend', 'descend'],
sorter: true,
},
width: 150,
},
{
title: 'common.operation',
slotName: 'operation',
dataIndex: 'operation',
fixed: 'right',
showInTable: true,
showDrag: false,
width: 150,
},
];
const { propsRes, propsEvent, loadList, setLoadListParams } = useTable(
getApiCaseExecuteHistory,
{
columns,
scroll: { x: '100%' },
selectable: false,
heightUsed: 374,
},
(item) => ({
...item,
startTime: dayjs(item.startTime).format('YYYY-MM-DD HH:mm:ss'),
})
);
function loadExecuteList() {
setLoadListParams({
projectId: appStore.currentProjectId,
keyword: keyword.value,
id: props.sourceId,
filter: {
triggerMode: triggerModeListFilters.value,
status: statusFilters.value,
},
});
loadList();
}
function handleFilterHidden(val: boolean) {
if (!val) {
loadExecuteList();
}
}
function showResult(record: ApiCaseExecuteHistoryItem) {}
onBeforeMount(() => {
loadExecuteList();
});
</script>
<style lang="less" scoped>
.history-container {
@apply h-full overflow-y-auto;
.ms-scroll-bar();
}
.history-table-before {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
}
</style>

View File

@ -18,6 +18,7 @@ export default {
'apiTestManagement.moveSearchTip': 'Please enter the module name to search',
'apiTestManagement.noMatchModule': 'No matching module/api yet',
'apiTestManagement.execute': 'Execute',
'apiTestManagement.executeMethod': 'Execute method',
'apiTestManagement.recycle.batchRecover': 'Recover',
'apiTestManagement.recycle.recoveredSuccessfully': 'recovery was successful',
'apiTestManagement.recycle.batchCleanOut': 'Completely delete',
@ -133,6 +134,7 @@ export default {
'apiTestManagement.reference': 'Reference',
'apiTestManagement.dependencies': 'Dependency',
'apiTestManagement.changeHistory': 'Change history',
'apiTestManagement.executeHistory': 'Execute history',
'apiTestManagement.requestParams': 'Request parameters',
'apiTestManagement.responseContent': 'Response content',
'apiTestManagement.requestHeader': 'Request header',
@ -144,6 +146,7 @@ export default {
'apiTestManagement.historyListTip':
'View and compare historical changes. According to the rules set by the administrator, the change history data will be automatically deleted.',
'apiTestManagement.changeOrder': 'Change serial number',
'apiTestManagement.order': 'Serial number',
'apiTestManagement.type': 'Type',
'apiTestManagement.recover': 'Recover',
'apiTestManagement.quote': 'Quote',
@ -200,4 +203,7 @@ export default {
'case.detail.operator': 'operator',
'case.detail.tableColumnUpdateTime': 'UpdateTime',
'case.detail.execute.success': 'Execute success',
'case.detail.execute.history.list': 'Execution history list',
'case.detail.dependency.list': 'Reference relationship list',
'case.detail.resource.api': 'API',
};

View File

@ -18,6 +18,7 @@ export default {
'apiTestManagement.moveSearchTip': '请输入模块名称搜索',
'apiTestManagement.noMatchModule': '暂无匹配的模块/接口',
'apiTestManagement.execute': '执行',
'apiTestManagement.executeMethod': '执行方式',
'apiTestManagement.recycle.batchRecover': '恢复',
'apiTestManagement.recycle.recoveredSuccessfully': '恢复成功',
'apiTestManagement.recycle.batchCleanOut': '彻底删除',
@ -126,6 +127,7 @@ export default {
'apiTestManagement.reference': '引用关系',
'apiTestManagement.dependencies': '依赖关系',
'apiTestManagement.changeHistory': '变更历史',
'apiTestManagement.executeHistory': '执行历史',
'apiTestManagement.requestParams': '请求参数',
'apiTestManagement.responseContent': '响应内容',
'apiTestManagement.requestHeader': '请求头',
@ -136,6 +138,7 @@ export default {
'apiTestManagement.apiNameRequired': '接口名称不能为空',
'apiTestManagement.historyListTip': '查看、对比历史修改,根据管理员设置规则,变更历史数据将自动删除',
'apiTestManagement.changeOrder': '变更序号',
'apiTestManagement.order': '序号',
'apiTestManagement.type': '类型',
'apiTestManagement.recover': '恢复',
'apiTestManagement.quote': '引用',
@ -192,4 +195,7 @@ export default {
'case.detail.operator': '操作人',
'case.detail.tableColumnUpdateTime': '更新时间',
'case.detail.execute.success': '执行成功',
'case.detail.execute.history.list': '执行历史列表',
'case.detail.dependency.list': '引用关系列表',
'case.detail.resource.api': '接口测试',
};