OpenProject 9.0 新版本特性解读:看板视图、工作包模板与源码实现剖析
【免费下载链接】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 9.0(发布于 2019-06-06)是该版本系列的起点版本,核心引入了三大能力:面向 Scrum/Kanban 的看板视图(Boards,Enterprise 附加模块)、工作包模板(Work Package Templates),以及可个性化定制工作包视图的 My 页面。本文以 9.0.0 版本发布说明为主线,逐一讲解各特性的功能定位与使用方式,并结合当前仓库中modules/boards的源码实现,剖析看板视图背后的数据模型、创建服务与权限体系,帮助读者既会用功能,也看得懂底层原理。
一、OpenProject 9.0 发布总览
9.0.0 是 OpenProject 9.x 系列的首个版本,后续 9.x 维护版本(9.0.1 ~ 9.0.4,发布于 2019-06-07 至 2019-10-02)见 9.x 版本发布说明索引。9.0.0 的新特性可概括为以下五点:
| 特性 | 说明 | 适用版本 |
|---|---|---|
| 看板视图(Boards) | 以看板形式管理工作包,支持 Scrum 与 Kanban 式敏捷管理 | Enterprise 云版 / Enterprise 本地版附加模块 |
| 工作包模板 | 为工作包类型定义模板,新建同类型工作包时自动填充描述 | 全部版本 |
| My 页面工作包小组件 | 每个用户可在 My 页面添加并自定义工作包视图 | 全部版本 |
| 工作包表格更新 | 负责人以头像直接显示,工作包类型选择器更新 | 全部版本 |
| 易用性改进 + 大量 Bug 修复 | 会议附件、全局工作包表筛选联动、过滤器自动补全等 | 全部版本 |
二、看板视图:Enterprise 敏捷管理新模块
2.1 功能定位与使用方式
看板视图(Board view)是 9.0 引入的全新模块,支持 Scrum 和 Kanban 风格的敏捷项目管理。根据发布说明,看板视图支持以下组织方式:
- 按状态分列:不同状态显示为看板列(类似 Kanban 板),可以直观、快速地更新工作包状态;
- 基础看板:使用自定义名称定义列,用于灵活搭建工作流;
- 按版本分列:以版本作为列(例如用于规划产品路线图)。
由于看板与工作包表格一样都是对工作包(Work Packages)的呈现方式,因此可以方便地把传统项目管理和敏捷管理结合起来:先在甘特图(Gantt chart)中排期任务,再在看板视图中推进执行。
需要特别注意的是版本边界:9.0 时期,使用看板功能必须使用 Enterprise 云版或 Enterprise 本地版;Community 版用户当时需要通过申请 Enterprise 试用许可证来体验。更详细的使用文档参见用户指南中的 Agile Boards 章节。
2.2 源码剖析:看板即“网格 + 查询”
当前仓库中的 boards 模块 保留了该功能的核心实现,可以作为理解 9.0 看板架构的最佳依据。
数据模型:Boards::Grid 继承自 Grids::Grid。在 grid.rb 中可以看到,看板在数据库层面并不是独立的“列 + 卡片”结构,而是一个网格模型:
module Boards class Grid < ::Grids::Grid belongs_to :project belongs_to :linked, polymorphic: true, optional: true, inverse_of: :task_boards validates :name, presence: true before_destroy :delete_queries, prepend: true set_acts_as_attachable_options view_permission: :show_board_views, delete_permission: :manage_board_views, add_permission: :manage_board_views这揭示了看板架构的三层结构:
- Grid(网格):整个看板本身,绑定到项目(
belongs_to :project),可附带附件; - Widget(组件/列):每一列是一个
Grids::Widget,通过start_column等属性占据网格位置,其options中携带一个queryId,指向一个独立的工作包查询; - Query(查询):列内展示的工作包完全由查询定义决定——这正是发布说明中“看板与工作包表格一样,都是工作包的呈现”的技术本质。
同时,源码明确了看板视图的权限三件套:查看需show_board_views,新增/删除需manage_board_views。common.yml 中的默认角色授权也印证了这一点:非成员(default_role_non_member)与只读者(default_role_reader)仅获得show_board_views,成员(default_role_member)额外获得manage_public_queries和manage_board_views。
列的两种类型。看板列的类型由 Grid 的 options 决定:board_type返回options[:type],取值为:free(自由列,基础看板)或:action(按某个工作包属性驱动,如状态);:action类型时再通过board_type_attribute记录具体属性名。这与发布说明中“状态列 / 自定义名称列 / 版本列”的划分一一对应。
创建流程:每种看板类型一个创建服务。在 boards_controller.rb 中,service_class方法按前端传入的attribute参数分派到不同的创建服务:
def service_class { "basic" => Boards::BasicBoardCreateService, "status" => Boards::StatusBoardCreateService, "assignee" => Boards::AssigneeBoardCreateService, "version" => Boards::VersionBoardCreateService, "subproject" => Boards::SubprojectBoardCreateService, "subtasks" => Boards::SubtasksBoardCreateService }.fetch(board_grid_params[:attribute]) end以状态看板为例,StatusBoardCreateService 会创建一个以默认状态过滤的公共查询,并把它挂到唯一的工作包查询组件上:
def query_filters [{ status_id: { operator: "=", values: [default_status.id.to_s] } }] end def options_for_widgets(params) [ Grids::Widget.new( start_row: 1, start_column: 1, end_row: 2, end_column: 2, identifier: "work_package_query", options: { "queryId" => params[:query_id], "filters" => query_filters } ) ] end而父类 BaseCreateService 封装了通用流程:before_perform阶段先通过Queries::CreateService创建查询并回填query_id,再构造Boards::Grid实例(默认 1 行 × 4 列:row_count_for_board返回 1、column_count_for_board返回 4)。从源码结构看,创建看板 = “先建查询、再建网格、把查询挂到组件上”,这与 2.1 节描述的“列即查询”模型完全吻合。
此外,当前仓库中还包含 SprintTaskBoardCreateService,它通过多态关联linked(linked_type: "Sprint")把看板与迭代(Sprint)绑定,并为每个状态创建一个查询、按列排布组件——这属于 9.0 之后版本对 Boards 模块的扩展,可作为理解该模块演进方向的参考。
生命周期管理。Boards::Grid的before_destroy :delete_queries回调(见 grid.rb)会在删除看板时,经 Policy 校验后级联清理其组件中关联的查询,保证不残留孤儿查询数据。控制器层面同样有双重校验:BoardsController在show/split_view之前执行authorize_work_package_permission,即“拥有 boards 权限并不足以查看工作包”,还需具备view_work_packages项目权限(见 boards_controller.rb)。
三、工作包模板:预定义结构快速创建工作包
发布说明指出:可以为工作包类型(work package type)定义模板。当创建一个定义了模板的新类型(例如 Bug)的工作包时,模板会自动显示在工作包描述(description)中,从而帮助用户以相似的信息快速创建工作包并减少出错。模板在工作包类型的配置中设置。
从使用流程看,该特性的价值在于:
- 管理员在工作包类型配置中为某一类型(如“缺陷”)填写模板文本;
- 用户新建该类型的工作包时,描述框自动带出模板内容;
- 用户在模板基础上补充具体信息即可提交,保证同类工作包信息结构一致、减少遗漏。
这是“配置一次、处处生效”的典型场景:模板与类型绑定,而非与具体项目或工作包绑定,因此所有使用该类型的项目均可受益。
四、My 页面工作包小组件:个人化的工作包视图
9.0 允许每个用户在 My 页面(个人首页)添加工作包小组件(work package widgets),并自定义显示哪些工作包:
- 支持按工作包属性进行过滤和分组;
- 小组件内也可以直接展示甘特图。
这一特性把“查询 + 视图”的能力下放到了个人层面:用户在项目级视图之外,拥有了跨项目、面向自己的定制化仪表盘。它与看板模块共享同一套查询驱动架构(视图皆由查询定义),是 OpenProject “一个查询模型支撑多种呈现”设计哲学的体现。
五、更新的工作包表格:头像化负责人与类型选择器
9.0 对工作包页面做了两处直接的界面升级:
- 负责人(Assignees)直接以头像显示在工作包页面,识别成本更低;
- 工作包类型选择器更新,创建/切换类型时的交互更清晰。
六、易用性改进
9.0 还包含一组面向日常操作的细节改进,发布说明列举了以下几项:
- 会议附件:可以直接向会议(议程 / 会议纪要)添加附件(例如图片);
- 全局工作包表创建流程优化:在全局工作包表格创建新工作包时,选定类型后,项目菜单中只会列出该类型已启用的项目,避免选择不可用的项目;
- 过滤器与工作包属性改进:过滤器和属性选择支持自动补全(auto-completion),减少手动输入和拼写错误。
这些改进的共同方向是缩短“选类型 → 选项目 → 填属性”操作链路上的每一步摩擦,与工作包模板的特性形成互补。
七、Bug 修复与升级指南
9.0 包含大量 Bug 修复。发布说明未逐项列举,而是指向了官方的特性清单与缺陷修复清单(原文档中的外链为 2019 年时期的外部系统链接,此处不再转载),建议结合 9.x 版本发布说明 中的 9.0.1 ~ 9.0.4 维护版本说明,获取后续小版本中针对 9.0 缺陷的持续修复记录。
关于升级:若使用 Enterprise 云版,则始终运行在最新版本上;对于本地安装,升级前需完成若干小幅变更。具体的升级操作步骤请参见 安装与运维指南中的升级章节。
八、小结
OpenProject 9.0.0 通过“看板视图 + 工作包模板 + My 页面小组件”三个特性,把敏捷管理与个性化视图能力正式纳入产品主线。从当前仓库源码可以看到,看板视图的实现是“Grid 承载、Widget 分列、Query 供数”的三层结构,权限上以show_board_views/manage_board_views精细控制,创建流程由一组按类型分派的 Service 完成(见 modules/boards/app/services/boards 目录)。理解这一架构,既能帮助使用者正确配置看板与模板,也能为开发者阅读 Boards/Grids 模块源码提供清晰的入口。
【免费下载链接】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),仅供参考