不做甘特图控件:流程引擎之上的工程运行时怎么设计

装修、施工、IT 交付这类业务,用流程"一个节点一项施工任务"硬套会越来越重。这篇文章讲一套工程运行时是怎么搭的:设计态与运行态怎么分、模板与实例为何脱耦、三类任务入口怎么落地。

一、先说结论

CCPrj 不是把甘特图硬塞进流程引擎,而是参照流程引擎的分层方式,单独做了一套工程运行时:

  • 设计态:工程类别 → 工程模板 → 任务组 / 任务
  • 运行态:工程实例 → 任务组实例 / 任务实例 → 待办人员
  • 创建规则 :选模板创建实例时,把结构复制 过去,之后模板与实例完全脱耦

用户侧体验对齐流程:发起、待办、在途、已完成。处理页不是节点审批表单,而是任务树 + 进度 + 项目表单 + 工作日志 + 文件工作区。

一句话概括:

流程管审批路径,工程管并行任务与工期落地。


二、为什么流程引擎不够用

流程引擎擅长串行/并行审批:谁发起、谁审批、谁会签、什么时候结束。装修、施工、IT 交付这类业务则是另一套问题:

典型诉求 流程引擎 工程管理
表现形态 流程图、审批轨迹 任务树、甘特进度
工作方式 节点顺序流转 多任务可并行推进
时间含义 到达时间、停留时长 计划开始/结束、工期、工时
人员角色 当前处理人 项目负责人 + 任务负责人 + 参与人
里程碑 通常用节点模拟 可作为独立任务类型
文件协作 表单附件为主 任务文件、工作区、送审

如果强行用流程"一个节点一项施工任务",会出现三个问题:

  1. 结构太重:改任务树等于改流程定义,现场很难灵活加节点。
  2. 时间轴缺失:流程没有原生甘特,工期只能靠字段硬记。
  3. 职责错位:审批通过 ≠ 任务做完,工时、日志、文件版本会挤在表单附件里。

所以 CCPrj 的定位很明确:复用 CCFlow 的组织、表单、菜单、HttpHandler 体系,但用独立的工程运行时承载项目执行。


三、核心设计:向流程引擎对齐,而不是复用流程表

CCFlow 流程是经典三层:

css 复制代码
流程类别 FlowSort  →  流程模板 Flow  →  流程实例 GenerWorkFlow

CCPrj 完全对称:

markdown 复制代码
工程类别 TemplateSort  →  工程模板 TemplatePrj  →  工程实例 GenerPrj
                              ↓                          ↓
                     任务组 / 任务模板            任务组 / 任务实例

对照关系:

维度 流程引擎 工程管理 CCPrj
类别 WF_FlowSort Prj_TemplateSort
模板 WF_Flow Prj_TemplatePrj
节点定义 WF_Node Prj_TemplateTaskGroup + Prj_TemplateTask
实例主键 WorkID OID(算法生成,不是库自增)
业务编号 BillNo BillNo(按模板 BillNoFormat 生成)
实例控制表 WF_GenerWorkFlow Prj_GenerPrj
待办人员 WF_GenerWorkerList Prj_GenerWorker
轨迹 WF_Track Prj_Track
用户入口 发起 / 待办 / 在途 / 已完成 同样四件套 + 任务中心
处理页 MyFlow.vue MyPrj.vue

最关键的一条规则:

模板只负责"长什么样",实例才负责"怎么执行"。创建后互不影响。

装修标准模板改了节点,已经开工的项目不会被带偏;某个项目现场加了"隐检验收",也不会污染标准模板。这和流程"发起后按当时版本跑"是同一类思路。


四、模块结构

前后端都独立成模块,不把工程逻辑塞进 Dev2Interface 流程大类里。

bash 复制代码
前端 Vue3/src/CCFast/CCPrj
├── Port.vue                 工程模块入口
├── MyPrj.vue                项目处理器(进度 / 表单 / 日志)
├── PrjToolBar.vue           状态感知工具栏
├── SearchPrj.vue            按模板查询实例
├── TaskCenter.vue           任务中心(待办 / 参与中 / 已办)
├── TaskGener.vue            通用任务工作台
├── TaskFlow.vue             绑定流程的任务
├── TaskBill.vue             绑定单据的任务
├── FileWorkspace.vue        工程文件工作区
├── Admin/                   模板库、步骤设计、文件工作区配置
└── GenerList/               发起 / 待办 / 在途 / 已完成列表

