feat: 替换任务中心所有的表头筛选&公共脚本筛选

This commit is contained in:
xinxin.wu 2024-05-15 18:59:16 +08:00 committed by 刘瑞斌
parent b74eef8a6c
commit f1fe90aeb1
12 changed files with 304 additions and 390 deletions

View File

@ -106,7 +106,7 @@
:options="item.filterConfig.options"
:data-index="item.dataIndex"
v-bind="item.filterConfig"
:filter="filter"
:filter="filterData"
@handle-confirm="(v) => handleFilterConfirm(v, item.dataIndex as string, item.isCustomParam || false)"
>
<template #item="{ filterItem }">
@ -356,8 +356,10 @@
value: string[] | (string | number)[] | undefined,
isCustomParam: boolean
): void;
(e: 'resetFilter', filterValue: Record<string, any>): void;
(e: 'moduleChange'): void;
(e: 'initEnd'): void;
(e: 'reset'): void;
}>();
const attrs = useAttrs();
@ -637,13 +639,11 @@
columnSelectorVisible.value = true;
};
const filter = ref<Record<string, any>>({});
const handleFilterConfirm = (
value: string[] | (string | number)[] | undefined,
dataIndex: string,
isCustomParam: boolean
) => {
filter.value[dataIndex] = value;
emit('filterChange', dataIndex, value, isCustomParam);
};
@ -652,9 +652,13 @@
batchLeft.value = getBatchLeft();
});
const filterData = computed(() => {
return (attrs.filter || {}) as Record<string, any>;
});
function hasSelectedFilter(item: MsTableColumnData) {
if (item.filterConfig && item.dataIndex) {
return (filter.value[item.dataIndex] || []).length > 0;
return (filterData.value[item.dataIndex] || []).length > 0;
}
return false;
}

View File

@ -124,9 +124,6 @@
const loading = ref(true);
const optionLabelRender = (option: SelectOptionData) => {
if (option.email !== '') {
return `<span class='text-[var(--color-text-1)]'>${option.name}</span><span class='text-[var(--color-text-4)] ml-[4px]'>(${option.email})</span>`;
}
return `<span class='text-[var(--color-text-1)]'>${option.name}</span>`;
};
@ -159,6 +156,25 @@
}
return false;
});
const isNoFilter = computed(() => {
if (props.filter && JSON.stringify(props.filter) !== '{}') {
return !Object.keys(props.filter).some((key: any) => {
return props.filter[key].length > 0;
});
}
return true;
});
//
watch(
() => isNoFilter.value,
(val) => {
if (val) {
checkedList.value = [];
}
}
);
</script>
<style scoped lang="less">

View File

