Claude-skill-registry add-multi-filter
为Flutter插件视图添加多条件过滤功能(MultiFilterBar),支持标签、关键词、日期、优先级、复选框等多种过滤类型。替代传统的FilterDialog,提供更直观的两层级交互UI。适用场景:(1) 列表视图需要多维度筛选,(2) 数据量较大需要快速过滤,(3) 需要实时显示过滤条件的应用
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/add-multi-filter" ~/.claude/skills/majiayu000-claude-skill-registry-add-multi-filter && rm -rf "$T"
manifest:
skills/data/add-multi-filter/SKILL.mdsource content
Add Multi-Filter
为Flutter插件视图添加强大的多条件过滤功能,使用 SuperCupertinoNavigationWrapper 的 MultiFilterBar 组件。
Usage
# 基础用法 - 自动检测过滤需求 /add-multi-filter <view-file> # 指定过滤条件类型 /add-multi-filter <view-file> --filters tags,priority,date,status # 指定控制器变量名 /add-multi-filter <view-file> --controller _controller
Examples:
# 为待办事项插件添加过滤 /add-multi-filter lib/plugins/todo/views/todo_main_view.dart # 为日记插件添加标签和日期过滤 /add-multi-filter lib/plugins/diary/views/diary_list_view.dart --filters tags,dateRange # 自定义控制器名称 /add-multi-filter lib/plugins/activity/views/activity_list_view.dart --controller _activityController
Arguments
: 目标 Flutter 视图文件路径(包含 SuperCupertinoNavigationWrapper)<view-file>
: 过滤条件类型列表(逗号分隔)--filters <types>- 可选值:
,tags
,keyword
,priority
,date
,dateRange
,statuscustom - 默认:自动检测(基于控制器方法)
- 可选值:
: 控制器变量名(默认:自动检测)--controller <name>
Workflow
1. Analyze Target File
读取目标文件并识别:
- SuperCupertinoNavigationWrapper 位置
- 控制器变量名(如
)_plugin.taskController - 现有的过滤/排序功能
- 可用的数据(标签列表、优先级枚举等)
2. Add Required Imports
在文件顶部添加导入:
import 'package:Memento/widgets/super_cupertino_navigation_wrapper/index.dart';
3. Create Filter Items Method
创建
_buildFilterItems() 方法,根据检测到的数据结构构建过滤条件:
/// 构建过滤条件列表 List<FilterItem> _buildFilterItems() { // 获取动态数据 final availableTags = _controller.getAllTags(); return [ // 1. 标签多选过滤(如果有标签) if (availableTags.isNotEmpty) FilterItem( id: 'tags', title: 'plugin_tags'.tr, type: FilterType.tagsMultiple, builder: (context, currentValue, onChanged) { return FilterBuilders.buildTagsFilter( context: context, currentValue: currentValue, onChanged: onChanged, availableTags: availableTags, ); }, getBadge: FilterBuilders.tagsBadge, ), // 2. 优先级过滤(如果有优先级枚举) FilterItem( id: 'priority', title: 'plugin_priority'.tr, type: FilterType.custom, builder: (context, currentValue, onChanged) { return FilterBuilders.buildPriorityFilter<PriorityEnum>( context: context, currentValue: currentValue, onChanged: onChanged, priorityLabels: { PriorityEnum.low: 'plugin_low'.tr, PriorityEnum.medium: 'plugin_medium'.tr, PriorityEnum.high: 'plugin_high'.tr, }, priorityColors: const { PriorityEnum.low: Colors.green, PriorityEnum.medium: Colors.orange, PriorityEnum.high: Colors.red, }, ); }, getBadge: (value) => FilterBuilders.priorityBadge( value, { PriorityEnum.low: 'plugin_low'.tr, PriorityEnum.medium: 'plugin_medium'.tr, PriorityEnum.high: 'plugin_high'.tr, }, ), ), // 3. 日期范围过滤 FilterItem( id: 'dateRange', title: 'plugin_dateRange'.tr, type: FilterType.dateRange, builder: (context, currentValue, onChanged) { return FilterBuilders.buildDateRangeFilter( context: context, currentValue: currentValue, onChanged: onChanged, ); }, getBadge: FilterBuilders.dateRangeBadge, ), // 4. 状态复选框过滤 FilterItem( id: 'status', title: 'plugin_status'.tr, type: FilterType.checkbox, builder: (context, currentValue, onChanged) { return FilterBuilders.buildCheckboxFilter( context: context, currentValue: currentValue, onChanged: onChanged, options: { 'option1': 'plugin_option1'.tr, 'option2': 'plugin_option2'.tr, }, ); }, getBadge: FilterBuilders.checkboxBadge, initialValue: const { 'option1': true, 'option2': true, }, ), ]; }
4. Create Filter Handler Method
创建
_applyMultiFilters() 方法处理过滤变更:
/// 应用多条件过滤 void _applyMultiFilters(Map<String, dynamic> filters) { // 构建过滤参数 final filterParams = <String, dynamic>{}; // 标签过滤 if (filters['tags'] != null && (filters['tags'] as List).isNotEmpty) { filterParams['tags'] = filters['tags']; } // 优先级过滤 if (filters['priority'] != null) { filterParams['priority'] = filters['priority']; } // 日期范围过滤 if (filters['dateRange'] != null) { final range = filters['dateRange'] as DateTimeRange; filterParams['startDate'] = range.start; filterParams['endDate'] = range.end; } // 状态过滤 if (filters['status'] != null) { final status = filters['status'] as Map<String, bool>; filterParams['option1'] = status['option1'] ?? true; filterParams['option2'] = status['option2'] ?? true; } // 应用过滤 if (filterParams.isEmpty) { _controller.clearFilter(); } else { _controller.applyFilter(filterParams); } setState(() {}); }
5. Update SuperCupertinoNavigationWrapper
在 SuperCupertinoNavigationWrapper 中添加多条件过滤配置:
SuperCupertinoNavigationWrapper( // ... 现有配置 ... // 启用多条件过滤 enableMultiFilter: true, multiFilterItems: _buildFilterItems(), multiFilterBarHeight: 50, onMultiFilterChanged: _applyMultiFilters, // ... 其他配置 ... )
6. Remove Old Filter Dialog (Optional)
如果存在旧的 FilterDialog:
- 移除 FilterDialog 导入
- 删除
方法_showFilterDialog() - 移除 actions 中的 filter 按钮:
// 移除这个按钮 IconButton( icon: const Icon(Icons.filter_alt), onPressed: _showFilterDialog, // ❌ 删除 ),
7. Add Internationalization Strings
在插件的国际化文件中添加必要的字符串:
中文 (zh):
'plugin_tags': '标签', 'plugin_priority': '优先级', 'plugin_low': '低', 'plugin_medium': '中', 'plugin_high': '高', 'plugin_dateRange': '日期范围', 'plugin_status': '状态', 'plugin_option1': '选项1', 'plugin_option2': '选项2',
英文 (en):
'plugin_tags': 'Tags', 'plugin_priority': 'Priority', 'plugin_low': 'Low', 'plugin_medium': 'Medium', 'plugin_high': 'High', 'plugin_dateRange': 'Date Range', 'plugin_status': 'Status', 'plugin_option1': 'Option 1', 'plugin_option2': 'Option 2',
Filter Types Guide
Available Filter Types
| 类型 | FilterType | 构建器方法 | Badge方法 | 返回值 |
|---|---|---|---|---|
| 标签多选 | | | | |
| 标签单选 | | | | |
| 关键词 | | | | |
| 优先级 | | | | |
| 日期范围 | | | | |
| 单日期 | | | | |
| 复选框 | | | | |
| 自定义 | | 自定义 widget | 自定义函数 | 任意类型 |
Detection Patterns
Tags Filter
查找方法:
,getAllTags()getTags()- 返回类型:
或List<String>Set<String>
Priority Filter
查找枚举:
- 名称包含
Priority - 值:
,low
,mediumhigh
Date Filter
查找方法:
接受applyFilter()
,startDate
参数endDate
类型的字段DateTime
Status Filter
查找方法:
接受applyFilter()
,showCompleted
等布尔参数showIncomplete
Controller Requirements
控制器需要实现以下方法:
class YourController extends ChangeNotifier { // 必需:应用过滤 void applyFilter(Map<String, dynamic> filter) { // 实现过滤逻辑 } // 必需:清除过滤 void clearFilter() { // 清除所有过滤条件 } // 可选:获取标签列表 List<String> getAllTags() { return _items.expand((item) => item.tags).toSet().toList(); } // 可选:获取过滤后的数据 List<YourModel> get filteredItems { return _applyFilterLogic(_items); } }
Example: Complete Implementation
以下是一个完整的示例(基于 todo 插件):
import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:Memento/widgets/super_cupertino_navigation_wrapper.dart'; import 'package:Memento/widgets/super_cupertino_navigation_wrapper/index.dart'; import 'package:Memento/plugins/todo/models/task.dart'; import 'package:Memento/plugins/todo/todo_plugin.dart'; class TodoListView extends StatefulWidget { const TodoListView({super.key}); @override State<TodoListView> createState() => _TodoListViewState(); } class _TodoListViewState extends State<TodoListView> { late TodoPlugin _plugin; @override void initState() { super.initState(); _plugin = TodoPlugin.instance; } /// 构建过滤条件列表 List<FilterItem> _buildFilterItems() { final availableTags = _plugin.taskController.getAllTags(); return [ // 标签多选 if (availableTags.isNotEmpty) FilterItem( id: 'tags', title: 'todo_tags'.tr, type: FilterType.tagsMultiple, builder: (context, currentValue, onChanged) { return FilterBuilders.buildTagsFilter( context: context, currentValue: currentValue, onChanged: onChanged, availableTags: availableTags, ); }, getBadge: FilterBuilders.tagsBadge, ), // 优先级 FilterItem( id: 'priority', title: 'todo_priority'.tr, type: FilterType.custom, builder: (context, currentValue, onChanged) { return FilterBuilders.buildPriorityFilter<TaskPriority>( context: context, currentValue: currentValue, onChanged: onChanged, priorityLabels: { TaskPriority.low: 'todo_low'.tr, TaskPriority.medium: 'todo_medium'.tr, TaskPriority.high: 'todo_high'.tr, }, priorityColors: const { TaskPriority.low: Colors.green, TaskPriority.medium: Colors.orange, TaskPriority.high: Colors.red, }, ); }, getBadge: (value) => FilterBuilders.priorityBadge( value, { TaskPriority.low: 'todo_low'.tr, TaskPriority.medium: 'todo_medium'.tr, TaskPriority.high: 'todo_high'.tr, }, ), ), // 日期范围 FilterItem( id: 'dateRange', title: 'todo_dateRange'.tr, type: FilterType.dateRange, builder: (context, currentValue, onChanged) { return FilterBuilders.buildDateRangeFilter( context: context, currentValue: currentValue, onChanged: onChanged, ); }, getBadge: FilterBuilders.dateRangeBadge, ), // 完成状态 FilterItem( id: 'status', title: 'todo_status'.tr, type: FilterType.checkbox, builder: (context, currentValue, onChanged) { return FilterBuilders.buildCheckboxFilter( context: context, currentValue: currentValue, onChanged: onChanged, options: { 'showCompleted': 'todo_showCompleted'.tr, 'showIncomplete': 'todo_showIncomplete'.tr, }, ); }, getBadge: FilterBuilders.checkboxBadge, initialValue: const { 'showCompleted': true, 'showIncomplete': true, }, ), ]; } /// 应用多条件过滤 void _applyMultiFilters(Map<String, dynamic> filters) { final filterParams = <String, dynamic>{}; if (filters['tags'] != null && (filters['tags'] as List).isNotEmpty) { filterParams['tags'] = filters['tags']; } if (filters['priority'] != null) { filterParams['priority'] = filters['priority']; } if (filters['dateRange'] != null) { final range = filters['dateRange'] as DateTimeRange; filterParams['startDate'] = range.start; filterParams['endDate'] = range.end; } if (filters['status'] != null) { final status = filters['status'] as Map<String, bool>; filterParams['showCompleted'] = status['showCompleted'] ?? true; filterParams['showIncomplete'] = status['showIncomplete'] ?? true; } if (filterParams.isEmpty) { _plugin.taskController.clearFilter(); } else { _plugin.taskController.applyFilter(filterParams); } setState(() {}); } @override Widget build(BuildContext context) { return SuperCupertinoNavigationWrapper( title: Text('todo_tasks'.tr), largeTitle: 'todo_tasks'.tr, // 启用多条件过滤 enableMultiFilter: true, multiFilterItems: _buildFilterItems(), multiFilterBarHeight: 50, onMultiFilterChanged: _applyMultiFilters, body: AnimatedBuilder( animation: _plugin.taskController, builder: (context, _) { return TaskListWidget( tasks: _plugin.taskController.filteredTasks, ); }, ), ); } }
Best Practices
1. Filter Count
建议不超过 4-5 个过滤条件,过多会影响用户体验。
2. Dynamic Data
对于动态数据(如标签列表),使用条件渲染:
if (availableTags.isNotEmpty) FilterItem( id: 'tags', // ... ),
3. Initial Values
为常用过滤条件设置合理的初始值:
FilterItem( id: 'status', // ... initialValue: const { 'showCompleted': true, 'showIncomplete': true, }, ),
4. Performance
在
onMultiFilterChanged 中使用防抖处理(如果过滤操作很耗时):
Timer? _filterDebounce; void _applyMultiFilters(Map<String, dynamic> filters) { _filterDebounce?.cancel(); _filterDebounce = Timer(const Duration(milliseconds: 300), () { // 执行过滤逻辑 }); }
5. Internationalization
所有用户可见的文本都应该使用国际化:
title: 'plugin_filterName'.tr,
Testing Checklist
完成后验证:
-
无错误flutter analyze - 所有过滤条件都能正常工作
- Badge 正确显示过滤状态
- 清空按钮能清除所有过滤
- 搜索模式下过滤栏正确隐藏
- 组合多个过滤条件测试
- 国际化字符串完整
Troubleshooting
过滤不生效
检查控制器的
applyFilter() 方法是否正确实现。
Badge 不显示
确保
getBadge 函数返回非空字符串。
标签列表为空
检查
getAllTags() 方法是否正确返回数据。
日期选择器异常
确保导入了 Material 组件:
import 'package:flutter/material.dart';
Notes
- 使用中文注释与现有代码库保持一致
- 优先使用 FilterBuilders 提供的构建器方法
- 自定义过滤器时注意类型安全
- 使用
验证代码flutter analyze - 参考
获取更多示例USAGE_EXAMPLE.md