跳转至

流程(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 根 BillDefiVOid 为**根属性**;图定义在子元素 flow(文本,常转义)
流程参数(可选) {流程名}.flow/{参数名}.parameter JAXB 根 FlowParameterparentId=流程 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

新建最低配置:

  1. 目录 {subject}.flow/ + 同名文件
  2. 外壳:idnamesubjectparentId=模块 id、非空 flow(内嵌图 XML)
  3. 图:至少 1×StartNode + 1×ManualNode(或可执行节点)+ 1×CompleteNode,以及连接它们的 Relation(设计器校验:节点≥3 且有起止)
  4. Manual 审批人:actorEditMode 对应填 namelist / actorListScript / 组织字段
  5. 表单挂接:相关 .activityonActionFlow=本流程 id(FORM_SKILL type=5/4/33)
  6. 推荐同步:应用级 .statelabel 字典条目 = 各节点 statelabel 文案

约定:

  • 外壳 JAXB:BillDefiVOid 根属性setSubject 会同步 name
  • 文件名 = name/subject + .flow;目录名同;同模块内 subject/name 不重名(「流程名称已存在」)
  • name/subject 勿含 / % \(落盘替换 =47/=37/=92
  • flow 内存是完整图 XML 字符串;**落盘时常整体 XML 转义**成 &lt;...&gt; 文本(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 根:所有属性一律用子元素表示idxynamestatelabelstartnodeidendnodeidactorEditModenamelist …),禁止写在标签属性上。正确:<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="…">只有外壳 BillDefiVOid 是根属性(内外两套 JAXB 绑定不同)。图内若把 id/x/y 写成属性 → JAXB 不绑定 → 节点 id 丢失、Relation 引用断裂、流程打不开。
  • 布尔字面量 true/false;整型 enum 用数字
  • **勿**把 .flow 放到应用级 task//statelabel/ 等;常规在 module/.../
  • GatewayNode:设计器 NODE_TYPES.gateway 有 FQCN,但 Java 无 GatewayNodeClass.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>&lt;cn.myapps.runtime.workflow.element.FlowDiagram&gt;...&lt;/cn.myapps.runtime.workflow.element.FlowDiagram&gt;</flow>
  <billdefiNo>0</billdefiNo>
</BillDefiVO>

写文件时两种等价做法:

  1. flow 内放 已转义 的整图(与存量一致)
  2. 编辑时持有未转义图 XML,保存前对整串做 XML escape(<&lt; 等),读出后再 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
  • 每节点:namestatelabel 非空;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

脚本示例(作者作审批人):

(function(){
  var doc = getCurrentDocument();
  return doc.getAuthor();
})();

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/actorListScriptorgField 被忽略——只改 orgField 不改 actorEditMode 会得到无审批人节点。

后续(非首个)审批节点默认 actorEditMode=0(角色/部门设计)+ namelist 角色项:格式 (R{角色id}|{角色名};)保留外层括号),如 (R__testapprole00000001|tester;)(多项以 ; 分隔;类型字 R角色 / U用户 / D部门,详见 §4 NameList)。flow_template_builderrole_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/jumpNameScriptexceedactionissetcurruserinputformisFrontEditapproverEditScriptcoApproverEditScriptrealnamelistuserList

Manual 默认值(设计器)

cBack=truepasscondition='0'actorEditMode=0issplit/isgather=false;多数能力开关 false。


5. AutoNode / CompleteNode / SubFlow / StartNode

AutoNode

字段 说明
autoAuditTimeEditMode 1 设计 / 2 脚本
autoAuditType(设计时) 1 立刻 / 2 指定时间 auditDateTimeyyyy-MM-dd HH:mm:ss)/ 3 滞后 delayDay/delayHour/delayMinute
auditDateTimeScript 脚本模式;返回 Date 或时间串
issplit/isgather/splitStartNode 同人工

注意:自动节点之后的审批人**勿用组织模式**(无可靠用户上下文);用角色或脚本。

CompleteNode

字段 说明
isgather/splitStartNode 可作聚合结束
isAutoArchive 自动归档

产品「结束节点」= CompleteNode(不是历史 EndNode)。

SubFlow

字段 值/说明
subFlowDefiType 01 选定流程 → subflowid+subflowname02 脚本 → 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/splitStartNodeisToPerson 同人工的指定审批

StartNode

仅公共字段即可;无额外业务字段。


6. fieldpermlist / activityPermList

fieldpermlist

分号分隔,每项前缀 + 字段 name:

前缀 权限
@ 只读 READONLY=1
# 可改 MODIFY=2
$ 隐藏 HIDDEN=3

例:@title;#amount;$secret;

未列出字段默认按引擎规则(常见未配置≈可改)。空串=不另限字段。

activityPermList

JSON 数组字符串(可再经 HTML/XML 转义):

[
  {"id":"ACTIVITY_UUID","permission":"show"},
  {"id":"ACTIVITY_UUID2","permission":"hide"}
]

permissionshow | 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)

节点:SMC

<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 流程处理 workFlowType0 预设 → 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_idcurrent_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 根):

.claude/skills/generate-flow-file/scripts/flow_template_builder.py

用法

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.pygen_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…)用子元素,不是标签属性;仅外壳 BillDefiVOid 是根属性(<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 空/错
按钮按态不显示 statelabelstateToShow 字符串不一致
条件分支永不出现 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;本文是流程定义