Skip to content

Commit

Permalink
table filter code optimize
Browse files Browse the repository at this point in the history
  • Loading branch information
wangjinpeng1235 committed Aug 13, 2024
1 parent 9433523 commit f26b4a7
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 72 deletions.
2 changes: 1 addition & 1 deletion src/components/base/DictSelect.vue
Original file line number Diff line number Diff line change
Expand Up @@ -202,5 +202,5 @@ async function loadDictItems(
<template>
<MInput ref="MInputRef" :options="selectedOptions" :showDictItems="showMenuComp" :deleteAValue="(_:number, index:number)=> deleteSelectedDictValue(index)" />
<MenuSelectComp ref="selectContainerCompRef" :values="selectedOptions.map(e=>e.value)"
:options="showOptions" :setFilterADictValue="addSelectedDictValue" />
:options="showOptions" @click="addSelectedDictValue" />
</template>
4 changes: 2 additions & 2 deletions src/components/base/MInput/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ defineExpose({
<Badge
v-for="(dictItemOrRawValue, valueIdx) in showBreviary ? options.slice(0, breviaryShowCount) : options"
:key="`${filterItem?.columnName}-${valueIdx}`" class="iw-badge max-w-24 flex"
:dictItemOrRawValue="dictItemOrRawValue" @click="handleInputClick"
:option="dictItemOrRawValue" @click="handleInputClick"
@delete="deleteAValue(filterItemIdx, valueIdx)" />
<div v-if="showBreviary && breviaryCount > 0" class="iw-dropdown iw-dropdown-hover">
<span tabindex="0" class="iw-badge">
Expand All @@ -87,7 +87,7 @@ defineExpose({
class="min-h-20 flex flex-wrap iw-dropdown-content menu bg-base-100 rounded-box z-[1] w-52 p-2 shadow">
<Badge v-for="(dictItemOrRawValue, valueIdx) in options.slice(breviaryShowCount)"
:key="`${filterItem?.columnName}-${valueIdx}`" class="iw-badge max-w-24 flex"
:dictItemOrRawValue="dictItemOrRawValue"
:option="dictItemOrRawValue"
@delete="deleteAValue(filterItemIdx, breviaryShowCount + valueIdx)" />
</div>
</div>
Expand Down
19 changes: 11 additions & 8 deletions src/components/base/MenuSelect/index.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<MenuComp ref="dictContainerCompRef" class="p2">
<MenuComp ref="menuSelectRef" class="p2">
<div ref="SelectRef" @click="handleClick" class="iw-tree__container w-full">
<div
v-for="dictItem in selectOptions"
Expand All @@ -17,6 +17,9 @@
<div v-if="dictItem.avatar !== undefined" class="avatar">
<img :src="dictItem.avatar" class="w-4 rounded-full" />
</div>
<div v-if="dictItem.icon !== undefined">
<i :class="`${dictItem.icon} mr-0.5`" />
</div>
<span
:class="['ml-1 whitespace-nowrap', { 'border-b-2': dictItem.filter }]"
>{{ dictItem.title }}</span
Expand All @@ -33,10 +36,10 @@ import MenuComp from '../../common/Menu.vue'
const props = defineProps<{
options: any[] | undefined
values: any
setFilterADictValue: (e: Event) => void
}>()
const emits = defineEmits(['click'])
const treeRef: Ref<HTMLDivElement | null> = ref(null)
const dictContainerCompRef = ref<InstanceType<typeof MenuComp>>(
const menuSelectRef = ref<InstanceType<typeof MenuComp>>(
{} as InstanceType<typeof MenuComp>
)
const selectOptions = ref<any[]>([])
Expand All @@ -50,21 +53,21 @@ watch(
function handleShow(
...args: Parameters<typeof dictContainerCompRef.value.show>
...args: Parameters<typeof menuSelectRef.value.show>
) {
return dictContainerCompRef.value?.show(...args)
return menuSelectRef.value?.show(...args)
}
function handleClose(
...args: Parameters<typeof dictContainerCompRef.value.close>
...args: Parameters<typeof menuSelectRef.value.close>
) {
return dictContainerCompRef.value?.close(...args)
return menuSelectRef.value?.close(...args)
}
function handleClick(e: Event) {
if (!(e.target instanceof HTMLElement)) {
return
}
props.setFilterADictValue(e)
emits('click', e)
}
defineExpose({
Expand Down
4 changes: 2 additions & 2 deletions src/components/base/MenuTree/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ import {
const props = defineProps<{
options: any[] | undefined
values: any
setFilterADictValue: (e: Event) => void
}>()
const emits = defineEmits(['click'])
const treeRef: Ref<HTMLDivElement | null> = ref(null)
const dictTreeContainerCompRef = ref<InstanceType<typeof MenuComp>>(
{} as InstanceType<typeof MenuComp>
Expand Down Expand Up @@ -93,7 +93,7 @@ function handleClick(e: Event) {
if (arrowEle) {
return
}
props.setFilterADictValue(e)
emits('click', e)
}
defineExpose({
Expand Down
2 changes: 1 addition & 1 deletion src/components/base/TreeSelect.vue
Original file line number Diff line number Diff line change
Expand Up @@ -202,5 +202,5 @@ async function loadDictItems(
<template>
<MInput ref="MInputRef" :options="selectedOptions" :showDictItems="showMenuComp" :deleteAValue="(_:number, index:number)=> deleteSelectedDictValue(index)" />
<MenuTreeComp ref="selectContainerCompRef" :values="selectedOptions.map(e=>e.value)"
:options="showOptions" :setFilterADictValue="addSelectedDictValue" />
:options="showOptions" @click="addSelectedDictValue" />
</template>
13 changes: 7 additions & 6 deletions src/components/common/Badge.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@
import * as iconSvg from '../../assets/icon'
defineProps<{
dictItemOrRawValue: any,
option: any,
readonly?: boolean
}>()
const emits = defineEmits<{
(e: 'delete'): void
}>()
</script>
<template>
<div class="iw-badge flex" :style="`background-color: ${dictItemOrRawValue.color ?? ''}`">
<span v-if="dictItemOrRawValue.avatar !== undefined" class="avatar">
<img :src="dictItemOrRawValue.avatar" class="w-4 rounded-full">
<div class="iw-badge px-1 flex rounded-md border-none" :style="`background-color: ${option.color ?? ''};color: ${option.color ? '#fff':''}`">
<span v-if="option.avatar !== undefined" class="avatar mr-1">
<img :src="option.avatar" class="w-4 rounded-full">
</span>
<span class="ml-1 whitespace-nowrap flex-1 truncate">{{ dictItemOrRawValue.title ?? dictItemOrRawValue }}</span>
<i :class="`${iconSvg.DELETE} ml-0.5 cursor-pointer`" @click="emits('delete')" />
<span class="whitespace-nowrap flex-1 truncate">{{ option.title ?? option }}</span>
<i v-if="!readonly" :class="`${iconSvg.DELETE} ml-0.5 cursor-pointer text-base`" @click="emits('delete')" />
</div>
</template>
106 changes: 54 additions & 52 deletions src/components/function/FilterSetting.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import { onMounted, ref, computed } from 'vue'
import * as iconSvg from '../../assets/icon'
import { DataKind, DictItemProps, DictItemsResp, DictKind, FilterDataGroupProps, FilterDataItemProps, FilterDataProps, LayoutModifyProps } from '../../props'
Expand All @@ -15,6 +15,7 @@ import { deepToRaw } from '../../utils/vueHelper'
import MenuSelectComp from '../base/MenuSelect/index.vue'
import MenuTreeComp from '../base/MenuTree/index.vue'
import MInput from '../base/MInput/index.vue'
import Badge from '../common/Badge.vue'
const props = defineProps<{
// 布局ID
Expand Down Expand Up @@ -79,7 +80,26 @@ const selectedFilterItemIdx = ref<number | undefined>()
// 所有过滤组中已选中的字典项,格式:列名 + '-' + 列值 -> 字典项
// Dictionary items selected in all filter groups, format: column name + '-' + column value -> dictionary item
const cachedAllSelectedDictItems = ref<{ [key: string | number]: DictItemProps }>({})
//可过滤的列
// Filterable columns
const filterColumnOptions = computed(()=> props.columnsConf.filter(col => props.filter.enabledColumnNames.includes(col.name)).map(e=> {
return {
...e,
value: e.name
}
}))
// 选中过滤单项
// Selected filter item
const selectedFilterItem = computed(()=> selectedFilterItems.value?.[selectedFilterItemIdx.value!])
//操作符 operator
const operatorOptions = computed(()=> {
return getOperatorKindsByDataKind(selectedFilterItem.value?.dataKind).map(e=> {
return {
title: translateOperatorKind(e),
value: e,
}
})
})
/**
* 将过滤数据项转换为过滤项
*
Expand Down Expand Up @@ -254,7 +274,8 @@ function showFilterOps(e: Event, filterItemIdx: number) {
// 设置已选中的过滤项ID
// Set the selected filter item ID
selectedFilterItemIdx.value = filterItemIdx
filterOpCompRef.value?.show(e.target as HTMLElement, undefined, MenuSizeKind.MINI, true)
const targetEle = (e.target as HTMLElement).closest('.iw-btn')
filterOpCompRef.value?.show(targetEle as HTMLElement, undefined, MenuSizeKind.MINI, true)
}
/**
Expand All @@ -276,13 +297,20 @@ async function deleteFilterItem(filterItemIdx: number) {
* @param e 事件 / Event
*/
function setFilterColumn(e: Event) {
const targetEle = e.target as HTMLElement
const currColumnName = targetEle.dataset.columnName!
if (!(e.target instanceof HTMLElement)) {
return
}
const itemEle = e.target.closest('.iw-contextmenu__item')
if (!itemEle || !(itemEle instanceof HTMLElement)) {
return
}
const currColumnName = itemEle.dataset.value!
const columnConf = props.columnsConf.find(col => col.name === currColumnName)!
if (selectedFilterItemIdx.value !== undefined) {
// 存在已选中的过滤项,重置过滤项到初始状态
// There is a selected filter item, reset the filter item to the initial state
const currFilterItem = selectedFilterItems.value?.[selectedFilterItemIdx.value]
if(currFilterItem!.columnName === currColumnName) return
currFilterItem!.columnName = currColumnName
currFilterItem!.operator = OperatorKind.EQ
currFilterItem!.values = []
Expand Down Expand Up @@ -321,8 +349,14 @@ function setFilterColumn(e: Event) {
* @param e 事件 / Event
*/
function setFilterOp(e: Event) {
const targetEle = e.target as HTMLElement
const selectedOp = targetEle.dataset.op as OperatorKind
if (!(e.target instanceof HTMLElement)) {
return
}
const targetEle = e.target!.closest('.iw-contextmenu__item')
if (!targetEle || !(targetEle instanceof HTMLElement)) {
return
}
const selectedOp = targetEle!.dataset!.value as OperatorKind
const currFilterItem = selectedFilterItems.value?.[selectedFilterItemIdx.value!]
currFilterItem!.operator = selectedOp
// 重置值
Expand Down Expand Up @@ -531,15 +565,13 @@ onMounted(() => {
translateOperatorKind(filterGroup.items[0].operator)
}}</span>
<span class="mr-0.5 max-w-[100px] whitespace-nowrap overflow-hidden text-ellipsis">
<span
<Badge
v-for="(dictItemOrRawValue, valueIdx) in tryParseDictItems(filterGroup.items[0].columnName, filterGroup.items[0].value)"
:key="`${filterGroup.items[0].columnName}-${valueIdx}`"
readonly
:option="dictItemOrRawValue"
:style="`background-color: ${dictItemOrRawValue.color ?? ''}`" class="iw-badge">
<span v-if="dictItemOrRawValue.avatar !== undefined" class="avatar">
<img :src="dictItemOrRawValue.avatar" class="w-4 rounded-full">
</span>
<span class="ml-1 whitespace-nowrap">{{ dictItemOrRawValue.title ?? dictItemOrRawValue }}</span>
</span>
</Badge>
</span>
</template>
<template v-else>
Expand Down Expand Up @@ -582,7 +614,7 @@ onMounted(() => {
<!-- Operator -->
<button class="iw-btn border-gray-200 bg-white iw-btn-xs rounded-sm mr-1 h-[30px]"
@click="e => { showFilterOps(e, filterItemIdx) }">
<span class="mr-0.5">{{ translateOperatorKind(filterItem.operator) }}</span>
<span class="mr-0.5 w-[28px] overflow-hidden text-ellipsis whitespace-nowrap">{{ translateOperatorKind(filterItem.operator) }}</span>
<i :class="`${iconSvg.CHEVRON_DOWN} ml-0.5`" />
</button>
<!---->
Expand Down Expand Up @@ -616,42 +648,12 @@ onMounted(() => {
<span class="absolute bottom-1 right-1 text-xs text-neutral-content">{{ $t('function.filter.note') }}</span>
</MenuComp>

<MenuComp ref="filterColumnCompRef" @click="setFilterColumn">
<div v-for="column in props.columnsConf.filter(col => props.filter.enabledColumnNames.includes(col.name))"
:key="column.name" class="iw-contextmenu__item flex w-full cursor-pointer" :data-column-name="column.name">
<i :class="`${column.icon} mr-0.5`" />
{{ column.title }}
</div>
</MenuComp>

<MenuComp ref="filterOpCompRef" @click="setFilterOp">
<template v-if="selectedFilterItemIdx !== undefined">
<div v-for="op in getOperatorKindsByDataKind(selectedFilterItems?.[selectedFilterItemIdx!].dataKind)" :key="op"
class="iw-contextmenu__item flex w-full cursor-pointer" :data-op="op">
{{ translateOperatorKind(op) }}
</div>
</template>
</MenuComp>

<!-- <MenuComp ref="dictContainerCompRef">
<div @click="setFilterADictValue">
<div v-for="dictItem in queryDictItemsResp?.records"
:key="`${props.layoutId}-${selectedFilterGroupIdx}-${selectedFilterItemIdx}-${dictItem.value}`"
:style="`background-color: ${dictItem.color}`"
class="iw-contextmenu__item flex cursor-pointer iw-badge m-1.5 pl-0.5"
:class="selectedFilterItems?.[selectedFilterItemIdx!]?.values.includes(dictItem.value) ? 'iw-badge-primary' : 'iw-badge-outline'"
:data-value="dictItem.value" :data-title="dictItem.title" :data-avatar="dictItem.avatar"
:data-color="dictItem.color">
<div v-if="dictItem.avatar !== undefined" class="avatar">
<img :src="dictItem.avatar" class="w-4 rounded-full">
</div>
<span class="ml-1 whitespace-nowrap">{{ dictItem.title }}{{ dictItem.title !== dictItem.value
? `(${dictItem.value})` : '' }}</span>
</div>
</div>
</MenuComp> -->
<MenuSelectComp ref="dictContainerCompRef" :values="selectedFilterItems?.[selectedFilterItemIdx!]?.values"
:options="queryDictItemsResp?.records" :setFilterADictValue="setFilterADictValue" />
<MenuTreeComp ref="dictTreeContainerCompRef" :values="selectedFilterItems?.[selectedFilterItemIdx!]?.values"
:options="queryDictItemsResp?.records" :setFilterADictValue="setFilterADictValue" />
<MenuSelectComp ref="filterColumnCompRef" :values="[selectedFilterItem?.columnName]"
:options="filterColumnOptions" @click="setFilterColumn" />
<MenuSelectComp ref="filterOpCompRef" :values="[selectedFilterItem?.operator]"
:options="operatorOptions" @click="setFilterOp" />
<MenuSelectComp ref="dictContainerCompRef" :values="selectedFilterItem?.values"
:options="queryDictItemsResp?.records" @click="setFilterADictValue" />
<MenuTreeComp ref="dictTreeContainerCompRef" :values="selectedFilterItem?.values"
:options="queryDictItemsResp?.records" @click="setFilterADictValue" />
</template>

0 comments on commit f26b4a7

Please sign in to comment.