流程(Flow / BillDefi)定义编写指南¶
目标:Agent 直接生成/修改 workspace 流程定义。知识以本文为准。不写原理;不依赖外链。
iScript:写 actorListScript / passScript / timeLimitScript / 路径 condition/validateScript / 子流程脚本等时,先读 iscript-usage(含 GraalVM 差异) → flow.md;本文只定属性名与落盘。
术语:实体类 cn.myapps.core.common.model.workflow.BillDefiVO;产品「流程 / 工作流」;设计器「模块下-流程」/ obpm-designer-workflow。新建图用短 className JSON(FlowDiagram / StartNode / ManualNode / Relation …);读入兼容长名 cn.myapps.runtime.workflow.element.* 与 cn.myapps.core.runtime.workflow.element.*。Java Factory.trnsXML2Dgrm 按 trim 后 {...} 走 JSON,否则 XML;二者建同一棵树再 FlowTemplateBinder(无 Class.forName)。**不是**定时任务 .task;**不是**运行态待办 TaskInfo / NodeRT / ActorRT;**不是**状态标签字典 .statelabel(见 STATELABEL_SKILL)。
依赖:挂在**模块(Module)下(常规);parentId=模块 id。历史/个别样例可挂软件根,新建一律挂模块。运行需:软件 activated、文档经 Activity onActionFlow/type=4|5|33 启动或流转。节点 statelabel 与字典/按钮 stateToShow **字符串对齐。
产出物一览¶
| 部分 | 落盘 | 形态 |
|---|---|---|
| 流程定义 | {流程名}.flow/{流程名}.flow |
JAXB 根 BillDefiVO;id 为**根属性**;图定义在子元素 flow(JSON 字符串;旧 XML 仍可加载) |
| 流程参数(可选) | {流程名}.flow/{参数名}.parameter |
JAXB 根 FlowParameter;parentId=流程 id |
storage/workspace/{软件名}.application/module/{模块名}.module/{流程名}.flow/{流程名}.flow
storage/workspace/{软件名}.application/module/{模块名}.module/{流程名}.flow/{参数名}.parameter
路径相对 storage/workspace。嵌套模块:把 {模块}.module 换成完整链。
常量(ModelSuffix) |
值 |
|---|---|
FLOW_PATH_SUFFIX / FLOW_FILE_SUFFIX |
flow |
FLOW_PARAMETER_FILE_SUFFIX |
parameter |
新建最低配置:
- 目录
{subject}.flow/+ 同名文件 - 外壳:
id、name≡subject、parentId=模块 id、非空flow(内嵌图 JSON,短 className) - 图:开始 → 起草 →(审批…)→ 完成。至少 1×StartNode + 起草 ManualNode + ≥1 审批/可执行 ManualNode(或 Auto/SubFlow)+ 1×CompleteNode,以及连接它们的 Relation(设计器校验:节点≥3 且有起止;业务审批流实际节点数通常 ≥4)
- Manual 审批人:
actorEditMode对应填namelist/actorListScript/ 组织字段(**起草**节点用发起人;**审批**节点用角色/上级等) - 表单挂接:相关
.activity的onActionFlow=本流程 id(FORM_SKILLtype=5/4/33) - 推荐同步:应用级
.statelabel字典条目 = 各节点statelabel文案
硬规则:开始 ≠ 起草(不可省略起草节点)¶
| 节点 | 含义 | 可否省略 |
|---|---|---|
| StartNode(开始) | 仅待办/流程引擎的**技术起点**(无业务办理人、不产生「起草」待办态) | 不可省略 |
| 起草 ManualNode | 首个业务人工节点:发起人填单/提交;name/statelabel 用「起草」(或「拟稿」「编制」) |
禁止省略 |
| 审批 ManualNode… | 部门经理审批等后续环节 | 按业务;线性审批至少 1 个 |
| CompleteNode(完成) | 流程结束 | 不可省略 |
**禁止**把「开始」当成起草,直接画成 开始 → 部门经理审批 → 完成(缺起草时:发起后首个待办落在审批节点,接收人/发起人语义错乱,易出现待办为空或自审混乱)。
正确拓扑(线性审批最低形态):
flow_template_builder:node_labels 必须以起草类标签开头(起草/拟稿/编制);若调用方只传审批名,脚本会自动前置 起草。
约定:
- 外壳 JAXB:
BillDefiVO;id根属性;setSubject会同步name - 文件名 =
name/subject+.flow;目录名同;同模块内 subject/name 不重名(「流程名称已存在」) name/subject勿含/%\(落盘替换=47/=37/=92)flow内存是完整图字符串。新建写 JSON(trim 后以{开头、以}结尾)。落盘:<flow><![CDATA[{...}]]></flow>(与表单templatecontext相同,CDataAdapter)。BillDefiVO.setFlow:以<开头才escapeXml(旧 XML 图,避免内层 CDATA 撑破外壳);以{开头禁止 XML escape。读取时仅对「既不是<也不是{」的旧转义串unescapeXml- 图 JSON 默认短
className:FlowDiagram、StartNode、CompleteNode、GatewayNode、AutoNode、ManualNode、SubFlow、Relation。读入兼容两种长前缀。**禁止**再写 FQCN 当 XML 标签(旧 XML 存量仍可加载) - 图内脚本是 JSON 字符串(可含换行);**不要**在 JSON 字段里再套 CDATA /
@lt;那套 XML 实体。外壳<flow>才用 CDATA id生成规则:根元素 id(流程外壳<BillDefiVO id>、流程参数.parameter根<FlowParameter id>)=__+ 短 UUID(示例__MpEzTToulqZtNEFisw6);图内节点 / Relation 的 id = 短 UUID(无__);同图唯一;Relation 用startnodeid/endnodeid引用- 图是 JSON 对象树:根
{ "className":"FlowDiagram", "subelems":[ ... ] };节点/线是subelems里的扁平对象(字段与旧 XML 子元素同名)。只有外壳BillDefiVO的id是 XML 根属性 - 把 JSON 嵌进外壳时:必须用 CDATA:
<flow><![CDATA[{...}]]></flow>。CDATA 内不要再escapeXml。存量无 CDATA 的 JSON/<...>XML 仍可加载 - 布尔 JSON
true/false;整型 enum 用数字。API 若误把flow放进net.sf.json.JSONObject.put,json-lib 会把{...}解析成嵌套对象,设计器加载失败——详情接口须把flow当 字符串(LinkedHashMap/ Fastjson,勿 json-lib morph) - **勿**把
.flow放到应用级task//statelabel/等;常规在module/.../ - GatewayNode:Java 已有类,JSON 可写
"className":"GatewayNode"(isgather/issplit/splitStartNode)。运行时并行/聚合若引擎尚未把GatewayNode纳入instanceof链,可运行并行仍优先用 ManualNode/AutoNode 的issplit/isgather - 每个 ManualNode 必须显式落盘回退三件套:
"cBack": true、"backType": 0(或1+bnodelist)、"bnodelist": ""。禁止省略(省略 ≠ 设计器默认 true;运行态流程面板无「回退」)。参考demo-basic请假串行流程;flow_template_builder已内置。
1. 心智模型¶
模块 Module
└─ {流程}.flow/
├─ {流程}.flow ← BillDefiVO + 内嵌 FlowDiagram JSON
└─ *.parameter ← 可选 FlowParameter(流程参数表单字段源)
BillDefiVO.flow 解析(JSON 或旧 XML)
→ FlowDiagram
├─ StartNode(技术起点;≠ 起草;唯一入边禁止;须有出边 → 起草)
├─ ManualNode「起草」(必有;发起人办理)/ 审批 ManualNode / AutoNode / SubFlow / CompleteNode …
└─ Relation(startnodeid → endnodeid;condition/action 脚本)
表单 .activity
type=5 onActionFlow=流程id → 流转
type=4 保存并启动
type=33 流程启动
│
▼ 运行时
Document + FlowStateRT + NodeRT + ActorRT
Document.STATELABEL ← 当前节点 Node.statelabel(可多节点逗号)
| 概念 | 说明 |
|---|---|
subject / name |
流程显示名;外壳与文件名;模块内唯一 |
flow |
图 JSON 字符串(新建);旧 XML 仍可加载 |
statelabel |
节点态名;驱动文档态、按钮 stateToShow、字段脚本 |
issplit / isgather |
并行送出 / 聚合到达;isgather 须填 splitStartNode |
Relation.condition |
路径进入条件(editMode 设计/脚本);返回 true 才可选该出边 |
Relation.action |
经过该线时执行的脚本 |
flowstatus(图 meta) |
设计盘常写 16(= FLOWSTATUS_OPEN_NOSTART 0x10);运行态另算 |
与其它对象:
| 对象 | 用途 |
|---|---|
.flow / BillDefiVO |
设计时流程定义(本文) |
.task |
应用级定时 iScript,无关待办 |
TaskInfo / 待办中心 |
运行时人工任务 |
.statelabel |
态名字典,供勾选对齐 |
| Form type=3 流程参数表 | 可由 FlowParameter 列表运行时拼出 |
2. BillDefiVO 外壳 → .flow XML¶
属性表¶
| 属性 | XML | 类型 | 说明 |
|---|---|---|---|
id |
根属性 | string | __ + 短 UUID;Activity.onActionFlow 引用此值 |
name |
子元素 | string | =subject;文件名 |
parentId |
子元素 | string | 模块 id(常规) |
applicationid |
常不落盘 | string | API 侧=软件 id |
subject |
子元素 | string | 必填;设 subject 同步 name |
authorname |
子元素 | string | 作者显示名;可空或抄 subject |
authorno |
子元素 | string | 作者账号;可空 |
lastmodify |
子元素 | xs:dateTime | 如 2023-04-13T17:58:39.468+08:00 |
flow |
子元素 CDATA | string | 整图 JSON(新建,CDATA 内 {...});旧 XML 以 < 开头仍 escape 后再进 CDATA |
billdefiNo |
子元素 | string | 排序号,默认 "0" |
description/remark |
基类 | 少用 | |
checkout / checkoutHandler |
不落盘或运行字段 | 设计器签出 |
外壳骨架¶
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<BillDefiVO id="FLOW_UUID">
<name>请假审批</name>
<parentId>MODULE_UUID</parentId>
<authorname></authorname>
<lastmodify>2026-07-15T12:00:00.000+08:00</lastmodify>
<subject>请假审批</subject>
<flow><![CDATA[{"className":"FlowDiagram","subject":"请假审批","subelems":[...]}]]></flow>
<billdefiNo>0</billdefiNo>
</BillDefiVO>
写文件时:
- 新建:
<flow><![CDATA[...JSON...]]></flow>。CDATA 内不要 XML-escape - 存量:无 CDATA 的 JSON 文本、或
<...>转义旧 XML,加载仍支持
API JSON 同字段名;flow 必须是字符串(不要让 json-lib 把 {...} morph 成对象)。
3. 内嵌 FlowDiagram JSON¶
根:
{
"className": "FlowDiagram",
"subject": "请假审批",
"authorname": "admin",
"flowstatus": "16",
"flowpath": "",
"deleteMSG": "",
"width": "10000",
"height": "1536",
"_applicationid": "",
"_sessionid": "",
"subelems": []
}
| meta | 默认 | 说明 |
|---|---|---|
flowstatus |
16 |
0x10 初始 |
width/height |
10000/1536 |
画布 |
flowpath/deleteMSG |
空 | 历史/删除提示 |
子元素(JSON)= subelems[] 里的对象;className 用短名。加载兼容长 FQCN。
节点类型一览¶
| 设计器 key | className | Java 类 | 默认同名/statelabel |
|---|---|---|---|
| start | StartNode |
✓ | 开始 / 开始 |
| complete | CompleteNode |
✓ | 完成 / 完成 |
| manual | ManualNode |
✓ | 人工节点 / 审批 |
| auto | AutoNode |
✓ | 自动 / 自动 |
| subflow | SubFlow |
✓ | 子流程 / 子流程 |
| gateway | GatewayNode |
✓ | 网关;运行时并行仍建议兼用 issplit/isgather |
| — | Relation |
✓ | 关联线 |
| — | EndNode/SuspendNode |
遗留 | 勿新建 |
可执行节点(getAllExecuteableNodes):Manual / Auto / SubFlow。
拓扑硬规则(validateFlow + 业务约定)¶
- 至少 1 个 start、1 个 complete;引擎校验节点总数 ≥ 3;业务审批流还须含起草 ManualNode(见上「开始 ≠ 起草」)
- 至少 1 条 Relation
- Start:出边≥1,入边=0;Start 出边须接到起草(或等价首个人工节点),禁止直接接到「部门经理审批」等审批节点作为唯一人工节点
- Complete:入边≥1,出边=0
- 中间节点:入边与出边皆 ≥1
- 每节点:
name、statelabel非空;orderNum≥0 isgather=true⇒ 必填splitStartNode(并行分散起点节点 id)
节点公共字段(所有 Node)¶
| 字段 | 类型 | 说明 |
|---|---|---|
id |
string | 图内唯一 |
name |
string | 节点名;同流程内建议不重名 |
x/y |
number | 坐标 |
width/height/m_width/m_height |
number | 尺寸;start 常 50;manual 常 75×50 |
prenodeid |
string | 常空 |
statelabel |
string | 必填;态名 |
orderNum |
string/int | 多下一节点时排序;默认 0 |
backnodeid |
string | 回退目标等;常空 |
formname |
string | 节点绑定表单名;可空 |
fieldpermlist |
string | 字段权限串,见 §6 |
isstartandnext |
bool | 启动时是否送下一人 |
_iscurrent |
bool | 监控/UI 当前标记;设计态 false |
scale/note |
存量可有;可空 |
4. ManualNode(人工)¶
审批人 actorEditMode¶
| 值 | 含义 | 必填 |
|---|---|---|
0 |
角色设计 | namelist(角色)和/或 deptlist(部门路径) |
1 |
脚本 | actorListScript(返回用户/用户集合) |
2 |
用户设计 | namelist/userList 用户 NameList |
3 |
组织 | orgField+orgScope(+可选 orgRoleCondition/roleCondition) |
脚本示例(作者作审批人):
NameList / namelist 格式¶
分号分隔项;单项:{类型字}{id}|{显示路径}
| 类型字 | 含义 |
|---|---|
R |
角色 |
U |
用户 |
D |
部门 |
例:R11e0-xxxx-yyyy|管理员;U11e0-zzzz|张三;
deptlist 部门路径(文档规则):
天翎/产品部/测试组/测试组(所有同名测试组)天翎/**/测试组(设计器**/通配;校验 regex 见flowValidation.js)- 多段用
;分隔
orgField / orgScope¶
| orgField | 含义 |
|---|---|
auditor |
上一提交者(默认) |
author |
表单作者 |
initiator |
流程发起人 |
curruser |
当前登录用户 |
起草节点(Start 之后第一个 ManualNode)必须
orgField=initiator(流程发起人)+actorEditMode=3:发起人办理起草待办后再提交给审批。开始节点没有审批人配置——不要用「首个审批=发起人」代替起草节点。orgField仅在actorEditMode=3(组织模式)下生效;actorEditMode=0/1/2时走namelist/actorListScript,orgField被忽略——只改orgField不改actorEditMode会得到无审批人节点。起草之后的审批节点默认
actorEditMode=0(角色/部门设计)+namelist角色项:格式(R{角色id}|{角色名};)(保留外层括号),如(R__testapprole00000001|tester;)(多项以;分隔;类型字R角色 /U用户 /D部门,详见 §4 NameList)。需要上级时可用组织模式orgField=initiator+orgScope=superior等。flow_template_builder:node_labels[0]=起草(initiator);后续用role_id/role_name。
| orgScope | 含义 |
|---|---|
self |
自身 |
superior / lower |
上/下级用户 |
default |
本级默认部门 |
lineSuperior / lineLower |
直属上/下级部门 |
allSuperior / allLower |
所有上/下级部门 |
belongAllSuperior |
所属及所有上级部门 |
发起人所在部门的某角色审批(部门负责人):
actorEditMode=3+orgField=initiator+orgScope=default+orgRoleCondition=(R{角色id}|部门负责人;)。运行时取发起人默认部门,再按T_USER_DEPARTMENT_ROLE_SET筛该角色用户。orgScope=self会派给发起人本人,**禁止**用在部门审批节点;仅superior则依赖用户「上级」字段,缺上级时待办为空或落到发起人。orgRoleCondition格式与namelist角色项相同(保留外层括号)。
roleCondition 筛选¶
| 值 | 含义 |
|---|---|
| 空/无 | 不额外筛 |
initiator_superior |
审批人为发起人上级 |
initiator_dep_superior |
审批人部门=发起人上级部门 |
curruser_default_dept |
审批人部门=提交人默认部门 |
通过条件 passcondition¶
| 值 | 含义 |
|---|---|
0 |
或:任一人处理通过 |
1 |
会签:皆需处理 |
2 |
有序会签 |
3 |
脚本:passScript 返回 "0"|"1"|"2" 等 |
回退 / 回撤 / 挂起 / 催办(硬性:回退字段必须落盘)¶
禁止依赖「设计器默认」省略
cBack。 手写 /flow_template_builder/ 精简 ManualNode 都必须显式写出**下面三字段;缺任一则流程处理面板**无「回退」(DocPublishFlow曾因此只能「提交/批准」)。参考:demo-basic→请假申请_串行流程.flow。
| 字段 | 说明 | 生成时必写 |
|---|---|---|
cBack |
可否回退;落盘写 true(省略 ≠ true,运行态当未开) |
是 |
backType |
0 自由/历史;1 指定节点 → 填 bnodelist(节点 id 列表) |
是(默认 0) |
bnodelist |
backType=1 时的目标节点 id;backType=0 可空元素 |
是(可空:<bnodelist></bnodelist>) |
cRetracement / retracementEditMode / retracementScript |
回撤(发起人撤回);须显式写出;业务审批流默认 cRetracement=true、retracementEditMode=0、空脚本(参考 报销申请_回撤_可回撤;省略/false 则无「撤回」) |
是(默认 true) |
isHandup / handupEditMode / handupScript |
挂起 | 按需 |
allowUrge2Approval / urge2ApprovalEditMode / allowUrge2ApprovalScript |
催办;模式:0 设计 / 1 脚本 | 按需 |
最小必写片段(每个 ManualNode):
仅允许审核驳回到编制时:该审核节点改 backType=1,bnodelist 填编制节点 id。
加签 / 协办 / 抄送 / 时限¶
| 字段 | 说明 |
|---|---|
isApproverEdit |
加签(主办) |
isCoApproverEdit |
加签(协办) |
isSupplementComments |
补签意见 |
isAllowEditAuditor |
允许改当前审批人 |
isAllowTermination |
允许终止(到完成) |
isAllowSkip |
审批人=上步提交人时可跳过 |
isAssist + assistEditMode/assistNamelist/assistListScript |
协办 |
isCarbonCopy + circulatorEditMode/circulatorNamelist/circulatorListScript/isSelectCirculator |
抄送 |
isLimited + timeLimitEditMode + day/hour/minute 或 timeLimitScript |
审批时限;设计模式三项勿全 0 |
协办/抄送 editMode:0 角色 / 1 脚本 / 2 用户(同 actor)。
指定下步审批人¶
| 字段 | 说明 |
|---|---|
isToPerson |
允许当前执行人指定下一步审批人 |
approverNumType |
0 单选 / 1 多选 |
checkedOnSinglePerson |
仅一人时默认勾选 |
checkedOnMultiplePerson |
多人默认全选 |
checkedSubmitSelectedNode / checkedCurrentUserNode |
UI 默认项 |
nextNodeCheckedStatus |
0 勾选 / 1 不勾选 / 2 勾选且锁定 |
并行¶
| 字段 | 说明 |
|---|---|
issplit |
分散(并行送出) |
isgather |
聚合;须 splitStartNode=分散起点节点 id |
字段/按钮权限¶
| 字段 | 格式 |
|---|---|
fieldpermlist |
见 §6 |
activityPermList |
JSON 数组字符串,见 §6 |
notificationStrategyJSON |
提醒策略 JSON,见 §7 |
Manual 额外存量字段(可空)¶
jump/jumpTo/jumpNameScript、exceedaction、issetcurruser、inputform、isFrontEdit、approverEditScript、coApproverEditScript、realnamelist、userList
Manual 默认值(生成必须写出,勿省略)¶
| 字段 | 生成落盘值 | 说明 |
|---|---|---|
cBack / backType / bnodelist |
true / 0 / 空 |
必写;省略则前台无回退 |
passcondition |
0 |
推荐写出 |
actorEditMode |
按审批人模式 | 见上表 |
issplit / isgather |
false |
推荐写出 |
cRetracement |
true |
必写;省略/false 则前台无撤回 |
设计器 UI 勾选「可回退」会写出 cBack=true;workspace 手写/脚本生成不会自动补默认值。
5. AutoNode / CompleteNode / SubFlow / StartNode¶
AutoNode¶
| 字段 | 说明 |
|---|---|
autoAuditTimeEditMode |
1 设计 / 2 脚本 |
autoAuditType(设计时) |
1 立刻 / 2 指定时间 auditDateTime(yyyy-MM-dd HH:mm:ss)/ 3 滞后 delayDay/delayHour/delayMinute |
auditDateTimeScript |
脚本模式;返回 Date 或时间串 |
issplit/isgather/splitStartNode |
同人工 |
注意:自动节点之后的审批人**勿用组织模式**(无可靠用户上下文);用角色或脚本。
CompleteNode¶
| 字段 | 说明 |
|---|---|
isgather/splitStartNode |
可作聚合结束 |
isAutoArchive |
自动归档 |
产品「结束节点」= CompleteNode(不是历史 EndNode)。
SubFlow¶
| 字段 | 值/说明 |
|---|---|
subFlowDefiType |
01 选定流程 → subflowid+subflowname;02 脚本 → subflowScript 返回流程 id |
displayMode |
thumb / full |
numberSetingType |
01 定数→numberSetingContent 正整数;02 父表单字段→填 parentFlowFormId/Name + content 字段名;03 脚本;04 审批人分组总数;05 审批人总数 |
paramPassingType |
01 共享父文档;02 表单映射→fieldMappingXML+子/父表单 id;03 脚本→paramPassingScript |
callback/callbackScript |
子流程结束后回调 |
issplit 默认 true;isgather/splitStartNode;isToPerson 等 |
同人工的指定审批 |
StartNode¶
仅公共字段即可;无额外业务字段。
语义硬规则:
- StartNode = 流程引擎**起点标记**,不是「起草」业务环节
- **禁止**省略其后的起草 ManualNode,把审批节点直接接在 Start 后面当作「第一个业务节点」
- Start 的
name/statelabel固定为「开始」;起草用独立 ManualNode(起草/拟稿/编制)
6. fieldpermlist / activityPermList¶
fieldpermlist¶
分号分隔,每项前缀 + 字段 name:
| 前缀 | 权限 |
|---|---|
@ |
只读 READONLY=1 |
# |
可改 MODIFY=2 |
$ |
隐藏 HIDDEN=3 |
例:@title;#amount;$secret;
未列出字段默认按引擎规则(常见未配置≈可改)。空串=不另限字段。
activityPermList¶
JSON 数组字符串(嵌在图 JSON 里,勿再 XML-escape):
permission:show | hide。未列按钮默认显示。
7. notificationStrategyJSON(人工提醒)¶
结构概要(键可缺):
{
"arrive": { "sendModeCodes":[0,1,2], "template":"reminderId", "smsApproval":0 },
"overdue": { "editMode":"0", "limittimecount":"12", "timeunit":"0", "isnotifysuperior":"false", "sendModeCodes":[2], "template":"id", "limittimeScript":"" },
"reject": { "sendModeCodes":[0], "responsibleType":256, "template":"id" },
"send": { "receiverTypes":[...], "sendModeCodes":[...], "template":"id" },
"reminder":{ "sendModeCodes":[...] },
"assist": { "sendModeCodes":[...], "template":"id" },
"carbonCopy":{ "sendModeCodes":[...], "template":"id" }
}
sendModeCodes:邮件/短信/企业消息等编码(存量 0/½…)。配置了策略块则对应接收人/方式/模板须填全(见设计器校验)。空串=不提醒。
8. Relation(关联线)¶
标签:Relation(className)
| 字段 | 说明 |
|---|---|
id |
线 id |
name |
显示名;可空 |
startnodeid / endnodeid |
必填,对应节点 id |
condition |
路径条件脚本,返回 boolean;与 editMode 配合(JSON 字符串,勿 CDATA) |
filtercondition |
设计模式条件序列化 |
editMode |
00 视图/设计条件(EDITMODE_VIEW);脚本模式时写脚本到 condition(产品文档称设计/脚本/无条件) |
action |
过线执行脚本(JSON 字符串) |
validateScript |
校验脚本(JSON 字符串) |
processDescription |
说明 |
formlist |
条件相关表单 |
ispassed / isreturn |
运行/UI:已走/回退线标记;设计态 false |
state |
常空 |
lineType |
line/polyline/orth/cubic;缺省存量常直线 |
pointstack |
折线/曲线控制点序列;可空 |
无条件出边:condition 空 + 非过滤即可在提交 UI 列出。多出边时靠 condition 过滤或用户勾选下一节点。
Relation.name(动作文案)建议显式填写:空名时运行态常回退为**下一节点 name**(末审→完成易显示成「完成」,与「提交」并列易误点)。线性审批约定:起草→首审=提交,末审→CompleteNode=同意(flow_template_builder 已按此生成)。
9. 最小可运行图(JSON;写入 <flow><![CDATA[...]]></flow>)¶
节点:开始→起草→部门审批→完成(**禁止**省略起草:开始→部门审批→完成)。
手工示例过长时可用 flow_template_builder.simple_flow_diagram(["起草", "部门审批"])。以下为结构示意(字段可按 §4 补全;每个 ManualNode 须含 cBack/backType/bnodelist 与 cRetracement):
{
"className": "FlowDiagram",
"subject": "请假审批",
"authorname": "admin",
"flowstatus": "16",
"flowpath": "",
"deleteMSG": "",
"width": "10000",
"height": "1536",
"_applicationid": "",
"_sessionid": "",
"subelems": [
{"className": "StartNode", "id": "1001", "name": "开始", "x": 80, "y": 120, "width": 50, "height": 50, "m_width": 50, "m_height": 50, "prenodeid": "", "statelabel": "开始", "orderNum": "0", "backnodeid": "", "formname": "", "fieldpermlist": "", "isstartandnext": false, "_iscurrent": false},
{"className": "ManualNode", "id": "1002", "name": "起草", "x": 220, "y": 120, "width": 75, "height": 50, "m_width": 75, "m_height": 50, "prenodeid": "", "statelabel": "起草", "orderNum": "0", "backnodeid": "", "formname": "", "fieldpermlist": "", "isstartandnext": false, "_iscurrent": false, "actorListScript": "", "actorEditMode": 3, "deptlist": "", "namelist": "", "realnamelist": "", "passcondition": "0", "passScript": "", "isApproverEdit": false, "isCoApproverEdit": false, "isSupplementComments": false, "isgather": false, "issplit": false, "splitStartNode": "", "cBack": true, "backType": 0, "bnodelist": "", "isToPerson": false, "checkedOnSinglePerson": false, "checkedOnMultiplePerson": false, "checkedSubmitSelectedNode": false, "checkedCurrentUserNode": false, "approverNumType": 0, "orgField": "initiator", "orgScope": "self", "orgRoleCondition": "", "roleCondition": "", "isLimited": false, "timeLimitEditMode": 0, "timeLimitDay": "", "timeLimitHour": "", "timeLimitMinute": "", "timeLimitScript": "", "isAssist": false, "assistEditMode": 0, "assistNamelist": "", "assistListScript": "", "isCarbonCopy": false, "circulatorEditMode": 0, "circulatorNamelist": "", "circulatorListScript": "", "isSelectCirculator": false, "isAllowEditAuditor": false, "isAllowTermination": false, "activityPermList": "", "retracementEditMode": 0, "cRetracement": true, "retracementScript": "", "isHandup": false, "handupEditMode": 0, "handupScript": "", "allowUrge2Approval": false, "urge2ApprovalEditMode": 0, "allowUrge2ApprovalScript": "", "isAllowSkip": false, "nextNodeCheckedStatus": 0, "notificationStrategyJSON": ""},
{"className": "ManualNode", "id": "1003", "name": "部门审批", "x": 400, "y": 120, "width": 75, "height": 50, "m_width": 75, "m_height": 50, "prenodeid": "", "statelabel": "部门审批", "orderNum": "0", "backnodeid": "", "formname": "", "fieldpermlist": "", "isstartandnext": false, "_iscurrent": false, "actorListScript": "", "actorEditMode": 0, "deptlist": "", "namelist": "(R__roleId|审批角色;)", "realnamelist": "", "passcondition": "0", "passScript": "", "isApproverEdit": false, "isCoApproverEdit": false, "isSupplementComments": false, "isgather": false, "issplit": false, "splitStartNode": "", "cBack": true, "backType": 0, "bnodelist": "", "isToPerson": false, "checkedOnSinglePerson": false, "checkedOnMultiplePerson": false, "checkedSubmitSelectedNode": false, "checkedCurrentUserNode": false, "approverNumType": 0, "orgField": "", "orgScope": "", "orgRoleCondition": "", "roleCondition": "", "isLimited": false, "timeLimitEditMode": 0, "timeLimitDay": "", "timeLimitHour": "", "timeLimitMinute": "", "timeLimitScript": "", "isAssist": false, "assistEditMode": 0, "assistNamelist": "", "assistListScript": "", "isCarbonCopy": false, "circulatorEditMode": 0, "circulatorNamelist": "", "circulatorListScript": "", "isSelectCirculator": false, "isAllowEditAuditor": false, "isAllowTermination": false, "activityPermList": "", "retracementEditMode": 0, "cRetracement": true, "retracementScript": "", "isHandup": false, "handupEditMode": 0, "handupScript": "", "allowUrge2Approval": false, "urge2ApprovalEditMode": 0, "allowUrge2ApprovalScript": "", "isAllowSkip": false, "nextNodeCheckedStatus": 0, "notificationStrategyJSON": ""},
{"className": "CompleteNode", "id": "1004", "name": "完成", "x": 580, "y": 120, "width": 75, "height": 50, "m_width": 75, "m_height": 50, "prenodeid": "", "statelabel": "完成", "orderNum": "0", "backnodeid": "", "formname": "", "fieldpermlist": "", "isstartandnext": false, "_iscurrent": false, "isgather": false, "splitStartNode": "", "isAutoArchive": false},
{"className": "Relation", "id": "2001", "name": "", "state": "", "startnodeid": "1001", "endnodeid": "1002", "ispassed": false, "isreturn": false, "condition": "", "filtercondition": "", "editMode": "00", "processDescription": "", "formlist": "", "action": "", "lineType": "orth", "pointstack": "", "validateScript": ""},
{"className": "Relation", "id": "2002", "name": "提交", "state": "", "startnodeid": "1002", "endnodeid": "1003", "ispassed": false, "isreturn": false, "condition": "", "filtercondition": "", "editMode": "00", "processDescription": "", "formlist": "", "action": "", "lineType": "orth", "pointstack": "", "validateScript": ""},
{"className": "Relation", "id": "2003", "name": "同意", "state": "", "startnodeid": "1003", "endnodeid": "1004", "ispassed": false, "isreturn": false, "condition": "", "filtercondition": "", "editMode": "00", "processDescription": "", "formlist": "", "action": "", "lineType": "orth", "pointstack": "", "validateScript": ""}
]
}
把上图 JSON 写入 <flow><![CDATA[...]]></flow>(CDATA 内不要 escapeXml)。
10. FlowParameter(.parameter)¶
挂在**流程目录**内;parentId=流程 id。
| 属性 | 说明 |
|---|---|
id |
根属性 |
name |
参数名→运行时拼 FormField name |
type |
longtext→TEXT;number→NUMBER;date→DATE;其它→VARCHAR |
orderno |
int 排序 |
description |
可空 |
parentId |
流程 id |
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<FlowParameter id="PARAM_UUID">
<name>amount</name>
<parentId>FLOW_UUID</parentId>
<description></description>
<orderno>1</orderno>
<type>number</type>
</FlowParameter>
FlowParameter.buildForm:合成临时 Form,type=FORM_TYPE_FLOW_PARAMETER(3),动态表前缀 PARM_。
11. 与表单 Activity 挂接¶
| Activity type | 含义 | 关键字段 |
|---|---|---|
4 |
保存并启动流程 | |
5 |
流程处理 | workFlowType:0 预设 → onActionFlow=流程 id 必填;1 自由;processPreview 0/1 |
33 |
流程启动 | editMode 0 用户选 / 1 脚本 startFlowScript |
{
"name": "提交审批",
"type": "5",
"workFlowType": "0",
"onActionFlow": "FLOW_UUID",
"processPreview": "0"
}
按钮按态显隐:stateToShow 与节点 statelabel 对齐(STATELABEL_SKILL)。
12. 设计态 API(可选;优先直接写文件)¶
Base:/api/designtime/applications(设计器常加 /designer 前缀)。
| 方法 | 路径 | 作用 |
|---|---|---|
| POST | /{appId}/modules/{moduleId}/workflows |
新建;body→BillDefiVO;服务端分配 id;parentId=moduleId |
| GET | /{appId}/modules/{moduleId}/workflows |
列表;query:pageNo/linesPerPage/name |
| GET/PUT/DELETE | 同资源 id | 详/改/删(以控制器为准) |
校验:subject 非空;同模块下 name 不与其它流程重复。
13. 运行时相关(只读速查,勿当设计盘字段)¶
| 库表/对象 | 用途 |
|---|---|
t_flow / 定义缓存 |
定义索引 |
t_flowstatert |
流程实例:flow_id、current_node_*、state |
t_actor / t_actorhis |
当前/历史审批人 |
NodeRT |
节点运行态含 statelabel |
Document 列 STATELABEL / STATELABELINFO / STATEID |
文档态 |
flowstatus 运行常量(FlowType):
| 常量 | 值 |
|---|---|
| OPEN_NOSTART | 0x10 = 16 |
| OPEN_RUN_RUNNING | 0x100 |
| OPEN_RUN_SUSPEND | 0x1000 |
| CLOSE_ABORT | 0x10000 |
| CLOSE_COMPLETE | 0x100000 |
| CLOSE_TERMINAT | 0x1000000 |
14. 知识边界¶
| 主题 | 本文 | 其它 |
|---|---|---|
.flow 外壳、图 JSON(及旧 XML)、节点/线字段、校验、挂接 |
✓ | |
| 模块目录、parentId | 交汇 | MODULE_SKILL |
| 表单 Activity onActionFlow / stateToShow | 交汇 | FORM_SKILL / STATELABEL_SKILL |
| 角色 id / namelist 的 R… | 消费 | ROLE_SKILL |
定时 .task |
否 | TASK_SKILL |
| 待办 TaskInfo / 监控干预 | 否 | 运行态/admin flow-monitor |
| GatewayNode | 可写入图 | 可运行并行优先 Manual/Auto 的 issplit/isgather |
15. 脚本库 scripts/flow_template_builder.py¶
Agent 批量生成线性审批流程(Start→起草→审批节点…→Complete)时,优先 import 本库(输出 JSON 图);复杂并行/会签/子流程仍按本文手写 FlowDiagram JSON。**禁止**生成 Start→审批→Complete(缺起草)。
路径(相对 workspace 根):
用法¶
import sys
from pathlib import Path
WORKSPACE = Path("<workspace-root>")
sys.path.insert(0, str(WORKSPACE / ".claude" / "skills" / "generate-flow-file" / "scripts"))
import flow_template_builder as ftb
labels = ftb.write_linear_flow(
Path("MyApp.application/module/mod.module/create_flow.flow"),
flow_id="__Flow_create",
flow_name="create_flow",
subject="文件新增流程",
module_id="__ModId",
application_id="__AppId",
node_labels=["起草", "部门审核", "文控发布"],
# 首个节点审批人=initiator(库默认);后续节点用角色审批人:
role_id="__RoleId",
role_name="审核员",
)
ftb.write_statelabels(
Path("MyApp.application/statelabels"),
application_id="__AppId",
labels=labels,
id_prefix="__SL_",
)
应用内薄脚本只保留:流程名/subject/模块/节点态名列表;图与外壳落盘 import 本库。配套状态标签可用 write_statelabels(亦见 generate-statelabel-file)。
API 摘要¶
| 类别 | 函数 |
|---|---|
| 图 | simple_flow_diagram(node_labels, *, role_id="", role_name="") → 明文 FlowDiagram JSON;自动确保首个人工节点为起草(缺则前置 起草);起草=initiator;后续节点 actorEditMode=0+(R{role_id}|{role_name};) |
| 外壳 | render_billdefi_xml(...)(flow 为 <![CDATA[图 JSON]]>) |
| 落盘 | write_linear_flow(flow_dir, …, role_id="", role_name="") → 返回用到的态名 set |
| 状态标签 | render_statelabel_xml(...)、write_statelabels(statelabels_dir, …) |
参考实现:iso_doc.application/_gen_menus_flows.py 的 gen_flows() / gen_statelabels()。
附录 A:脚本字段清单(图内 JSON 字符串;勿 CDATA)¶
actorListScript passScript timeLimitScript assistListScript circulatorListScript retracementScript handupScript allowUrge2ApprovalScript auditDateTimeScript subflowScript paramPassingScript callbackScript validateScript condition action approverEditScript coApproverEditScript allowEditAuditorScript notificationStrategyJSON fieldMappingXML(及存量 jumpNameScript)
附录 B:生成检查清单¶
- 路径:
.../module/{模块}.module/{name}.flow/{name}.flow - 根
<BillDefiVO id>=__+短 UUID(流程参数<FlowParameter id>同);图内节点/线 id = 短 UUID(无__);name=subject=文件名去后缀;parentId=模块 id -
flow为 CDATA 包着的 JSONFlowDiagram(短className+subelems);以{开头,CDATA 内 不要 XML-escape - 图内节点 / Relation 是 JSON 对象字段(
id/x/y/name/statelabel/startnodeid/endnodeid…);仅外壳BillDefiVO的id是 XML 根属性 - ≥1 Start、≥1 Complete、≥1 起草 ManualNode、≥1 审批/可执行节点;Relation 拓扑合法;禁止
开始→审批→完成省略起草 - 每节点
name+statelabel;起草=initiator(actorEditMode=3);审批节点审批人模式字段齐全 - Start 出边接到起草(或拟稿/编制),**不**直接把唯一人工节点做成「部门经理审批」
- 每个 ManualNode 显式含
"cBack": true+"backType"+"bnodelist"(禁止省略;否则流程面板无「回退」) - 每个 ManualNode 显式含
"cRetracement": true(及retracementEditMode)(业务审批默认开;否则无「回撤/撤回」) - 可运行并行用
issplit/isgather+splitStartNode(GatewayNode 可进图;引擎若未接线则仍靠 Manual/Auto 标记) - 表单 type=5 预设流程时
onActionFlow=本 id - 态名与
.statelabel/stateToShow字符串一致 - 同模块 subject 不冲突;改名时目录名+文件名+
<name>/<subject>同步
附录 C:常见失败¶
| 现象 | 原因 |
|---|---|
| 流程处理无流程 | Activity 未设 onActionFlow 或 id 错误 |
| 打开报节点类异常/节点丢失 | 未知 className / 坏 JSON / 截断 |
打开空白画布 / [object Object] |
GET 详情把 JSON flow 放进 json-lib JSONObject,字符串被 morph 成对象;须保持字符串 |
| 图解析空 / 坏 JSON | 对 {...} 做了 escapeXml 且未用 CDATA;或坏 JSON 回退 XML(禁止回退) |
| 保存名称已存在 | 同模块另一流程 subject 冲突 |
| 前台无审批人 / 待办接收人为空 | namelist/脚本空;组织模式接在 Auto 后;或缺起草导致首个审批节点审批人解析失败 |
| 提交后直接停在「部门经理审批」且发起人无起草待办 | 省略了起草节点(开始→审批→完成);须补 ManualNode「起草」 |
| 流程面板无「回退」/只有提交前进 | ManualNode 未落盘 cBack(或为 false);须写 cBack=true + backType + bnodelist |
| 聚合卡住 | isgather 未设或 splitStartNode 空/错 |
| 按钮按态不显示 | statelabel 与 stateToShow 字符串不一致 |
| 条件分支永不出现 | Relation condition 恒 false / editMode 与字段不匹配 |
| 改名找不到 | 目录/文件/name/subject 未同步 |
| 放错目录 | 须在 module 下;非 task/statelabel |
| id 写成子元素(外壳) | BillDefiVO 的 id 必须是**根属性** |
| 节点 id 丢失 / Relation 引用断裂 | subelems 缺 id,或 Relation 的 startnodeid/endnodeid 对不上 |
| 与「任务」混淆 | 待办≠.task;本文是流程定义 |