跳转至

流程(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

新建最低配置:

  1. 目录 {subject}.flow/ + 同名文件
  2. 外壳:id、name≡subject、parentId=模块 id、非空 flow(内嵌图 JSON,短 className)
  3. 图:开始 → 起草 →(审批…)→ 完成。至少 1×StartNode + 起草 ManualNode + ≥1 审批/可执行 ManualNode(或 Auto/SubFlow)+ 1×CompleteNode,以及连接它们的 Relation(设计器校验:节点≥3 且有起止;业务审批流实际节点数通常 ≥4)
  4. Manual 审批人:actorEditMode 对应填 namelist / actorListScript / 组织字段(**起草**节点用发起人;**审批**节点用角色/上级等)
  5. 表单挂接:相关 .activity 的 onActionFlow=本流程 id(FORM_SKILL type=5/4/33)
  6. 推荐同步:应用级 .statelabel 字典条目 = 各节点 statelabel 文案

硬规则:开始 ≠ 起草(不可省略起草节点)

节点 含义 可否省略
StartNode(开始) 仅待办/流程引擎的**技术起点**(无业务办理人、不产生「起草」待办态) 不可省略
起草 ManualNode 首个业务人工节点:发起人填单/提交;name/statelabel 用「起草」(或「拟稿」「编制」) 禁止省略
审批 ManualNode… 部门经理审批等后续环节 按业务;线性审批至少 1 个
CompleteNode(完成) 流程结束 不可省略

**禁止**把「开始」当成起草,直接画成 开始 → 部门经理审批 → 完成(缺起草时:发起后首个待办落在审批节点,接收人/发起人语义错乱,易出现待办为空或自审混乱)。

正确拓扑(线性审批最低形态):

开始(StartNode) → 起草(ManualNode, initiator) → 部门经理审批(ManualNode, …) → 完成(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/&lt;...&gt; 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>

写文件时:

  1. 新建:<flow><![CDATA[...JSON...]]></flow>。CDATA 内不要 XML-escape
  2. 存量:无 CDATA 的 JSON 文本、或 &lt;...&gt; 转义旧 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)

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

(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 当前登录用户

起草节点(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):

"cBack": true,
"backType": 0,
"bnodelist": ""

仅允许审核驳回到编制时:该审核节点改 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):

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

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 根):

.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 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 包着的 JSON FlowDiagram(短 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;本文是流程定义