流程(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。设计盘图根标签历史 FQCN cn.myapps.runtime.workflow.element.FlowDiagram(落盘无 .core.;加载时 XMLOperate 替换为 cn.myapps.core.runtime.workflow.)。**不是**定时任务 .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(文本,常转义) |
| 流程参数(可选) | {流程名}.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(内嵌图 XML) - 图:至少 1×StartNode + 1×ManualNode(或可执行节点)+ 1×CompleteNode,以及连接它们的 Relation(设计器校验:节点≥3 且有起止)
- Manual 审批人:
actorEditMode对应填namelist/actorListScript/ 组织字段 - 表单挂接:相关
.activity的onActionFlow=本流程 id(FORM_SKILLtype=5/4/33) - 推荐同步:应用级
.statelabel字典条目 = 各节点statelabel文案
约定:
- 外壳 JAXB:
BillDefiVO;id根属性;setSubject会同步name - 文件名 =
name/subject+.flow;目录名同;同模块内 subject/name 不重名(「流程名称已存在」) name/subject勿含/%\(落盘替换=47/=37/=92)flow内存是完整图 XML 字符串;**落盘时常整体 XML 转义**成<...>文本(BillDefiVO.setFlow:以<开头则escapeXml);读取时unescapeXml- 图内元素标签用历史包名
cn.myapps.runtime.workflow.element.*;勿写cn.myapps.core...(虽加载兼容) - 图内脚本字段用 CDATA;图内普通文本特殊字符可用设计器约定
@lt;@gt;@amp;@quot;(xml.js encodeXml),或标准实体(存量多为标准实体 + CDATA) id生成规则:根元素 id(流程外壳<BillDefiVO id>、流程参数.parameter根<FlowParameter id>—— 独立文件根)=__+ 短 UUID(示例__MpEzTToulqZtNEFisw6);图内节点 / Relation 的 id(嵌套在<flow>内)= 短 UUID(无__);同一图内节点 id 唯一;Relation 用startnodeid/endnodeid引用- 图内(
<flow>内的 FlowDiagram)节点 / Relation / FlowDiagram 根:所有属性一律用子元素表示(id、x、y、name、statelabel、startnodeid、endnodeid、actorEditMode、namelist…),禁止写在标签属性上。正确:<cn.myapps.runtime.workflow.element.ManualNode><id>…</id><name>…</name><x>…</x><y>…</y>…</cn.myapps.runtime.workflow.element.ManualNode>;错误:<cn.myapps.runtime.workflow.element.ManualNode id="…" x="…" y="…">。只有外壳BillDefiVO的id是根属性(内外两套 JAXB 绑定不同)。图内若把id/x/y写成属性 → JAXB 不绑定 → 节点 id 丢失、Relation 引用断裂、流程打不开。 - 布尔字面量
true/false;整型 enum 用数字 - **勿**把
.flow放到应用级task//statelabel/等;常规在module/.../ - GatewayNode:设计器
NODE_TYPES.gateway有 FQCN,但 Java 无GatewayNode类,Class.forName会失败。生成可运行流程时用 ManualNode/AutoNode 的issplit/isgather,不要写 GatewayNode
1. 心智模型¶
模块 Module
└─ {流程}.flow/
├─ {流程}.flow ← BillDefiVO + 转义后的 FlowDiagram XML
└─ *.parameter ← 可选 FlowParameter(流程参数表单字段源)
BillDefiVO.flow 解析
→ FlowDiagram
├─ StartNode(唯一入边禁止;须有出边)
├─ 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 |
图 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 |
子元素 | string | 整图 XML(落盘转义) |
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><cn.myapps.runtime.workflow.element.FlowDiagram>...</cn.myapps.runtime.workflow.element.FlowDiagram></flow>
<billdefiNo>0</billdefiNo>
</BillDefiVO>
写文件时两种等价做法:
flow内放 已转义 的整图(与存量一致)- 编辑时持有未转义图 XML,保存前对整串做 XML escape(
<→<等),读出后再 unescape
API JSON 同字段名;flow 仍是字符串。
3. 内嵌 FlowDiagram XML¶
根:
<cn.myapps.runtime.workflow.element.FlowDiagram>
<subject>请假审批</subject> <!-- 设计器 meta;可与外壳 subject 同 -->
<authorname>admin</authorname>
<flowstatus>16</flowstatus>
<flowpath></flowpath>
<deleteMSG></deleteMSG>
<width>10000</width>
<height>1536</height>
<_applicationid></_applicationid>
<_sessionid></_sessionid>
<!-- 节点们 -->
<!-- Relation们 -->
</cn.myapps.runtime.workflow.element.FlowDiagram>
| meta | 默认 | 说明 |
|---|---|---|
flowstatus |
16 |
0x10 初始 |
width/height |
10000/1536 |
画布 |
flowpath/deleteMSG |
空 | 历史/删除提示 |
子元素标签 = 节点/线 FQCN(历史包名)。加载映射:cn.myapps.runtime.workflow. → cn.myapps.core.runtime.workflow.。
节点类型一览¶
| 设计器 key | 标签(写此 FQCN) | Java 类 | 默认同名/statelabel |
|---|---|---|---|
| start | ...StartNode |
✓ | 开始 / 开始 |
| complete | ...CompleteNode |
✓ | 完成 / 完成 |
| manual | ...ManualNode |
✓ | 人工节点 / 审批 |
| auto | ...AutoNode |
✓ | 自动 / 自动 |
| subflow | ...SubFlow |
✓ | 子流程 / 子流程 |
| gateway | ...GatewayNode |
✗ 无类 | 勿生成 |
| — | ...Relation |
✓ | 关联线 |
| — | EndNode/SuspendNode |
遗留 | 勿新建 |
可执行节点(getAllExecuteableNodes):Manual / Auto / SubFlow。
拓扑硬规则(validateFlow)¶
- 至少 1 个 start、1 个 complete;节点总数 ≥ 3
- 至少 1 条 Relation
- Start:出边≥1,入边=0
- 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 |
当前登录用户 |
首个审批节点建议
orgField=initiator(流程发起人):发起人收到首个任务,适合自测与「发起人先行」场景。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)。flow_template_builder用role_id/role_name参数生成;手写图按 §9(首节点 initiator)+ 此规则(后续节点角色)组合。
| orgScope | 含义 |
|---|---|
self |
自身 |
superior / lower |
上/下级用户 |
default |
本级默认部门 |
lineSuperior / lineLower |
直属上/下级部门 |
allSuperior / allLower |
所有上/下级部门 |
belongAllSuperior |
所属及所有上级部门 |
roleCondition 筛选¶
| 值 | 含义 |
|---|---|
| 空/无 | 不额外筛 |
initiator_superior |
审批人为发起人上级 |
initiator_dep_superior |
审批人部门=发起人上级部门 |
curruser_default_dept |
审批人部门=提交人默认部门 |
通过条件 passcondition¶
| 值 | 含义 |
|---|---|
0 |
或:任一人处理通过 |
1 |
会签:皆需处理 |
2 |
有序会签 |
3 |
脚本:passScript 返回 "0"|"1"|"2" 等 |
回退 / 回撤 / 挂起 / 催办¶
| 字段 | 说明 |
|---|---|
cBack |
可否回退;默认 true |
backType |
0 自由/历史;1 指定节点 → 填 bnodelist(节点 id 列表) |
cRetracement / retracementEditMode / retracementScript |
回撤;模式 1 须脚本 |
isHandup / handupEditMode / handupScript |
挂起 |
allowUrge2Approval / urge2ApprovalEditMode / allowUrge2ApprovalScript |
催办;模式:0 设计 / 1 脚本 |
加签 / 协办 / 抄送 / 时限¶
| 字段 | 说明 |
|---|---|
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=true;passcondition='0';actorEditMode=0;issplit/isgather=false;多数能力开关 false。
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¶
仅公共字段即可;无额外业务字段。
6. fieldpermlist / activityPermList¶
fieldpermlist¶
分号分隔,每项前缀 + 字段 name:
| 前缀 | 权限 |
|---|---|
@ |
只读 READONLY=1 |
# |
可改 MODIFY=2 |
$ |
隐藏 HIDDEN=3 |
例:@title;#amount;$secret;
未列出字段默认按引擎规则(常见未配置≈可改)。空串=不另限字段。
activityPermList¶
JSON 数组字符串(可再经 HTML/XML 转义):
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(关联线)¶
标签:cn.myapps.runtime.workflow.element.Relation
| 字段 | 说明 |
|---|---|
id |
线 id |
name |
显示名;可空 |
startnodeid / endnodeid |
必填,对应节点 id |
condition |
CDATA;路径条件脚本,返回 boolean;与 editMode 配合 |
filtercondition |
设计模式条件序列化 |
editMode |
00 视图/设计条件(EDITMODE_VIEW);脚本模式时写脚本到 condition(产品文档称设计/脚本/无条件) |
action |
CDATA;过线执行脚本 |
validateScript |
CDATA;校验脚本 |
processDescription |
说明 |
formlist |
条件相关表单 |
ispassed / isreturn |
运行/UI:已走/回退线标记;设计态 false |
state |
常空 |
lineType |
line/polyline/orth/cubic;缺省存量常直线 |
pointstack |
折线/曲线控制点序列;可空 |
无条件出边:condition 空 + 非过滤即可在提交 UI 列出。多出边时靠 condition 过滤或用户勾选下一节点。
9. 最小可运行图(逻辑明文;写入外壳前整体 escape)¶
节点:S→M→C。
<cn.myapps.runtime.workflow.element.FlowDiagram>
<flowstatus>16</flowstatus>
<flowpath></flowpath>
<deleteMSG></deleteMSG>
<width>10000</width>
<height>1536</height>
<_applicationid></_applicationid>
<_sessionid></_sessionid>
<cn.myapps.runtime.workflow.element.StartNode>
<id>1001</id><name>开始</name><x>80</x><y>120</y>
<width>50</width><height>50</height><m_width>50</m_width><m_height>50</m_height>
<prenodeid></prenodeid><statelabel>开始</statelabel><orderNum>0</orderNum>
<backnodeid></backnodeid><formname></formname><fieldpermlist></fieldpermlist>
<isstartandnext>false</isstartandnext><_iscurrent>false</_iscurrent>
</cn.myapps.runtime.workflow.element.StartNode>
<cn.myapps.runtime.workflow.element.ManualNode>
<id>1002</id><name>部门审批</name><x>280</x><y>120</y>
<width>75</width><height>50</height><m_width>75</m_width><m_height>50</m_height>
<prenodeid></prenodeid><statelabel>部门审批</statelabel><orderNum>0</orderNum>
<backnodeid></backnodeid><formname></formname><fieldpermlist></fieldpermlist>
<isstartandnext>false</isstartandnext><_iscurrent>false</_iscurrent>
<actorListScript><![CDATA[]]></actorListScript>
<actorEditMode>3</actorEditMode>
<deptlist></deptlist>
<namelist></namelist>
<realnamelist></realnamelist>
<passcondition>0</passcondition>
<passScript><![CDATA[]]></passScript>
<isApproverEdit>false</isApproverEdit>
<isCoApproverEdit>false</isCoApproverEdit>
<isSupplementComments>false</isSupplementComments>
<isgather>false</isgather><issplit>false</issplit><splitStartNode></splitStartNode>
<cBack>true</cBack><backType>0</backType><bnodelist></bnodelist>
<isToPerson>false</isToPerson>
<checkedOnSinglePerson>false</checkedOnSinglePerson>
<checkedOnMultiplePerson>false</checkedOnMultiplePerson>
<checkedSubmitSelectedNode>false</checkedSubmitSelectedNode>
<checkedCurrentUserNode>false</checkedCurrentUserNode>
<approverNumType>0</approverNumType>
<orgField>initiator</orgField><orgScope>self</orgScope>
<orgRoleCondition></orgRoleCondition><roleCondition></roleCondition>
<isLimited>false</isLimited><timeLimitEditMode>0</timeLimitEditMode>
<timeLimitDay></timeLimitDay><timeLimitHour></timeLimitHour><timeLimitMinute></timeLimitMinute>
<timeLimitScript><![CDATA[]]></timeLimitScript>
<isAssist>false</isAssist><assistEditMode>0</assistEditMode>
<assistNamelist></assistNamelist><assistListScript><![CDATA[]]></assistListScript>
<isCarbonCopy>false</isCarbonCopy><circulatorEditMode>0</circulatorEditMode>
<circulatorNamelist></circulatorNamelist><circulatorListScript><![CDATA[]]></circulatorListScript>
<isSelectCirculator>false</isSelectCirculator>
<isAllowEditAuditor>false</isAllowEditAuditor><isAllowTermination>false</isAllowTermination>
<activityPermList></activityPermList>
<retracementEditMode>0</retracementEditMode><cRetracement>false</cRetracement>
<retracementScript><![CDATA[]]></retracementScript>
<isHandup>false</isHandup><handupEditMode>0</handupEditMode>
<handupScript><![CDATA[]]></handupScript>
<allowUrge2Approval>false</allowUrge2Approval><urge2ApprovalEditMode>0</urge2ApprovalEditMode>
<allowUrge2ApprovalScript><![CDATA[]]></allowUrge2ApprovalScript>
<isAllowSkip>false</isAllowSkip><nextNodeCheckedStatus>0</nextNodeCheckedStatus>
<notificationStrategyJSON></notificationStrategyJSON>
</cn.myapps.runtime.workflow.element.ManualNode>
<cn.myapps.runtime.workflow.element.CompleteNode>
<isgather>false</isgather><splitStartNode></splitStartNode><isAutoArchive>false</isAutoArchive>
<id>1003</id><name>完成</name><x>520</x><y>120</y>
<width>75</width><height>50</height><m_width>75</m_width><m_height>50</m_height>
<prenodeid></prenodeid><statelabel>完成</statelabel><orderNum>0</orderNum>
<backnodeid></backnodeid><formname></formname><fieldpermlist></fieldpermlist>
<isstartandnext>false</isstartandnext><_iscurrent>false</_iscurrent>
</cn.myapps.runtime.workflow.element.CompleteNode>
<cn.myapps.runtime.workflow.element.Relation>
<id>2001</id><name></name><state></state>
<startnodeid>1001</startnodeid><endnodeid>1002</endnodeid>
<ispassed>false</ispassed><isreturn>false</isreturn>
<condition><![CDATA[]]></condition>
<filtercondition></filtercondition><editMode>00</editMode>
<processDescription></processDescription><formlist></formlist>
<action><![CDATA[]]></action>
<lineType>line</lineType><pointstack></pointstack>
<validateScript><![CDATA[]]></validateScript>
</cn.myapps.runtime.workflow.element.Relation>
<cn.myapps.runtime.workflow.element.Relation>
<id>2002</id><name></name><state></state>
<startnodeid>1002</startnodeid><endnodeid>1003</endnodeid>
<ispassed>false</ispassed><isreturn>false</isreturn>
<condition><![CDATA[]]></condition>
<filtercondition></filtercondition><editMode>00</editMode>
<processDescription></processDescription><formlist></formlist>
<action><![CDATA[]]></action>
<lineType>line</lineType><pointstack></pointstack>
<validateScript><![CDATA[]]></validateScript>
</cn.myapps.runtime.workflow.element.Relation>
</cn.myapps.runtime.workflow.element.FlowDiagram>
把上图字符串 XML-escape 后写入 <flow>...</flow>。
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 外壳、图 XML、节点/线字段、校验、挂接 |
✓ | |
| 模块目录、parentId | 交汇 | MODULE_SKILL |
| 表单 Activity onActionFlow / stateToShow | 交汇 | FORM_SKILL / STATELABEL_SKILL |
| 角色 id / namelist 的 R… | 消费 | ROLE_SKILL |
定时 .task |
否 | TASK_SKILL |
| 待办 TaskInfo / 监控干预 | 否 | 运行态/admin flow-monitor |
| GatewayNode 设计器专有 | 勿生成 | 用 issplit/isgather |
15. 脚本库 scripts/flow_template_builder.py¶
Agent 批量生成线性审批流程(Start→人工节点…→Complete)时,优先 import 本库;复杂并行/会签/子流程仍按本文手写 FlowDiagram。
路径(相对 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 XML(首节点 initiator;后续节点 actorEditMode=0+(R{role_id}|{role_name};),保留括号) |
| 外壳 | render_billdefi_xml(...)(flow 内为 html.escape 后的图) |
| 落盘 | 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:脚本 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为转义后的FlowDiagram;元素 FQCN 用cn.myapps.runtime.workflow.element.* - 图内节点 / Relation 所有属性(
id/x/y/name/statelabel/startnodeid/endnodeid…)用子元素,不是标签属性;仅外壳BillDefiVO的id是根属性(<ManualNode><id>…</id>…,禁止<ManualNode id="…">) - ≥1 Start、≥1 Complete、≥1 可执行节点;Relation 拓扑合法
- 每节点
name+statelabel;人工审批人模式字段齐全 - 无 GatewayNode;并行用
issplit/isgather+splitStartNode - 表单 type=5 预设流程时
onActionFlow=本 id - 态名与
.statelabel/stateToShow字符串一致 - 同模块 subject 不冲突;改名时目录名+文件名+
<name>/<subject>同步
附录 C:常见失败¶
| 现象 | 原因 |
|---|---|
| 流程处理无流程 | Activity 未设 onActionFlow 或 id 错误 |
| 打开报节点类异常/节点丢失 | 写了 GatewayNode 或错误包名/截断 XML |
| 图解析空 | flow 未正确 unescape / 双重转义 |
| 保存名称已存在 | 同模块另一流程 subject 冲突 |
| 前台无审批人 | namelist/脚本空;组织模式接在 Auto 后 |
| 聚合卡住 | isgather 未设或 splitStartNode 空/错 |
| 按钮按态不显示 | statelabel 与 stateToShow 字符串不一致 |
| 条件分支永不出现 | Relation condition 恒 false / editMode 与字段不匹配 |
| 改名找不到 | 目录/文件/name/subject 未同步 |
| 放错目录 | 须在 module 下;非 task/statelabel |
| id 写成子元素(外壳) | BillDefiVO 的 id 必须是**根属性** |
| 节点 id 丢失 / Relation 引用断裂 / 流程打不开 | 图内节点或 Relation 把 id/x/y 写成了标签属性(<ManualNode id="…">);改为子元素 <id>…</id><x>…</x><y>…</y>(仅外壳 BillDefiVO 的 id 是属性) |
| 与「任务」混淆 | 待办≠.task;本文是流程定义 |