后端 BP.CCPrj
├── Template/*               模板实体:类别、模板、任务组、任务
├── GenerPrj / GenerTask*    运行时实体
├── GenerWorker              待办人员
├── PrjTrack / PrjWorkerLog  轨迹与工时日志
├── PrjDev2Interface         工程接口工具类
├── WF_CCPrj                 运行时 HttpHandler
└── WF_Admin_CCPrj           管理端 HttpHandler

调用链也很"CCFlow 化":

scss 复制代码
菜单
  → GenerList / TaskCenter / SearchPrj
    → HttpHandler(WF_CCPrj)
      → PrjDev2Interface
        → 实体表
          → MyPrj / TaskGener / TaskFlow / TaskBill

前端统一通过:

ts 复制代码
new HttpHandler('BP.CCPrj.HttpHandler.WF_CCPrj')

管理端走 WF_Admin_CCPrj。实体仍是 BP 框架那套:Attr 常量 + Entity + Entities + EnMap。


五、数据模型

5.1 设计态:模板怎么描述一个工程

一个工程模板不是"一张任务清单",而是 任务组 + 任务:

markdown 复制代码
室内装修标准模板
├─ 施工准备
│    ├─ 场地勘察
│    └─ 材料进场
├─ 顶面工程
│    ├─ 门头钢结构
│    ├─ 轻钢龙骨
│    └─ 隐检验收
└─ 墙面工程
     ├─ 抹灰
     └─ 腻子

对应表:

表 实体 作用
Prj_TemplateSort TemplateSort 工程类别树,对应流程类别
Prj_TemplatePrj TemplatePrj 工程模板主表
Prj_TemplateTaskGroup TemplateTaskGroup 任务组(阶段)
Prj_TemplateTask TemplateTask 任务定义

模板主表里,有几项是直接从流程"抄作业"的:

  • BillNoFormat:如 PRJ-{yyyy}-{MM}-{0000},创建实例时生成业务编号
  • TitleRole:标题规则,如 @WebUser.Name的{Name}
  • PTable:项目表单存储表,默认可落到 Prj + 模板编号
  • Draft:草稿规则,与流程一致
    • 0 不设草稿
    • 1 保存到待办
    • 2 保存到草稿箱
  • IsCanEditTemplate:实例是否允许改任务结构

任务模板上还有一个很关键的字段:TaskType

TaskType 含义 运行时页面
0 通用任务 TaskGener.vue:填日志、记工时、标记完成
1 绑定单流程 TaskFlow.vue:进入已绑定的 CCFlow 流程
2 绑定单表单/单据 TaskBill.vue:在任务里填一张独立表单

也就是说,工程不是替代流程,而是可以内嵌流程和单据。一个项目里,隐检验收走审批流,材料进场填单据,日常施工记工时,三种活可以并存。

5.2 运行态:实例怎么落地

表 实体 作用
Prj_GenerPrj GenerPrj 工程实例控制表
Prj_GenerTaskGroup GenerTaskGroup 任务组实例
Prj_GenerTask GenerTask 任务实例
Prj_GenerWorker GenerWorker 任务待办/参与人
Prj_Track PrjTrack 工程操作轨迹
Prj_WorkerLog PrjWorkerLog 工作日志(含工时)

实例主键 OID 用后端算法生成(DBAccess.GenerOID("PrjID")),编号风格对齐 WorkID。任务编号采用:

ini 复制代码
任务No = 工程OID + "_" + 模板任务No
任务组No = 工程OID + "_" + 模板任务组No

例如工程 10001 下,模板任务 N007 的实例号是 10001_N007。这样查询、权限、文件挂接都有稳定主键,又不依赖数据库自增。

工程实例还带了一组按钮权限字段,避免所有人都能点"完成/移交":

  • DataRight:数据只读 / 不可见
  • BtnSaveRole:谁能保存
  • BtnCompleteRole:谁能标记完成
  • BtnTransferRole:是否允许移交
  • BtnPrintRole:是否允许打印

5.3 创建时发生了什么

接口:PrjDev2Interface.Prj_CreateBlankPrjID(templateNo)

大致步骤:

  1. 读模板 TemplatePrj
  2. 生成 GenerPrj,状态先是草稿
  3. 按 BillNoFormat 生成 BillNo
  4. 复制任务组 → GenerTaskGroup
  5. 复制任务 → GenerTask,带上负责人、参与人、任务类型、关联模板
  6. 同步 GenerWorker
  7. 确保项目表单 MapData 存在,并写入一份业务数据
  8. 写一条轨迹:创建工程: xxx

之后模板怎么改,都不会再回头改这份实例。

如果模板草稿规则是"保存到待办",创建后会给发起人在 Idx 最小的任务上写一条待办。这点和流程"发起节点产生待办"是对齐的。


六、状态机

这里要特别注意:工程状态枚举值和口语习惯不完全一样,开发时不要按"1=进行中"去猜。

6.1 工程状态 PrjSta

scss 复制代码
草稿(0) ──发起──> 进行中(2) ──完成──> 已完成(1)
                    │                   │
                    ├──暂停──> 暂停(3)   └──回滚──> 进行中(2)
                    │
                    └──作废──> 作废(4)
值 枚举 说明
0 Draft 草稿,可删、可发起
1 Complete 已完成
2 Runing 进行中
3 Pause 暂停
4 Invalid 作废

发起前会做完整性校验:至少有一个任务、任务有名称和负责人;如果时效是日期范围,开始/结束日期必须合法。

全部任务完成后,系统可以把工程自动置为已完成。管理端仍保留手动"设置完成 / 回滚 / 作废"。

6.2 任务状态 TaskSta

值 含义
0 未开始
1 已完成
2 延期
3 暂停

任务还有三种时效:无期限 / 按照工时 / 日期范围。日期范围任务会校验 DTFrom、DTTo;工时任务则和 PrjWorkerLog.Hours 配合做人力统计。

6.3 人员状态 WorkerSta

值 含义
0 未阅
1 已完成
2 已阅
3 拒绝(标记,不走审批流)

待办列表看的就是:当前人在 Prj_GenerWorker 上,且任务尚未完成。


七、用户能看到什么

7.1 任务中心

TaskCenter.vue 是个人工作台,三个范围:

  • 待办:当前要处理的工程任务
  • 参与中:我是负责人、参与人或工程发起人
  • 已办:已经处理过的任务

点开任务后,按 TaskType 打开不同工作台,而不是一股脑进同一个表单。

7.2 项目处理器 MyPrj.vue

这是工程模块的"MyFlow"。三个 Tab:

  1. 节点进度:任务组/任务树,选中后看详情和任务文件
  2. 项目表单 :模板对应的 Fool 表单(FrmID 默认 Prj + 模板编号)
  3. 日志动态:工程轨迹时间线

工具栏按状态和角色动态出现:

按钮 草稿 进行中 已完成 暂停 作废
发起 有 有 有
删除 有 有 有
暂停 有
设置完成 有 有
移交 可配置 可配置
作废 有 有
回滚 有
文件工作区 有 有 有 有 有

权限不是"登录就能改"。保存、完成、移交分别看:

  • 是不是管理员 / 发起人
  • 是不是任务负责人
  • 实例上的 BtnSaveRole / BtnCompleteRole / BtnTransferRole

7.3 三种任务工作台

通用任务适合施工、巡检、日常执行:

  • 填报工作内容
  • 记工时
  • 日志附件
  • 标记完成
  • 累计工时

流程任务 适合验收、变更、付款审批:任务上绑定一个可发起流程,处理时直接进 MyFlow。

单据任务适合材料申报、隐蔽验收记录:任务上绑定一张独立表单,保存的是单据数据,不是工程主表。

这是 CCPrj 和"纯项目管理工具"最大的差别:它长在 CCFlow 上,所以任务可以变成流程,也可以变成单据。

7.4 工程查询 SearchPrj.vue

对齐流程查询页:

  • 关键字、参与范围、工程状态、日期区间
  • 列表看标题、编号、发起人、计划周期、状态
  • 管理员可进模板设计、表单设计、步骤设计
  • 允许发起时,可直接从查询页创建新实例

7.5 文件工作区

工程不只是进度条,现场往往还有图纸、方案、送审文件。模板上可以配:

  • MinIO Bucket / 对象前缀
  • 工作区参与人
  • 文件送审流程

运行时 FileWorkspace.vue 提供目录树、任务过滤、打开/定位文件、送审。任务行上也能看到当前节点挂接的文件。

对装修、施工、设计类项目,这比"所有附件堆在一张表单底部"更接近真实协作。


八、管理端:先设计模板,再让业务去发起

管理入口是 项目模板库 TemplateList.vue:

  • 模板数量、实例数量、进行中、已完成
  • 每个模板能看到任务组数、任务数、实例分布
  • 新建模板、设计步骤、设计表单、配置文件工作区
  • 查看该模板下的实例并进入处理页

步骤设计不是画流程图,而是维护:

复制代码
模板 → 任务组 → 任务(类型 / 负责人 / 默认工期 / 关联流程或表单)

模板设计完后,可以通过菜单"引入工程组件",给某个模板挂上:

  • 工程查询
  • 发起
  • 待办
  • 在途
  • 已完成

这和流程的 LinkFlow 是同一套路:低代码门户里,工程也可以被当成组件嵌进应用。


九、接口层:列表一套,动作一套

PrjDev2Interface 是工程版 Dev2Interface。命名习惯保持一致:DB_ 查列表,Prj_ / Node_ 做动作。

9.1 列表

方法 用途
DB_Starter 可发起的工程模板
DB_Todolist / DB_TaskTodolist 我的任务待办
DB_TaskDoneList 已办
DB_TaskParticipatingList 我参与的
DB_TaskAllList 全部(管理员) / 可感知任务
DB_Runing 在途工程
DB_Complete 已完成工程
DB_SearchPrj 按模板查询实例

任务列表支持分页和关键字,返回结构给任务中心直接用:工程标题、任务名、类型、负责人、计划时间、状态。

9.2 工程动作

方法 说明
Prj_CreateBlankPrjID 按模板创建草稿实例,返回 OID
Prj_Start 草稿/暂停 → 进行中
Prj_SetOver 完成
Prj_Pause 暂停
Prj_SetInvalid 作废
Prj_Rollback 已完成回滚为进行中
Prj_Delete 删除(草稿等允许删除的状态)
Prj_Save 保存标题、周期、表单数据
Prj_Transfer 移交
Prj_Quit 退出参与
Prj_GetGanttData 甘特/任务树数据
Prj_GetLogs 轨迹

9.3 任务动作

方法 说明
Node_CheckAuth 打开任务前鉴权
Node_SetOver 完成任务;若全部完成则自动完成工程
SyncTaskWorkers 同步负责人/参与人到待办表
Node_WorkerAdd / Remove 加减人

HttpHandler 只做参数接收和 JSON 组装,业务都放接口类。前后端约定仍然是 CCFlow 那套 err@ / info@ 消息协议。


十、几个值得写进分享的实现细节

10.1 项目表单自动落地

创建工程时,不会要求管理员先手工建业务表。接口会:

  1. 用模板 PTable(或 Prj + 模板编号)作为 FrmID
  2. 没有 MapData 就自动建 Fool 表单
  3. 补齐 OID、BillNo、Title、周期、发起人、参与人等默认字段
  4. CheckPhysicsTable 保证物理表存在
  5. 把当前 GenerPrj 同步进业务表

MyPrj 的"项目表单"Tab 直接渲染这张表。业务字段可以继续用表单设计器加,不必改工程内核。

10.2 待办不是按"工程"算,而是按"任务+人"算

流程待办是"我有一个 WorkID 要批"。工程待办是"我在某个任务上有一条 Worker"。

所以一个工程里,张三可能待办"龙骨安装",李四可能待办"隐检验收",两人同时推进。这才是项目并行的本质。

10.3 日志分两条线

  • Prj_Track:系统轨迹,创建、发起、完成、作废、回滚
  • Prj_WorkerLog:人写的工作日志,带工时和附件

甘特上看进度,日志里看"今天具体干了什么"。人力统计走 DurationDays / TimeLimitHours + 日志工时,第一版不引入金额成本。

10.4 第一版明确不做的事

需求里写得很清楚,避免做成"四不像项目管理":

  • 不做前置任务依赖(FS/SS 等),后期再增强
  • 不做成本金额,只统计工期和工时
  • 拒绝只是人员标记,不衍生一套审批子流程

先把"模板复制成实例 + 并行任务 + 三类任务入口"跑稳,再谈依赖网络和成本。


十一、一次完整业务闭环

以"室内装修标准模板"为例:

  1. 管理员在模板库新建模板,设计任务组/任务,配置项目表单和文件工作区。
  2. 业务人员在发起列表或查询页选择该模板。
  3. 后端复制出工程实例,生成 BillNo,状态为草稿。
  4. 发起人补负责人、日期、项目表单,点击发起。
  5. 各任务负责人在任务中心看到待办:
    • 施工任务进通用工作台记日志
    • 验收任务进绑定流程
    • 材料申报进绑定单据
  6. MyPrj 上看整棵任务树和文件。
  7. 任务陆续完成后,工程自动或手动完成。
  8. 已完成可查询、可回滚,轨迹全程可追。

这和流程"发起 → 待办 → 归档"是同一用户心智,只是处理对象从"审批节点"换成了"项目任务"。


十二、适合什么场景,不适合什么场景

适合:

  • 装修、施工、巡检、交付实施等"有阶段、有并行、有工期"的业务
  • 已经在用 CCFlow,希望项目执行和审批、表单、组织权限在一个体系里
  • 需要模板化复制项目结构,而不是每次从零搭流程

不适合硬套:

  • 纯审批(请假、报销、合同签批)------继续用流程
  • 强依赖关键路径、资源平衡的专业项目管理------当前没有前置依赖和资源直方图
  • 以金额成本为核心的工程造价系统------当前只统计工时

更务实的用法是组合:

工程管执行结构,流程管关键审批,单据管结构化填报。


十三、小结

CCPrj 的需求可以收成五句话:

  1. 用流程引擎的分层方法做工程:类别 → 模板 → 实例。
  2. 创建即复制,模板与实例脱耦,现场可改任务树。
  3. 用户入口对齐发起/待办/在途/已完成,处理页是任务树而不是审批表单。
  4. 任务分三种:通用执行、绑定流程、绑定单据。
  5. 表单、轨迹、待办、文件工作区都长在 CCFlow 现有能力上,而不是另起一套中台。

如果把 CCFlow 理解成"组织 + 表单 + 流程"的底座,那么 CCPrj 就是在这个底座上补了一块 项目执行引擎。它不是甘特图控件,而是一套可发起、可待办、可授权、可追溯的工程运行时。

后续如果继续增强,比较自然的方向是:任务前置依赖、甘特拖拽排期、移动端任务处理、以及基于工时的简单产能报表。这些都可以在现有 GenerTask / PrjWorkerLog 上长出来,不必推翻这套三层模型。


相关代码位置

  • 前端:Vue3/src/CCFast/CCPrj
  • 后端:CCFlow/Components/BP.WF/CCPrj

建议标签 :CCFlow 低代码 工程管理 甘特图 流程引擎 Vue3 .NET

相关推荐
开源驰骋低代码_工作流2 小时前
三类任务、一个工作台:把项目执行收进流程平台的产品设计
bpmn-js
开源驰骋低代码_工作流1 天前
同一道请假审批,六款 Java 工作流引擎的实现路径与成本对比
bpmn-js
开源驰骋低代码_工作流1 天前
把请假审批交给六款 .NET 引擎:实现路径、场景适配与相对打分
bpmn-js
开源驰骋低代码_工作流6 天前
不走寻常路的 ORM:Map/Attr 元数据体系如何同时驱动持久化与表单渲染
bpmn-js
zm4351 年前
bpmn.js 自定义绘制流程图节点
前端·bpmn-js
Solon阿杰1 年前
solon-flow基于bpmnJs的流程设计器
javascript·bpmn-js
MiyueFE2 年前
07-源码篇6:Featrues 体验优化与功能扩展(一)
bpmn-js
MiyueFE2 年前
06-源码篇5:CommandStack 命令处理与记录的栈
bpmn-js
MiyueFE2 年前
02-源码篇1:Injector 依赖注入模式的实现
工作流引擎·bpmn-js