提交条件与权限
把「什么时候不能改、谁不能改」写成条件,配好失败信息;角色、提交条件与数据权限各挡什么。

本课目标
读完这一课,你将能够
- 把「什么时候不能改、谁不能改」写成提交条件,并写好失败信息
- 用 and、or、not 组合条件,选对运算符
- 分清
roles、提交条件与数据权限各挡什么
提交条件是什么
上一节决定了改什么、怎么改,这一节决定什么时候不能改。提交条件把业务规则编进数据编辑权限:订单已经确认就不能再确认,审批人不能批自己起草的单。所有条件满足才执行,任何一条不满足,整个请求被拒绝。条件读到的是提交那一刻对象的当前值,所以它也能挡住基于过期画面的操作:别人刚把订单确认了,你手里那个还显示「草稿」的确认请求就会被拦下。
每条条件是一次比较:左值、运算符、右值。值可以是参数、对象参数的某个属性、当前用户(id、name、role)或写死的字面量。运算符按值的形状分两组:
单个值
is、isNot、matches(正则)、lt、lte、gt、gte、isNull、isNotNull。
多个值
includes、includesAny、isIncludedIn、eachIs、eachIsNot:用来判断列表,或「是否在这几个值之内」。
几条条件可以用 and、or、not 组合,也可以嵌套。每一条提交条件都有自己的 failureMessage。同一个对象类型上可以有很多 Action,各有各的提交条件,confirm-order 的条件不会影响 hold-work-order。
示例:approve-purchase-order
示例工厂的采购订单从 draft 开始,批准后变成 approved。批准要满足三件事:订单是草稿;批准人不是起草人;数量超过 5000 的单只有 developer 能批。
{
"kind": "actionType",
"apiName": "approve-purchase-order",
"title": "批准采购订单",
"schema": {
"parameters": [
{ "name": "purchaseOrder", "type": "object", "objectType": "purchaseOrder", "title": "采购订单", "required": true }
],
"rules": [
{ "type": "modifyObject", "objectType": "purchaseOrder", "object": "$purchaseOrder", "values": { "status": "approved" } }
],
"roles": ["developer", "editor"],
"submissionCriteria": [
{
"condition": { "type": "comparison", "left": { "param": "purchaseOrder", "property": "status" }, "operator": "is", "right": { "literal": "draft" } },
"failureMessage": "只有草稿采购订单可以批准"
},
{
"condition": { "type": "comparison", "left": { "param": "purchaseOrder", "property": "ownerId" }, "operator": "isNot", "right": { "user": "id" } },
"failureMessage": "不能批准自己起草的采购订单,请换另一位有权限的同事批准"
},
{
"condition": {
"type": "or",
"conditions": [
{ "type": "comparison", "left": { "param": "purchaseOrder", "property": "qty" }, "operator": "lte", "right": { "literal": 5000 } },
{ "type": "comparison", "left": { "user": "role" }, "operator": "is", "right": { "literal": "developer" } }
]
},
"failureMessage": "数量超过 5000 的采购订单只有 developer 可以批准"
}
],
"actionLog": true
}
}
三条提交条件是「且」的关系:都满足才执行。第三条自己用了 or:数量不超过 5000,或者执行人是 developer,二者有一个成立就行,所以只需要一句失败信息。roles 在条件之前先挡一道,这里只允许 developer 和 editor。
「校验失败」
「不能批准自己起草的采购订单,请换另一位有权限的同事批准」
失败信息是写给执行人看的一句话,界面、命令行和智能体看到的一字不差。写清为什么被拦、下一步怎么办。
再看 report-output 的两条条件(submissionCriteria 数组)。第一条用 isIncludedIn 判断状态是否在两个值之内:
[
{
"condition": { "type": "comparison", "left": { "param": "workOrder", "property": "status" }, "operator": "isIncludedIn", "right": { "literal": ["released", "running"] } },
"failureMessage": "只有已下达或生产中的工单可以报产出"
},
{
"condition": { "type": "comparison", "left": { "param": "goodQty" }, "operator": "gte", "right": { "param": "workOrder", "property": "goodQty" } },
"failureMessage": "累计合格数不能少于已经报过的数"
}
]
第二条要小心:goodQty 是必填参数,一定有值,所以能这样比较。如果对可选的 scrapQty 写同样的条件,没传时比较的左边是空值,gte 判为不通过,会把根本没打算改报废数的调用也拦下。要写成「没传,或者不小于现在的值」,也就是 or 加 isNull。
三道关:roles、提交条件、数据权限
roles:哪类人
roles 决定谁能执行 Action。缺省允许 developer、member、editor。只读分享的访客不能执行。Open to Internet 应用有匿名只读入口,匿名访客也不能执行 Action。
提交条件:这一次
这一次能不能:看参数、看对象现在的值、看当前用户。同一个对象类型上的每个 Action 各有自己的提交条件。
数据权限:哪些对象
数据权限检查 Object Type、行、列和 Markings。修改属性要能读到它当前的值;删除要能读到整个对象;链接两端都要可见。第 9 门课讲这些控制。
三道关各挡各的,不能互相代替。比如「只有质量经理能暂停工单」,应该写进 roles 与提交条件,而不是指望界面上不显示按钮。提交条件与「谁能编辑这个 Action 的定义」也是两回事。
写完条件,用 --validate-only 逐条验证:故意传一张已经确认的订单,看返回里是哪一条不通过、显示的是哪一句话。
另有两条通用做法里的提醒:不要对用户组、标记、组织成员身份用 not,受限令牌可能没带这个属性,条件反而通过;列表参数用在提交条件里,元素最多 1,000 个。
拦得住错误,还要留得下证据。下一节讲通知与写回这些副作用,再下一节讲日志与撤销。
要点
- 提交条件把业务规则编进编辑权限,全部满足才执行。
- 条件按参数、对象属性、当前用户判断,可用 and、or、not 组合。
- 失败信息写给执行人:说清为什么被拦、下一步怎么办。
- 可选参数没传时,比较的一边是空值;要用
or加isNull兜底,别误拦。 roles、提交条件、数据权限各挡各的,不能互相代替。
练一练
为工单写提交条件
用示例工厂的工单练习:先想清楚业务规则,再翻译成条件。
第一条:工单现在必须是 planned。第二条:工单的 plannedQty 不能超过所选产线的 capacityPerShift(本练习假定一张工单一个班次做完)。写出 JSON,并给每条配失败信息。
累计报废数 scrapQty(可选)不能少于工单现在的报废数。想一想没传 scrapQty 时会怎样,用 or 和 isNull 写对,再用 --validate-only 分别传与不传它,各试一次。
把「校验失败」「非法操作」「Error 422」改成三句能让人知道下一步怎么办的话,任选上面的条件。
小测
选一个答案,马上看解析。
Q1「审批人不能批准自己起草的采购订单」应该怎么表达?
roles 只按角色分类,分不出「这一张单是不是你起的」;隐藏按钮挡不住命令行和智能体。要拿对象属性和当前用户比,就是提交条件。
Q2要表达「数量不超过 5000,或者执行人是 developer」,怎么组合?
多条提交条件之间是「且」:全部满足才执行。要「或」,就在一条条件里用 or。
Q3通过公开链接打开应用的访客点了批准,会怎样?
只读分享与公开链接的访客永远不能执行 Action,这一步在提交条件之前就挡住了。