Appearance
BizFilterPreset 筛选方案
筛选组合的保存与应用:下拉列出已存方案(点击套用、星标默认、悬浮删除),「保存当前查询」把当前 values 命名存为新方案。presets 受控(服务端持久化)或 storage-key 本地 localStorage 双模式,内置方案不可删除。运营 / 财务每天按固定组合查数据的系统标配,与 BizSearchForm、BizQueryBuilder 的筛选值配套。
本地存储模式
当前筛选值:
调整关键词后点「筛选方案 → 保存当前查询」命名保存;下次直接套用。刷新页面方案仍在(localStorage)。
storage-key 落 localStorage:保存 / 套用 / 星标 / 删除全自动,刷新不丢。<script setup lang="ts">
/** 本地存储:storage-key 落 localStorage;保存当前 / 应用 / 星标默认 / 删除 */
import { ref } from 'vue'
import { ElInput, ElMessage } from 'element-plus'
import { BizFilterPreset } from 'vue3-ep-biz-lib'
/** 当前筛选值(真实项目通常与搜索表单 v-model 同源) */
const values = ref({ keyword: '', status: 'pending' })
const onApply = (applied: Record<string, unknown>): void => {
values.value = { ...values.value, ...applied }
ElMessage.success(`已套用方案,keyword = ${String(applied.keyword ?? '')}`)
}
</script>
<template>
<div style="display: flex; flex-direction: column; gap: 12px; max-width: 420px">
<div style="display: flex; gap: 8px; align-items: center">
<span>当前筛选值:</span>
<ElInput v-model="values.keyword" placeholder="关键词" style="width: 160px" />
<BizFilterPreset :values="values" storage-key="demo-orders" @apply="onApply" />
</div>
<div style="font-size: 12px; color: var(--el-text-color-secondary)">
调整关键词后点「筛选方案 → 保存当前查询」命名保存;下次直接套用。刷新页面方案仍在(localStorage)。
</div>
</div>
</template>
显示代码
受控模式(服务端持久化)
服务端方案数:2(「本月待支付」为内置方案,不可删除)
presets 传入即受控:save / remove 只派发事件,业务调接口后回写列表;builtin 方案不可删除。<script setup lang="ts">
/** 受控模式:presets 服务端持久化(save/remove 后回写);内置方案不可删除 */
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
import { BizFilterPreset } from 'vue3-ep-biz-lib'
import type { BizFilterPresetItem } from 'vue3-ep-biz-lib'
/** 模拟服务端方案表(真实项目:登录后拉取 / 保存后调接口再回写) */
const serverItems = ref<BizFilterPresetItem[]>([
{ id: 'b1', name: '本月待支付', values: { status: 'pending', month: '2026-09' }, builtin: true },
{ id: 'b2', name: '高额已支付', values: { status: 'paid', minAmount: 10000 } },
])
const current = ref<Record<string, unknown>>({ status: 'pending', minAmount: 5000 })
const onApply = (values: Record<string, unknown>, item: BizFilterPresetItem): void => {
current.value = { ...values }
ElMessage.success(`套用「${item.name}」`)
}
/** 受控模式:save / remove 只派发事件,持久化由业务完成后回写 presets */
const onSave = (item: BizFilterPresetItem): void => {
serverItems.value = [...serverItems.value, item]
}
const onRemove = (id: string): void => {
serverItems.value = serverItems.value.filter((it) => it.id !== id)
}
</script>
<template>
<div style="display: flex; flex-direction: column; gap: 12px; max-width: 480px">
<BizFilterPreset
:values="current"
:presets="serverItems"
@apply="onApply"
@save="onSave"
@remove="onRemove"
/>
<div style="font-size: 12px; color: var(--el-text-color-secondary)">
服务端方案数:{{ serverItems.length }}(「本月待支付」为内置方案,不可删除)
</div>
</div>
</template>
显示代码
与 BizSearchForm 联动
查询参数: (点查询或套用方案后显示)
方案值经 search-form 的
setValues 回填并 search();保存数据源即表单 v-model。<script setup lang="ts">
/** 与 BizSearchForm 联动:方案值经 setValues 回填表单并触发查询;保存取当前表单值 */
import { ref } from 'vue'
import { ElTag } from 'element-plus'
import { BizFilterPreset, BizSearchForm } from 'vue3-ep-biz-lib'
import type { BizSearchField, BizSearchValues } from 'vue3-ep-biz-lib'
const fields: BizSearchField[] = [
{ prop: 'keyword', label: '关键词', type: 'input' },
{
prop: 'status',
label: '状态',
type: 'select',
options: [
{ label: '待支付', value: 'pending' },
{ label: '已支付', value: 'paid' },
{ label: '已关闭', value: 'closed' },
],
},
{ prop: 'dateRange', label: '创建日期', type: 'date-range' },
]
/** 表单值双绑:既供查询,也作为「保存当前查询」的数据源 */
const values = ref<BizSearchValues>({})
const lastQuery = ref<BizSearchValues>({})
const searchRef = ref<{ setValues: (v: Record<string, unknown>) => void; search: () => void }>()
const onSearch = (query: BizSearchValues): void => {
lastQuery.value = query
}
/** 套用方案:回填表单并立即查询 */
const onApply = (applied: Record<string, unknown>): void => {
searchRef.value?.setValues(applied)
searchRef.value?.search()
}
</script>
<template>
<div style="display: flex; flex-direction: column; gap: 4px">
<div style="display: flex; justify-content: flex-end">
<BizFilterPreset :values="values" storage-key="demo-search-form" @apply="onApply" />
</div>
<BizSearchForm ref="searchRef" v-model="values" :fields="fields" @search="onSearch" />
<div style="margin-top: 8px; display: flex; gap: 8px; align-items: center; font-size: 12px; color: var(--el-text-color-secondary)">
查询参数:
<ElTag v-for="(v, k) in lastQuery" :key="k" size="small" effect="plain">{{ k }}: {{ Array.isArray(v) ? v.join('~') : v }}</ElTag>
<span v-if="Object.keys(lastQuery).length === 0">(点查询或套用方案后显示)</span>
</div>
</div>
</template>
显示代码
内置方案与默认套用
当前筛选值:{}——「今日待办 / 逾期预警」为内置方案,悬浮无删除入口
isDefault 星标默认方案,初始化经 getDefault() 自动套用;内置方案不可删除。<script setup lang="ts">
/** 内置方案与默认套用:builtin 不可删除;isDefault 星标 + getDefault() 初始化自动套用 */
import { onMounted, ref } from 'vue'
import { ElMessage } from 'element-plus'
import { BizFilterPreset } from 'vue3-ep-biz-lib'
import type { BizFilterPresetItem } from 'vue3-ep-biz-lib'
const presets = ref<BizFilterPresetItem[]>([
{ id: 'sys-1', name: '今日待办', values: { status: 'todo', range: 'today' }, builtin: true, isDefault: true },
{ id: 'sys-2', name: '逾期预警', values: { status: 'overdue' }, builtin: true },
{ id: 'u-1', name: '我创建的', values: { status: 'todo', mine: true } },
])
const current = ref<Record<string, unknown>>({})
const presetRef = ref<{ getDefault: () => BizFilterPresetItem | null }>()
const onApply = (values: Record<string, unknown>, item: BizFilterPresetItem): void => {
current.value = { ...values }
ElMessage.success(`套用「${item.name}」`)
}
onMounted(() => {
const def = presetRef.value?.getDefault()
if (def) {
current.value = { ...def.values }
ElMessage.info(`默认方案「${def.name}」已自动套用`)
}
})
</script>
<template>
<div style="display: flex; flex-direction: column; gap: 12px; max-width: 480px">
<BizFilterPreset
ref="presetRef"
:values="current"
:presets="presets"
trigger-text="工单视图"
@apply="onApply"
@save="(item) => presets.push(item)"
@remove="(id) => (presets = presets.filter((it) => it.id !== id))"
/>
<div style="font-size: 12px; color: var(--el-text-color-secondary)">
当前筛选值:{{ JSON.stringify(current) }}——「今日待办 / 逾期预警」为内置方案,悬浮无删除入口
</div>
</div>
</template>
显示代码
纯消费模式
当前筛选值:{}——下拉底部无「保存当前查询」,方案由运营统一维护
editable=false 关闭保存 / 删除 / 星标,仅保留套用(方案由运营统一维护)。<script setup lang="ts">
/** 纯消费模式:editable=false 关闭保存 / 删除 / 星标,只保留套用;trigger-text 自定义触发文案 */
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
import { BizFilterPreset } from 'vue3-ep-biz-lib'
import type { BizFilterPresetItem } from 'vue3-ep-biz-lib'
const presets: BizFilterPresetItem[] = [
{ id: 'k1', name: '近 30 天活跃客户', values: { range: 30, active: true }, builtin: true },
{ id: 'k2', name: '高客单待回访', values: { minAmount: 5000, todo: 'callback' }, builtin: true },
{ id: 'k3', name: '流失预警', values: { risk: 'churn' }, builtin: true },
]
const current = ref<Record<string, unknown>>({})
const onApply = (values: Record<string, unknown>, item: BizFilterPresetItem): void => {
current.value = { ...values }
ElMessage.success(`套用运营推荐视图「${item.name}」`)
}
</script>
<template>
<div style="display: flex; flex-direction: column; gap: 12px; max-width: 480px">
<BizFilterPreset
:values="current"
:presets="presets"
:editable="false"
trigger-text="推荐视图"
@apply="onApply"
/>
<div style="font-size: 12px; color: var(--el-text-color-secondary)">
当前筛选值:{{ JSON.stringify(current) }}——下拉底部无「保存当前查询」,方案由运营统一维护
</div>
</div>
</template>
显示代码
数量上限
已存 3 / 3 个方案——现在点「保存当前查询」会被拦截提示;删除一个自定义方案后再试即可保存
max 限制方案数量,超上限保存被拦截提示;删除旧方案后恢复可存。<script setup lang="ts">
/** 数量上限:max=3,保存第 4 个方案时提示先清理;删除旧方案后即可继续保存 */
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
import { BizFilterPreset } from 'vue3-ep-biz-lib'
import type { BizFilterPresetItem } from 'vue3-ep-biz-lib'
const items = ref<BizFilterPresetItem[]>([
{ id: 'b1', name: '待支付', values: { status: 'pending' }, builtin: true },
{ id: 'u1', name: '本周已发货', values: { status: 'shipped', week: 1 } },
{ id: 'u2', name: '金额 > 5000', values: { minAmount: 5000 } },
])
const current = ref<Record<string, unknown>>({ status: 'pending', keyword: '打印机' })
const onApply = (values: Record<string, unknown>, item: BizFilterPresetItem): void => {
current.value = { ...values }
ElMessage.success(`套用「${item.name}」`)
}
const onSave = (item: BizFilterPresetItem): void => {
items.value = [...items.value, item]
}
const onRemove = (id: string): void => {
items.value = items.value.filter((it) => it.id !== id)
ElMessage.info('已删除,腾出一个方案名额')
}
</script>
<template>
<div style="display: flex; flex-direction: column; gap: 12px; max-width: 480px">
<BizFilterPreset
:values="current"
:presets="items"
:max="3"
@apply="onApply"
@save="onSave"
@remove="onRemove"
/>
<div style="font-size: 12px; color: var(--el-text-color-secondary)">
已存 {{ items.length }} / 3 个方案——现在点「保存当前查询」会被拦截提示;删除一个自定义方案后再试即可保存
</div>
</div>
</template>
显示代码
Props
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| values | Record<string, unknown> | — | 当前筛选值(保存当前查询的数据源) |
| presets | BizFilterPresetItem[] | — | 受控方案列表(传入即受控模式) |
| storage-key | string | — | 本地存储键(biz-filter-preset:{key}) |
| max | number | 10 | 方案数量上限 |
| editable | boolean | true | 允许保存 / 删除 / 设默认(纯消费置 false) |
| trigger-text | string | 筛选方案 | 触发按钮文案 |
BizFilterPresetItem
| 属性 | 类型 | 说明 |
|---|---|---|
| id | string | 方案标识 |
| name | string | 方案名 |
| values | Record<string, unknown> | 筛选值快照(套用时原样回传) |
| builtin | boolean | 内置方案:不可删除 |
| isDefault | boolean | 默认方案星标 |
Events
| 事件名 | 参数 | 说明 |
|---|---|---|
| apply | (values, item) | 套用方案 |
| save | (item) | 保存新方案(受控模式由业务持久化后回写 presets) |
| remove | (id) | 删除方案 |
| change | (items) | 方案列表变化(本地模式) |
Expose
| 属性/方法 | 说明 |
|---|---|
| getDefault() | 获取星标默认方案(无则 null),可初始化时自动套用 |
| getItems() | 全部方案快照 |
与 BizSearchForm 一等联动
BizSearchForm 传 preset 配置即可内置本组件(保存取值 / 应用回填 + 自动查询 / 事件转发全自动接线),无需手工拼装双方 props——详见 BizSearchForm 文档「筛选方案联动」。