Filter Bar 并联筛选 2.14.1
用于后台列表页的高密度筛选条。它通过组合式结构连接标签与任意 Vue 3 表单控件,并统一处理布局、操作区和高级筛选。
基础用法
使用 FilterBarItem 组织每个筛选条件。组件不会接管字段数据,表单状态仍由业务通过 v-model 管理。默认仅显示筛选按钮;示例通过 show-reset 额外启用了重置按钮。操作按钮会跟随最后一个筛选项参与换行。
修改条件后点击查询
<template>
<elp-filter-bar
search-text="查询"
reset-text="清空"
show-reset
:loading="loading"
@search="handleSearch"
@reset="handleReset"
>
<elp-filter-bar-item label="数据范围" width="220">
<elp-select v-model="filters.scope" placeholder="全部">
<elp-option label="全部" value="all" />
<elp-option label="仅自己" value="mine" />
<elp-option label="本部门" value="department" />
</elp-select>
</elp-filter-bar-item>
<elp-filter-bar-item label="关键词" width="300">
<elp-input
v-model="filters.keyword"
placeholder="昵称 / wxid / 机器人备注"
clearable
/>
</elp-filter-bar-item>
<elp-filter-bar-item label="状态筛选" width="255">
<elp-select v-model="filters.status" placeholder="全部" clearable>
<elp-option label="全部" value="" />
<elp-option label="在线" value="online" />
<elp-option label="离线" value="offline" />
</elp-select>
</elp-filter-bar-item>
<elp-filter-bar-item label="分组搜索" width="255">
<elp-select v-model="filters.group" placeholder="选择分组" clearable>
<elp-option label="默认分组" value="default" />
<elp-option label="重点客户" value="important" />
</elp-select>
</elp-filter-bar-item>
<elp-filter-bar-item label="到期筛选" width="255">
<elp-select v-model="filters.expire" placeholder="全部" clearable>
<elp-option label="7 天内" value="7" />
<elp-option label="30 天内" value="30" />
<elp-option label="已过期" value="expired" />
</elp-select>
</elp-filter-bar-item>
</elp-filter-bar>
<p class="filter-result">{{ result }}</p>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue'
const createFilters = () => ({
scope: 'all',
keyword: '',
status: '',
group: '',
expire: '',
})
const filters = reactive(createFilters())
const loading = ref(false)
const result = ref('修改条件后点击查询')
const handleSearch = () => {
loading.value = true
result.value = `查询参数:${JSON.stringify(filters)}`
window.setTimeout(() => (loading.value = false), 400)
}
const handleReset = () => {
Object.assign(filters, createFilters())
result.value = '筛选条件已清空'
}
</script>
<style scoped>
.filter-result {
margin: 12px 0 0;
color: var(--elp-text-color-secondary);
font-size: 12px;
}
</style>
混合表单控件
内容插槽可以放置 Input、Select、DatePicker、InputNumber 或业务自定义控件。通过 width、min-width 和 grow 控制项目宽度。
支持 Input、Select、DatePicker、InputNumber 等任意控件
<template>
<elp-filter-bar
:label-width="96"
:item-width="280"
search-text="应用筛选"
reset-text="重置"
show-reset
@search="message = '筛选条件已应用'"
@reset="reset"
>
<elp-filter-bar-item
label="任务名称"
min-width="280"
aria-label="按任务名称筛选"
grow
>
<elp-input v-model="form.name" placeholder="输入任务名称" clearable />
</elp-filter-bar-item>
<elp-filter-bar-item label="渠道" width="320">
<elp-select
v-model="form.channels"
placeholder="选择渠道"
multiple
collapse-tags
clearable
>
<elp-option label="企业微信" value="wechat" />
<elp-option label="公众号" value="official" />
<elp-option label="小程序" value="mini" />
</elp-select>
</elp-filter-bar-item>
<elp-filter-bar-item label="创建时间" width="390">
<elp-date-picker
v-model="form.range"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
/>
</elp-filter-bar-item>
<elp-filter-bar-item label="最低数量" width="230">
<elp-input-number
v-model="form.minimum"
:min="0"
controls-position="right"
/>
</elp-filter-bar-item>
</elp-filter-bar>
<p class="filter-result">{{ message }}</p>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue'
const initial = () => ({
name: '',
channels: [] as string[],
range: [] as Date[],
minimum: 0,
})
const form = reactive(initial())
const message = ref('支持 Input、Select、DatePicker、InputNumber 等任意控件')
const reset = () => {
Object.assign(form, initial())
message.value = '已恢复默认筛选条件'
}
</script>
<style scoped>
.filter-result {
margin: 12px 0 0;
color: var(--elp-text-color-secondary);
font-size: 12px;
}
</style>
三段并联
FilterBarItem 可以组合左侧标签、中间默认插槽和右侧 append 插槽。三个区域都支持自定义内容;组件会处理常用表单控件的边框重叠、外侧圆角和聚焦层级。左侧需要放置 Select、Input 或业务组件时,将 label-mode 设置为 control,再通过 label 插槽传入组件。
<template>
<elp-filter-bar
:label-width="96"
search-text="筛选"
reset-text="清空"
show-reset
@reset="reset"
>
<elp-filter-bar-item label="客户筛选" width="600" append-width="230">
<elp-select v-model="customerType" placeholder="客户类型">
<elp-option label="全部客户" value="all" />
<elp-option label="企业客户" value="company" />
<elp-option label="个人客户" value="personal" />
</elp-select>
<template #append>
<elp-input v-model="keyword" placeholder="名称 / 手机号" clearable />
</template>
</elp-filter-bar-item>
<elp-filter-bar-item width="560" append-width="200">
<template #label>
<span class="channel-label">渠道</span>
</template>
<elp-segmented
v-model="channel"
:options="['全部', '线上', '线下']"
block
/>
<template #append>
<elp-select v-model="region" placeholder="所属区域" clearable>
<elp-option label="华东" value="east" />
<elp-option label="华南" value="south" />
<elp-option label="华北" value="north" />
</elp-select>
</template>
</elp-filter-bar-item>
<elp-filter-bar-item
label-mode="control"
label-width="180"
width="650"
append-width="240"
aria-label="自定义字段筛选"
>
<template #label>
<elp-select v-model="customField" aria-label="筛选字段">
<elp-option label="客户名称" value="name" />
<elp-option label="客户编号" value="code" />
<elp-option label="联系电话" value="phone" />
</elp-select>
</template>
<elp-select v-model="operator" aria-label="筛选条件">
<elp-option label="包含" value="contains" />
<elp-option label="等于" value="equals" />
<elp-option label="不等于" value="not-equal" />
</elp-select>
<template #append>
<elp-input v-model="customValue" placeholder="输入筛选值" clearable />
</template>
</elp-filter-bar-item>
</elp-filter-bar>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
const customerType = ref('all')
const keyword = ref('')
const channel = ref('全部')
const region = ref('')
const customField = ref('name')
const operator = ref('contains')
const customValue = ref('')
const reset = () => {
customerType.value = 'all'
keyword.value = ''
channel.value = '全部'
region.value = ''
customField.value = 'name'
operator.value = 'contains'
customValue.value = ''
}
</script>
<style scoped>
.channel-label {
color: var(--elp-color-primary);
font-weight: 600;
}
</style>
尺寸
通过 size 统一控制筛选条、内部表单控件和操作按钮,支持 large、default 和 small。
Large
Default
Small
<template>
<div class="size-stack">
<div>
<p>Large</p>
<elp-filter-bar size="large" :show-search="false" :show-reset="false">
<elp-filter-bar-item label="客户" width="100%" append-width="45%">
<elp-select v-model="large.type" placeholder="客户类型">
<elp-option label="全部" value="all" />
<elp-option label="企业" value="company" />
</elp-select>
<template #append>
<elp-input v-model="large.keyword" placeholder="输入关键词" />
</template>
</elp-filter-bar-item>
</elp-filter-bar>
</div>
<div>
<p>Default</p>
<elp-filter-bar size="default" :show-search="false" :show-reset="false">
<elp-filter-bar-item label="客户" width="100%" append-width="45%">
<elp-select v-model="normal.type" placeholder="客户类型">
<elp-option label="全部" value="all" />
<elp-option label="企业" value="company" />
</elp-select>
<template #append>
<elp-input v-model="normal.keyword" placeholder="输入关键词" />
</template>
</elp-filter-bar-item>
</elp-filter-bar>
</div>
<div>
<p>Small</p>
<elp-filter-bar size="small" :show-search="false" :show-reset="false">
<elp-filter-bar-item label="客户" width="100%" append-width="45%">
<elp-select v-model="small.type" placeholder="客户类型">
<elp-option label="全部" value="all" />
<elp-option label="企业" value="company" />
</elp-select>
<template #append>
<elp-input v-model="small.keyword" placeholder="输入关键词" />
</template>
</elp-filter-bar-item>
</elp-filter-bar>
</div>
</div>
</template>
<script lang="ts" setup>
import { reactive } from 'vue'
const large = reactive({ type: 'all', keyword: '' })
const normal = reactive({ type: 'all', keyword: '' })
const small = reactive({ type: 'all', keyword: '' })
</script>
<style scoped>
.size-stack {
display: grid;
gap: 18px;
}
.size-stack p {
margin: 0 0 6px;
color: var(--elp-text-color-secondary);
font-size: 12px;
font-weight: 600;
letter-spacing: 0.04em;
text-transform: uppercase;
}
</style>
标签对齐
使用 label-align 分别设置标签左对齐、居中或右对齐。
<template>
<elp-filter-bar
:show-search="false"
:show-reset="false"
:label-width="90"
:item-width="300"
>
<elp-filter-bar-item label="左对齐" label-align="left">
<elp-input v-model="left" placeholder="label-align: left" />
</elp-filter-bar-item>
<elp-filter-bar-item label="居中" label-align="center">
<elp-input v-model="center" placeholder="label-align: center" />
</elp-filter-bar-item>
<elp-filter-bar-item label="右对齐" label-align="right">
<elp-input v-model="right" placeholder="label-align: right" />
</elp-filter-bar-item>
</elp-filter-bar>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
const left = ref('')
const center = ref('')
const right = ref('')
</script>
高级筛选
通过 advanced 插槽声明次要筛选项,并使用 v-model:expanded 控制展开状态。
展开状态:已收起;高级条件按需展示
<template>
<elp-filter-bar
v-model:expanded="expanded"
search-text="搜索"
reset-text="重置"
expand-text="高级筛选"
collapse-text="收起筛选"
show-reset
collapsible
@search="handleSearch"
@reset="handleReset"
>
<elp-filter-bar-item label="客户关键词" width="340">
<elp-input
v-model="form.keyword"
placeholder="名称、手机号或备注"
clearable
/>
</elp-filter-bar-item>
<elp-filter-bar-item label="客户状态">
<elp-select v-model="form.status" placeholder="全部" clearable>
<elp-option label="跟进中" value="following" />
<elp-option label="已成交" value="converted" />
<elp-option label="已流失" value="lost" />
</elp-select>
</elp-filter-bar-item>
<template #advanced>
<elp-filter-bar-item label="负责人">
<elp-select v-model="form.owner" placeholder="选择负责人" clearable>
<elp-option label="李明" value="liming" />
<elp-option label="王芳" value="wangfang" />
</elp-select>
</elp-filter-bar-item>
<elp-filter-bar-item label="客户等级">
<elp-select v-model="form.level" placeholder="全部等级" clearable>
<elp-option label="A级" value="a" />
<elp-option label="B级" value="b" />
<elp-option label="C级" value="c" />
</elp-select>
</elp-filter-bar-item>
<elp-filter-bar-item label="活跃日期" width="390">
<elp-date-picker
v-model="form.activeRange"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
/>
</elp-filter-bar-item>
</template>
</elp-filter-bar>
<p class="filter-result">
展开状态:{{ expanded ? '已展开' : '已收起' }};{{ message }}
</p>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue'
const initial = () => ({
keyword: '',
status: '',
owner: '',
level: '',
activeRange: [] as Date[],
})
const expanded = ref(false)
const form = reactive(initial())
const message = ref('高级条件按需展示')
const handleSearch = () => (message.value = '已提交全部筛选条件')
const handleReset = () => {
Object.assign(form, initial())
message.value = '条件已重置'
}
</script>
<style scoped>
.filter-result {
margin: 12px 0 0;
color: var(--elp-text-color-secondary);
font-size: 12px;
}
</style>
自定义标签和操作区
使用 label 与 actions 插槽扩展业务内容。actions 插槽会提供 search、reset 和 toggle 方法。
操作区、标签区和内容区均可通过插槽定制
<template>
<elp-filter-bar
:show-search="false"
:show-reset="false"
aria-label="订单筛选"
@search="message = '订单列表已刷新'"
@reset="reset"
>
<elp-filter-bar-item width="360" grow>
<template #label>
<span class="label-with-dot"><i />订单检索</span>
</template>
<elp-input v-model="keyword" placeholder="订单号 / 客户名称" clearable />
</elp-filter-bar-item>
<elp-filter-bar-item label="风险状态" width="250">
<elp-segmented v-model="risk" :options="['全部', '正常', '异常']" block />
</elp-filter-bar-item>
<template #actions="{ search, reset: resetFilters }">
<elp-button @click="exportData">导出</elp-button>
<elp-button @click="resetFilters">清空</elp-button>
<elp-button type="primary" @click="search">刷新列表</elp-button>
</template>
</elp-filter-bar>
<p class="filter-result">{{ message }}</p>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
const keyword = ref('')
const risk = ref('全部')
const message = ref('操作区、标签区和内容区均可通过插槽定制')
const exportData = () => (message.value = '已触发导出操作')
const reset = () => {
keyword.value = ''
risk.value = '全部'
message.value = '筛选条件已清空'
}
</script>
<style scoped>
.label-with-dot {
display: inline-flex;
align-items: center;
gap: 6px;
}
.label-with-dot i {
width: 6px;
height: 6px;
border-radius: 50%;
background: var(--elp-color-primary);
box-shadow: 0 0 0 3px var(--elp-color-primary-light-9);
}
.filter-result {
margin: 12px 0 0;
color: var(--elp-text-color-secondary);
font-size: 12px;
}
</style>
完整属性配置
下面的示例集中演示尺寸、标签宽度与对齐、项目宽度与间距、加载状态、默认操作按钮、高级筛选、无障碍标签以及三段 append 用法。
<template>
<div class="config-panel">
<label>
尺寸
<elp-select v-model="config.size" style="width: 110px">
<elp-option label="Large" value="large" />
<elp-option label="Default" value="default" />
<elp-option label="Small" value="small" />
</elp-select>
</label>
<label>
标签对齐
<elp-select v-model="config.labelAlign" style="width: 100px">
<elp-option label="左" value="left" />
<elp-option label="中" value="center" />
<elp-option label="右" value="right" />
</elp-select>
</label>
<label>显示筛选 <elp-switch v-model="config.showSearch" /></label>
<label>显示重置 <elp-switch v-model="config.showReset" /></label>
<label>高级筛选 <elp-switch v-model="config.collapsible" /></label>
<label>加载状态 <elp-switch v-model="config.loading" /></label>
</div>
<elp-filter-bar
v-model:expanded="expanded"
:size="config.size"
:label-width="100"
:item-width="480"
:gap="12"
:loading="config.loading"
:show-search="config.showSearch"
:show-reset="config.showReset"
:collapsible="config.collapsible"
search-text="应用"
reset-text="清空"
expand-text="更多条件"
collapse-text="收起条件"
aria-label="可配置筛选条件"
>
<elp-filter-bar-item
label="业务筛选"
:label-align="config.labelAlign"
width="560"
min-width="360"
append-width="220"
aria-label="业务类型和关键词"
grow
>
<elp-select v-model="form.type" placeholder="业务类型">
<elp-option label="全部" value="all" />
<elp-option label="新增" value="new" />
<elp-option label="续费" value="renew" />
</elp-select>
<template #append>
<elp-input v-model="form.keyword" placeholder="输入关键词" clearable />
</template>
</elp-filter-bar-item>
<template #advanced>
<elp-filter-bar-item label="归属部门" label-align="left">
<elp-select v-model="form.department" placeholder="全部部门" clearable>
<elp-option label="销售部" value="sales" />
<elp-option label="运营部" value="operation" />
</elp-select>
</elp-filter-bar-item>
</template>
</elp-filter-bar>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue'
const expanded = ref(false)
const config = reactive({
size: 'default' as 'large' | 'default' | 'small',
labelAlign: 'left' as 'left' | 'center' | 'right',
showSearch: true,
showReset: false,
collapsible: false,
loading: false,
})
const form = reactive({ type: 'all', keyword: '', department: '' })
</script>
<style scoped>
.config-panel {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 10px 18px;
margin-bottom: 12px;
padding: 10px 12px;
border-radius: var(--elp-border-radius-base);
background: var(--elp-fill-color-extra-light);
}
.config-panel label {
display: inline-flex;
align-items: center;
gap: 8px;
color: var(--elp-text-color-secondary);
font-size: 12px;
white-space: nowrap;
}
</style>
Filter Bar Item 属性总览
下面集中展示 FilterBarItem 的属性和插槽。第二个筛选项启用 grow 后,会在保留 min-width 的前提下占满当前行的剩余空间;第三个筛选项展示左、中、右三个区域都使用表单控件的写法。
<template>
<elp-filter-bar
:show-search="false"
:show-reset="false"
:label-width="96"
:item-width="300"
>
<elp-filter-bar-item
label="固定宽度"
label-align="right"
width="300"
aria-label="固定宽度筛选项"
>
<elp-input v-model="fixedValue" placeholder="width: 300" />
</elp-filter-bar-item>
<elp-filter-bar-item
label="自动扩展"
label-align="left"
width="320"
min-width="260"
append-width="190"
aria-label="自动占满剩余空间的筛选项"
grow
>
<elp-select v-model="growType" placeholder="选择类型">
<elp-option label="全部类型" value="all" />
<elp-option label="企业客户" value="company" />
<elp-option label="个人客户" value="personal" />
</elp-select>
<template #append>
<elp-input
v-model="growKeyword"
placeholder="grow:占满剩余空间"
clearable
/>
</template>
</elp-filter-bar-item>
<elp-filter-bar-item
label-mode="control"
label-width="170"
width="620"
append-width="220"
aria-label="自定义左侧控件筛选项"
>
<template #label>
<elp-select v-model="field" aria-label="筛选字段">
<elp-option label="客户名称" value="name" />
<elp-option label="客户编号" value="code" />
</elp-select>
</template>
<elp-select v-model="operator" aria-label="筛选条件">
<elp-option label="包含" value="contains" />
<elp-option label="等于" value="equals" />
</elp-select>
<template #append>
<elp-input v-model="customValue" placeholder="输入筛选值" />
</template>
</elp-filter-bar-item>
</elp-filter-bar>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
const fixedValue = ref('')
const growType = ref('all')
const growKeyword = ref('')
const field = ref('name')
const operator = ref('contains')
const customValue = ref('')
</script>
Filter Bar API 2.14.1
属性
| 名称 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| expanded / v-model:expanded | 高级筛选是否展开 | boolean | false |
| size | 内部控件与按钮尺寸 | enum | default |
| label-width | 默认标签宽度 | string / number | 88 |
| item-width | 默认筛选项宽度 | string / number | 260 |
| gap | 筛选项之间的间距 | string / number | 8 |
| loading | 搜索按钮是否处于加载状态 | boolean | false |
| show-search | 是否显示默认搜索按钮 | boolean | true |
| show-reset | 是否显示默认重置按钮 | boolean | false |
| collapsible | 是否显示高级筛选展开按钮 | boolean | false |
| search-text | 搜索按钮文案 | string | Search |
| reset-text | 重置按钮文案 | string | Reset |
| expand-text | 展开按钮文案 | string | More |
| collapse-text | 收起按钮文案 | string | Less |
| aria-label | 筛选区域的无障碍标签 | string | Filter conditions |
事件
| 名称 | 说明 | 类型 |
|---|---|---|
| search | 点击默认搜索按钮时触发 | Function |
| reset | 点击默认重置按钮时触发 | Function |
| update:expanded | 展开状态变化时触发 | Function |
插槽
| 名称 | 说明 | 类型 |
|---|---|---|
| default | 主要筛选项 | — |
| advanced | 可折叠的高级筛选项 | — |
| actions | 自定义操作区 | object |
暴露
| 名称 | 说明 | 类型 |
|---|---|---|
| toggle | 切换高级筛选展开状态 | Function |
| expand | 展开高级筛选 | Function |
| collapse | 收起高级筛选 | Function |
Filter Bar Item API 2.14.1
属性
| 名称 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| label | 筛选项标签 | string | '' |
| label-mode | 左侧区域的展示模式 | enum | text |
| label-align | 标签内容的水平对齐方式 | enum | left |
| label-width | 当前筛选项标签宽度 | string / number | — |
| width | 当前筛选项宽度 | string / number | — |
| min-width | 当前筛选项最小宽度 | string / number | — |
| append-width | 右侧追加区域宽度 | string / number | 42% |
| grow | 是否占用剩余空间 | boolean | false |
| aria-label | 当前筛选项的无障碍标签 | string | — |
插槽
| 名称 | 说明 |
|---|---|
| default | 表单控件或业务内容 |
| label | 自定义标签内容;控件需配合 label-mode="control" |
| append | 右侧并联的表单控件或业务内容 |