feat(接口测试): 场景表格支持是否显示子目录数据

This commit is contained in:
song-tianyang 2024-03-20 17:13:53 +08:00 committed by Craftsman
parent 2585ccaaa3
commit e2190b63c4
10 changed files with 47 additions and 73 deletions

View File

@ -245,6 +245,7 @@
:show-subdirectory="!!attrs.showSubdirectory" :show-subdirectory="!!attrs.showSubdirectory"
@init-data="handleInitColumn" @init-data="handleInitColumn"
@page-size-change="pageSizeChange" @page-size-change="pageSizeChange"
@module-change="emit('moduleChange')"
></ColumnSelector> ></ColumnSelector>
</div> </div>
</template> </template>
@ -325,6 +326,7 @@
(e: 'cell-click', record: TableData, column: TableColumnData, ev: Event): void | Promise<any>; (e: 'cell-click', record: TableData, column: TableColumnData, ev: Event): void | Promise<any>;
(e: 'clearSelector'): void; (e: 'clearSelector'): void;
(e: 'filterChange', dataIndex: string, value: (string | number)[], multiple: boolean, isCustomParam: boolean): void; (e: 'filterChange', dataIndex: string, value: (string | number)[], multiple: boolean, isCustomParam: boolean): void;
(e: 'moduleChange'): void;
}>(); }>();
const attrs = useAttrs(); const attrs = useAttrs();
// - // -

View File

@ -50,18 +50,18 @@
<template v-if="props.showSubdirectory"> <template v-if="props.showSubdirectory">
<div class="mt-4"> <div class="mt-4">
<a-switch v-model="subdirectoryVal" class="mb-1" size="small" type="line" @change="handleSubSwitch" /> <a-switch v-model="subdirectoryVal" class="mb-1" size="small" type="line" @change="handleSubSwitch" />
<span class="ml-2 text-[var(--color-text-4)]">{{ t('msTable.columnSetting.showSubdirectoryTips') }}</span> <span class="ml-2 text-[var(--color-text-1)]">{{ t('msTable.columnSetting.showSubdirectoryTips') }}</span>
<a-popover position="rt"> <a-tooltip position="rt">
<icon-question-circle <icon-question-circle
class="ml-[4px] text-[var(--color-text-3)] hover:text-[rgb(var(--primary-5))]" class="ml-[4px] text-[var(--color-text-3)] hover:text-[rgb(var(--primary-5))]"
size="16" size="16"
/> />
<template #title> <template #content>
<div class="w-[250px]"> {{ t('msTable.columnSetting.showSubdirectoryTips1') }} </div> <div class="w-[250px]"> {{ t('msTable.columnSetting.showSubdirectoryTips1') }} </div>
<br /> <br />
<div class="w-[250px]"> {{ t('msTable.columnSetting.showSubdirectoryTips2') }} </div> <div class="w-[250px]"> {{ t('msTable.columnSetting.showSubdirectoryTips2') }} </div>
</template> </template>
</a-popover> </a-tooltip>
</div> </div>
</template> </template>
<a-divider /> <a-divider />
@ -129,6 +129,7 @@
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'initData'): void; (e: 'initData'): void;
(e: 'moduleChange'): void;
(e: 'pageSizeChange', value: number): void; (e: 'pageSizeChange', value: number): void;
(e: 'update:visible', value: boolean): void; (e: 'update:visible', value: boolean): void;
}>(); }>();
@ -170,8 +171,9 @@
tableStore.setMode(props.tableKey, value as TableOpenDetailMode); tableStore.setMode(props.tableKey, value as TableOpenDetailMode);
}; };
const handleSubSwitch = () => { const handleSubSwitch = async () => {
tableStore.setSubdirectory(props.tableKey, subdirectoryVal.value); await tableStore.setSubdirectory(props.tableKey, subdirectoryVal.value);
emit('moduleChange');
}; };
const handleSwitchChange = () => { const handleSwitchChange = () => {

View File

@ -28,7 +28,7 @@ export default {
tooltipContentDrawer: 'Drawer: open a new page as a drawer', tooltipContentDrawer: 'Drawer: open a new page as a drawer',
tooltipContentWindow: 'New Window: open a new page with a new page', tooltipContentWindow: 'New Window: open a new page with a new page',
pageSize: 'Number of items per page', pageSize: 'Number of items per page',
showSubdirectoryTips: 'Show Subdirectory', showSubdirectoryTips: 'Show sub module resource',
showSubdirectoryTips1: 'On: Show resources under the module and submodules.', showSubdirectoryTips1: 'On: Show resources under the module and submodules.',
showSubdirectoryTips2: 'Off: Only show resources under the module.', showSubdirectoryTips2: 'Off: Only show resources under the module.',
}, },

View File

@ -28,9 +28,9 @@ export default {
tooltipContentDrawer: '抽屉:以抽屉形式打开新页面', tooltipContentDrawer: '抽屉:以抽屉形式打开新页面',
tooltipContentWindow: '新窗口:以新开网页打开新页面', tooltipContentWindow: '新窗口:以新开网页打开新页面',
pageSize: '每页显示数量', pageSize: '每页显示数量',
showSubdirectoryTips: '显示子目录', showSubdirectoryTips: '显示子模块资源',
showSubdirectoryTips1: '开启: 显示模块及子模块下的资源.', showSubdirectoryTips1: '开启: 显示模块及子模块下的资源',
showSubdirectoryTips2: '关闭: 选中模块时, 只显示模块下的资源, 子模块里的资源不显示.', showSubdirectoryTips2: '关闭: 选中模块时, 只显示模块下的资源, 子模块里的资源不显示',
}, },
cancel: '取消', cancel: '取消',
confirm: '确定', confirm: '确定',

