feat: 修改table过滤筛选样式和新增过滤筛选自定义内容(还未统一替换完)_测试计划
This commit is contained in:
parent
725f46d0f0
commit
a3394c7a24
|
@ -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 |
|
@ -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 |
|
@ -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">
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
export enum FilterSlotNameEnum {
|
||||
TEST_PLAN_STATUS_FILTER = 'TEST_PLAN_STATUS_FILTER',
|
||||
}
|
||||
|
||||
export default {};
|
|
@ -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,
|
||||
},
|
||||
|
|
|
@ -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'),
|
||||
},
|
||||
];
|
||||
|
|
Loading…
Reference in New Issue