装修、施工、IT 交付这类业务,用流程"一个节点一项施工任务"硬套会越来越重。这篇文章讲一套工程运行时是怎么搭的:设计态与运行态怎么分、模板与实例为何脱耦、三类任务入口怎么落地。
一、先说结论
CCPrj 不是把甘特图硬塞进流程引擎,而是参照流程引擎的分层方式,单独做了一套工程运行时:
- 设计态:工程类别 → 工程模板 → 任务组 / 任务
- 运行态:工程实例 → 任务组实例 / 任务实例 → 待办人员
- 创建规则 :选模板创建实例时,把结构复制 过去,之后模板与实例完全脱耦
用户侧体验对齐流程:发起、待办、在途、已完成。处理页不是节点审批表单,而是任务树 + 进度 + 项目表单 + 工作日志 + 文件工作区。
一句话概括:
流程管审批路径,工程管并行任务与工期落地。
二、为什么流程引擎不够用
流程引擎擅长串行/并行审批:谁发起、谁审批、谁会签、什么时候结束。装修、施工、IT 交付这类业务则是另一套问题:
| 典型诉求 | 流程引擎 | 工程管理 |
|---|---|---|
| 表现形态 | 流程图、审批轨迹 | 任务树、甘特进度 |
| 工作方式 | 节点顺序流转 | 多任务可并行推进 |
| 时间含义 | 到达时间、停留时长 | 计划开始/结束、工期、工时 |
| 人员角色 | 当前处理人 | 项目负责人 + 任务负责人 + 参与人 |
| 里程碑 | 通常用节点模拟 | 可作为独立任务类型 |
| 文件协作 | 表单附件为主 | 任务文件、工作区、送审 |
如果强行用流程"一个节点一项施工任务",会出现三个问题:
- 结构太重:改任务树等于改流程定义,现场很难灵活加节点。
- 时间轴缺失:流程没有原生甘特,工期只能靠字段硬记。
- 职责错位:审批通过 ≠ 任务做完,工时、日志、文件版本会挤在表单附件里。
所以 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)
大致步骤:
- 读模板
TemplatePrj - 生成
GenerPrj,状态先是草稿 - 按
BillNoFormat生成BillNo - 复制任务组 →
GenerTaskGroup - 复制任务 →
GenerTask,带上负责人、参与人、任务类型、关联模板 - 同步
GenerWorker - 确保项目表单
MapData存在,并写入一份业务数据 - 写一条轨迹:
创建工程: 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:
- 节点进度:任务组/任务树,选中后看详情和任务文件
- 项目表单 :模板对应的 Fool 表单(
FrmID默认Prj+ 模板编号) - 日志动态:工程轨迹时间线
工具栏按状态和角色动态出现:
| 按钮 | 草稿 | 进行中 | 已完成 | 暂停 | 作废 |
|---|---|---|---|---|---|
| 发起 | 有 | 有 | 有 | ||
| 删除 | 有 | 有 | 有 | ||
| 暂停 | 有 | ||||
| 设置完成 | 有 | 有 | |||
| 移交 | 可配置 | 可配置 | |||
| 作废 | 有 | 有 | |||
| 回滚 | 有 | ||||
| 文件工作区 | 有 | 有 | 有 | 有 | 有 |
权限不是"登录就能改"。保存、完成、移交分别看:
- 是不是管理员 / 发起人
- 是不是任务负责人
- 实例上的
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 项目表单自动落地
创建工程时,不会要求管理员先手工建业务表。接口会:
- 用模板
PTable(或Prj+ 模板编号)作为FrmID - 没有
MapData就自动建 Fool 表单 - 补齐 OID、BillNo、Title、周期、发起人、参与人等默认字段
CheckPhysicsTable保证物理表存在- 把当前
GenerPrj同步进业务表
MyPrj 的"项目表单"Tab 直接渲染这张表。业务字段可以继续用表单设计器加,不必改工程内核。
10.2 待办不是按"工程"算,而是按"任务+人"算
流程待办是"我有一个 WorkID 要批"。工程待办是"我在某个任务上有一条 Worker"。
所以一个工程里,张三可能待办"龙骨安装",李四可能待办"隐检验收",两人同时推进。这才是项目并行的本质。
10.3 日志分两条线
Prj_Track:系统轨迹,创建、发起、完成、作废、回滚Prj_WorkerLog:人写的工作日志,带工时和附件
甘特上看进度,日志里看"今天具体干了什么"。人力统计走 DurationDays / TimeLimitHours + 日志工时,第一版不引入金额成本。
10.4 第一版明确不做的事
需求里写得很清楚,避免做成"四不像项目管理":
- 不做前置任务依赖(FS/SS 等),后期再增强
- 不做成本金额,只统计工期和工时
- 拒绝只是人员标记,不衍生一套审批子流程
先把"模板复制成实例 + 并行任务 + 三类任务入口"跑稳,再谈依赖网络和成本。
十一、一次完整业务闭环
以"室内装修标准模板"为例:
- 管理员在模板库新建模板,设计任务组/任务,配置项目表单和文件工作区。
- 业务人员在发起列表或查询页选择该模板。
- 后端复制出工程实例,生成
BillNo,状态为草稿。 - 发起人补负责人、日期、项目表单,点击发起。
- 各任务负责人在任务中心看到待办:
- 施工任务进通用工作台记日志
- 验收任务进绑定流程
- 材料申报进绑定单据
MyPrj上看整棵任务树和文件。- 任务陆续完成后,工程自动或手动完成。
- 已完成可查询、可回滚,轨迹全程可追。
这和流程"发起 → 待办 → 归档"是同一用户心智,只是处理对象从"审批节点"换成了"项目任务"。
十二、适合什么场景,不适合什么场景
适合:
- 装修、施工、巡检、交付实施等"有阶段、有并行、有工期"的业务
- 已经在用 CCFlow,希望项目执行和审批、表单、组织权限在一个体系里
- 需要模板化复制项目结构,而不是每次从零搭流程
不适合硬套:
- 纯审批(请假、报销、合同签批)------继续用流程
- 强依赖关键路径、资源平衡的专业项目管理------当前没有前置依赖和资源直方图
- 以金额成本为核心的工程造价系统------当前只统计工时
更务实的用法是组合:
工程管执行结构,流程管关键审批,单据管结构化填报。
十三、小结
CCPrj 的需求可以收成五句话:
- 用流程引擎的分层方法做工程:类别 → 模板 → 实例。
- 创建即复制,模板与实例脱耦,现场可改任务树。
- 用户入口对齐发起/待办/在途/已完成,处理页是任务树而不是审批表单。
- 任务分三种:通用执行、绑定流程、绑定单据。
- 表单、轨迹、待办、文件工作区都长在 CCFlow 现有能力上,而不是另起一套中台。
如果把 CCFlow 理解成"组织 + 表单 + 流程"的底座,那么 CCPrj 就是在这个底座上补了一块 项目执行引擎。它不是甘特图控件,而是一套可发起、可待办、可授权、可追溯的工程运行时。
后续如果继续增强,比较自然的方向是:任务前置依赖、甘特拖拽排期、移动端任务处理、以及基于工时的简单产能报表。这些都可以在现有 GenerTask / PrjWorkerLog 上长出来,不必推翻这套三层模型。
相关代码位置
- 前端:
Vue3/src/CCFast/CCPrj - 后端:
CCFlow/Components/BP.WF/CCPrj
建议标签 :CCFlow 低代码 工程管理 甘特图 流程引擎 Vue3 .NET