一个项目管理软件的诞生(四):工作项元模型设计,类型、字段、工作流与配置方案

0 评论 1477 浏览 0 收藏 36 分钟

一个项目管理软件的诞生:工作项元模型设计

做项目管理产品时,经常会收到一句听起来很轻的需求:

缺陷从“待验证”进入“已关闭”时,能不能要求必须填写验证结果?

这句话比较合理。测试人员执行关闭动作,系统要求他说明“验证通过”“无法复现”还是“拒绝修复”,这些信息共同构成关闭结论。

如果把“验证结果”换成“根因”,规则就未必成立。根因通常来自定位与分析,可能在“提交修复”之前已经产生;有些低风险缺陷也未必值得做完整根因分析。更稳妥的设计是:关闭时必填验证结果;严重等级达到一定条件时,再要求根因已经存在。前者是关闭动作需要收集的信息,后者是关闭动作执行前需要满足的质量规则。

看起来只是换了一个字段,背后其实已经出现了工作项平台最重要的几类对象:

  • “缺陷”是什么,由工作项类型定义;
  • “验证结果”和“根因”保存什么,由属性定义;
  • 用户在关闭时看到什么,由流转表单定义;
  • 从“待验证”到“已关闭”是否合法,由工作流定义;
  • 哪些严重缺陷必须完成根因分析,由规则定义;
  • 这条规则在哪个空间、工作项类型和流程版本中生效,由配置作用域定义。

所以,真正要设计的从来不是一个输入框,而是:企业如何定义一类工作对象,又如何让每一条具体工作项按照确定的规则运行。

从固定表单到可配置工作项

01 工作项元模型,先把六个问题分开

普通工作项保存一条具体需求、缺陷或任务;元模型保存“需求、缺陷和任务应该怎样被定义”。如果从第一性原理出发,一类工作项至少要回答六个问题:

1. 这是什么对象? 由类型身份回答,包括稳定标识、名称、图标、说明和生命周期管理;

2. 这个对象可以保存什么? 由属性模型回答,包括文本、人员、枚举、工时、附件、关联和计算结果;

3. 用户在不同场景怎样填写与阅读? 由表单和页面布局回答,包括新建、详情、编辑、流转、列表与卡片;

4. 对象允许怎样变化? 由工作流回答,包括状态、步骤、权限、校验、后置动作和自动触发;

5. 它可以和哪些对象连接? 由关系模型回答,包括父子层级、依赖、阻塞和普通关联;

6. 这些规则在哪里生效? 由配置作用域回答,包括组织、空间、工作项类型、业务上下文和配置版本。

工作项由六层元模型共同定义

这六层可以组合,但不能混成一张巨大的“类型配置表”。类型负责识别对象,属性负责表达事实,布局负责组织交互,工作流负责约束变化,关系负责连接对象,作用域负责决定规则影响谁。运行时,平台再把六层定义解析成一条工作项真正使用的配置。

为什么一定要拆开?因为它们变化的频率与复用方式不同。

“缺陷”可以改名为“问题”,但接口引用不能失效;负责人属性可以出现在需求、任务和缺陷上,但不同空间的候选范围可能不同;同一组属性可以组成精简的新建页和完整的详情页;同一套流程可以被多个空间复用,也可能在升级后只影响新建实例。

如果把这些内容全部复制进工作项类型,管理员改一处就要同步几十份配置;如果全部做成独立配置,却没有清晰的映射和生效解释,平台又会变成只有少数专家能维护的“方案迷宫”。元模型设计的难点,正是在复用、隔离和可理解之间取得平衡。

02 工作项类型只定义对象身份,不定义负责人

很多项目管理软件的新建类型弹窗只有名称和图标,容易让人误以为类型只是一个分类标签。更准确的理解是:类型是一类工作对象的稳定身份,也是其他配置挂载和解析的入口。

一套足够稳定的类型基本信息,应该包括:

表格:配置项、作用、关键约束,共 5 行

工作项类型只保存稳定身份,并引用其他配置

这里有一个很重要的边界:工作项类型本身不应该拥有“默认负责人”。

负责人是工作项实例上的一个人员属性。默认负责人、可选人员范围、是否允许为空,都是这个属性在某个空间、业务线或创建场景中的规则。把它们写进类型基本信息,会造成三个问题:

