V1.0 · Vue 3 + Element Plus · MIT

smart-filter-vue
配置驱动 + AI 增强的精确筛选组件库

一份字段配置,七个智能筛选组件。componentType 是一等公民,FilterField 自动分发渲染; 所有组件输出统一的 Criteria 语义节点;数据库联想与 AI 解析通过 api 适配器注入,全部可选、优雅降级。

为什么是 smart-filter-vue

精确筛选的交互细节已经做好,你只管声明字段

配置驱动

FilterField 按 field.componentType 自动渲染 7 种组件,统一透传 props、统一转发事件,告别成片的 v-if / v-else-if。

{ }

统一语义输出

每个组件通过 criteria-change 输出标准 Criteria 节点(field / componentType / operator / value),空值输出 null,直接序列化提交任意后端。

AI 增强可选

自然语言时间/数值解析、语义正反向词扩充,由你注入的 api 适配器完成;未配置时规则、直接等本地模式照常可用。

后端无关

库本身不发起任何 HTTP 请求。6 个适配器函数覆盖全部外部能力,可对接任意 REST 后端与任意 AI 服务。

精确优先

选项内值精确匹配(eq / in),自定义输入模糊匹配(like),混选输出 mixed 节点;蓝橙标签让匹配方式一目了然。

三模式时间计算

AI 对话 / 规则 / 直接三种输入模式自由切换,虚拟标签(年龄)与真实字段标签(出生日期)双标签联动。

七个字段组件

纯 HTML/CSS 绘制的示意界面 · 交互细节见 组件详情Playground

智能选项smart_option

选项选择(单选/多选),本地选项过滤不查库,自动区分精确 / 模糊

部门
?
研发部 × 研 🔍 ×
选项
研发部
研究院 配置
要点:选项内值精确(eq/in),回车自定义模糊(like),混选输出 mixed;distinct_scan 灰显配置补充项。
智能文本text_input

文本 LIKE 模糊搜索,数据库 LIKE 实时搜索参考片段,点击上屏

姓名
?
参考结果(点击可填入)
伟(研发部)…
媛(市场部)…
晨,入职于 2021 年…
要点:防抖 500ms 调 suggestFieldValues;参考片段由后端截取;上屏仍可修改,恒为 LIKE。
智能语义搜索semantic_search

关键词经 AI 扩充为正 / 反向词集合,标签化编辑

技能
Vue
智能语义搜索重新生成
Vue × Vue.js × 前端框架 × 实习 ×
要点:魔法棒三态;失焦自动扩充;正向 LIKE OR、反向 NOT LIKE AND。
智能时间计算time_calc

AI 对话 / 规则 / 直接三模式,虚拟字段(年龄)⇄ 真实日期列换算

年龄
35岁以上
AI对话模式 · 时间计算
基准时间:2026-07
出生日期 ≤ 1991-07
1991-07
要点:三模式共享日期值、切换自动翻转算符;直接模式行标签切为"出生日期"。
智能数值计算number_calc

数值比较:规则模式(算符 + 数值)/ AI 对话模式两选一

月薪 ≥ ▾
8000
规则模式 · 数值计算
当前:≥ 8000
要点:between 双输入框;AI 模式输入"大于8000"自动解析;失焦 / 回车发出条件。
布尔开关boolean_switch

三态开关:开 / 关 / 未设置,标签可自定义

在职状态 在职
  未设置(双击/长按重置)
要点:点击切换开/关,双击或长按重置为未设置(不参与筛选);输出标签字符串。
精确ID输入id_input

单个标识码精确查询,eq 匹配,极简交互

工号
E100231 ×
要点:输入即生效,可一键清空;仅单值 eq,不多值、不模糊。
FilterField配置驱动分发器

读取字段配置的 componentType,自动渲染上述组件并统一转发事件——筛选栏里每一行都是它

<FilterField v-model="values[f.field]" :field="f"
  @criteria-change="onCriteriaChange(f.field, $event)" />
要点:componentType 无法识别时渲染禁用占位;另有 FilterSearchBox / FilterMagicIcon / FilterMagicPanel / FilterInfoIcon 四个外壳组件可复用。

快速开始

三分钟跑通:安装 → 注入 api → FilterField 渲染 → 收集 Criteria

bash
npm i smart-filter-vue
# peer 依赖(如尚未安装)
npm i vue@^3 element-plus@^2 @element-plus/icons-vue@^2
main.js
import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import SmartFilter from 'smart-filter-vue'
import 'smart-filter-vue/style.css'
import App from './App.vue'

// mock api:所有函数可选,缺失时组件优雅降级
const mockApi = {
  suggestFieldValues: async (field, keyword, { limit }) => {
    const db = { name: ['张伟', '张媛', '李娜'] }
    const list = (db[field] || []).filter(v => v.includes(keyword))
    return { suggestions: list.slice(0, limit) }
  },
}

createApp(App)
  .use(ElementPlus)
  .use(SmartFilter, { api: mockApi })
  .mount('#app')
App.vue
<script setup>
import { reactive, computed } from 'vue'
import { FilterField } from 'smart-filter-vue'

const fields = [
  { field: 'department', label: '部门',
    componentType: 'smart_option', operator: 'in',
    options: ['研发部', '市场部', '人事部'],
    optionSource: { type: 'static' },
    componentProps: { multiple: true } },
  { field: 'name', label: '姓名',
    componentType: 'text_input', operator: 'like' },
]
const values = reactive({})
const nodes = reactive({})
const criteria = computed(() =>
  Object.values(nodes).filter(Boolean))
</script>

<template>
  <el-form-item v-for="f in fields" :key="f.field"
    :label="f.label">
    <FilterField v-model="values[f.field]" :field="f"
      @criteria-change="nodes[f.field] = $event" />
  </el-form-item>
  <pre>{{ criteria }}</pre>
</template>
输出的 Criteria JSON
[
  { "field": "department", "componentType": "smart_option",
    "operator": "in", "value": ["研发部", "市场部"] },
  { "field": "name", "componentType": "text_input",
    "operator": "like", "value": "张" }
]

文档

使用说明书(仓库 docs/ 目录)