@ -1,4 +1,6 @@
import { getProjectMemberOptions } from '@/api/modules/project-management/projectMember';
import { getProjectList } from '@/api/modules/setting/member';
import { getOrgOptions, getSystemProjectList } from '@/api/modules/system';
import { FilterRemoteMethodsEnum } from '@/enums/tableFilterEnum';
@ -6,6 +8,12 @@ export function initRemoteOptionsFunc(remoteMethod: string, params: Record<strin
switch (remoteMethod) {
case FilterRemoteMethodsEnum.PROJECT_PERMISSION_MEMBER:
return getProjectMemberOptions(params.projectId, params.keyword);
case FilterRemoteMethodsEnum.SYSTEM_ORGANIZATION_LIST:
return getOrgOptions();
case FilterRemoteMethodsEnum.SYSTEM_PROJECT_LIST:
return getSystemProjectList(params.keyword);
case FilterRemoteMethodsEnum.SYSTEM_ORGANIZATION_PROJECT:
return getProjectList(params.organizationId, params.keyword);
default:
break;
}

View File

@ -345,6 +345,11 @@ export default function useTableProps<T>(
const getTableQueryParams = () => {
return tableQueryParams.value;
};
// 重置表头筛选
const resetFilterParams = () => {
filterItem.value = {};
propsRes.value.filter = cloneDeep(filterItem.value);
};
// 事件触发组
const propsEvent = ref({
@ -472,5 +477,6 @@ export default function useTableProps<T>(
resetSelector,
getTableQueryParams,
setTableSelected,
resetFilterParams,
};
}

View File

@ -8,10 +8,16 @@ export enum FilterSlotNameEnum {
API_TEST_API_REQUEST_METHODS = 'API_TEST_API_REQUEST_METHODS', // 接口测试请求方式
API_TEST_API_REQUEST_API_STATUS = 'API_TEST_API_REQUEST_API_STATUS', // 接口测试接口状态
TEST_PLAN_REPORT_EXEC_STATUS = 'TEST_PLAN_REPORT_EXEC_STATUS',
PROJECT_MANAGEMENT_COMMON_SCRIPT = 'PROJECT_MANAGEMENT_COMMON_SCRIPT', // 项目管理公共脚本脚本状态
GLOBAL_TASK_CENTER_API_CASE_STATUS = 'GLOBAL_TASK_CENTER_API_CASE_STATUS', // 任务中心执行状态
GLOBAL_TASK_CENTER_API_CASE_TRIGGED_MODE = 'GLOBAL_TASK_CENTER_API_CASE_TRIGGED_MODE', // 任务中心触发方式
}
export enum FilterRemoteMethodsEnum {
PROJECT_PERMISSION_MEMBER = 'PROJECT_PERMISSION_MEMBER', // 项目下成员
SYSTEM_ORGANIZATION_LIST = 'SYSTEM_ORGANIZATION_LIST', // 组织列表
SYSTEM_PROJECT_LIST = 'SYSTEM_PROJECT_LIST', // 系统下项目
SYSTEM_ORGANIZATION_PROJECT = 'SYSTEM_ORGANIZATION_PROJECT', // 组织下项目
}
export default {};

View File

@ -8,6 +8,12 @@ export enum TaskCenterEnum {
TEST_RESOURCE = 'TEST_RESOURCE', // 测试资源
API_IMPORT = 'API_IMPORT', // API导入
}
export type ResourceTypeMapKey =
| TaskCenterEnum.API_CASE
| TaskCenterEnum.API_SCENARIO
| TaskCenterEnum.UI_TEST
| TaskCenterEnum.LOAD_TEST
| TaskCenterEnum.TEST_PLAN;
// 执行方式
export enum ExecutionMethods {

View File

@ -50,47 +50,19 @@
@change="() => handleStatusChange(record)"
>
<template #label>
<commonScriptStatus :status="record.status" />
<CommonScriptStatus :status="record.status" />
</template>
<a-option :key="CommonScriptStatusEnum.PASSED" :value="CommonScriptStatusEnum.PASSED">
<commonScriptStatus :status="CommonScriptStatusEnum.PASSED" />
<CommonScriptStatus :status="CommonScriptStatusEnum.PASSED" />
</a-option>
<a-option :key="CommonScriptStatusEnum.DRAFT" :value="CommonScriptStatusEnum.DRAFT">
<commonScriptStatus :status="CommonScriptStatusEnum.DRAFT" />
<CommonScriptStatus :status="CommonScriptStatusEnum.DRAFT" />
</a-option>
</a-select>
<commonScriptStatus v-else :status="record.status" />
<CommonScriptStatus v-else :status="record.status" />
</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 ml-[10px]" @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="ml-[6px] flex items-center justify-start px-[6px] py-[2px]">
<a-checkbox-group v-model:model-value="statusFilters" direction="vertical" size="small">
<a-checkbox v-for="val of Object.values(CommonScriptStatusEnum)" :key="val" :value="val">
<commonScriptStatus :status="val" />
</a-checkbox>
</a-checkbox-group>
</div>
<div class="filter-button">
<a-button size="mini" class="mr-[8px]" @click="resetStatusFilter">
{{ t('common.reset') }}
</a-button>
<a-button type="primary" size="mini" @click="handleFilterHidden(false)">
{{ t('system.orgTemplate.confirm') }}
</a-button>
</div>
</div>
</template>
</a-trigger>
<template #[FilterSlotNameEnum.PROJECT_MANAGEMENT_COMMON_SCRIPT]="{ filterContent }">
<CommonScriptStatus :status="filterContent.value" />
</template>
<template #operation="{ record }">
<MsButton v-permission="['PROJECT_CUSTOM_FUNCTION:READ+UPDATE']" status="primary" @click="editHandler(record)">
@ -141,7 +113,7 @@
import MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
import AddScriptDrawer from '@/components/business/ms-common-script/ms-addScriptDrawer.vue';
import commonScriptStatus from './components/commonScriptStatus.vue';
import CommonScriptStatus from './components/commonScriptStatus.vue';
import ScriptDetailDrawer from './components/scriptDetailDrawer.vue';
import {
@ -163,6 +135,7 @@
} from '@/models/projectManagement/commonScript';
import { CommonScriptStatusEnum } from '@/enums/commonScriptStatusEnum';
import { TableKeyEnum } from '@/enums/tableEnum';
import { FilterSlotNameEnum } from '@/enums/tableFilterEnum';
const appStore = useAppStore();
const currentProjectId = computed(() => appStore.currentProjectId);
@ -172,14 +145,21 @@
const { openModal } = useModal();
const { t } = useI18n();
const statusFilterVisible = ref(false);
const keyword = ref<string>('');
const statusFilters = ref<string[]>([]);
const hasOperationPermission = computed(() =>
hasAnyPermission(['PROJECT_CUSTOM_FUNCTION:READ+UPDATE', 'PROJECT_CUSTOM_FUNCTION:READ+DELETE'])
);
const statusFilterOptions = computed(() => {
return Object.values(CommonScriptStatusEnum).map((key) => {
return {
value: key,
label: key,
};
});
});
const columns: MsTableColumn = [
{
title: 'project.commonScript.name',
@ -204,11 +184,14 @@
showInTable: true,
width: 150,
showDrag: true,
titleSlotName: 'statusFilter',
sortable: {
sortDirections: ['ascend', 'descend'],
sorter: true,
},
filterConfig: {
options: statusFilterOptions.value,
filterSlotName: FilterSlotNameEnum.PROJECT_MANAGEMENT_COMMON_SCRIPT,
},
},
{
title: 'project.commonScript.tags',
@ -290,26 +273,10 @@
setLoadListParams({
projectId: currentProjectId.value,
keyword: keyword.value,
filter: {
status: statusFilters.value,
},
});
loadList();
}
function handleFilterHidden(val: boolean) {
if (!val) {
statusFilterVisible.value = false;
initData();
}
}
function resetStatusFilter() {
statusFilters.value = [];
statusFilterVisible.value = false;
initData();
}
function deleteScript(record: CommonScriptItem) {
openModal({
type: 'error',
@ -370,6 +337,7 @@
};
await addOrUpdateCommonScriptReq(paramsObj);
showScriptDrawer.value = false;
resetSelector();
initData();
Message.success(form.id ? t('common.updateSuccess') : t('common.createSuccess'));
if (showDetailDrawer.value) {

View File

@ -14,7 +14,6 @@
></a-input-search>
</div>
</div>
<ms-base-table
v-bind="propsRes"
ref="tableRef"
@ -42,42 +41,8 @@
>{{ record.resourceName }}
</div>
</template>
<template #statusFilter="{ columnConfig }">
<a-trigger
v-model:popup-visible="statusFilterVisible"
trigger="click"
@popup-visible-change="handleFilterHidden"
>
<a-button type="text" class="arco-btn-text--secondary p-[8px_4px]" @click.stop="statusFilterVisible = true">
<div class="font-medium">
{{ t(columnConfig.title as string) }}
</div>
<icon-down :class="statusFilterVisible ? 'text-[rgb(var(--primary-5))]' : ''" />
</a-button>
<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="statusFiltersMap[props.moduleType]"
direction="vertical"
size="small"
>
<a-checkbox v-for="key of statusFilters" :key="key" :value="key">
<ExecutionStatus :module-type="props.moduleType" :status="key" />
</a-checkbox>
</a-checkbox-group>
</div>
<div class="arco-table-filters-bottom">
<a-button size="mini" type="secondary" @click="handleFilterReset">
{{ t('common.reset') }}
</a-button>
<a-button size="mini" type="primary" @click="handleFilterSubmit()">
{{ t('common.confirm') }}
</a-button>
</div>
</div>
</template>
</a-trigger>
<template #[FilterSlotNameEnum.GLOBAL_TASK_CENTER_API_CASE_STATUS]="{ filterContent }">
<ExecutionStatus :module-type="props.moduleType" :status="filterContent.value" />
</template>
<template #status="{ record }">
<ExecutionStatus
@ -86,63 +51,19 @@
:script-identifier="record.scriptIdentifier"
/>
</template>
<template #projectName="{ record }">
<a-tooltip :content="`${record.projectName}`" position="tl">
<div class="one-line-text">{{ characterLimit(record.projectName) }}</div>
</a-tooltip>
</template>
<template #organizationName="{ record }">
<a-tooltip :content="`${record.organizationName}`" position="tl">
<div class="one-line-text">{{ characterLimit(record.organizationName) }}</div>
</a-tooltip>
</template>
<template #triggerMode="{ record }">
<span>{{ t(ExecutionMethodsLabel[record.triggerMode as keyof typeof ExecutionMethodsLabel]) }}</span>
</template>
<template #triggerModeFilter="{ columnConfig }">
<TableFilter
v-model:visible="triggerModeVisible"
v-model:status-filters="triggerModeFiltersMap[props.moduleType]"
:title="(columnConfig.title as string)"
:list="triggerModeList"
label-key="label"
@search="initData()"
>
<template #item="{ item }">
{{ item.label }}
</template>
</TableFilter>
</template>
<template v-if="appStore.packageType === 'enterprise' && xPack" #orgFilterName="{ columnConfig }">
<TableFilter
v-model:visible="orgFilterVisible"
v-model:status-filters="orgFiltersMap[props.moduleType]"
:title="(columnConfig.title as string)"
mode="remote"
value-key="id"
label-key="name"
:type="UserRequestTypeEnum.SYSTEM_ORGANIZATION_PROJECT"
:placeholder-text="t('project.taskCenter.filterOrgPlaceholderText')"
@search="initData()"
>
</TableFilter>
</template>
<template
v-if="
hasAnyPermission(
groupColumnsMap[props.group].key === TableKeyEnum.TASK_API_CASE_SYSTEM
? ['SYSTEM_ORGANIZATION_PROJECT:READ']
: ['ORGANIZATION_PROJECT:READ']
)
"
#projectFilterName="{ columnConfig }"
>
<TableFilter
v-model:visible="projectFilterVisible"
v-model:status-filters="projectFiltersMap[props.moduleType]"
:title="(columnConfig.title as string)"
mode="remote"
:load-option-params="{ organizationId: appStore.currentOrgId }"
:placeholder-text="t('project.taskCenter.filterProPlaceholderText')"
:type="
groupColumnsMap[props.group].key === TableKeyEnum.TASK_API_CASE_SYSTEM
? UserRequestTypeEnum.SYSTEM_PROJECT_LIST
: UserRequestTypeEnum.SYSTEM_ORGANIZATION_PROJECT
"
@search="initData()"
>
</TableFilter>
</template>
<template #operationTime="{ record }">
<span>{{ dayjs(record.operationTime).format('YYYY-MM-DD HH:mm:ss') }}</span>
</template>
@ -201,11 +122,9 @@
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
import type { BatchActionParams, BatchActionQueryParams, MsTableColumn } from '@/components/pure/ms-table/type';
import useTable from '@/components/pure/ms-table/useTable';
import { UserRequestTypeEnum } from '@/components/business/ms-user-selector/utils';
import ExecutionStatus from './executionStatus.vue';
import caseAndScenarioReportDrawer from '@/views/api-test/components/caseAndScenarioReportDrawer.vue';
import ReportDetailDrawer from '@/views/api-test/report/component/reportDetailDrawer.vue';
import TableFilter from '@/views/case-management/caseManagementFeature/components/tableFilter.vue';
import {
batchStopRealOrdApi,
@ -221,32 +140,30 @@
import { useI18n } from '@/hooks/useI18n';
import useModal from '@/hooks/useModal';
import useOpenNewPage from '@/hooks/useOpenNewPage';
import { useAppStore, useTableStore } from '@/store';
import useLicenseStore from '@/store/modules/setting/license';
import { useTableStore } from '@/store';
import { characterLimit } from '@/utils';
import { hasAnyPermission } from '@/utils/permission';
import { BatchApiParams } from '@/models/common';
import { RouteEnum } from '@/enums/routeEnum';
import { TableKeyEnum } from '@/enums/tableEnum';
import { FilterSlotNameEnum } from '@/enums/tableFilterEnum';
import { ExecutionMethodsLabel } from '@/enums/taskCenter';
import type { ResourceTypeMapKey } from './utils';
import { Group, ordAndProjectColumn, TaskStatus } from './utils';
import type { ExtractedKeys } from './utils';
import { getOrgColumns, getProjectColumns, Group, TaskStatus } from './utils';
const { openNewPage } = useOpenNewPage();
const tableStore = useTableStore();
const appStore = useAppStore();
const { openModal } = useModal();
const { t } = useI18n();
const props = defineProps<{
group: Group;
moduleType: ResourceTypeMapKey;
moduleType: ExtractedKeys;
name: string;
}>();
const keyword = ref<string>('');
const statusFilterVisible = ref(false);
const permissionsMap: Record<Group, any> = {
organization: {
@ -307,7 +224,35 @@
const hasJumpPermission = computed(() => hasAnyPermission(permissionsMap[props.group][props.moduleType].jump));
const hasOperationPermission = computed(() => hasAnyPermission(permissionsMap[props.group][props.moduleType].stop));
const columns: MsTableColumn = [
const statusFilters = computed(() => {
return Object.keys(TaskStatus[props.moduleType]).map((key: any) => {
return {
value: key,
...TaskStatus[props.moduleType][key],
};
});
});
const triggerModeList = [
{
value: 'SCHEDULE',
label: t('project.taskCenter.scheduledTask'),
},
{
value: 'MANUAL',
label: t('project.taskCenter.manualExecution'),
},
{
value: 'API',
label: t('project.taskCenter.interfaceCall'),
},
{
value: 'BATCH',
label: t('project.taskCenter.batchExecution'),
},
];
const staticColumns: MsTableColumn = [
{
title: 'project.taskCenter.resourceID',
dataIndex: 'resourceNum',
@ -334,11 +279,14 @@
title: 'project.taskCenter.executionResult',
dataIndex: 'status',
slotName: 'status',
titleSlotName: 'statusFilter',
sortable: {
sortDirections: ['ascend', 'descend'],
sorter: true,
},
filterConfig: {
options: statusFilters.value,
filterSlotName: FilterSlotNameEnum.GLOBAL_TASK_CENTER_API_CASE_STATUS,
},
showInTable: true,
width: 200,
showDrag: true,
@ -347,11 +295,13 @@
title: 'project.taskCenter.executionMode',
dataIndex: 'triggerMode',
slotName: 'triggerMode',
titleSlotName: 'triggerModeFilter',
sortable: {
sortDirections: ['ascend', 'descend'],
sorter: true,
},
filterConfig: {
options: triggerModeList,
},
showInTable: true,
width: 150,
showDrag: true,
@ -390,25 +340,22 @@
},
];
const groupColumnsMap = {
system: {
key: TableKeyEnum.TASK_API_CASE_SYSTEM,
columns: [...ordAndProjectColumn, ...columns],
},
organization: {
key: TableKeyEnum.TASK_API_CASE_ORGANIZATION,
columns: [...ordAndProjectColumn.slice(-1), ...columns],
},
project: {
key: TableKeyEnum.TASK_API_CASE_PROJECT,
columns,
},
const tableKeysMap: Record<string, any> = {
system: TableKeyEnum.TASK_API_CASE_SYSTEM,
organization: TableKeyEnum.TASK_API_CASE_ORGANIZATION,
project: TableKeyEnum.TASK_API_CASE_PROJECT,
};
const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector } = useTable(
const groupColumnsMap: Record<string, any> = {
system: [getOrgColumns(), getProjectColumns(tableKeysMap[props.group]), ...staticColumns],
organization: [getProjectColumns(tableKeysMap[props.group]), ...staticColumns],
project: staticColumns,
};
const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector, resetFilterParams } = useTable(
loadRealMap.value[props.group].list,
{
tableKey: groupColumnsMap[props.group].key,
tableKey: tableKeysMap[props.group],
scroll: {
x: 1400,
},
@ -419,25 +366,6 @@
showSelectAll: true,
}
);
const triggerModeList = ref([
{
value: 'SCHEDULE',
label: t('project.taskCenter.scheduledTask'),
},
{
value: 'MANUAL',
label: t('project.taskCenter.manualExecution'),
},
{
value: 'API',
label: t('project.taskCenter.interfaceCall'),
},
{
value: 'BATCH',
label: t('project.taskCenter.batchExecution'),
},
]);
const triggerModeVisible = ref<boolean>(false);
const triggerModeApiCase = ref([]);
const triggerModeApiScenario = ref([]);
@ -454,8 +382,6 @@
API_SCENARIO: statusFilterApiScenario.value,
});
const orgFilterVisible = ref<boolean>(false);
const projectFilterVisible = ref<boolean>(false);
const orgApiCaseFilter = ref([]);
const orgApiScenarioFilter = ref([]);
@ -470,32 +396,14 @@
API_CASE: projectApiCaseFilter.value,
API_SCENARIO: projectApiScenarioFilter.value,
});
const licenseStore = useLicenseStore();
const xPack = computed(() => licenseStore.hasLicense());
function initData() {
setLoadListParams({
keyword: keyword.value,
moduleType: props.moduleType,
filter: {
status: statusFiltersMap.value[props.moduleType],
triggerMode: triggerModeFiltersMap.value[props.moduleType],
organizationIds: orgFiltersMap.value[props.moduleType],
projectIds: projectFiltersMap.value[props.moduleType],
},
});
loadList();
}
function handleFilterReset() {
statusFiltersMap.value[props.moduleType] = [];
statusFilterVisible.value = false;
initData();
}
function handleFilterSubmit() {
statusFilterVisible.value = false;
initData();
}
const tableBatchActions = {
baseAction: [
@ -600,16 +508,6 @@
initData();
});
const statusFilters = computed(() => {
return Object.keys(TaskStatus[props.moduleType]);
});
function handleFilterHidden(val: boolean) {
if (!val) {
initData();
}
}
/**
* 报告详情 showReportDetail
*/
@ -633,6 +531,7 @@
(val) => {
if (val) {
resetSelector();
resetFilterParams();
initData();
}
}
@ -665,7 +564,7 @@
}
});
await tableStore.initColumn(groupColumnsMap[props.group].key, groupColumnsMap[props.group].columns, 'drawer', true);
await tableStore.initColumn(tableKeysMap[props.group], groupColumnsMap[props.group], 'drawer', true);
</script>
<style scoped></style>

View File

@ -22,10 +22,9 @@
import { useI18n } from '@/hooks/useI18n';
import type { ResourceTypeMapKey } from '@/enums/taskCenter';
import { TaskCenterEnum } from '@/enums/taskCenter';
import type { ResourceTypeMapKey } from './utils';
const { t } = useI18n();
const props = defineProps<{
status: string;

View File

@ -54,6 +54,16 @@
{{ t(resourceTypeMap[record.resourceType as ResourceTypeMapKey].label) }}
</div>
</template>
<template #projectName="{ record }">
<a-tooltip :content="`${record.projectName}`" position="tl">
<div class="one-line-text">{{ characterLimit(record.projectName) }}</div>
</a-tooltip>
</template>
<template #organizationName="{ record }">
<a-tooltip :content="`${record.organizationName}`" position="tl">
<div class="one-line-text">{{ characterLimit(record.organizationName) }}</div>
</a-tooltip>
</template>
<template #value="{ record }">
<a-select
v-model:model-value="record.value"
@ -70,48 +80,6 @@
</a-option>
</a-select>
</template>
<template v-if="appStore.packageType === 'enterprise' && xPack" #orgFilterName="{ columnConfig }">
<TableFilter
v-model:visible="orgFilterVisible"
v-model:status-filters="orgFiltersMap[props.moduleType]"
:title="(columnConfig.title as string)"
mode="remote"
value-key="id"
label-key="name"
:type="UserRequestTypeEnum.SYSTEM_ORGANIZATION_LIST"
:placeholder-text="t('project.taskCenter.filterOrgPlaceholderText')"
@search="initData()"
>
</TableFilter>
</template>
<template
v-if="
hasAnyPermission(
groupColumnsMap[props.group].key === TableKeyEnum.TASK_SCHEDULE_TASK_API_IMPORT_SYSTEM ||
groupColumnsMap[props.group].key === TableKeyEnum.TASK_SCHEDULE_TASK_API_SCENARIO_SYSTEM
? ['SYSTEM_ORGANIZATION_PROJECT:READ']
: ['ORGANIZATION_PROJECT:READ']
)
"
#projectFilterName="{ columnConfig }"
>
<TableFilter
v-model:visible="projectFilterVisible"
v-model:status-filters="projectFiltersMap[props.moduleType]"
:title="(columnConfig.title as string)"
mode="remote"
:load-option-params="{ organizationId: appStore.currentOrgId }"
:placeholder-text="t('project.taskCenter.filterProPlaceholderText')"
:type="
groupColumnsMap[props.group].key === TableKeyEnum.TASK_SCHEDULE_TASK_API_IMPORT_SYSTEM ||
groupColumnsMap[props.group].key === TableKeyEnum.TASK_SCHEDULE_TASK_API_SCENARIO_SYSTEM
? UserRequestTypeEnum.SYSTEM_PROJECT_LIST
: UserRequestTypeEnum.SYSTEM_ORGANIZATION_PROJECT
"
@search="initData()"
>
</TableFilter>
</template>
<template #operation="{ record }">
<a-switch
v-model="record.enable"
@ -147,8 +115,6 @@
import type { BatchActionParams, BatchActionQueryParams, MsTableColumn } from '@/components/pure/ms-table/type';
import useTable from '@/components/pure/ms-table/useTable';
import type { ActionsItem } from '@/components/pure/ms-table-more-action/types';
import { UserRequestTypeEnum } from '@/components/business/ms-user-selector/utils';
import TableFilter from '@/views/case-management/caseManagementFeature/components/tableFilter.vue';
import {
batchDisableScheduleOrgTask,
@ -173,19 +139,18 @@
import { useI18n } from '@/hooks/useI18n';
import useModal from '@/hooks/useModal';
import useOpenNewPage from '@/hooks/useOpenNewPage';
import { useAppStore, useTableStore } from '@/store';
import useLicenseStore from '@/store/modules/setting/license';
import { useTableStore } from '@/store';
import { characterLimit } from '@/utils';
import { hasAnyPermission } from '@/utils/permission';
import { BatchApiParams } from '@/models/common';
import { TimingTaskCenterApiCaseItem } from '@/models/projectManagement/taskCenter';
import { RouteEnum } from '@/enums/routeEnum';
import { TableKeyEnum } from '@/enums/tableEnum';
import type { ResourceTypeMapKey } from '@/enums/taskCenter';
import { TaskCenterEnum } from '@/enums/taskCenter';
import { Group, ordAndProjectColumn, resourceTypeMap, ResourceTypeMapKey } from './utils';
const appStore = useAppStore();
import { getOrgColumns, getProjectColumns, Group, resourceTypeMap } from './utils';
const { openNewPage } = useOpenNewPage();
@ -268,7 +233,7 @@
hasAnyPermission([...(permissionsMap[props.group][props.moduleType]?.edit || '')])
);
const columns: MsTableColumn = [
const resourceColumns: MsTableColumn = [
{
title: 'project.taskCenter.resourceID',
dataIndex: 'resourceNum',
@ -291,6 +256,9 @@
columnSelectorDisabled: true,
showInTable: true,
},
];
const staticColumns: MsTableColumn = [
{
title: 'project.taskCenter.operationRule',
dataIndex: 'value',
@ -352,50 +320,56 @@
},
];
const groupColumnsMap: Record<string, any> = {
const tableKeyMap: Record<string, any> = {
system: {
API_IMPORT: {
key: TableKeyEnum.TASK_SCHEDULE_TASK_API_IMPORT_SYSTEM,
columns: [
...ordAndProjectColumn,
...columns.slice(0, 2),
...swaggerUrlColumn,
...columns.slice(2, columns.length),
],
},
API_SCENARIO: {
key: TableKeyEnum.TASK_SCHEDULE_TASK_API_SCENARIO_SYSTEM,
columns: [...ordAndProjectColumn, ...columns],
},
API_IMPORT: TableKeyEnum.TASK_SCHEDULE_TASK_API_IMPORT_SYSTEM,
API_SCENARIO: TableKeyEnum.TASK_SCHEDULE_TASK_API_SCENARIO_SYSTEM,
},
organization: {
API_IMPORT: {
key: TableKeyEnum.TASK_SCHEDULE_TASK_API_IMPORT_ORGANIZATION,
columns: [
...ordAndProjectColumn.slice(-1),
...columns.slice(0, 2),
...swaggerUrlColumn,
...columns.slice(2, columns.length),
],
},
API_SCENARIO: {
key: TableKeyEnum.TASK_SCHEDULE_TASK_API_SCENARIO_ORGANIZATION,
columns: [...ordAndProjectColumn.slice(-1), ...columns],
},
API_IMPORT: TableKeyEnum.TASK_SCHEDULE_TASK_API_IMPORT_ORGANIZATION,
API_SCENARIO: TableKeyEnum.TASK_SCHEDULE_TASK_API_SCENARIO_ORGANIZATION,
},
project: {
API_IMPORT: {
key: TableKeyEnum.TASK_SCHEDULE_TASK_API_IMPORT_PROJECT,
columns: [...columns.slice(0, 2), ...swaggerUrlColumn, ...columns.slice(2, columns.length)],
},
API_SCENARIO: {
key: TableKeyEnum.TASK_SCHEDULE_TASK_API_SCENARIO_PROJECT,
columns,
},
API_IMPORT: TableKeyEnum.TASK_SCHEDULE_TASK_API_IMPORT_PROJECT,
API_SCENARIO: TableKeyEnum.TASK_SCHEDULE_TASK_API_SCENARIO_PROJECT,
},
};
const groupColumnsMap: Record<string, any> = {
system: {
API_IMPORT: [
getOrgColumns(),
getProjectColumns(tableKeyMap[props.group][props.moduleType]),
...resourceColumns,
...swaggerUrlColumn,
...staticColumns,
],
API_SCENARIO: [
getOrgColumns(),
getProjectColumns(tableKeyMap[props.group][props.moduleType]),
...resourceColumns,
...staticColumns,
],
},
organization: {
API_IMPORT: [
getProjectColumns(tableKeyMap[props.group][props.moduleType]),
...resourceColumns,
...swaggerUrlColumn,
...staticColumns,
],
API_SCENARIO: [
getProjectColumns(tableKeyMap[props.group][props.moduleType]),
...resourceColumns,
...staticColumns,
],
},
project: {
API_IMPORT: [...resourceColumns, ...swaggerUrlColumn, ...staticColumns],
API_SCENARIO: [...resourceColumns, ...staticColumns],
},
};
const orgFilterVisible = ref<boolean>(false);
const projectFilterVisible = ref<boolean>(false);
const orgApiCaseFilter = ref([]);
const orgApiScenarioFilter = ref([]);
@ -413,13 +387,10 @@
const hasJumpPermission = computed(() => hasAnyPermission(permissionsMap[props.group][props.moduleType].jump));
const licenseStore = useLicenseStore();
const xPack = computed(() => licenseStore.hasLicense());
const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector } = useTable(
const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector, resetFilterParams } = useTable(
loadRealMap.value[props.group].list,
{
tableKey: groupColumnsMap[props.group][props.moduleType].key,
tableKey: tableKeyMap[props.group][props.moduleType],
scroll: {
x: 1200,
},
@ -440,10 +411,6 @@
setLoadListParams({
keyword: keyword.value,
scheduleTagType: props.moduleType,
filter: {
organizationIds: orgFiltersMap.value[props.moduleType],
projectIds: projectFiltersMap.value[props.moduleType],
},
});
loadList();
}
@ -570,10 +537,7 @@
excludeIds,
condition: {
keyword: keyword.value,
filter: {
organizationIds: orgFiltersMap.value[props.moduleType],
projectIds: projectFiltersMap.value[props.moduleType],
},
filter: propsRes.value.filter,
},
});
resetSelector();
@ -649,8 +613,8 @@
);
await tableStore.initColumn(
groupColumnsMap[props.group][props.moduleType].key,
groupColumnsMap[props.group][props.moduleType].columns,
tableKeyMap[props.group][props.moduleType],
groupColumnsMap[props.group][props.moduleType],
'drawer',
true
);
@ -660,7 +624,8 @@
() => props.moduleType,
(val) => {
if (val) {
tableRef.value.initColumn(groupColumnsMap[props.group][props.moduleType].columns);
resetFilterParams();
tableRef.value.initColumn(groupColumnsMap[props.group][props.moduleType]);
}
}
);

View File

@ -28,9 +28,10 @@
import { useI18n } from '@/hooks/useI18n';
import type { ResourceTypeMapKey } from '@/enums/taskCenter';
import { TaskCenterEnum } from '@/enums/taskCenter';
import type { ResourceTypeMapKey } from './utils';
import type { ExtractedKeys } from './utils';
const { t } = useI18n();
@ -77,7 +78,7 @@
]);
const activeTask = ref(route.query.tab || 'real');
const activeTab = ref<ResourceTypeMapKey>((route.query.type as ResourceTypeMapKey) || TaskCenterEnum.API_CASE);
const activeTab = ref<ExtractedKeys>((route.query.type as ExtractedKeys) || TaskCenterEnum.API_CASE);
const rightTabList = computed(() => {
return activeTask.value === 'real' ? realTabList.value : timingTabList.value;

View File

@ -1,148 +1,159 @@
import type { MsTableColumn } from '@/components/pure/ms-table/type';
import type { MsTableColumnData } from '@/components/pure/ms-table/type';
import { useI18n } from '@/hooks/useI18n';
import { useAppStore } from '@/store';
import useLicenseStore from '@/store/modules/setting/license';
import { hasAnyPermission } from '@/utils/permission';
import { TableKeyEnum } from '@/enums/tableEnum';
import { FilterRemoteMethodsEnum } from '@/enums/tableFilterEnum';
import type { ResourceTypeMapKey } from '@/enums/taskCenter';
import { TaskCenterEnum } from '@/enums/taskCenter';
export const TaskStatus = {
const appStore = useAppStore();
const licenseStore = useLicenseStore();
const { t } = useI18n();
export const TaskStatus: Record<ResourceTypeMapKey, Record<string, { icon: string; label: string; color?: string }>> = {
[TaskCenterEnum.API_CASE]: {
SUCCESS: {
icon: 'icon-icon_succeed_colorful',
label: 'project.taskCenter.successful',
label: t('project.taskCenter.successful'),
},
ERROR: {
icon: 'icon-icon_close_colorful',
label: 'project.taskCenter.failure',
label: t('project.taskCenter.failure'),
},
FAKE_ERROR: {
icon: 'icon-icon_warning_colorful',
label: 'project.taskCenter.falseAlarm',
label: t('project.taskCenter.falseAlarm'),
},
STOPPED: {
icon: 'icon-icon_block_filled',
label: 'project.taskCenter.stop',
label: t('project.taskCenter.stop'),
color: '!var(--color-text-input-border)',
},
RUNNING: {
icon: 'icon-icon_testing',
label: 'project.taskCenter.inExecution',
label: t('project.taskCenter.inExecution'),
color: '!text-[rgb(var(--link-6))]',
},
// RERUNNING: {
// icon: 'icon-icon_testing',
// label: 'project.taskCenter.rerun',
// label: t('project.taskCenter.rerun',
// color: '!text-[rgb(var(--link-6))]',
// },
PENDING: {
icon: 'icon-icon_wait',
label: 'project.taskCenter.queuing',
label: t('project.taskCenter.queuing'),
color: '!text-[rgb(var(--link-6))]',
},
},
[TaskCenterEnum.API_SCENARIO]: {
SUCCESS: {
icon: 'icon-icon_succeed_colorful',
label: 'project.taskCenter.successful',
label: t('project.taskCenter.successful'),
},
ERROR: {
icon: 'icon-icon_close_colorful',
label: 'project.taskCenter.failure',
label: t('project.taskCenter.failure'),
},
FAKE_ERROR: {
icon: 'icon-icon_warning_colorful',
label: 'project.taskCenter.falseAlarm',
label: t('project.taskCenter.falseAlarm'),
},
STOPPED: {
icon: 'icon-icon_block_filled',
label: 'project.taskCenter.stop',
label: t('project.taskCenter.stop'),
color: 'var(--color-text-input-border)',
},
RUNNING: {
icon: 'icon-icon_testing',
label: 'project.taskCenter.inExecution',
label: t('project.taskCenter.inExecution'),
color: '!text-[rgb(var(--link-6))]',
},
// RERUNNING: {
// icon: 'icon-icon_testing',
// label: 'project.taskCenter.rerun',
// label: t('project.taskCenter.rerun',
// color: '!text-[rgb(var(--link-6))]',
// },
PENDING: {
icon: 'icon-icon_wait',
label: 'project.taskCenter.queuing',
label: t('project.taskCenter.queuing'),
color: '!text-[rgb(var(--link-6))]',
},
},
[TaskCenterEnum.LOAD_TEST]: {
STARTING: {
icon: 'icon-icon_restarting',
label: 'project.taskCenter.starting',
label: t('project.taskCenter.starting'),
color: '!text-[rgb(var(--link-6))]',
},
RUNNING: {
icon: 'icon-icon_testing',
label: 'project.taskCenter.inExecution',
label: t('project.taskCenter.inExecution'),
color: '!text-[rgb(var(--link-6))]',
},
ERROR: {
icon: 'icon-icon_close_colorful',
label: 'project.taskCenter.failure',
label: t('project.taskCenter.failure'),
},
SUCCESS: {
icon: 'icon-icon_succeed_colorful',
label: 'project.taskCenter.successful',
label: t('project.taskCenter.successful'),
},
COMPLETED: {
icon: 'icon-icon_succeed_colorful',
label: 'project.taskCenter.complete',
label: t('project.taskCenter.complete'),
},
STOPPED: {
icon: 'icon-icon_block_filled',
label: 'project.taskCenter.stop',
label: t('project.taskCenter.stop'),
color: 'var(--color-text-input-border)',
},
},
[TaskCenterEnum.UI_TEST]: {
PENDING: {
icon: 'icon-icon_wait',
label: 'project.taskCenter.queuing',
label: t('project.taskCenter.queuing'),
color: '!text-[rgb(var(--link-6))]',
},
RUNNING: {
icon: 'icon-icon_testing',
label: 'project.taskCenter.inExecution',
label: t('project.taskCenter.inExecution'),
color: '!text-[rgb(var(--link-6))]',
},
// RERUNNING: {
// icon: 'icon-icon_testing',
// label: 'project.taskCenter.rerun',
// label: t('project.taskCenter.rerun',
// color: '!text-[rgb(var(--link-6))]',
// },
ERROR: {
icon: 'icon-icon_close_colorful',
label: 'project.taskCenter.failure',
label: t('project.taskCenter.failure'),
},
SUCCESS: {
icon: 'icon-icon_succeed_colorful',
label: 'project.taskCenter.successful',
label: t('project.taskCenter.successful'),
},
STOPPED: {
icon: 'icon-icon_block_filled',
label: 'project.taskCenter.stop',
label: t('project.taskCenter.stop'),
color: 'var(--color-text-input-border)',
},
},
[TaskCenterEnum.TEST_PLAN]: {
RUNNING: {
icon: 'icon-icon_testing',
label: 'project.taskCenter.queuing',
label: t('project.taskCenter.queuing'),
color: '!text-[rgb(var(--link-6))]',
},
SUCCESS: {
icon: 'icon-icon_succeed_colorful',
label: 'project.taskCenter.successful',
label: t('project.taskCenter.successful'),
},
STARTING: {
icon: 'icon-icon_restarting',
label: 'project.taskCenter.starting',
label: t('project.taskCenter.starting'),
color: '!text-[rgb(var(--link-6))]',
},
},
@ -150,57 +161,82 @@ export const TaskStatus = {
export type Group = 'system' | 'organization' | 'project';
export type ResourceTypeMapKey =
| TaskCenterEnum.API_CASE
| TaskCenterEnum.API_SCENARIO
| TaskCenterEnum.UI_TEST
| TaskCenterEnum.LOAD_TEST
| TaskCenterEnum.TEST_PLAN;
export type ExtractedKeys = Extract<ResourceTypeMapKey, TaskCenterEnum.API_CASE | TaskCenterEnum.API_SCENARIO>;
export const resourceTypeMap: Record<ResourceTypeMapKey, Record<string, any>> = {
[TaskCenterEnum.API_CASE]: {
value: TaskCenterEnum.API_CASE,
label: 'project.taskCenter.interfaceCase',
label: t('project.taskCenter.interfaceCase'),
},
[TaskCenterEnum.API_SCENARIO]: {
value: TaskCenterEnum.API_SCENARIO,
label: 'project.taskCenter.apiScenario',
label: t('project.taskCenter.apiScenario'),
},
[TaskCenterEnum.UI_TEST]: {
value: TaskCenterEnum.UI_TEST,
label: 'project.taskCenter.uiDefaultFile',
label: t('project.taskCenter.uiDefaultFile'),
},
[TaskCenterEnum.LOAD_TEST]: {
value: TaskCenterEnum.LOAD_TEST,
label: 'project.taskCenter.performanceTest',
label: t('project.taskCenter.performanceTest'),
},
[TaskCenterEnum.TEST_PLAN]: {
value: TaskCenterEnum.TEST_PLAN,
label: 'project.taskCenter.testPlan',
label: t('project.taskCenter.testPlan'),
},
};
export const ordAndProjectColumn: MsTableColumn = [
{
export function getOrgColumns(): MsTableColumnData {
const config: MsTableColumnData = {
title: 'project.belongOrganization',
dataIndex: 'organizationName',
dataIndex: 'organizationIds',
slotName: 'organizationName',
titleSlotName: 'orgFilterName',
showTooltip: true,
showDrag: true,
width: 200,
showInTable: true,
},
{
title: 'project.belongProject',
dataIndex: 'projectName',
slotName: 'projectName',
titleSlotName: 'projectFilterName',
showTooltip: true,
showDrag: true,
width: 200,
showInTable: true,
},
};
if (licenseStore.hasLicense()) {
config.filterConfig = {
mode: 'remote',
remoteMethod: FilterRemoteMethodsEnum.SYSTEM_ORGANIZATION_LIST,
placeholderText: t('project.taskCenter.filterOrgPlaceholderText'),
};
}
return config;
}
export function getProjectColumns(key: TableKeyEnum): MsTableColumnData {
const systemKey = [
TableKeyEnum.TASK_API_CASE_SYSTEM,
TableKeyEnum.TASK_SCHEDULE_TASK_API_IMPORT_SYSTEM,
TableKeyEnum.TASK_SCHEDULE_TASK_API_SCENARIO_SYSTEM,
];
const filterKeyPermission = systemKey.includes(key)
? hasAnyPermission(['SYSTEM_ORGANIZATION_PROJECT:READ'])
: hasAnyPermission(['ORGANIZATION_PROJECT:READ']);
const remoteMethod = systemKey.includes(key)
? FilterRemoteMethodsEnum.SYSTEM_PROJECT_LIST
: FilterRemoteMethodsEnum.SYSTEM_ORGANIZATION_PROJECT;
const config: MsTableColumnData = {
title: 'project.belongProject',
dataIndex: 'projectIds',
slotName: 'projectName',
showDrag: true,
width: 200,
showInTable: true,
};
if (filterKeyPermission && remoteMethod) {
config.filterConfig = {
mode: 'remote',
loadOptionParams: {
organizationId: appStore.currentOrgId,
},
remoteMethod,
placeholderText: t('project.taskCenter.filterProPlaceholderText'),
};
}
return config;
}
export default {};