第一,同一种“需求”进入不同团队时,负责人规则往往不同。产品空间可能默认取创建者,交付空间可能取业务线 Owner,职能空间可能不需要默认负责人。它们没有必要因此拆成三种需求类型。

第二,默认值只是创建时的计算结果,不是类型身份。固定人员离职、空间角色为空或业务线变化时,系统需要重新计算或提示,而不是修改类型定义。

第三,人员资格还要与权限、空间成员和账号状态取交集。“可以成为负责人”可以作为类型级权限入口出现,但它约束的是人员属性的候选集合,不能反过来被理解为类型身份的一部分。

所以更准确的模型是:类型只回答“这是什么对象”;负责人属性回答“当前由谁承担责任”;属性规则回答“创建时如何得到默认值、哪些人可以被选择”。

工作流也遵循相同原则。类型可以引用工作流映射,但初始状态、状态迁移和步骤校验属于工作流。页面也不属于类型本体,类型只是通过配置关系选择对应布局。

03 从字段到属性:一切都可以进入统一的表单模型

早期项目管理产品通常把配置能力叫“自定义字段”。这个名字很直观,却容易把设计限制在文本框、单选框和日期框里。

真实的工作项远比一行普通字段复杂:负责人是人员对象;附件是一组带文件名、大小、上传者和权限的资源;工时包含预估、剩余、登记明细、登记人和日期;父工作项、迭代、版本本质上是对其他对象的引用;子项进度又可能是动态计算结果。

因此,我更愿意把这一层称为“属性模型”。在产品配置层,可以采用一种很有扩展性的思路:一切皆属性,属性组成表单。

常见属性至少包括以下几类:

表格:属性类型、示例、模型重点,共 7 行

工作项属性不是几个输入框,而是一套统一的数据契约

“一切皆属性”并不意味着底层数据库必须把所有内容塞进一张字段值表。附件和工时明细通常仍需要独立的资源表与权限逻辑,关联关系也可能有专门的图结构。统一的是产品与接口契约:每种属性都要说明身份、类型、值结构、基数、默认规则、权限、查询能力、布局方式和变更历史。

这带来一个直接好处:新建页、详情页、流转页和列表不再各自实现一套字段。它们从同一个属性资源库中选择属性,再配置不同的展示和交互方式。开放 API、导入导出、自动化和 Agent 也能通过同一份属性定义理解数据。

属性定义必须比控件更稳定

“严重程度”在页面上可能是一个单选控件,但平台还要用它筛选、分组、统计、授权、导入和触发自动化。控件决定用户怎样输入;属性决定系统如何理解并长期保存这份事实。

一份完整的属性定义至少需要包含:

  • 稳定 ID、名称、说明和维护者;
  • 数据类型、值结构、单值或多值;
  • 选项、单位、精度、时区和有效范围;
  • 默认规则、空值规则和服务端校验;
  • 适用的空间、类型与业务场景;
  • 是否支持筛选、排序、分组、统计、计算与 API 写入;
  • 被哪些布局、流程、报表、自动化和接口引用;
  • 停用、迁移和历史兼容策略。

属性类型一旦产生数据,就不能把“修改类型”当成普通编辑。把自由文本优先级改成单选,要处理“很高”“紧急”“P0”等历史值;把数字工时从“小时”改成“人日”,要明确换算口径;把单选改成人员属性,旧值甚至不存在可靠转换关系。

负责人是属性,默认值和候选范围也是属性规则

以负责人为例,属性定义是“单值人员”;候选范围可以是“空间成员中的研发角色”;默认值可以是“当前业务线的技术负责人”;空值规则可以是“创建时允许为空,进入开发前必须存在”。

运行时的候选集合通常是:

组织有效账号 ∩ 空间成员 ∩ 指定角色或用户组 ∩ 当前操作者可分配范围

这不是为了把模型写得复杂,而是为了避免三个常见错误:把工作项分配给无权查看的人、固定默认人员离职后持续产生脏数据、API 绕过前端候选列表写入非法负责人。

如果默认规则没有命中合法候选人,系统应该回退为空并给出明确提示,或者阻止配置发布;不能悄悄把候选范围放宽到全组织。

