FilterPanel 筛选侧栏
筛选侧栏壳层 + FilterSection 子项;可选「已保存视图」行;统一的应用 / 重置 footer。
基础用法
CfFilterPanel 是壳层(header + saved views row + body + footer);具体筛选项通过 CfFilterSection 划分章节,每个 section 可折叠、可显示当前应用数。
背景 视口
<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
| 属性 | 类型 | 默认 | 说明 |
|---|---|---|---|
title | string | '筛选' | 头部标题 |
savedViews | SavedView[] | — | 顶部已保存视图横排;省略则不渲染该行 |
activeViewId | string | — | 当前激活的视图 id |
activeFilters | number | — | 头部右侧 badge 显示已应用筛选数 |
showFooter | boolean | true | 显示 清空 / 应用 footer |
applying | boolean | false | apply 按钮 loading 态 |
Events
| Vue | React | payload |
|---|---|---|
view-change | onViewChange | (id, view) |
apply | onApply | — |
reset | onReset | — |
CfFilterSection API
| 属性 | 类型 | 默认 | 说明 |
|---|---|---|---|
title | string | — | 章节标题 |
count | number | — | 章节内已应用筛选数 |
open / defaultOpen | boolean | — / true | 受控 / 默认展开 |
反馈与讨论
FilterPanel 筛选侧栏 的讨论