跳转至

状态标签(StateLabel)定义编写指南

目标:Agent 直接生成/修改 workspace 状态标签,并正确接到流程节点、按钮可见性、表单脚本。知识以本文为准。不写原理;不依赖外链。

术语:实体类 cn.myapps.core.common.model.statelabel.StateLabel;产品「状态标签 / 常用工具-状态标签」;设计器路由 statuslabellist / statuslabel。是软件级 流程状态名字典,供按钮 stateToShow 勾选与流程节点 statelabel 对齐;不是 Document 运行时字段本体,**不是**流程节点配置文件,**不是**角色/权限。

依赖:挂在**软件(Application)下;parentId=applicationid=软件 id。运行匹配靠**字符串相等(文档当前状态串 ⊇ / 相交 配置串),不是靠 StateLabel 的 id。

产出物一览

部分 落盘 形态
状态标签 见下路径 JAXB 根 stateLabelid 为根属性
# 现行样例/存量软件(几乎全部):目录组 + 目录型落盘
storage/workspace/{软件名}.application/statelabels/{标签名}.statelabel/{标签名}.statelabel

# ModelSuffix 常量定义的落盘组(新建 API  theoretically 走这条,扁平单文件):
storage/workspace/{软件名}.application/statelabel/{标签名}.statelabel

路径相对 storage/workspace

