开发预览 更新于 2026-05-10

FilterPanel 筛选侧栏

筛选侧栏壳层 + FilterSection 子项;可选「已保存视图」行;统一的应用 / 重置 footer。

基础用法

CfFilterPanel 是壳层(header + saved views row + body + footer);具体筛选项通过 CfFilterSection 划分章节,每个 section 可折叠、可显示当前应用数。

背景 视口
src/App.vue
<script setup lang="ts">
import { ref } from 'vue';
import { CfFilterPanel, CfFilterSection, CfCheckbox, CfInput, type SavedView } from '@chufix-design/vue';

const views: SavedView[] = [
  { id: 'mine', label: '我的', count: 24 },
  { id: 'team', label: '团队', count: 87 },
  { id: 'all',  label: '全部', count: 312 },
];
const activeView = ref('mine');

const status = ref({ open: true, closed: false, draft: true });
const team   = ref({ design: true, eng: true, pm: false });
const query  = ref('');
</script>
<template>
  <CfFilterPanel
    :saved-views="views"
    :active-view-id="activeView"
    :active-filters="3"
    @view-change="activeView = $event"
    @apply="$emit('apply')"
    @reset="status = { open: false, closed: false, draft: false }; team = { design: false, eng: false, pm: false }; query = ''"
  >
    <CfFilterSection title="搜索">
      <CfInput v-model="query" placeholder="按关键词搜索…" />
    </CfFilterSection>
    <CfFilterSection title="状态" :count="2">
      <label class="demo-row"><CfCheckbox v-model="status.open"   /> 进行中</label>
      <label class="demo-row"><CfCheckbox v-model="status.closed" /> 已完成</label>
      <label class="demo-row"><CfCheckbox v-model="status.draft"  /> 草稿</label>
    </CfFilterSection>
    <CfFilterSection title="团队" :count="2">
      <label class="demo-row"><CfCheckbox v-model="team.design" /> 设计</label>
      <label class="demo-row"><CfCheckbox v-model="team.eng"    /> 工程</label>
      <label class="demo-row"><CfCheckbox v-model="team.pm"     /> 产品</label>
    </CfFilterSection>
  </CfFilterPanel>
</template>
<style scoped>
.demo-row { display: flex; align-items: center; gap: 8px; font-size: var(--t-13); cursor: pointer; }
</style>
<script setup>
import { ref } from 'vue';
import { CfFilterPanel, CfFilterSection, CfCheckbox, CfInput } from '@chufix-design/vue';

const views= [
  { id: 'mine', label: '我的', count: 24 },
  { id: 'team', label: '团队', count: 87 },
  { id: 'all',  label: '全部', count: 312 },
];
const activeView = ref('mine');

const status = ref({ open: true, closed, draft: true });
const team   = ref({ design: true, eng, pm: false });
const query  = ref('');
</script>
<template>
  <CfFilterPanel
    :saved-views="views"
    :active-view-id="activeView"
    :active-filters="3"
    @view-change="activeView = $event"
    @apply="$emit('apply')"
    @reset="status = { open: false, closed, draft: false }; team = { design: false, eng, pm: false }; query = ''"
  >
    <CfFilterSection title="搜索">
      <CfInput v-model="query" placeholder="按关键词搜索…" />
    </CfFilterSection>
    <CfFilterSection title="状态" :count="2">
      <label class="demo-row"><CfCheckbox v-model="status.open"   /> 进行中</label>
      <label class="demo-row"><CfCheckbox v-model="status.closed" /> 已完成</label>
      <label class="demo-row"><CfCheckbox v-model="status.draft"  /> 草稿</label>
    </CfFilterSection>
    <CfFilterSection title="团队" :count="2">
      <label class="demo-row"><CfCheckbox v-model="team.design" /> 设计</label>
      <label class="demo-row"><CfCheckbox v-model="team.eng"    /> 工程</label>
      <label class="demo-row"><CfCheckbox v-model="team.pm"     /> 产品</label>
    </CfFilterSection>
  </CfFilterPanel>
</template>
<style scoped>
.demo-row { display: flex; align-items: center; gap: 8px; font-size: var(--t-13); cursor: pointer; }
</style>
import { useState } from 'react';
import { CfCheckbox, CfFilterPanel, CfFilterSection, CfInput } from '@chufix-design/react';