04 字段作用域:全局字段与空间字段

很多平台历史上使用“全局字段”和“项目字段”这组名称,因为当时 Project 就是承载工作的配置容器。如果产品已经把这个长期容器定义为 Space,就不应该再在空间下面增加一层“项目字段”。否则,命名变了,模型却仍然保留两套容器。

在本文采用的模型中,属性定义只有两个主要配置来源:组织提供跨空间复用的通用属性,空间维护本团队、产品线或业务域的专业属性。一次交付所需的“迁移批次”“专项验收编号”“试验分组”仍然是空间属性,只是通过版本、迭代、目标或条件布局限定使用范围,不会因此产生第三种项目级字段。

因此,属性作用域可以收敛成两层配置和一层运行数据:

表格:层次、适合承载什么、示例,共 3 行

比较稳妥的治理原则是:组织维护通用语言,空间维护业务语言,工作项实例只保存当前事实。 一次专项不应该因为临时需要就复制一个同名属性;空间也不应该把所有局部概念上升为全局属性。

飞书项目的公开模型里,既有跨空间可聚合的通用字段,也有某个空间工作项特有的字段。这个设计背后的问题不是菜单放在哪里,而是跨空间查询如何保持语义:同名字段不一定是同一属性;不同空间的属性只有在数据类型与业务语义一致时,才应该通过聚合字段映射到统一口径。

判断两个属性能否共用,有一个很直接的标准:它们的值能不能放进同一张跨空间报表比较? 如果一个空间的“客户”指签约主体,另一个空间指最终使用品牌,它们就不应因为名称相同而共享同一个属性 ID。

05 页面布局不是一张表,而是属性在不同场景中的组合

有了统一属性资源库,页面布局就不再负责定义数据,而是负责回答:用户在当前场景要看什么、填什么、做什么。

以关闭缺陷为例:

  • 创建缺陷时,验证结果和根因都不应成为门槛;
  • 定位完成时,可以填写根因与修复方案;
  • 从“待验证”进入“已关闭”时,流转表单要求填写验证结果;
  • 如果严重程度为“致命”或“严重”,关闭前再校验根因是否存在;
  • 关闭后,验证结果与根因继续展示,但普通成员可能只读。

同一组属性在创建、分析、关闭和详情场景中的不同用法

成熟的布局模型至少要区分五类界面:

表格:布局、用户要完成什么、关键设计点,共 5 行

新建布局:先建立有效对象

企业软件的新建弹窗很容易变成“详情页所有字段的缩小版”。管理员每加一个属性,弹窗就长一点,最后用户只能为了提交而随便填写。

新建页首先要保证对象成立:确认空间、工作项类型、标题和必要上下文;其次才是确定初始责任与流程路由。如果“业务线”决定工作流,就必须在创建时出现;如果“根因”只有分析完成后才能得到,就不应该提前变成创建门槛。

去品牌化的新建工作项弹窗原型:属性组成表单,路由字段前置

这张原型没有复制 ONES 的界面,而是保留了企业工作项新建页更重要的产品逻辑:上方确定空间、类型与交付目标;主体保留标题、负责人、父项和业务线等必要属性;描述与附件可以继续补充;高级属性默认折叠。

注意,负责人虽然出现在新建页,但它仍然只是人员属性。候选范围和默认值由当前空间、业务线与角色规则共同计算,不属于类型基本信息。

详情布局:先让用户判断,再让用户编辑

用户打开工作项,首先要判断它是什么、卡在哪里、谁在负责、下一步能做什么,然后才会阅读描述、验收标准、子项、关联内容和历史动态。

因此详情页适合形成稳定骨架:顶部放身份、状态和合法动作;主区域承载描述、验收标准与关键业务属性;侧栏放负责人、优先级、迭代等高频信息;下方或标签页承载子项、依赖、附件、评论和变更记录。

去品牌化的工作项详情抽屉原型:先判断状态与动作,再阅读属性和关系

属性和页面控件也要保持边界。附件可以作为资源型属性进入表单,工时可以作为聚合属性展示并进入登记明细;评论和变更记录更适合作为协作流与审计流,而不是伪装成一个可编辑文本字段。

这里有一条很实用的分工:属性配置负责长期数据规则,页面布局负责交互呈现,工作流步骤负责特定动作的准入条件。 “标题始终必填”可以属于属性规则;“关闭时填写验证结果”属于关闭步骤;“验证结果在详情页放在哪一组”才属于布局。

真正影响数据合法性的规则必须由服务端统一执行。只在前端把属性标成必填,批量操作、导入、API、自动化和 Agent 都可能绕过它。

06 工作流定义生命周期,步骤定义一次合法变化

工作流不是页面布局的附属配置。状态表示工作项此刻所处的稳定阶段,步骤或迁移表示用户或系统执行什么动作,使它从一个状态进入另一个状态。

“待验证”和“已关闭”是状态,“验证通过并关闭”是步骤。这个步骤可以要求测试角色执行,打开一张流转表单,收集验证结果,检查严重缺陷是否已有根因,成功后更新关闭人和关闭时间,并写入审计记录。

工作流步骤把状态、表单、校验和后置动作连接成一次业务操作

一条可执行步骤通常包含:

  • 起始状态与目标状态;
  • 面向用户的动作名称;
  • 哪些角色或人员可以执行;
  • 流转页需要展示与填写的属性;
  • 执行前条件和服务端校验;
  • 成功后的字段更新、通知、自动化和审计;
  • 由代码、流水线或其他系统触发的入口。

只配置状态列表,用户仍可以把状态任意改来改去;配置了步骤,平台才能解释“谁在什么条件下,执行了什么动作,为什么进入下一个状态”。

Jira 把这类动作称为 Transition;ONES 的公开帮助中,一条步骤连接起始状态和目标状态,并继续配置验证、步骤属性与后置动作。术语不同,产品模型相同:步骤不是另一个状态,而是一项受约束的业务动作。

“一种类型支持多流程”,至少有三种完全不同的实现

讨论多流程时,最容易把三件事混在一起:

1. 配置层是否允许同一类工作对象准备多套候选流程;

2. 创建工作项时,系统根据什么条件选中其中一套;

3. 选中的单套流程内部,是否支持多个节点并行运行。

把这三层分开,几个典型产品的差异就清楚了。

Jira:空间中的类型映射到一套工作流。 公司管理型空间通过 Workflow Scheme,把工作项类型映射到工作流。一个空间可以有多套工作流,但同一类型在该空间运行时使用其中一套;具体实例在任一时刻只有一个当前状态。不同团队需要不同流程,通常通过不同空间或不同工作流方案实现。

ONES:在其原产品术语中,工作项类型在项目内配置一套工作流。 每种工作项类型带有默认工作流,管理员可以调整,也可以把工作流复制给其他类型。映射到本文模型,这个配置边界可以理解为空间级:在一个确定的空间和类型下,实例沿一套状态工作流运行,同一时刻只有一个当前状态。

飞书项目:业务线字段承担流程路由。 同一种工作项类型可以面向不同业务线准备流程模板。创建时填写业务线,系统自动匹配对应流程,实例不需要先让用户理解所有候选流程。这里的关键不是“类型同时绑定几条流程”,而是通过业务字段把同一类型路由到不同流程模板。

TAPD:类别选择工作流,工作流再选择串行或并行模式。 TAPD 的多类别需求管理允许“美术需求”“技术需求”等类别分别选择已有工作流和模板;一条需求创建时先确定类别,因此得到一套具体工作流。与此同时,TAPD 的工作流本身又区分串行与并行模式:串行模式更接近单一当前状态的状态流;并行模式把一条需求的协作过程拆成可独立推进的节点,可根据字段动态生成后续环节,并支持多个节点同时处理。

Jira、ONES、飞书项目与 TAPD 的流程绑定方式并不相同

表格:产品模型、配置层怎样选流程、实例怎样运行、并行从哪里来,共 4 行

这张表里最重要的不是比较“谁更强”,而是理解三种建模选择:

  • 固定映射 简单、稳定、易于审计,适合对象生命周期相对统一的团队;
  • 条件路由 能让同一类型适应多条业务线,但必须处理规则优先级、命中冲突和流程版本;
  • 流程内并行 能直接表达跨角色协作,却会引入节点负责人、汇聚条件、回滚边界和整体进度计算。

无论采用哪一种,运行实例都必须保存明确的流程或流程版本。否则管理员修改配置后,正在运行的工作项会突然失去状态、节点或可执行动作。

07 一条工作项怎样被“生产”出来

把类型、属性、布局和流程分别配置好,还不等于系统已经能稳定创建工作项。真正的运行链路,要把管理端定义、发布校验、创建时解析和运行时执行串起来。

一条工作项从类型配置、规则发布到运行执行的完整生产链路

管理员先定义类型身份,再连接属性集合、布局、工作流映射、关系与权限;发布前,平台检查初始状态是否唯一、必填属性是否存在可填写入口、默认负责人是否落在合法候选范围、流程路由是否出现重复命中、关系规则是否冲突。

用户点击新建时,系统根据组织、空间、工作项类型和业务上下文解析出唯一配置,计算属性默认值与人员候选,匹配流程版本,完成服务端校验后才创建实例。创建以后,任何变化都继续经过步骤权限、动作输入、业务校验、原子更新和审计记录。

布局不是运行规则的来源,它只是把运行规则翻译成用户能操作的界面。页面、批量操作、导入、API、自动化和 Agent 必须走同一套服务端能力。否则,配置中心里的“必填”“权限”和“工作流”只对人工点页面有效。

08 关系规则让属性表单变成业务网络

工作项不是彼此孤立的记录。一个需求会拆成产品、前端、后端和测试子项;一条后端任务可能阻塞联调;一个缺陷又可能关联需求、测试用例和发布版本。

这里至少要区分两类关系:层级关系 表达分解、归属与汇总,关联关系 表达两个对象之间具名的业务联系。依赖、阻塞、前置、后置属于带方向和约束的关联,不能因为界面上都是“连一条线”就和父子关系混用。

工作项关系配置要分别定义父子层级与具名关联

层级关系不能只保存一个 parent_id。平台还要定义哪些类型可以成为父项和子项、一条工作项能否有多个父项、最大深度、是否允许跨空间、进度与工时怎样汇总、子项完成后是否触发父项校验。

关联关系则需要定义名称与反向名称、方向、两端类型范围、基数、跨域范围、权限和业务效果。“阻塞”与“被阻塞”是同一条有向关系的两端表达;“相似需求”通常是无向关系;“前置—后置”还可能参与排期冲突与关键路径计算。

从统一属性模型看,父工作项和关联版本可以作为引用型属性出现在表单中;但引用是否合法,仍要由关系模型校验。属性负责承载关系入口,关系模型负责定义关系语义。

下一篇会单独展开层级、依赖、关联与跨空间追踪。本篇先守住一个边界:工作项之间的一条线,不只是页面上的链接,而是会影响汇总、权限、排期与流程的业务事实。

09 配置作用域:从 Project 到 Space,长期协作边界的形成

这里先纠正一个容易画错的模型:在本文采用的术语中,空间与项目不会作为上下两层容器同时存在。 至少在 Jira Cloud 当前的产品定义中,Space 就是原来的 Project,二者指向同一个工作容器,并不是“空间下面再创建项目”。

Atlassian 在 2025 年解释这次改名时专门提到,传统项目往往有明确的起止时间、范围和交付目标,但 Jira 里的 Project 实际上是承载工作项的容器,并不受一次项目生命周期约束。因此,这次变化在功能上主要是术语替换,却揭示了一个很重要的产品建模问题:当一个容器长期承载团队协作时,继续叫“项目”,很容易让用户误以为它应该随着一次交付结束。

从产品设计角度看,Space 更适合表达长期工作边界。一个产品团队、一条业务线或一个职能团队,可以在同一个空间里持续迭代多年。工作项类型、属性、工作流、页面布局、视图、角色权限、自动化规则,以及由这些规则创建出来的工作项,都由空间统一管理。人员会变化,版本会发布,专项会结束,但这套团队语言和历史记录仍然留在空间中。

Jira 从 Project 到 Space 的命名变化,反映的是长期工作容器的定义

那一次具体的项目交付放在哪里?答案不是再造一个“项目”实体,而是在空间内组织出一组有共同目标和时间边界的工作。产品可以用目标、版本、迭代、里程碑、标签、父工作项或组合视图来界定这次交付。例如“支付国际化一期”可以由一个目标、两个版本和一组需求与缺陷组成;交付结束后,这些对象被归档或关闭,支付空间仍然继续承载下一次迭代。