View File

@ -12,6 +12,7 @@ export enum TableKeyEnum {
API_TEST_DEBUG_FORM_DATA = 'apiTestDebugFormData', API_TEST_DEBUG_FORM_DATA = 'apiTestDebugFormData',
API_TEST_DEBUG_FORM_URL_ENCODE = 'apiTestDebugFormUrlEncoded', API_TEST_DEBUG_FORM_URL_ENCODE = 'apiTestDebugFormUrlEncoded',
API_TEST_REPORT = 'apiTestReport', API_TEST_REPORT = 'apiTestReport',
API_SCENARIO = 'apiScenario',
SYSTEM_USER = 'systemUser', SYSTEM_USER = 'systemUser',
SYSTEM_RESOURCEPOOL = 'systemResourcePool', SYSTEM_RESOURCEPOOL = 'systemResourcePool',
SYSTEM_AUTH = 'systemAuth', SYSTEM_AUTH = 'systemAuth',

View File

@ -76,7 +76,7 @@ const ApiTest: AppRouteRecordRaw = {
// 接口场景回收站 // 接口场景回收站
{ {
path: 'scenarioRecycle', path: 'scenario/recycle',
name: ApiTestRouteEnum.API_TEST_SCENARIO_RECYCLE, name: ApiTestRouteEnum.API_TEST_SCENARIO_RECYCLE,
component: () => import('@/views/api-test/scenario/recycle.vue'), component: () => import('@/views/api-test/scenario/recycle.vue'),
meta: { meta: {

View File

@ -1,19 +1,6 @@
<template> <template>
<div :class="['p-[16px_16px]', props.class]"> <div :class="['p-[16px_16px]', props.class]">
<div class="mb-[16px] flex items-center justify-between"> <div class="mb-[16px] flex items-center justify-between">
<div>
<span class="flex items-center">
<a-switch
v-model:model-value="showItemFolderScenario"
size="small"
type="line"
@change="loadScenarioList(false)"
/>
<span style="margin-left: 8px; font-family: 'PingFang SC'; color: #323233">{{
t('apiScenario.table.showChildrenModuleScenario')
}}</span>
</span>
</div>
<div class="flex items-center gap-[8px]"> <div class="flex items-center gap-[8px]">
<a-input-search <a-input-search
v-model:model-value="keyword" v-model:model-value="keyword"
@ -39,6 +26,7 @@
v-on="propsEvent" v-on="propsEvent"
@selected-change="handleTableSelect" @selected-change="handleTableSelect"
@batch-action="handleTableBatch" @batch-action="handleTableBatch"
@module-change="loadScenarioList(false)"
> >
<template #statusFilter="{ columnConfig }"> <template #statusFilter="{ columnConfig }">
<a-trigger <a-trigger
@ -292,8 +280,6 @@
offspringIds: string[]; offspringIds: string[];
readOnly?: boolean; // readOnly?: boolean; //
}>(); }>();
//
const showItemFolderScenario = ref(false);
const appStore = useAppStore(); const appStore = useAppStore();
const { t } = useI18n(); const { t } = useI18n();
@ -451,7 +437,7 @@
{ {
columns: props.readOnly ? columns : [], columns: props.readOnly ? columns : [],
scroll: { x: '100%' }, scroll: { x: '100%' },
tableKey: props.readOnly ? undefined : TableKeyEnum.API_TEST, tableKey: TableKeyEnum.API_SCENARIO,
showSetting: !props.readOnly, showSetting: !props.readOnly,
selectable: true, selectable: true,
showSelectAll: !props.readOnly, showSelectAll: !props.readOnly,
@ -507,27 +493,27 @@
const statusFilterVisible = ref(false); const statusFilterVisible = ref(false);
const statusFilters = ref(Object.keys(ApiScenarioStatus)); const statusFilters = ref(Object.keys(ApiScenarioStatus));
const moduleIds = computed(() => { const tableStore = useTableStore();
if (props.activeModule === 'all') {
return [];
}
if (showItemFolderScenario.value) {
return [props.activeModule, ...props.offspringIds];
}
return [props.activeModule];
});
function loadScenarioList(refreshTreeCount?: boolean) { async function loadScenarioList(refreshTreeCount?: boolean) {
let moduleIds: string[] = [];
if (props.activeModule && props.activeModule !== 'all') {
moduleIds = [props.activeModule];
const getAllChildren = await tableStore.getSubShow(TableKeyEnum.API_SCENARIO);
if (getAllChildren) {
moduleIds = [props.activeModule, ...props.offspringIds];
}
}
const params = { const params = {
keyword: keyword.value, keyword: keyword.value,
projectId: appStore.currentProjectId, projectId: appStore.currentProjectId,
moduleIds: moduleIds.value, moduleIds,
filter: { filter: {
status: statusFilters.value.length === Object.keys(ApiScenarioStatus).length ? undefined : statusFilters.value, status: statusFilters.value.length === Object.keys(ApiScenarioStatus).length ? undefined : statusFilters.value,
}, },
}; };
setLoadListParams(params); setLoadListParams(params);
loadList(); await loadList();
if (refreshTreeCount) { if (refreshTreeCount) {
emit('refreshModuleTree', params); emit('refreshModuleTree', params);
} }
@ -857,8 +843,7 @@
}); });
if (!props.readOnly) { if (!props.readOnly) {
const tableStore = useTableStore(); await tableStore.initColumn(TableKeyEnum.API_SCENARIO, columns, 'drawer', true);
await tableStore.initColumn(TableKeyEnum.API_TEST, columns, 'drawer', true);
} else { } else {
columns = columns.filter( columns = columns.filter(
(item) => !['version', 'createTime', 'updateTime', 'operation'].includes(item.dataIndex as string) (item) => !['version', 'createTime', 'updateTime', 'operation'].includes(item.dataIndex as string)

View File

@ -5,7 +5,6 @@ export default {
'apiScenario.importScenario': 'Import scenario', 'apiScenario.importScenario': 'Import scenario',
'apiScenario.tree.selectorPlaceholder': 'Please enter the module name', 'apiScenario.tree.selectorPlaceholder': 'Please enter the module name',
'apiScenario.tree.folder.allScenario': 'All scenarios', 'apiScenario.tree.folder.allScenario': 'All scenarios',
'apiScenario.tree.showLeafNodeScenario': 'Show subdirectory scenarios',
'apiScenario.tree.recycleBin': 'Recycle bin', 'apiScenario.tree.recycleBin': 'Recycle bin',
'apiScenario.tree.noMatchModule': 'No matching module/scene yet', 'apiScenario.tree.noMatchModule': 'No matching module/scene yet',
'apiScenario.createSubModule': 'Create sub-module', 'apiScenario.createSubModule': 'Create sub-module',
@ -33,7 +32,6 @@ export default {
'apiScenario.params.paramValue': 'Parameter value', 'apiScenario.params.paramValue': 'Parameter value',
'apiScenario.params.tag': 'Tag', 'apiScenario.params.tag': 'Tag',
'apiScenario.params.desc': 'Description', 'apiScenario.params.desc': 'Description',
'apiScenario.table.showChildrenModuleScenario': 'Show subdirectory scenarios',
'apiScenario.table.columns.name': 'Name', 'apiScenario.table.columns.name': 'Name',
'apiScenario.table.columns.level': 'Level', 'apiScenario.table.columns.level': 'Level',
'apiScenario.table.columns.status': 'status', 'apiScenario.table.columns.status': 'status',

View File

@ -5,7 +5,6 @@ export default {
'apiScenario.importScenario': '导入场景', 'apiScenario.importScenario': '导入场景',
'apiScenario.tree.selectorPlaceholder': '请输入模块名称', 'apiScenario.tree.selectorPlaceholder': '请输入模块名称',
'apiScenario.tree.folder.allScenario': '全部场景', 'apiScenario.tree.folder.allScenario': '全部场景',
'apiScenario.tree.showLeafNodeScenario': '显示子目录场景',
'apiScenario.tree.recycleBin': '回收站', 'apiScenario.tree.recycleBin': '回收站',
'apiScenario.tree.noMatchModule': '暂无匹配的模块/场景', 'apiScenario.tree.noMatchModule': '暂无匹配的模块/场景',
'apiScenario.createSubModule': '新建子模块', 'apiScenario.createSubModule': '新建子模块',
@ -32,7 +31,6 @@ export default {
'apiScenario.params.paramValue': '参数值', 'apiScenario.params.paramValue': '参数值',
'apiScenario.params.tag': '标签', 'apiScenario.params.tag': '标签',
'apiScenario.params.desc': '描述', 'apiScenario.params.desc': '描述',
'apiScenario.table.showChildrenModuleScenario': '显示子目录场景',
'apiScenario.table.columns.name': '场景名称', 'apiScenario.table.columns.name': '场景名称',
'apiScenario.table.columns.level': '场景等级', 'apiScenario.table.columns.level': '场景等级',
'apiScenario.table.columns.status': '状态', 'apiScenario.table.columns.status': '状态',

View File

@ -1,19 +1,6 @@
<template> <template>
<div :class="['p-[16px_16px]', props.class]"> <div :class="['p-[16px_16px]', props.class]">
<div class="mb-[16px] flex items-center justify-between"> <div class="mb-[16px] flex items-center justify-between">
<div>
<span class="flex items-center">
<a-switch
v-model:model-value="showItemFolderScenario"
size="small"
type="line"
@change="loadScenarioList(false)"
/>
<span style="margin-left: 8px; font-family: 'PingFang SC'; color: #323233">{{
t('apiScenario.table.showChildrenModuleScenario')
}}</span>
</span>
</div>
<div class="flex items-center gap-[8px]"> <div class="flex items-center gap-[8px]">
<a-input-search <a-input-search
v-model:model-value="keyword" v-model:model-value="keyword"
@ -40,6 +27,7 @@
v-on="propsEvent" v-on="propsEvent"
@selected-change="handleTableSelect" @selected-change="handleTableSelect"
@batch-action="handleTableBatch" @batch-action="handleTableBatch"
@module-change="loadScenarioList(false)"
> >
<template #statusFilter="{ columnConfig }"> <template #statusFilter="{ columnConfig }">
<a-trigger <a-trigger
@ -118,6 +106,7 @@
} from '@/api/modules/api-test/scenario'; } from '@/api/modules/api-test/scenario';
import { useI18n } from '@/hooks/useI18n'; import { useI18n } from '@/hooks/useI18n';
import useModal from '@/hooks/useModal'; import useModal from '@/hooks/useModal';
import useTableStore from '@/hooks/useTableStore';
import useAppStore from '@/store/modules/app'; import useAppStore from '@/store/modules/app';
import { ApiScenarioDetail } from '@/models/apiTest/scenario'; import { ApiScenarioDetail } from '@/models/apiTest/scenario';
@ -130,8 +119,6 @@
offspringIds: string[]; offspringIds: string[];
readOnly?: boolean; // readOnly?: boolean; //
}>(); }>();
//
const showItemFolderScenario = ref(false);
const appStore = useAppStore(); const appStore = useAppStore();
const { t } = useI18n(); const { t } = useI18n();
@ -270,7 +257,7 @@
{ {
columns: props.readOnly ? columns : [], columns: props.readOnly ? columns : [],
scroll: { x: '100%' }, scroll: { x: '100%' },
tableKey: props.readOnly ? undefined : TableKeyEnum.API_TEST, tableKey: props.readOnly ? undefined : TableKeyEnum.API_SCENARIO,
showSetting: !props.readOnly, showSetting: !props.readOnly,
selectable: true, selectable: true,
showSelectAll: !props.readOnly, showSelectAll: !props.readOnly,
@ -301,27 +288,28 @@
const statusFilterVisible = ref(false); const statusFilterVisible = ref(false);
const statusFilters = ref(Object.keys(ApiScenarioStatus)); const statusFilters = ref(Object.keys(ApiScenarioStatus));
const moduleIds = computed(() => { const tableStore = useTableStore();
if (props.activeModule === 'all') {
return []; async function loadScenarioList(refreshTreeCount?: boolean) {
} let moduleIds: string[] = [];
if (showItemFolderScenario.value) { if (props.activeModule && props.activeModule !== 'all') {
return [props.activeModule, ...props.offspringIds]; moduleIds = [props.activeModule];
} const getAllChildren = await tableStore.getSubShow(TableKeyEnum.API_SCENARIO);
return [props.activeModule]; if (getAllChildren) {
}); moduleIds = [props.activeModule, ...props.offspringIds];
}
}
function loadScenarioList(refreshTreeCount?: boolean) {
const params = { const params = {
keyword: keyword.value, keyword: keyword.value,
projectId: appStore.currentProjectId, projectId: appStore.currentProjectId,
moduleIds: moduleIds.value, moduleIds,
filter: { filter: {
status: statusFilters.value.length === Object.keys(ApiScenarioStatus).length ? undefined : statusFilters.value, status: statusFilters.value.length === Object.keys(ApiScenarioStatus).length ? undefined : statusFilters.value,
}, },
}; };
setLoadListParams(params); setLoadListParams(params);
loadList(); await loadList();
if (refreshTreeCount) { if (refreshTreeCount) {
emit('refreshModuleTree', params); emit('refreshModuleTree', params);
} }