feat(缺陷管理): 缺陷管理回收站增加部分筛选字段和排序字段
--bug=1036456 --user=宋天阳 【缺陷管理】回收站列表,部分字段表头需支持筛选和排序 https://www.tapd.cn/55049933/s/1472938
This commit is contained in:
parent
da550b75f7
commit
0a902b5781
|
@ -169,6 +169,16 @@
|
||||||
and b.handle_user in
|
and b.handle_user in
|
||||||
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
|
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
|
||||||
</when>
|
</when>
|
||||||
|
<!-- 删除人 -->
|
||||||
|
<when test="key == 'deleteUser'">
|
||||||
|
and b.delete_user in
|
||||||
|
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
|
||||||
|
</when>
|
||||||
|
<!-- 更新人 -->
|
||||||
|
<when test="key == 'updateUser'">
|
||||||
|
and b.update_user in
|
||||||
|
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
|
||||||
|
</when>
|
||||||
<!-- 创建人 -->
|
<!-- 创建人 -->
|
||||||
<when test="key == 'createUser'">
|
<when test="key == 'createUser'">
|
||||||
and b.create_user in
|
and b.create_user in
|
||||||
|
|
|
@ -758,12 +758,6 @@
|
||||||
sort.value = sortObj;
|
sort.value = sortObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function searchData() {
|
|
||||||
// eslint-disable-next-line no-use-before-define
|
|
||||||
setLoadListParams(initTableParams());
|
|
||||||
await loadList();
|
|
||||||
}
|
|
||||||
|
|
||||||
function initTableParams() {
|
function initTableParams() {
|
||||||
const filterParams = {
|
const filterParams = {
|
||||||
status: statusFilterValue.value,
|
status: statusFilterValue.value,
|
||||||
|
@ -782,6 +776,12 @@
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function searchData() {
|
||||||
|
setLoadListParams(initTableParams());
|
||||||
|
loadList();
|
||||||
|
}
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
setProps({ heightUsed: heightUsed.value });
|
setProps({ heightUsed: heightUsed.value });
|
||||||
});
|
});
|
||||||
|
|
|
@ -28,26 +28,120 @@
|
||||||
}}</MsButton>
|
}}</MsButton>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template #createUserFilter="{ columnConfig }">
|
||||||
|
<TableFilter
|
||||||
|
v-model:visible="createUserFilterVisible"
|
||||||
|
v-model:status-filters="createUserFilterValue"
|
||||||
|
:title="(columnConfig.title as string)"
|
||||||
|
:list="createUserFilterOptions"
|
||||||
|
value-key="value"
|
||||||
|
@search="searchData()"
|
||||||
|
>
|
||||||
|
<template #item="{ item }">
|
||||||
|
{{ item.text }}
|
||||||
|
</template>
|
||||||
|
</TableFilter>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #updateUserFilter="{ columnConfig }">
|
||||||
|
<TableFilter
|
||||||
|
v-model:visible="updateUserFilterVisible"
|
||||||
|
v-model:status-filters="updateUserFilterValue"
|
||||||
|
:title="(columnConfig.title as string)"
|
||||||
|
:list="updateUserFilterOptions"
|
||||||
|
value-key="value"
|
||||||
|
@search="searchData()"
|
||||||
|
>
|
||||||
|
<template #item="{ item }">
|
||||||
|
{{ item.text }}
|
||||||
|
</template>
|
||||||
|
</TableFilter>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #deleteUserFilter="{ columnConfig }">
|
||||||
|
<TableFilter
|
||||||
|
v-model:visible="deleteUserFilterVisible"
|
||||||
|
v-model:status-filters="deleteUserFilterValue"
|
||||||
|
:title="(columnConfig.title as string)"
|
||||||
|
:list="deleteUserFilterOptions"
|
||||||
|
value-key="value"
|
||||||
|
@search="searchData()"
|
||||||
|
>
|
||||||
|
<template #item="{ item }">
|
||||||
|
{{ item.text }}
|
||||||
|
</template>
|
||||||
|
</TableFilter>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #handleUserFilter="{ columnConfig }">
|
||||||
|
<TableFilter
|
||||||
|
v-model:visible="handleUserFilterVisible"
|
||||||
|
v-model:status-filters="handleUserFilterValue"
|
||||||
|
:title="(columnConfig.title as string)"
|
||||||
|
:list="handleUserFilterOptions"
|
||||||
|
value-key="value"
|
||||||
|
@search="searchData()"
|
||||||
|
>
|
||||||
|
<template #item="{ item }">
|
||||||
|
{{ item.text }}
|
||||||
|
</template>
|
||||||
|
</TableFilter>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #statusFilter="{ columnConfig }">
|
||||||
|
<TableFilter
|
||||||
|
v-model:visible="statusFilterVisible"
|
||||||
|
v-model:status-filters="statusFilterValue"
|
||||||
|
:title="(columnConfig.title as string)"
|
||||||
|
:list="statusFilterOptions"
|
||||||
|
value-key="value"
|
||||||
|
@search="searchData()"
|
||||||
|
>
|
||||||
|
<template #item="{ item }">
|
||||||
|
{{ item.text }}
|
||||||
|
</template>
|
||||||
|
</TableFilter>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #severityFilter="{ columnConfig }">
|
||||||
|
<TableFilter
|
||||||
|
v-model:visible="severityFilterVisible"
|
||||||
|
v-model:status-filters="severityFilterValue"
|
||||||
|
:title="(columnConfig.title as string)"
|
||||||
|
:list="severityFilterOptions"
|
||||||
|
value-key="value"
|
||||||
|
@search="searchData()"
|
||||||
|
>
|
||||||
|
<template #item="{ item }">
|
||||||
|
{{ item.text }}
|
||||||
|
</template>
|
||||||
|
</TableFilter>
|
||||||
|
</template>
|
||||||
|
|
||||||
<template #empty> </template>
|
<template #empty> </template>
|
||||||
</MsBaseTable>
|
</MsBaseTable>
|
||||||
</MsCard>
|
</MsCard>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" async setup>
|
<script lang="ts" async setup>
|
||||||
import { Message } from '@arco-design/web-vue';
|
import { ref } from 'vue';
|
||||||
import dayjs from 'dayjs';
|
import { Message, TableData } from '@arco-design/web-vue';
|
||||||
|
|
||||||
import { MsAdvanceFilter } from '@/components/pure/ms-advance-filter';
|
import { MsAdvanceFilter } from '@/components/pure/ms-advance-filter';
|
||||||
import { FilterFormItem, FilterType } from '@/components/pure/ms-advance-filter/type';
|
import { BackEndEnum, FilterFormItem, FilterType } from '@/components/pure/ms-advance-filter/type';
|
||||||
import MsButton from '@/components/pure/ms-button/index.vue';
|
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||||
import MsCard from '@/components/pure/ms-card/index.vue';
|
import MsCard from '@/components/pure/ms-card/index.vue';
|
||||||
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
||||||
import { BatchActionParams, BatchActionQueryParams, MsTableColumn } from '@/components/pure/ms-table/type';
|
import { BatchActionParams, BatchActionQueryParams, MsTableColumn } from '@/components/pure/ms-table/type';
|
||||||
import useTable from '@/components/pure/ms-table/useTable';
|
import useTable from '@/components/pure/ms-table/useTable';
|
||||||
|
import TableFilter from '@/views/case-management/caseManagementFeature/components/tableFilter.vue';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
deleteBatchByRecycle,
|
deleteBatchByRecycle,
|
||||||
deleteSingleByRecycle,
|
deleteSingleByRecycle,
|
||||||
|
getCustomFieldHeader,
|
||||||
|
getCustomOptionHeader,
|
||||||
getRecycleList,
|
getRecycleList,
|
||||||
recoverBatchByRecycle,
|
recoverBatchByRecycle,
|
||||||
recoverSingleByRecycle,
|
recoverSingleByRecycle,
|
||||||
|
@ -55,9 +149,14 @@
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useModal from '@/hooks/useModal';
|
import useModal from '@/hooks/useModal';
|
||||||
import { useAppStore, useTableStore } from '@/store';
|
import { useAppStore, useTableStore } from '@/store';
|
||||||
import { characterLimit, tableParamsToRequestParams } from '@/utils';
|
import {
|
||||||
|
characterLimit,
|
||||||
|
customFieldDataToTableData,
|
||||||
|
customFieldToColumns,
|
||||||
|
tableParamsToRequestParams,
|
||||||
|
} from '@/utils';
|
||||||
|
|
||||||
import { BugListItem } from '@/models/bug-management';
|
import { BugEditCustomField, BugListItem, BugOptionItem } from '@/models/bug-management';
|
||||||
import { TableKeyEnum } from '@/enums/tableEnum';
|
import { TableKeyEnum } from '@/enums/tableEnum';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
@ -68,6 +167,8 @@
|
||||||
const filterVisible = ref(false);
|
const filterVisible = ref(false);
|
||||||
const filterRowCount = ref(0);
|
const filterRowCount = ref(0);
|
||||||
const keyword = ref('');
|
const keyword = ref('');
|
||||||
|
// 自定义字段
|
||||||
|
const customFields = ref<BugEditCustomField[]>([]);
|
||||||
const filterConfigList = reactive<FilterFormItem[]>([
|
const filterConfigList = reactive<FilterFormItem[]>([
|
||||||
{
|
{
|
||||||
title: 'bugManagement.ID',
|
title: 'bugManagement.ID',
|
||||||
|
@ -76,11 +177,9 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'bugManagement.bugName',
|
title: 'bugManagement.bugName',
|
||||||
dataIndex: 'name',
|
dataIndex: 'title',
|
||||||
type: FilterType.SELECT,
|
type: FilterType.INPUT,
|
||||||
selectProps: {
|
backendType: BackEndEnum.STRING,
|
||||||
mode: 'static',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'bugManagement.createTime',
|
title: 'bugManagement.createTime',
|
||||||
|
@ -89,6 +188,27 @@
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// 表头筛选
|
||||||
|
const createUserFilterOptions = ref<BugOptionItem[]>([]);
|
||||||
|
const createUserFilterVisible = ref(false);
|
||||||
|
const createUserFilterValue = ref<string[]>([]);
|
||||||
|
const updateUserFilterOptions = ref<BugOptionItem[]>([]);
|
||||||
|
const updateUserFilterVisible = ref(false);
|
||||||
|
const updateUserFilterValue = ref<string[]>([]);
|
||||||
|
const handleUserFilterOptions = ref<BugOptionItem[]>([]);
|
||||||
|
const handleUserFilterVisible = ref(false);
|
||||||
|
const handleUserFilterValue = ref<string[]>([]);
|
||||||
|
const deleteUserFilterOptions = ref<BugOptionItem[]>([]);
|
||||||
|
const deleteUserFilterVisible = ref(false);
|
||||||
|
const deleteUserFilterValue = ref<string[]>([]);
|
||||||
|
const statusFilterOptions = ref<BugOptionItem[]>([]);
|
||||||
|
const statusFilterVisible = ref(false);
|
||||||
|
const statusFilterValue = ref<string[]>([]);
|
||||||
|
const severityFilterOptions = ref<BugOptionItem[]>([]);
|
||||||
|
const severityFilterVisible = ref(false);
|
||||||
|
const severityFilterValue = ref<string[]>([]);
|
||||||
|
const severityColumnId = ref('');
|
||||||
|
|
||||||
const heightUsed = computed(() => 286 + (filterVisible.value ? 160 + (filterRowCount.value - 1) * 60 : 0));
|
const heightUsed = computed(() => 286 + (filterVisible.value ? 160 + (filterRowCount.value - 1) * 60 : 0));
|
||||||
|
|
||||||
const columns: MsTableColumn = [
|
const columns: MsTableColumn = [
|
||||||
|
@ -96,12 +216,22 @@
|
||||||
title: 'bugManagement.recycle.deleteTime',
|
title: 'bugManagement.recycle.deleteTime',
|
||||||
dataIndex: 'deleteTime',
|
dataIndex: 'deleteTime',
|
||||||
showDrag: true,
|
showDrag: true,
|
||||||
width: 180,
|
width: 199,
|
||||||
|
sortable: {
|
||||||
|
sortDirections: ['ascend', 'descend'],
|
||||||
|
sorter: true,
|
||||||
|
},
|
||||||
|
showInTable: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'bugManagement.recycle.deleteMan',
|
title: 'bugManagement.recycle.deleteMan',
|
||||||
dataIndex: 'deleteUserName',
|
dataIndex: 'deleteUserName',
|
||||||
|
width: 112,
|
||||||
showDrag: true,
|
showDrag: true,
|
||||||
|
slotName: 'deleteUser',
|
||||||
|
showTooltip: true,
|
||||||
|
titleSlotName: 'deleteUserFilter',
|
||||||
|
showInTable: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'bugManagement.ID',
|
title: 'bugManagement.ID',
|
||||||
|
@ -128,21 +258,72 @@
|
||||||
columnSelectorDisabled: true,
|
columnSelectorDisabled: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'bugManagement.creator',
|
title: 'bugManagement.handleMan',
|
||||||
dataIndex: 'createUserName',
|
dataIndex: 'handleUser',
|
||||||
showDrag: true,
|
slotName: 'handleUser',
|
||||||
showTooltip: true,
|
showTooltip: true,
|
||||||
|
titleSlotName: 'handleUserFilter',
|
||||||
|
width: 112,
|
||||||
|
showDrag: true,
|
||||||
|
showInTable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'bugManagement.creator',
|
||||||
|
dataIndex: 'createUser',
|
||||||
|
slotName: 'createUser',
|
||||||
|
width: 112,
|
||||||
|
showTooltip: true,
|
||||||
|
showDrag: true,
|
||||||
|
titleSlotName: 'createUserFilter',
|
||||||
|
sortable: {
|
||||||
|
sortDirections: ['ascend', 'descend'],
|
||||||
|
sorter: true,
|
||||||
|
},
|
||||||
|
showInTable: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'bugManagement.createTime',
|
title: 'bugManagement.createTime',
|
||||||
dataIndex: 'createTime',
|
dataIndex: 'createTime',
|
||||||
showDrag: true,
|
showDrag: true,
|
||||||
width: 180,
|
width: 199,
|
||||||
|
sortable: {
|
||||||
|
sortDirections: ['ascend', 'descend'],
|
||||||
|
sorter: true,
|
||||||
|
},
|
||||||
|
showInTable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'bugManagement.updateUser',
|
||||||
|
dataIndex: 'updateUser',
|
||||||
|
width: 112,
|
||||||
|
showTooltip: true,
|
||||||
|
showDrag: true,
|
||||||
|
titleSlotName: 'updateUserFilter',
|
||||||
|
sortable: {
|
||||||
|
sortDirections: ['ascend', 'descend'],
|
||||||
|
sorter: true,
|
||||||
|
},
|
||||||
|
showInTable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'bugManagement.updateTime',
|
||||||
|
dataIndex: 'updateTime',
|
||||||
|
showDrag: true,
|
||||||
|
width: 199,
|
||||||
|
sortable: {
|
||||||
|
sortDirections: ['ascend', 'descend'],
|
||||||
|
sorter: true,
|
||||||
|
},
|
||||||
|
showInTable: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'bugManagement.status',
|
title: 'bugManagement.status',
|
||||||
dataIndex: 'statusName',
|
dataIndex: 'statusName',
|
||||||
|
width: 84,
|
||||||
|
slotName: 'status',
|
||||||
|
titleSlotName: 'statusFilter',
|
||||||
showDrag: true,
|
showDrag: true,
|
||||||
|
showInTable: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'bugManagement.handleMan',
|
title: 'bugManagement.handleMan',
|
||||||
|
@ -153,6 +334,7 @@
|
||||||
{
|
{
|
||||||
title: 'bugManagement.tag',
|
title: 'bugManagement.tag',
|
||||||
showDrag: true,
|
showDrag: true,
|
||||||
|
width: 456,
|
||||||
isStringTag: true,
|
isStringTag: true,
|
||||||
dataIndex: 'tags',
|
dataIndex: 'tags',
|
||||||
},
|
},
|
||||||
|
@ -164,7 +346,42 @@
|
||||||
width: 150,
|
width: 150,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
await tableStore.initColumn(TableKeyEnum.BUG_MANAGEMENT_RECYCLE, columns, 'drawer');
|
|
||||||
|
// 获取自定义字段
|
||||||
|
const getCustomFieldColumns = async () => {
|
||||||
|
const res = await getCustomFieldHeader(projectId.value);
|
||||||
|
customFields.value = res;
|
||||||
|
|
||||||
|
// 实例化自定义字段的filters
|
||||||
|
customFields.value.forEach((item) => {
|
||||||
|
if ((item.fieldName === '严重程度' || item.fieldName === 'Bug Degree') && item.options) {
|
||||||
|
severityFilterOptions.value = [];
|
||||||
|
severityColumnId.value = `custom_single_${item.fieldId}`;
|
||||||
|
item.options.forEach((option) => {
|
||||||
|
severityFilterOptions.value.push({
|
||||||
|
value: option.value,
|
||||||
|
text: option.text,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return customFieldToColumns(res);
|
||||||
|
};
|
||||||
|
|
||||||
|
const customColumns = await getCustomFieldColumns();
|
||||||
|
|
||||||
|
customColumns.forEach((item) => {
|
||||||
|
if (item.title === '严重程度' || item.title === 'Bug Degree') {
|
||||||
|
item.showInTable = true;
|
||||||
|
item.titleSlotName = 'severityFilter';
|
||||||
|
item.slotName = 'severity';
|
||||||
|
} else {
|
||||||
|
item.showInTable = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await tableStore.initColumn(TableKeyEnum.BUG_MANAGEMENT_RECYCLE, columns.concat(customColumns), 'drawer');
|
||||||
|
|
||||||
const { propsRes, propsEvent, loadList, setKeyword, setLoadListParams, setProps } = useTable(
|
const { propsRes, propsEvent, loadList, setKeyword, setLoadListParams, setProps } = useTable(
|
||||||
getRecycleList,
|
getRecycleList,
|
||||||
|
@ -175,10 +392,13 @@
|
||||||
showSetting: true,
|
showSetting: true,
|
||||||
scroll: { x: '1900px' },
|
scroll: { x: '1900px' },
|
||||||
},
|
},
|
||||||
(record) => {
|
(record: TableData) => ({
|
||||||
record.deleteTime = dayjs(record.deleteTime).format('YYYY-MM-DD HH:mm:ss');
|
...record,
|
||||||
return record;
|
handleUser: record.handleUserName,
|
||||||
}
|
createUser: record.createUserName,
|
||||||
|
updateUser: record.updateUserName,
|
||||||
|
...customFieldDataToTableData(record.customFields, customFields.value),
|
||||||
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const tableAction = {
|
const tableAction = {
|
||||||
|
@ -280,8 +500,43 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function initTableParams() {
|
||||||
|
const filterParams = {
|
||||||
|
status: statusFilterValue.value,
|
||||||
|
handleUser: handleUserFilterValue.value,
|
||||||
|
updateUser: updateUserFilterValue.value,
|
||||||
|
createUser: createUserFilterValue.value,
|
||||||
|
deleteUser: deleteUserFilterValue.value,
|
||||||
|
};
|
||||||
|
filterParams[severityColumnId.value] = severityFilterValue.value;
|
||||||
|
return {
|
||||||
|
keyword: keyword.value,
|
||||||
|
projectId: projectId.value,
|
||||||
|
filter: { ...filterParams },
|
||||||
|
condition: {
|
||||||
|
keyword: keyword.value,
|
||||||
|
filter: propsRes.value.filter,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function searchData() {
|
||||||
|
setLoadListParams(initTableParams());
|
||||||
|
loadList();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function initFilterOptions() {
|
||||||
|
const res = await getCustomOptionHeader(appStore.currentProjectId);
|
||||||
|
createUserFilterOptions.value = res.userOption;
|
||||||
|
updateUserFilterOptions.value = res.userOption;
|
||||||
|
deleteUserFilterOptions.value = res.userOption;
|
||||||
|
handleUserFilterOptions.value = res.handleUserOption;
|
||||||
|
statusFilterOptions.value = res.statusOption;
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
setLoadListParams({ projectId: projectId.value });
|
setLoadListParams({ projectId: projectId.value });
|
||||||
|
initFilterOptions();
|
||||||
fetchData();
|
fetchData();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<a-trigger v-model:popup-visible="innerVisible" trigger="click" @popup-visible-change="handleFilterHidden">
|
<a-trigger v-model:popup-visible="innerVisible" trigger="click" @popup-visible-change="handleFilterHidden">
|
||||||
<a-button type="text" class="arco-btn-text--secondary p-[8px_4px]" @click="innerVisible = true">
|
<a-button type="text" class="arco-btn-text--secondary p-[8px_4px]" @click.stop="innerVisible = true">
|
||||||
<div class="font-medium">
|
<div class="font-medium">
|
||||||
{{ t(props.title) }}
|
{{ t(props.title) }}
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue