项目管理
本页是一篇完整方案指南:以开源 project-management 模板插件(com.auraboot.template.project-management,命名空间 tpm)为例,从用户场景一路讲到开发实施和典型错误。它是 config 型插件——3 个 model、24 条命令、9 个页面全部是 DSL JSON 声明,没有任何后端 Java;下面每个标识符你都能在插件里 grep 到、对运行实例调得通。
源码:project-management on GitHub ↗
它的定位是「团队级简单项目跟踪」(
catalogType: template),覆盖项目、任务、里程碑的完整生命周期。需要项目集汇总、RACI 分配、工时审批、燃尽看板的更复杂场景,本插件不内置,但都能用同样的 model + command + DSL 方式扩出来(见「6. 常见配置」)。
1. 用户场景
一个产品研发团队,平时同时推进几个项目(官网改版、移动端 App、内部工具),每个项目下拆若干任务,关键节点标里程碑。日常:
- 立项 → 排期 → 启动项目 → 推进 → 完成或取消;
- 任务从待办领取 → 进行中 → 提交审核 → 完成;
- 给项目挂里程碑(如「MVP 发布」),到期标达成或错过;
- 项目经理看全局,成员只关心分到自己的任务,查看者只读。
项目编号、任务编号要自动生成,状态流转要可控、可审计,而不是谁都能随便把任务直接拖到「完成」。
2. 需求痛点
- 没有受控状态机:Excel / 看板工具里任务状态随便改,跳过审核直接「完成」,没人拦得住。
- 编号靠手填:
PRJ-001这种编号靠人维护,重复、断号、格式不统一。 - 操作无授权无审计:谁在什么时候启动/取消了项目、把任务推进到哪一步,没有记录。
- 集成困难:想让其他系统(CRM、自动化规则、AI agent)触发「新建任务」「完成项目」,却只能靠人工二次录入。
这些都不是「再加一张表」能解决的,而是受控状态变更的问题。
3. 产品方案
在 AuraBoot 里,每一个项目/任务/里程碑动作都是一条命令,走统一的 命令管道:
- 任务详情页的「开始任务」按钮调用
tpm:start_task,而不是裸写状态字段;命令在管道里统一鉴权 → 校验 → 执行 → 审计 → 发事件。 - 状态流转命令(
type: state_transition)带fromStates/toState,平台据此挡住非法跳转——任务必须in_review才能tpm:complete_task,跳步直接被拒。 - 项目/任务/里程碑编号由命令的
autoSetFields自动生成(PRJ-{yyyyMMdd}-{seq}/TSK-{yyyyMMdd}-{seq}/MS-{yyyyMMdd}-{seq}),不需要前端或人工填。 - 同一条命令既是 UI 按钮的目标,也能被自动化规则、AI agent 调用——每条命令都带
cmd_risk_level和agent_hint(如删除类是L4,新建是L1,查询是L0),CRM/自动化因此能安全地自动触发项目动作。
4. 功能设计
4.1 数据模型(3 个)
| Model | 用途 | 状态字典 / 关键状态值 |
|---|---|---|
tpm_project | 项目主实体,带起止日期、负责人、生命周期 | tpm_project_status:planning / active / on_hold / completed / cancelled |
tpm_task | 项目下的任务,带负责人、优先级、截止日期 | tpm_task_status:todo / in_progress / in_review / done |
tpm_milestone | 项目里程碑,标记关键交付节点 | tpm_milestone_status:pending / reached / missed |
字段示例(均可在 config/fields/ grep 到):
tpm_project字段:tpm_pj_code(编号,只读自动生成)、tpm_pj_name、tpm_pj_description、tpm_pj_status、tpm_pj_priority、tpm_pj_owner、tpm_pj_start_date、tpm_pj_end_date。tpm_task字段:tpm_ts_code、tpm_ts_title、tpm_ts_project_id(dataType: reference,引用tpm_project)、tpm_ts_description、tpm_ts_status、tpm_ts_priority、tpm_ts_assignee、tpm_ts_due_date。- 优先级共用字典
tpm_priority:low / medium / high / urgent。
任务通过
tpm_ts_project_id这个reference字段挂到项目上,这就是 model 之间的关联方式——不是裸外键,而是平台理解的引用关系。详见 Model 与 Field。
4.2 命令与状态机
命令命名 tpm:<动词>_<名词>(冒号分隔,不是点号)。共 24 条:tpm_project 9 条、tpm_task 8 条、tpm_milestone 7 条。代表性命令:
| 命令 | 类型 | 模型 | 权限 |
|---|---|---|---|
tpm:create_project | create | tpm_project | tpm.project.manage |
tpm:activate_project | state_transition | tpm_project | tpm.project.manage |
tpm:hold_project / tpm:complete_project / tpm:cancel_project | state_transition | tpm_project | tpm.project.manage |
tpm:create_task | create | tpm_task | tpm.task.manage |
tpm:start_task / tpm:review_task / tpm:complete_task | state_transition | tpm_task | tpm.task.manage |
tpm:delete_task | delete | tpm_task | tpm.task.manage |
tpm:create_milestone | create | tpm_milestone | tpm.milestone.manage |
tpm:reach_milestone / tpm:miss_milestone | state_transition | tpm_milestone | tpm.milestone.manage |
任务状态机(来自 config/commands/tpm_task.json 的 fromStates/toState):
todo ──tpm:start_task──> in_progress ──tpm:review_task──> in_review ──tpm:complete_task──> done
delete:仅 todo 可删(tpm:delete_task 带 precondition tpm_ts_status IN [todo])
项目状态机(来自 config/commands/tpm_project.json):
planning ──tpm:activate_project──> active ──tpm:complete_project──> completed
│ │
│ tpm:hold_project ↕ tpm:activate_project
│ │
└────tpm:cancel_project────────> cancelled (planning/active 都可取消)
每条命令都是一段声明。例如 tpm:start_task(config/commands/tpm_task.json 中的一条)的真实定义:
{
"code": "tpm:start_task",
"displayName:zh-CN": "开始任务",
"type": "state_transition",
"modelCode": "tpm_task",
"stateField": "tpm_ts_status",
"fromStates": ["todo"],
"toState": "in_progress",
"permissions": ["tpm.task.manage"],
"agent_hint": "Start working on a task.",
"cmd_risk_level": "L1",
"precondition_description": "Task must be TODO.",
"idempotent": false,
"reversible": false
}读出来的设计信息:这是一条 state_transition(todo → in_progress),只允许从 todo 出发(fromStates),要求 tpm.task.manage 权限,风险级 L1,并通过 agent_hint 告诉 agent 它能做什么。任务不在 todo 时调用它会被状态机直接拒绝。
create 类命令则靠 autoSetFields 自动落编号和初始状态。例如 tpm:create_task 里:
"autoSetFields": {
"tpm_ts_code": { "strategy": "auto_generate", "pattern": "TSK-{yyyyMMdd}-{seq}" },
"tpm_ts_status": { "strategy": "fixed_value", "value": "todo" }
}新建任务时,前端只填 tpm_ts_title 等 inputFields,编号和初始状态由平台补齐。
4.3 权限与角色
config/permissions.json 定义 6 个权限码(<模块>.<资源>.<动作>,每资源 manage + read):
tpm.project.manage tpm.project.read
tpm.task.manage tpm.task.read
tpm.milestone.manage tpm.milestone.read
manage(operation 型)管所有写动作(创建/编辑/状态流转/删除),read(data 型)管查看与列表。菜单项也绑了 read 权限——tpm_projects 菜单的 permissionCode 是 tpm.project.read,没有该权限的用户连菜单都看不到。
这个模板插件不内置 roles.json——它只声明权限码,角色与授权由部署方按团队结构在权限治理里配(例如把
tpm.project.manage+tpm.task.manage给项目经理,只给成员tpm.task.manage+ 三个read,给查看者三个read)。这正是 AuraBoot 的分层:插件声明能力(权限码),部署方决定谁有这些能力(角色)。详见 权限。
4.4 页面
config/pages/ 下 9 个页面:每个 model 一套 list / form / detail(tpm_project_list/form/detail、tpm_task_list/form/detail、tpm_milestone_list/form/detail)。
- list 页:列表 + 列头(状态/优先级走字典渲染成彩色标签)+ 搜索 + 行级操作(状态流转、编辑、删除)。
- form 页:全字段录入,编号字段只读(
tpm_ts_code/tpm_pj_code由命令自动生成,不让填)。 - detail 页:字段展示 + 生命周期操作工具栏(把
tpm:start_task这类状态命令挂成按钮)。
菜单 config/menus.json 把三个 list 页挂到「项目管理」根菜单下,路径分别是 /p/tpm_project、/p/tpm_task、/p/tpm_milestone。
配套 1 条命名查询
tpm_task_summary(config/named-queries.json):按项目分组统计各状态任务数,可用来给项目详情页做「任务分布」展示。本插件没有内置 dashboard 页面;要做管理驾驶舱,用这条命名查询 + 自己加图表块即可(见「6. 常见配置」)。
5. 具体开发与实施
先掌握基础。本插件没有任何后端 Java,全靠平台的几个核心契约。动手前请先读:Model 与 Field · Command · 命令管道 · Permission · 插件清单 · 纯配置 Plugin · Page Designer。
落地一个像 project-management 这样的 config 插件,步骤是:
- 写插件清单 ——
plugin.json声明pluginType: "config"、namespace: "tpm"、provides(三个 model)和resourceDirs(把每类资源指到对应目录/文件)。详见 插件清单。 - 定义 model 与字段 ——
config/models.json(三个 model)+config/fields/<model>.json,字段类型用平台dataType(string/text/enum/date/reference…)。关联用reference+referenceModelCode,不要写裸外键。详见 Model 与 Field。 - 声明命令 —— 每个 model 一个
config/commands/<model>.json,状态流转用type: state_transition+fromStates/toState,创建用type: create+autoSetFields(编号、初始状态),并在每条命令的permissions绑权限码。详见 Command。 - 配 model-field binding ——
config/bindings/<model>.json控制字段在列表/表单里的顺序、是否必填/可见/可编辑;并在resourceDirs.modelFieldBindings注册(见「典型错误」)。 - 设计页面 ——
config/pages/,每个 model 的 list / form / detail 用 Page Designer 出 DSL,把状态命令挂成详情页工具栏按钮、行级操作。 - 权限、字典、菜单 ——
config/permissions.json/dicts.json/menus.json。角色授权留给部署方在权限治理里配。 - 打包导入 —— 用
auraCLI 的import-directory-sync(参数是目录 path)或平台导入接口;校验返回success:true才算导入成功。详见 纯配置 Plugin。
6. 常见配置
- 新增任务优先级 / 状态:在
tpm_priority或tpm_task_status字典里追加一个 item,即可新增一档,无需改代码;若新状态要参与流转,补一条对应的state_transition命令。 - 任务挂项目:
tpm_ts_project_id是reference字段(referenceModelCode: tpm_project),表单里渲染成项目选择器;同理可加reference字段把任务关联到 CRM 客户、关联里程碑——跨插件接线自动继承同一套权限模型。 - 管理驾驶舱:本插件不内置 dashboard,但可基于已有的命名查询
tpm_task_summary(按项目分组统计各状态任务数)新增图表块,或再写命名查询(逾期任务、负责人工时分布等),组成一个 dashboard 页面。 - 里程碑预警:
tpm_milestone有tpm_ms_target_date,用自动化规则在到期未达成时发命令tpm:miss_milestone或通知。 - AI / 自动化触发:每条命令带
agent_hint和cmd_risk_level,可被自动化规则或 AI agent 调用——例如 CRM 成交后自动tpm:create_project。注意删除类是L4高风险,按风险级决定是否需要人工确认。
7. 典型错误
- 命令码用点号:写成
tpm.task.start跑不通——真实是冒号 + 动词_名词:tpm:start_task。注意权限码反而用点号(tpm.task.manage),两者别混。 - 绕过命令直接改状态字段:直接 UPDATE
tpm_ts_status会跳过状态机校验(fromStates/toState)、autoSetFields、鉴权和审计/事件。一切状态变更都走命令,这样跳步(如todo直接到done)才会被拦住。 - 跳步状态流转:任务必须
todo → in_progress → in_review → done逐级走;在in_progress直接调tpm:complete_task(它的fromStates只有in_review)会被拒——这是设计,不是 bug。同理删除有 precondition:任务仅todo可删、项目仅planning可删、里程碑仅pending可删。 - 手填自动编号:
tpm_pj_code/tpm_ts_code/tpm_ms_code是autoSetFields自动生成的只读字段(PRJ-/TSK-/MS-{yyyyMMdd}-{seq}),表单里不要让用户填,也别在inputFields里带它。 - bindingRules 写进 commands.json 内联:不会被导入;必须独立放在
config/bindings/并在resourceDirs注册,否则报[S-EXT-HANDLER] references unregistered handler。详见 纯配置 Plugin。 - 命令执行 payload 结构:字段放在
{ "payload": { ... }, "operationType": ... },目标记录用targetRecordId(不是recordId)——放错位会出现「执行成功却字段为空」的迷惑性报错。