feat: 修改table过滤筛选样式和新增过滤筛选自定义内容(还未统一替换完)_测试计划

This commit is contained in:
xinxin.wu 2024-05-11 10:47:19 +08:00 committed by Craftsman
parent 725f46d0f0
commit a3394c7a24
8 changed files with 129 additions and 93 deletions

View File

@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2 3C2 2.44772 2.44772 2 3 2H13C13.5523 2 14 2.44772 14 3V4.78597L9.75 7.28597V14H6.25V7.28597L2 4.78597V3ZM13 3H3V4.21403L7.25 6.71403V13H8.75V6.71403L13 4.21403V3Z" fill="#783887"/>
</svg>

After

Width:  |  Height:  |  Size: 296 B

View File

@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2 3C2 2.44772 2.44772 2 3 2H13C13.5523 2 14 2.44772 14 3V4.78597L9.75 7.28597V14H6.25V7.28597L2 4.78597V3ZM13 3H3V4.21403L7.25 6.71403V13H8.75V6.71403L13 4.21403V3Z" fill="#7D7D7F"/>
</svg>

After

Width:  |  Height:  |  Size: 296 B

View File

@ -66,7 +66,9 @@
:sortable="item.sortable"
:filterable="item.filterable"
:cell-class="item.cellClass"
:header-cell-class="item.headerCellClass"
:header-cell-class="`${
item.headerCellClass || (item.filterConfig && isHeighten) ? 'header-cell-filter' : ''
}`"
:body-cell-class="item.bodyCellClass"
:summary-cell-class="item.summaryCellClass"
:cell-style="item.cellStyle"
@ -80,7 +82,13 @@
<template #title>
<div :class="{ 'flex w-full flex-row flex-nowrap items-center gap-[4px]': !item.align }">
<slot :name="item.titleSlotName" :column-config="item">
<div v-if="item.title" class="text-[var(--color-text-3)]">{{ t(item.title as string) }}</div>
<div
v-if="item.title"
:class="`${
item.filterConfig && isHeighten ? 'text-[rgb(var(--primary-5))]' : 'text-[var(--color-text-3)]'
} pl-1`"
>{{ t(item.title as string) }}</div
>
</slot>
<columnSelectorIcon
v-if="
@ -92,22 +100,18 @@
@show-setting="handleShowSetting"
@init-data="handleInitColumn"
/>
<slot v-else-if="item.filterConfig" :name="item.filterConfig.filterSlotName">
<!-- <DefaultFilter
<DefaultFilter
v-else-if="item.filterConfig"
class="ml-[4px]"
:options="item.filterConfig.options"
@handle-confirm="(v) => handleFilterConfirm(v, item.dataIndex as string, item.isCustomParam || false)"
/> -->
<!-- TODO 待办 过滤选项不生效 -->
<!-- <TableFilter
v-bind="item.filterConfig"
@handle-confirm="(v) => handleFilterConfirm(v, item.dataIndex as string,item.isCustomParam || false)"
@show="showFilter(true)"
@hide="showFilter(false)"
>
<template #item="{ item: itemValue, index }">
<slot name="filter-content" :item="itemValue" :index="index"> </slot>
<template #item="{ filterItem }">
<slot :name="item.filterConfig.filterSlotName" :filter-content="filterItem"> </slot>
</template>
</TableFilter> -->
</slot>
</DefaultFilter>
</div>
</template>
<template #cell="{ column, record, rowIndex }">
@ -280,9 +284,7 @@
import BatchAction from './batchAction.vue';
import ColumnSelector from './columnSelector.vue';
import columnSelectorIcon from './columnSelectorIcon.vue';
// TODO
// import DefaultFilter from './comp/defaultFilter.vue';
// import TableFilter from './comp/tableFilter.vue';
import DefaultFilter from './comp/defaultFilter.vue';
import SelectALL from './select-all.vue';
import { useI18n } from '@/hooks/useI18n';
@ -628,15 +630,20 @@
columnSelectorVisible.value = true;
};
// const handleFilterConfirm = (value: (string | number)[], dataIndex: string, isCustomParam: boolean) => {
// emit('filterChange', dataIndex, value, isCustomParam);
// };
const handleFilterConfirm = (value: (string | number)[], dataIndex: string, isCustomParam: boolean) => {
emit('filterChange', dataIndex, value, isCustomParam);
};
onMounted(async () => {
await initColumn();
batchLeft.value = getBatchLeft();
});
const isHeighten = ref<boolean>(false);
function showFilter(visible: boolean) {
isHeighten.value = visible;
}
watch(
() => props.columns,
() => {
@ -809,6 +816,20 @@
}
}
}
:deep(.header-cell-filter) {
.arco-table-cell-with-filter {
float: left;
border-radius: 4px;
.arco-table-th-title {
border-radius: 4px;
color: rgb(var(--primary-5));
background: rgb(var(--primary-1)) content-box;
.filter-icon {
color: rgb(var(--primary-5)) !important;
}
}
}
}
</style>
<style lang="less">

View File

@ -1,24 +1,36 @@
<template>
<a-trigger v-model:popup-visible="visible" trigger="click">
<a-button type="text" @click="visible = true">
<template #icon>
<icon-filter class="text-[var(--color-text-4)]" />
</template>
</a-button>
<span class="cursor-pointer pr-[2px]" @click="visible = true">
<svg-icon
width="16px"
height="16px"
:name="visible ? 'filter-icon-color' : 'filter-icon'"
class="text-[12px] font-medium text-[rgb(var(--danger-6))]"
/>
</span>
<template #content>
<div class="arco-table-filters-content">
<div class="arco-table-filters-content-list">
<div class="max-h-[300px] overflow-y-auto px-[12px] py-[4px]">
<a-checkbox-group v-if="props.multiple" v-model="checkedList" size="mini" direction="vertical">
<a-checkbox v-for="item in props.options" :key="item.value" :value="item.value">
{{ item.label }}
<a-checkbox-group v-model="checkedList" size="mini" direction="vertical">
<a-checkbox
v-for="(item, index) of props.options"
:key="item[props.valueKey || 'value']"
:value="item[props.valueKey || 'value']"
>
<a-tooltip
:content="item[props.labelKey || 'label']"
:mouse-enter-delay="300"
:disabled="!item[props.labelKey || 'label']"
>
<div class="one-line-text max-w-[120px]">
<slot name="item" :filter-item="item" :index="index">
<div class="one-line-text max-w-[120px]">{{ item[props.labelKey || 'label'] }}</div>
</slot>
</div>
</a-tooltip>
</a-checkbox>
</a-checkbox-group>
<a-radio-group v-else v-model="checkedValue" size="mini" direction="vertical">
<a-radio v-for="item in props.options" :key="item.value" :value="item.value">
{{ item.label }}
</a-radio>
</a-radio-group>
</div>
<div class="arco-table-filters-bottom">
<a-button size="mini" type="secondary" @click="handleFilterReset">
@ -38,9 +50,14 @@
import { useI18n } from '@/hooks/useI18n';
const { t } = useI18n();
export interface FilterListItem {
[key: string]: any;
}
const props = defineProps<{
multiple: boolean;
options?: { label: string; value: string | number }[];
options?: FilterListItem[];
valueKey?: string;
labelKey?: string;
}>();
const emit = defineEmits<{
(e: 'handleConfirm', value: (string | number)[]): void;
@ -49,24 +66,15 @@
const visible = ref(false);
const checkedList = ref<(string | number)[]>([]);
const checkedValue = ref<string | number>('');
const handleFilterReset = () => {
if (props.multiple) {
checkedList.value = [];
} else {
checkedValue.value = '';
}
emit('handleConfirm', []);
visible.value = false;
};
const handleFilterSubmit = () => {
if (props.multiple) {
emit('handleConfirm', checkedList.value);
} else {
emit('handleConfirm', checkedValue.value ? [checkedValue.value] : []);
}
visible.value = false;
};
</script>

View File

@ -1,5 +1,6 @@
import type { TableQueryParams } from '@/models/common';
import { ColumnEditTypeEnum, SelectAllEnum, TableKeyEnum } from '@/enums/tableEnum';
import { FilterSlotNameEnum } from '@/enums/tableFilterEnum';
import type { TableChangeExtra, TableColumnData, TableData, TableDraggable } from '@arco-design/web-vue';
@ -15,13 +16,10 @@ export interface MsPaginationI {
}
export interface MsTableColumnFilterConfig {
filterSlotName?: string; // 筛选组件的slotName
multiple?: boolean; // 是否多选
// 筛选数据
options?: {
label: string;
value: string;
}[];
filterSlotName?: FilterSlotNameEnum; // 筛选组件的slotName @desc 定义枚举是为了table组件内的插槽的filterSlotName 可以精确的让外部组件使用的时候可以拿到插槽作用域的值
options?: Record<string, any>[]; // 筛选数据
valueKey?: string;
labelKey?: string;
}
export interface MsTableColumnData extends TableColumnData {
@ -51,6 +49,8 @@ export interface MsTableColumnData extends TableColumnData {
columnTitle?: string;
// 是否是自定义字段
isCustomParam?: boolean;
// 插槽表格过滤筛选数据item
filterItem?: any;
// 自定义属性
[key: string]: any;
}

View File

@ -0,0 +1,5 @@
export enum FilterSlotNameEnum {
TEST_PLAN_STATUS_FILTER = 'TEST_PLAN_STATUS_FILTER',
}
export default {};

View File

@ -96,40 +96,9 @@
</a-tooltip></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" @click="statusFilterVisible = true">
{{ t(columnConfig.title as string) }}
<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="statusFilters" direction="vertical" size="small">
<a-checkbox v-for="key of Object.keys(planStatusMap)" :key="key" :value="key">
<a-tag
:color="planStatusMap[key as planStatusType].color"
:class="[planStatusMap[key as planStatusType].class, 'px-[4px]']"
size="small"
>
{{ t(planStatusMap[key as planStatusType].label) }}
</a-tag>
</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 #[FilterSlotNameEnum.TEST_PLAN_STATUS_FILTER]="{ filterContent }">
<statusTag :status="filterContent.value" />
</template>
</a-trigger>
</template>
<template #status="{ record }">
<statusTag :status="record.status" />
</template>
@ -298,9 +267,10 @@
import type { planStatusType, TestPlanItem } from '@/models/testPlan/testPlan';
import { TestPlanRouteEnum } from '@/enums/routeEnum';
import { ColumnEditTypeEnum, TableKeyEnum } from '@/enums/tableEnum';
import { FilterSlotNameEnum } from '@/enums/tableFilterEnum';
import { testPlanTypeEnum } from '@/enums/testPlanEnum';
import { planStatusMap } from '../config';
import { planStatusOptions } from '../config';
const tableStore = useTableStore();
const appStore = useAppStore();
@ -358,7 +328,10 @@
title: 'testPlan.testPlanIndex.executionResult',
dataIndex: 'status',
slotName: 'status',
titleSlotName: 'statusFilter',
filterConfig: {
options: planStatusOptions,
filterSlotName: FilterSlotNameEnum.TEST_PLAN_STATUS_FILTER,
},
showInTable: true,
showDrag: true,
width: 150,
@ -610,7 +583,6 @@
selectAll: !!batchParams.value?.selectAll,
selectIds: batchParams.value.selectedIds || [],
keyword: keyword.value,
filter: {},
condition: {
keyword: keyword.value,
},

View File

@ -1,5 +1,9 @@
import { useI18n } from '@/hooks/useI18n';
import type { planStatusType } from '@/models/testPlan/testPlan';
const { t } = useI18n();
export type PlanStatusMap = Record<
planStatusType,
{
@ -8,6 +12,7 @@ export type PlanStatusMap = Record<
class: string;
}
>;
export const planStatusMap: PlanStatusMap = {
PREPARED: {
label: 'caseManagement.caseReview.unStart',
@ -30,3 +35,22 @@ export const planStatusMap: PlanStatusMap = {
class: '!text-[var(--color-text-4)]',
},
};
export const planStatusOptions: { value: planStatusType; label: string }[] = [
{
value: 'PREPARED',
label: t('caseManagement.caseReview.unStart'),
},
{
value: 'UNDERWAY',
label: t('caseManagement.caseReview.going'),
},
{
value: 'COMPLETED',
label: t('caseManagement.caseReview.unStart'),
},
{
value: 'ARCHIVED',
label: t('caseManagement.caseReview.going'),
},
];