export default function Demo() {
  const views: SavedView[] = [
    { id: 'mine', label: '我的', count: 24 },
    { id: 'team', label: '团队', count: 87 },
    { id: 'all',  label: '全部', count: 312 },
  ];
  const [activeView, setActiveView] = useState('mine');

  const [status, setStatus] = useState({ open: true, closed: false, draft: true });
  const [team, setTeam] = useState({ design: true, eng: true, pm: false });
  const [query, setQuery] = useState('');
  return (
    <>
      <CfFilterPanel savedViews={views} activeViewId={activeView} activeFilters={3} onViewChange={() => setActiveView($event)}
          onApply={() => $emit('apply')}
          onReset={() => setStatus({ open: false), closed: false, draft: false }; setTeam({ design: false), eng: false, pm: false }; setQuery('')}
        >
          <CfFilterSection title="搜索">
            <CfInput value={query} onChange={setQuery} placeholder="按关键词搜索…" />
          </CfFilterSection>
          <CfFilterSection title="状态" count={2}>
            <label className="demo-row"><CfCheckbox value={status.open} /> 进行中</label>
            <label className="demo-row"><CfCheckbox value={status.closed} /> 已完成</label>
            <label className="demo-row"><CfCheckbox value={status.draft} /> 草稿</label>
          </CfFilterSection>
          <CfFilterSection title="团队" count={2}>
            <label className="demo-row"><CfCheckbox value={team.design} /> 设计</label>
            <label className="demo-row"><CfCheckbox value={team.eng} /> 工程</label>
            <label className="demo-row"><CfCheckbox value={team.pm} /> 产品</label>
          </CfFilterSection>
        </CfFilterPanel>
    </>
  );
}
import { useState } from 'react';
import { CfCheckbox, CfFilterPanel, CfFilterSection, CfInput } from '@chufix-design/react';

export default function Demo() {
  const views= [
    { id: 'mine', label: '我的', count: 24 },
    { id: 'team', label: '团队', count: 87 },
    { id: 'all',  label: '全部', count: 312 },
  ];
  const [activeView, setActiveView] = useState('mine');

  const [status, setStatus] = useState({ open: true, closed, draft: true });
  const [team, setTeam] = useState({ design: true, eng, pm: false });
  const [query, setQuery] = useState('');
  return (
    <>
      <CfFilterPanel savedViews={views} activeViewId={activeView} activeFilters={3} onViewChange={() => setActiveView($event)}
          onApply={() => $emit('apply')}
          onReset={() => setStatus({ open: false), closed, draft: false }; setTeam({ design: false), eng, pm: false }; setQuery('')}
        >
          <CfFilterSection title="搜索">
            <CfInput value={query} onChange={setQuery} placeholder="按关键词搜索…" />
          </CfFilterSection>
          <CfFilterSection title="状态" count={2}>
            <label className="demo-row"><CfCheckbox value={status.open} /> 进行中</label>
            <label className="demo-row"><CfCheckbox value={status.closed} /> 已完成</label>
            <label className="demo-row"><CfCheckbox value={status.draft} /> 草稿</label>
          </CfFilterSection>
          <CfFilterSection title="团队" count={2}>
            <label className="demo-row"><CfCheckbox value={team.design} /> 设计</label>
            <label className="demo-row"><CfCheckbox value={team.eng} /> 工程</label>
            <label className="demo-row"><CfCheckbox value={team.pm} /> 产品</label>
          </CfFilterSection>
        </CfFilterPanel>
    </>
  );
}

CfFilterPanel API

属性类型默认说明
titlestring'筛选'头部标题
savedViewsSavedView[]顶部已保存视图横排;省略则不渲染该行
activeViewIdstring当前激活的视图 id
activeFiltersnumber头部右侧 badge 显示已应用筛选数
showFooterbooleantrue显示 清空 / 应用 footer
applyingbooleanfalseapply 按钮 loading 态

Events

VueReactpayload
view-changeonViewChange(id, view)
applyonApply
resetonReset

CfFilterSection API

属性类型默认说明
titlestring章节标题
countnumber章节内已应用筛选数
open / defaultOpenboolean— / true受控 / 默认展开

反馈与讨论

FilterPanel 筛选侧栏 的讨论

0
0 / 600
正在加载评论...