常量(ModelSuffix
STATELABEL_PATH_SUFFIX / STATELABEL_FILE_SUFFIX statelabel
STATELABEL_FILE_GROUP /statelabel

现实:当前工作区里所有应用目录组名均为 statelabels(复数);无单独 statelabel/。DAO 保存有路径兼容:已存在旧组名/目录型时**保持原 uri**,不全量迁到 /statelabel。设计态索引(url.index)按 id→相对路径;加载靠后缀 .statelabel + 缓存。

新建最低配置:

  1. 目标软件若已有 statelabels/写入该组;目录 {name}.statelabel/ + 同名文件
  2. 全新软件:优先仍用 statelabels/ 目录型(与存量一致);或扁平 statelabel/{name}.statelabel(对齐常量)
  3. 写 XML:idnamevalueparentId=软件 id、applicationid=软件 id、orderNodescription
  4. 推荐 namevalue(同中文态名),并与流程节点 statelabel、按钮 stateToShow 使用同一字符串
  5. 同软件 name 不重名(设计态校验「该名称已存在,请重新命名再保存!」)

约定:

  • JAXB;根 stateLabel(camelCase L);id根属性
  • description 用 CDATA(基类);可空
  • 文件名 = name + .statelabel;目录型则「目录名 = 文件名」
  • name / value 勿含 / \ : * ? " < > |(设计器 nameCheck / validateSpecial);name 另有落盘替换 / % \=47/=37/=92
  • name 长度设计器 UI ≤40
  • parentId = 软件 idapplicationid 样例常写;缺则靠路径归属 / API save set
  • **勿**放到 module/ 下;永远在应用级 statelabel(s)/
  • orderNo:模型类型为 String;比较按整数(NumberUtils.toInt,空→Integer.MAX_VALUE);UI/JSON 常传数字再转字符串
  • color 字段(designer-api.md 若写 color 为过时/错误)

1. 心智模型

软件 Application
  └─ statelabels/*.statelabel     ← 本文:字典条目(name/value/orderNo)
        │  设计器勾选 / 人工抄写 **同一字符串**
流程 .flow 节点属性 Node.statelabel     ← 设计盘内嵌 XML 字符串(必填)
        ▼ 流转 / 启动
Document.STATELABEL / FlowStateRT / NodeRT.statelabel
        │  getStateLabel() 聚合当前实例标签(多节点常逗号或冒号拼接)
按钮 Activity.stateToShow(逗号分隔)    ← 设计器 state_select 写入的是字典 **name**
        isStateToHidden(doc):当前标签列表含任一 show 值 → 显示,否则隐藏

表单字段 hiddenScript / readonlyScript
        CURDOC.getStateLabel() / getStateLabel()  equals / indexOf 判断
概念 说明
字典 StateLabel 应用下可维护名录;**运行引擎不强制**走字典表;无条目也能手写节点/按钮态名
name 显示名;按钮勾选 stateToShow 写入的是 name;应用内唯一
value 「值」;JSR @NotEmpty;常与 name 相同;按钮选择器不写入 value
节点 statelabel 流程设计属性;校验「请输入节点名称和状态标签」;写入运行态 NodeRT
文档 stateLabel 运行列 STATELABEL;当前流程态展示/脚本读取源
stateLabelInfo 运行列 STATELABELINFO(CLOB/JSON);审批人等扩展信息 UI
stateToShow Activity / ButtonField:空=不限态;非空=逗号列表,与文档态 字符串匹配 才显示

三层易混对象:

对象 位置 用途
.statelabel 应用 statelabels/ 字典定义(本文)
Node.statelabel .flow 节点 该节点对外状态名
Document.stateLabel 运行库 当前单据所处状态名(由节点拷贝/聚合)

2. StateLabel 属性 → .statelabel XML

属性表

属性 XML 类型 默认/样例 说明
id 根属性 string 须生成 __ + 短 UUID
name 子元素 string 必填;文件名;应用内唯一;stateToShow 勾选键
parentId 子元素 string = 软件 id
applicationid 子元素 string = 软件 id 样例常写;API create/update 会 set
description CDATA string 可空 列表/概览描述
remark CDATA string 基类备注;少用
value 子元素 string 必填@NotEmpty,i18n page.value.notexist
orderNo 子元素 string "0"/"1" 排序;compareTo 按 int

基类还有 uri(运行算路径,一般不手写进文件)。

完整 XML 样例(目录型,对齐存量)

路径:…/statelabels/人事.statelabel/人事.statelabel

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<stateLabel id="3vx33GoJUElQdo0VuWA">
    <name>人事</name>
    <parentId>sOZu9kthmxyP8qQfq0e</parentId>
    <applicationid>sOZu9kthmxyP8qQfq0e</applicationid>
    <description><![CDATA[]]></description>
    <value>人事</value>
    <orderNo>1</orderNo>
</stateLabel>

扁平单文件样例(对齐 STATELABEL_FILE_GROUP

路径:…/statelabel/草稿.statelabel

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<stateLabel id="NEW_STATELABEL_ID">
    <name>草稿</name>
    <parentId>APP_ID</parentId>
    <applicationid>APP_ID</applicationid>
    <description><![CDATA[未启动或首节点]]></description>
    <value>草稿</value>
    <orderNo>0</orderNo>
</stateLabel>

API JSON(设计器 Commontools)

POST/PUT …/api/designtime/applications/{applicationId}/statelabels[/{id}]

{
  "id": "可选;空则服务端生成",
  "name": "人事",
  "value": "人事",
  "description": "",
  "orderNo": "1",
  "parentId": "软件id",
  "applicationid": "软件id"
}

Controller 强制:applicationid/parentId=路径上的 applicationIdname 非空;同名校验。返回新建 { id }


3. 与流程节点联动

流程设计(.flow)每个节点有属性 statelabel(开始/完成/人工/自动/网关/子流程等)。默认文案示例:开始=开始,完成=完成,网关=网关(见 workflow nodeTypes.defaultStateLabel)。

节点 XML 片段(HTML 转义嵌在 flow 文本里常见):

<statelabel>申请</statelabel>

规则:

  1. 节点 name 与 statelabel 均必填flowValidation请输入节点名称和状态标签!
  2. 流转时 NodeRT/FlowStateRT/Document 拷贝该字符串为当前态
  3. 多活动节点:FlowStateRT.getStateLabel() 常把多个 NodeRT.statelabel 用 **逗号**拼;Document 聚合主/子流程时可能用 **冒号**拼接路径
  4. 多分支展示可前缀 (多分支)
  5. 字典条目**不会自动**写入节点;须在流程设计里填**相同字符串**(或 UI 手输)

实践:

StateLabel.name = StateLabel.value = 流程节点.statelabel = Activity.stateToShow 中的一项
例:全部用「部门审批」

若字典 name≠value:按钮勾选写 name;流程节点须写成 与 stateToShow 相同的串(通常是 name),否则按钮永远隐藏。


4. 与按钮 / Activity.stateToShow

Activity 字段:<stateToShow>…</stateToShow>(可空)。

stateToShow 行为(Activity.isStateToHidden
空 / 仅空白 不按状态隐藏(其它 hiddenScript 仍可隐藏)
A,B,C 文档当前态列表与 {A,B,C} 有交集 → 显示;否则隐藏

匹配细节:

  1. doc.stateid:用 doc.getStateLableList()(注意方法名拼写 Lable)= stateLabel.split(",")
  2. stateid 但表单配置了 onActionFlow:取该流程 首节点statelabel 列表再比
  3. 当前标签列表为空且已配置 show 列表:代码路径返回 不隐藏return false)——边界场景勿依赖
  4. 设计器 state_select.vue:勾选字典后拼接 item.name(不是 value、不是 id)

表单内嵌按钮控件 ButtonField.stateToShow 同语义,转成 Activity 时 act.setStateToShow

空示例:

<stateToShow></stateToShow>

仅「人事」「财务审批」可见:

<stateToShow>人事,财务审批</stateToShow>

视图工具栏 Activity 同样有 stateToShow;逻辑同源。


5. 与文档 / 脚本 / 视图

Document 与库列

动态单表头常见列(DDL):

含义
STATELABEL 当前状态标签字符串
STATELABELINFO 状态扩展 JSON(审批人信息等)

IDocument / AbstractDocument

  • getStateLabel() / setStateLabel
  • getStateLableList()(拼写 Lable)
  • getStateLabelInfo() / setStateLabelInfo

getStateLabel():字段已有值直接返回;否则从流程实例聚合未完成主/子流程的 FlowStateRT.stateLabel

iScript

// 隐藏/只读脚本常见写法
var st = CURDOC.getStateLabel();
// 或全局别名 getStateLabel()
if (st && st === "流程登记") {
  // ...
}
API 说明
CURDOC.getStateLabel() 当前文档状态标签 String
doc.getStateLabel() Document 实例同义
getStateLabel() 旧全局别名 → CURDOC

多态逗号串时用 indexOf / split,勿只 === 单节点名。

历史/上一节点:常查流程历史表 state_label 字段(脚本合集 get-previous-node-state);那是**运行历史**,不是读 .statelabel 文件。

视图系统字段

列名 说明
$StateLabel / $stateLabel 绑定文档状态;导出/列渲染特殊处理;JSON info 可影响展示
回退样式 flowReturnCss 等用 backstatelabel*.gif 图标

DQL/SQL 视图脚本里常见 fs.state_label 别名「流程状态」。


6. 生成清单(Agent)

  1. 确认软件 id、目录名;检查是否已有 statelabels/
  2. 选定态名串 S(中文业务态);name=value=SorderNo 递增字符串
  3. 生成 id(__ + 短 UUID);写文件到约定路径;文件名=name
  4. 流程各节点:需要该态时 statelabel=S(勿用字典 id)
  5. 需按态显隐的 Activity:stateToShowS(多选用逗号、无空格或与存量一致)
  6. 字段权限脚本:getStateLabel()S 比较时注意多标签逗号串
  7. 纯落盘后:设计器刷新/重建索引后列表可见;运行匹配**不依赖**文件是否在字典——但勾选 UI 依赖字典 list API

批量建字典示例(同一软件):

name=value orderNo
开始 0
申请 1
部门审批 2
财务审批 3
完成 9

然后 flow 节点与按钮按表对齐。


7. 与其它技能边界

内容 本文 其它
.statelabel 字段、路径、name/value
软件下 statelabel(s)/ 分组存在性 交汇 APPLICATION_SKILL
Activity.stateToShow、表单按钮 语义在此;XML 字段在 FORM FORM_SKILL
流程节点 statelabel、流转写 Document 字符串契约在此 流程设计 / FLOW(无独立 SKILL 时写在本文)
视图 $StateLabel 简述在此 VIEW_SKILL
iScript getStateLabel 全量 API 要点在此 iscript 文档
角色权限、菜单 ROLE / MENU

附录 A:匹配算法伪代码

# Activity.isStateToHidden(doc) → true 表示隐藏
if blank(stateToShow): return false
labels = 
  if blank(doc.stateid) && form.onActionFlow:
    firstNodes(form.onActionFlow).map(n => n.statelabel)
  else:
    doc.stateLableList   # stateLabel.split(",")
show[] = stateToShow.split(",")
if labels 非空:
  if any(s in labels for s in show): return false  # 显示
  else: return true                                # 隐藏
else:
  return false  # 无当前标签时不隐藏

附录 B:URI 计算(代码)

StateLabel 不在「目录后缀再拼文件名」白名单(form/view/module/flow…)中:

  • getPath() = parentPath + "/statelabel/" + name + ".statelabel"
  • getUri() = getPath() → **扁平单文件**路径

存量文件多为:

  • parentPath + "/statelabels/" + name + ".statelabel/" + name + ".statelabel"

保存兼容:若磁盘已是「同名目录+同名文件」布局,更新时按 folder 重命名,不强制改成扁平。

附录 C:常见失败

现象 原因
按钮勾了态仍不显示 stateToShow 用了 name,节点 statelabel 写成了 value 或别字;或文档当前态是逗号串未包含该项
勾选器无选项 未建 .statelabel 或索引未加载;API list 空
保存名称已存在 同应用另一条目同 name
保存值不存在 value 空(@NotEmpty
文件在列表仍没有 落在错误应用目录;后缀不是 .statelabel;未进 url.index/缓存
脚本 equals 永远 false 多节点态为 "A,B""A:B";或首尾空格
改名丢文件 文件名/<name>/目录名三者不一致
按 id 配 stateToShow 无效;只认状态字符串
API 文档写 color 模型无此字段;忽略

附录 D:类与包

模型 cn.myapps.core.common.model.statelabel.StateLabel
DAO FileSystemStateLabelDAO / StateLabelDAO
Service StateLabelService / StateLabelServiceImpl
Controller cn.myapps.designtime.statelabel.controller.StateLabelController
后缀映射 ModelSuffixExstatelabelStateLabel.class
父服务 applicationDesignTimeService(parent=Application)