OpenProject 7.2.3 Assigned to 过滤器行为修复新增 Assignee or belonging group 过滤器实战解析【免费下载链接】openprojectOpenProject is the leading open source project management software for product, project and portfolio management. A powerful Jira alternative with agile planning, issue tracking, roadmaps, Gantt charts, time tracking, collaboration features, and more. Available on premises or in the cloud. ⭐ Star us on GitHub项目地址: https://gitcode.com/GitHub_Trending/op/openproject本篇技术指南聚焦 OpenProject 7.2.3 版本中工作包Work Package过滤器的一次关键行为变更修复自 7.0 起Assigned to指派给过滤器按单个用户筛选时会顺带返回分配给该用户所属用户组的工作包导致部分依赖精确指派语义的团队无法正确筛选。本版本恢复了原有精确行为并新增 Assignee or belonging group指派人或所属组 过滤器以保留扩展语义。读完本文你将掌握这两个过滤器的语义差异、使用场景、底层实现原理与测试验证方式。修复背景7.0 引入的组指派行为变更在 OpenProject 7.0 之前当用户在过滤器Assigned to中选择单个用户时系统只返回直接分配给该用户的工作包。从 7.0 起开发团队有意做了一处行为调整为了让按用户筛选时也能覆盖指派给组的场景过滤器被改为同时返回分配给所选用户本人的工作包分配给该用户所属任意用户组的工作包。这一改动在组指派协作场景下是便利的例如组内成员应能看到分配给本组的工作包但对另一些团队而言却打破了原有预期——他们依赖只返回分配给单一用户的工作包这一精确语义例如用于个人待办统计、绩效考核或跨组职责隔离。该问题被记录为 bug #26207此处仅作引用标识不展开外部链接。修复方案恢复原行为 新增独立过滤器7.2.3 的修复采用兼容与取舍并存的策略而不是简单回退Assigned to 过滤器恢复 7.0 之前的精确行为选择单个用户时只返回分配给该用户本人的工作包不再隐式包含其所属组的工作包。新增 Assignee or belonging group 过滤器对于仍然需要用户 其所属组扩展语义的团队可以使用这个新过滤器语义更加明确、可控。这种设计让两类用户各取所需需要精确指派的团队恢复原有习惯需要组扩展语义的团队获得一个语义显式、可独立配置的过滤入口。新过滤器 Assignee or belonging group 的语义根据官方发布说明新过滤器在两种取值场景下的行为如下筛选单个用户时返回分配给该用户的工作包以及分配给该用户所属任意用户组的工作包筛选一个用户组时返回分配给该组的工作包以及分配给组内任意用户的工作包。也就是说该过滤器在用户 ⇄ 组两个方向上做双向扩展选用户则带上其所属组选组则带上其成员。这与旧的 Assigned to 行为相比更完整且方向性明确。源码级解析AssigneeOrGroupFilter 的实现原理新过滤器在仓库中的核心实现位于 app/models/queries/work_packages/filter/assignee_or_group_filter.rb类定义为Queries::WorkPackages::Filter::AssigneeOrGroupFilter继承自PrincipalBaseFilterprincipal_base_filter.rb。关键设计点过滤器键keyself.key返回:assignee_or_group这是它在查询系统中的唯一标识也是 API 与前端引用它的依据。过滤器类型type返回:list_optional即可选列表类型——可以不填值也可以选择多个 principal用户/组/占位用户。显示名称human_name读取国际化键query_fields.assignee_or_group在 config/locales/en.yml 中定义为Assignee or belonging group。SQL 生成where方法基于assigned_to_id字段构造条件即过滤底层仍是工作包的指派字段只是传入的取值集合被动态扩展。取值扩展的核心逻辑values_replaced该过滤器语义的关键在values_replaced方法同文件第 55-59 行它对用户选择的每个值做双向扩展def values_replaced vals super vals group_members_added(vals) vals user_groups_added(vals) endgroup_members_added(vals)当选中值是用户组 ID时通过User.joins(:groups).where(groups_users: { id: vals })查出这些组的所有成员用户 ID一并加入取值集合——对应选组则含成员。user_groups_added(vals)当选中值是用户 ID时通过Group.joins(:users).where(users_users: { id: vals })查出这些用户所属的所有组 ID一并加入取值集合——对应选用户则含其所属组。最终生成的 SQL 条件即assigned_to_id IN (选中值 扩展出的组/成员 ID)。这一实现直接印证了发布说明中双向扩展的语义描述。与 AssignedToFilter 的对比原有的 assigned_to_filter.rb 中AssignedToFilter与新版过滤器同继承自PrincipalBaseFilter但没有覆写values_replaced因此取值集合不被扩展assigned_to_id严格等于用户所选值——这就是 7.2.3 恢复的精确行为。两者共享基类提供的公共能力包括allowed_values由me_allowed_value我与principal_loader.principal_values当前项目可选的 principal 列表构成available?仅当用户已登录或存在可选值时才可用autocomplete_options渲染服务端自动补全组件opce-user-autocompleter资源指向 API v3 的 principals 端点并按当前项目成员范围过滤。过滤器注册机制工作包过滤器通过统一注册表接入查询系统注册位置在 app/models/queries/work_packages.rb::Queries::Register.register(Query) do filter Filter::AncestorFilter filter Filter::AssignedToFilter filter Filter::AssigneeOrGroupFilter # ... end只要在此注册新过滤器即自动出现在工作包查询的可用过滤器集合中供列表视图、保存的查询Saved Query以及 API 使用。API v3 层的支持新过滤器在 API v3 查询 Schema 层有对应的依赖描述器lib/api/v3/queries/schemas/assignee_or_group_filter_dependency_representer.rb 中的AssigneeOrGroupFilterDependencyRepresenter继承自ProjectMembersFilterDependencyRepresenter。从 filter_dependency_representer_factory.rb 的分发逻辑可以看到AssignedToFilter被映射为ProjectMembersFilter依赖描述器第 59 行而AssigneeOrGroupFilter因为存在同名专属描述器类会通过filter_specific_representer_class优先命中专属类。这说明该过滤器在 API 表单中同样表现为项目成员类型的候选值选择器与旧过滤器在交互层保持一致仅语义不同。测试验证行为即契约仓库为新过滤器提供了完整的单元测试spec/models/queries/work_packages/filter/assignee_or_group_filter_spec.rb覆盖了全部关键分支是理解语义最直观的契约文档测试场景过滤取值预期结果用户值工作包直接指派给该用户[assignee.id]返回该工作包me值当前登录用户即被指派人[me]返回该工作包me值但当前登录的是另一用户[me]不返回组值工作包直接指派给该组[group.id]返回该工作包组值工作包指派给组内成员[group.id]返回该工作包组成员被扩展占位用户placeholder user值[placeholder_user.id]返回指派给它的工作包组值组内无人被指派[group.id]不返回用户值工作包指派给该用户所属的组[user.id]返回该工作包所属组被扩展用户值该用户不属于被指派的组[user.id]不返回无效值[0]不返回此外测试还验证了valid_values!会剔除不在候选集中的非法值如99999保证过滤器取值始终落在合法 principal 集合内。这些测试用例与 发布说明 中描述的两种语义完全对应。使用建议与注意事项明确需求再选择过滤器如果团队工作流严格依赖按人精确指派请继续使用 Assigned to如果需要人 其所属组的聚合视图请改用 Assignee or belonging group。前端使用注意在部分按需定制的前端页面中该过滤器会被主动隐藏。例如团队规划器Team Planner页面在 team-planner-page.component.ts 中将assigneeOrGroup、assignee、memberOfGroup等过滤器加入隐藏列表避免与规划器自身的筛选机制冲突。自定义查询时需留意此类隐藏逻辑。语义只影响过滤不改变指派字段两个过滤器底层都作用于assigned_to_id字段扩展逻辑仅发生在查询取值阶段不会改动工作包的实际指派数据。版本前提本修复及新过滤器随 OpenProject 7.2.32017-09-04 发布引入若你的实例早于该版本则无法获得新过滤器与修复后的精确行为升级前请先在测试环境验证过滤结果是否符合预期。延伸阅读发布说明原文docs/release-notes/7/7-2-3/README.md新过滤器实现app/models/queries/work_packages/filter/assignee_or_group_filter.rb原过滤器实现app/models/queries/work_packages/filter/assigned_to_filter.rb过滤器公共基类app/models/queries/work_packages/filter/principal_base_filter.rb过滤器注册表app/models/queries/work_packages.rbAPI 依赖描述器lib/api/v3/queries/schemas/assignee_or_group_filter_dependency_representer.rb单元测试spec/models/queries/work_packages/filter/assignee_or_group_filter_spec.rb【免费下载链接】openprojectOpenProject is the leading open source project management software for product, project and portfolio management. A powerful Jira alternative with agile planning, issue tracking, roadmaps, Gantt charts, time tracking, collaboration features, and more. Available on premises or in the cloud. ⭐ Star us on GitHub项目地址: https://gitcode.com/GitHub_Trending/op/openproject创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考