|
@@ -9,76 +9,84 @@
|
|
|
},
|
|
|
]"
|
|
|
>
|
|
|
- <template v-if="!filterable || filterStyle === 'arrow'">
|
|
|
+ <template v-if="filterable && filterStyle === 'underline'">
|
|
|
+ <span
|
|
|
+ ref="buttonRef"
|
|
|
+ v-click-outside="clickOutsideHandler"
|
|
|
+ :class="['filter-button', { 'filter-button-active': active }]"
|
|
|
+ >
|
|
|
+ <span class="filter-button-text">{{ label }}</span>
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
<span style="flex: 1">{{ label }}</span>
|
|
|
</template>
|
|
|
- <template v-if="filterable">
|
|
|
- <el-popover
|
|
|
- :width="224"
|
|
|
- trigger="click"
|
|
|
- class="table-header-cell-popover"
|
|
|
- placement="bottom"
|
|
|
- @show="expand = true"
|
|
|
- @hide="expand = false"
|
|
|
- >
|
|
|
- <template v-if="filterStyle === 'underline'" #reference>
|
|
|
- <span
|
|
|
- :class="['filter-button', { 'filter-button-active': active }]"
|
|
|
- >{{ label }}</span
|
|
|
- >
|
|
|
- </template>
|
|
|
- <template v-if="filterStyle === 'arrow'" #reference>
|
|
|
- <div class="filter-arrow-wrapper">
|
|
|
- <el-icon
|
|
|
- :class="[
|
|
|
- 'filter-arrow',
|
|
|
- { 'arrow-active': active, 'arrow-expand': expand },
|
|
|
- ]"
|
|
|
- >
|
|
|
- <CaretBottom />
|
|
|
- </el-icon>
|
|
|
- </div>
|
|
|
- </template>
|
|
|
- <el-select
|
|
|
- v-model="selections"
|
|
|
- size="default"
|
|
|
- placeholder="筛选"
|
|
|
- multiple
|
|
|
- filterable
|
|
|
- default-first-option
|
|
|
- collapse-tags
|
|
|
- clearable
|
|
|
- :teleported="false"
|
|
|
- @change="
|
|
|
- newVal => {
|
|
|
- $emit('update:filter-values', newVal)
|
|
|
- }
|
|
|
- "
|
|
|
+ <div
|
|
|
+ v-if="(filterable && filterStyle === 'arrow') || sortable"
|
|
|
+ class="button-wrapper"
|
|
|
+ >
|
|
|
+ <template v-if="filterable && filterStyle === 'arrow'">
|
|
|
+ <el-icon
|
|
|
+ ref="buttonRef"
|
|
|
+ v-click-outside="clickOutsideHandler"
|
|
|
+ :class="[
|
|
|
+ 'filter-arrow',
|
|
|
+ { 'arrow-active': active, 'arrow-expand': expand },
|
|
|
+ ]"
|
|
|
>
|
|
|
- <el-option
|
|
|
- v-for="(option, index) in filterOptions"
|
|
|
- :key="option.value + index"
|
|
|
- :value="option.value"
|
|
|
- :label="option.label"
|
|
|
- />
|
|
|
- </el-select>
|
|
|
- </el-popover>
|
|
|
- </template>
|
|
|
- <template v-if="sortable">
|
|
|
- <span class="sort-wrapper" @click="sortChange">
|
|
|
- <el-icon class="sort">
|
|
|
+ <CaretBottom />
|
|
|
+ </el-icon>
|
|
|
+ </template>
|
|
|
+ <template v-if="sortable">
|
|
|
+ <el-icon class="sort-button" @click="sortChange">
|
|
|
<SortUp v-show="sortRule === 'ascending'" />
|
|
|
<SortDown v-show="sortRule === 'descending'" />
|
|
|
<Sort v-show="!sortRule" />
|
|
|
</el-icon>
|
|
|
- </span>
|
|
|
- </template>
|
|
|
+ </template>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
+ <el-popover
|
|
|
+ ref="popoverRef"
|
|
|
+ :virtual-ref="buttonRef"
|
|
|
+ virtual-triggering
|
|
|
+ trigger="click"
|
|
|
+ :width="224"
|
|
|
+ class="table-header-cell-popover"
|
|
|
+ placement="bottom"
|
|
|
+ @show="expand = true"
|
|
|
+ @hide="expand = false"
|
|
|
+ >
|
|
|
+ <el-select
|
|
|
+ v-model="selections"
|
|
|
+ size="default"
|
|
|
+ placeholder="筛选"
|
|
|
+ multiple
|
|
|
+ filterable
|
|
|
+ default-first-option
|
|
|
+ collapse-tags
|
|
|
+ clearable
|
|
|
+ :teleported="false"
|
|
|
+ @change="
|
|
|
+ newVal => {
|
|
|
+ $emit('update:filter-values', newVal)
|
|
|
+ }
|
|
|
+ "
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="(option, index) in filterOptions"
|
|
|
+ :key="option.value + index"
|
|
|
+ :value="option.value"
|
|
|
+ :label="option.label"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-popover>
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
import { PropType } from 'vue'
|
|
|
import { CaretBottom, Sort, SortUp, SortDown } from '@element-plus/icons-vue'
|
|
|
+import { ClickOutside as vClickOutside } from 'element-plus'
|
|
|
|
|
|
const props = defineProps({
|
|
|
label: {
|
|
@@ -116,6 +124,12 @@ watchEffect(() => {
|
|
|
selections.value = props.filterValues
|
|
|
}
|
|
|
})
|
|
|
+const buttonRef = ref()
|
|
|
+const popoverRef = ref()
|
|
|
+const clickOutsideHandler = () => {
|
|
|
+ unref(popoverRef).popperRef?.delayHide?.()
|
|
|
+}
|
|
|
+
|
|
|
const sortChange = () => {
|
|
|
const sortRule =
|
|
|
props.sortRule === ''
|
|
@@ -136,76 +150,59 @@ const sortChange = () => {
|
|
|
align-items: center;
|
|
|
text-align: center;
|
|
|
line-height: 14px;
|
|
|
- position: relative;
|
|
|
&.table-header-cell-space-between {
|
|
|
justify-content: space-between;
|
|
|
}
|
|
|
- .filter-arrow-wrapper {
|
|
|
- width: 14px;
|
|
|
- height: 100%;
|
|
|
- background-color: #dfc37f;
|
|
|
- position: relative;
|
|
|
- cursor: pointer;
|
|
|
- .filter-arrow {
|
|
|
- display: inline;
|
|
|
- position: absolute;
|
|
|
- top: 0;
|
|
|
- right: 0;
|
|
|
- bottom: 0;
|
|
|
- left: 0;
|
|
|
- margin: auto;
|
|
|
- transition: 0.3s transform;
|
|
|
- &.arrow-expand {
|
|
|
- transform: rotate(-180deg);
|
|
|
- }
|
|
|
- &.arrow-active {
|
|
|
- color: #2d7cff;
|
|
|
- font-weight: bold;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
.filter-button {
|
|
|
flex: 1;
|
|
|
cursor: pointer;
|
|
|
- position: relative;
|
|
|
-
|
|
|
+ &-text {
|
|
|
+ position: relative;
|
|
|
+ &::after {
|
|
|
+ content: '';
|
|
|
+ display: block;
|
|
|
+ width: calc(100% + 4px);
|
|
|
+ position: absolute;
|
|
|
+ bottom: -4px;
|
|
|
+ left: -2px;
|
|
|
+ border-bottom: 1px solid #101116;
|
|
|
+ }
|
|
|
+ }
|
|
|
&:hover {
|
|
|
color: #2d7cff;
|
|
|
}
|
|
|
-
|
|
|
- &::after {
|
|
|
- content: '';
|
|
|
- display: block;
|
|
|
- width: calc(100% + 4px);
|
|
|
- position: absolute;
|
|
|
- bottom: -4px;
|
|
|
- left: -2px;
|
|
|
- border-bottom: 1px solid #101116;
|
|
|
- }
|
|
|
-
|
|
|
- &.filter-button-active,
|
|
|
+ &-active,
|
|
|
&:hover {
|
|
|
- &::after {
|
|
|
+ .filter-button-text::after {
|
|
|
border-bottom: 2px solid #2d7cff;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- .sort-wrapper {
|
|
|
+ .button-wrapper {
|
|
|
width: 14px;
|
|
|
height: 100%;
|
|
|
background-color: #dfc37f;
|
|
|
- position: relative;
|
|
|
- cursor: pointer;
|
|
|
- .sort {
|
|
|
- display: inline;
|
|
|
- position: absolute;
|
|
|
- top: 0;
|
|
|
- right: 0;
|
|
|
- bottom: 0;
|
|
|
- left: 0;
|
|
|
- margin: auto;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ justify-content: space-around;
|
|
|
+ align-items: center;
|
|
|
+ .filter-arrow {
|
|
|
+ display: block;
|
|
|
+ transition: 0.3s transform;
|
|
|
+ cursor: pointer;
|
|
|
+ &.arrow-expand {
|
|
|
+ transform: rotate(-180deg);
|
|
|
+ }
|
|
|
+ &.arrow-active {
|
|
|
+ color: #2d7cff;
|
|
|
+ font-weight: bold;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
+ .sort-button {
|
|
|
+ display: block;
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
.el-select-dropdown__item.hover {
|