smithery.ai

add-multi-filter

为Flutter插件视图添加多条件过滤功能(MultiFilterBar),支持标签、?

First seen Apr 17, 2026

Installation

$ npx skills add https://smithery.ai

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery.ai · top by installs.

npx skills add https://smithery.ai

Browse all from smithery.ai

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 16,905 B
  • docs SUMMARY.md 383 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 1 installs

SKILL.md

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

  • <view-file>: 目标 Flutter 视图文件路径(包含 SuperCupertinoNavigationWrapper)
  • --filters <types>: 过滤条件类型列表(逗号分隔)

- 可选值:tags, keyword, priority, date, dateRange, status, custom - 默认:自动检测(基于控制器方法)

  • --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:

  1. 移除 FilterDialog 导入
  2. 删除 _showFilterDialog() 方法
  3. 移除 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方法 返回值
标签多选 tagsMultiple buildTagsFilter tagsBadge List<String>
标签单选 tagsSingle buildTagFilter tagBadge String?
关键词 input buildKeywordFilter keywordBadge String
优先级 custom buildPriorityFilter<T> priorityBadge T?
日期范围 dateRange buildDateRangeFilter dateRangeBadge DateTimeRange?
单日期 date buildDateFilter dateBadge DateTime?
复选框 checkbox buildCheckboxFilter checkboxBadge Map<String, bool>
自定义 custom 自定义 widget 自定义函数 任意类型

Detection Patterns

Tags Filter

查找方法:

  • getAllTags(), getTags()
  • 返回类型:List<String> 或 Set<String>

Priority Filter

查找枚举:

  • 名称包含 Priority
  • 值:low, medium, high

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 获取更多示例