因此,这一层的配置作用域应该收敛成三层:

表格:作用域、管理什么、生命周期,共 3 行

版本、迭代和专项交付目标属于交付上下文,可以参与筛选、路由、权限和统计,但不应因此变成一层新的配置容器。否则,同一团队每启动一个专项就复制一套字段和流程,很快会出现同名字段含义不同、工作流版本分叉、跨专项报表无法合并的问题。

运行时,平台真正要做的是:先读取组织标准,再解析当前空间启用的配置,根据工作项类型和业务上下文选择规则,最后叠加用户权限,得到唯一的页面与行为。系统还应该解释这个结果:属性来自组织还是空间,为什么当前类型命中这套流程,负责人为什么只有三个人可选,正在运行的是流程 v3 还是 v4。

没有“为什么生效”的诊断能力,配置越灵活,排查越依赖少数熟悉系统的人。

10 配置变更不是保存表单,而是在修改运行规则

属性、流程、布局和关系会被大量存量工作项引用。管理员把“验证结果”改成关闭必填,可能让批量关闭接口突然失败;删除“待验证”状态,可能让存量缺陷找不到当前位置;把一条 1:n 层级关系改成 n:n,又会改变汇总与权限语义。

因此,工作项元模型必须补上配置本身的生命周期。

稳定 ID 与引用分析

类型、属性、状态、步骤、布局、关系和配置方案都需要稳定 ID。配置中心还要反向展示哪些空间、筛选器、报表、自动化、接口和运行实例正在使用它。没有引用关系,影响分析只能靠猜。

草稿、发布与版本

高风险配置不能点击保存后立即影响所有空间。新增可选属性、修改帮助文案可以快速传播;删除状态、改变属性类型、增加流转必填、修改路由规则、改变关系基数,应默认进入新版本,并明确哪些空间和实例升级。

停用、迁移与历史兼容

字段、枚举选项和关系不再使用时,优先停用而不是直接删除;类型转换和跨空间移动,要处理属性、状态、流程、层级、关联和权限映射;工作流升级时,要明确存量实例继续旧版本,还是映射到新版本。

类型转换需要同时迁移属性、状态、关系与运行规则

把 Task 转成 Bug,看起来只是换一个类型,实际上要重新解析目标属性、布局、工作流和关系:目标必填属性缺失怎么办,源状态在目标流程中不存在如何映射,原父子关系是否仍然合法,附件和工时是否保留。类型转换是一场受约束的数据迁移,不是一个没有代价的下拉选择。

11 总结:类型是入口,属性是事实,工作流才是规则

从产品表面看,工作项配置像是在后台新建类型、拖拽字段、调整页面、画一张流程图。真正决定平台上限的,是这些能力背后的边界是否清楚。

类型只定义一类对象的稳定身份,不把负责人默认值、字段规则和工作流状态塞进自身;属性用统一契约承载标题、人员、工时、附件、引用与计算结果,再由不同布局组成新建、详情和流转表单;工作流用状态和步骤约束对象如何变化;关系模型决定对象怎样分解与连接;空间把长期团队规则与一次性交付范围分离;配置版本则保证正在运行的工作项不会被一次后台修改突然改变。

最后再回到开头的问题。

“关闭缺陷时必须填写验证结果”,不是给详情页增加一个必填框,而是给“关闭缺陷”这个步骤增加动作输入。“严重缺陷关闭前必须有根因”,也不是把根因设成全局必填,而是增加一条带条件的服务端校验。它们可以出现在同一张流转表单里,却属于不同的规则。

当一个项目管理平台能稳定回答“这是什么对象、保存什么事实、此刻怎样交互、允许怎样变化、能够连接什么、规则在哪里生效”,它才真正从一个可配置表格,走向企业级工作项平台。

下一篇,我们继续拆工作项之间的关系。父子、依赖、阻塞和普通关联看起来都像一条线,表达的却是完全不同的业务语义。

本文由作者@AI产品零度,授权发布于平台,未经许可禁止转载。

更多精彩内容,请关注人人都是产品经理微信公众号或下载App
评论
评论请登录
  1. 目前还没评论,等你发挥!