在应用里用 Action
表单从定义里长出来;先只校验再提交;批量、权限与界面上的失败信息。

本课目标
读完这一课,你将能够
- 说出应用里一个 Action 的完整流程:填参数、只校验、提交、刷新
- 用
$validateOnly与错误信息,把参数问题和提交条件问题分别显示在界面上 - 判断该用单个 Action 还是批量,并说出应用里谁能执行哪个 Action
表单从定义里长出来
上一节说,事件里最要紧的一类是「点一下,改一条数据」。在应用里,这件事有个好处:表单是根据 Action 的定义生成的,写数据的界面和写数据的规则不是两套东西。规则只写在 Action 里,应用只负责把参数放到界面上。
官方有两种放法。按钮一次触发一个 Action;行内 Action 有表单和表格两种:表单一次一个 Action,适合少量对象,表格适合大批量或从 CSV 来的数据,但批量调用有上限,改动之间不能冲突。参数还可以带默认值,例如绑定到「当前选中的工单」,并选择让它可见、隐藏或只读。
示例工厂看板的每一行有一个「登记缺陷」。flag-defect 有四个参数:检验(对象)、缺陷代码、严重程度、描述,规则是新建一个 defect。检验由程序填好,用户只填后三项。
- 01选中一行把对象填进参数
- 02填参数代码、严重程度、描述
- 03只校验逐项结果,什么都不写
- 04提交一个事务
- 05刷新并提示「成功之后」的事件
两种失败,两种样子
$validateOnly: true 返回每个参数和每条提交条件的结果,但一个字也不写。两种问题的来源不同,放在界面上的位置也应该不同:
| 参数不合格 | 提交条件不满足 | |
|---|---|---|
| 来自哪里 | 参数的类型、必填、取值约束 | Action 作者写的提交条件 |
| 返回里在哪 | validation.parameters.{name}.message | validation.submissionCriteria[].configuredFailureMessage |
| 界面上放哪 | 标在对应的输入框旁(aidc-field__error,输入框加 aria-invalid) | 表单顶部的一条提示(aidc-alert--destructive),它不属于某一个输入框 |
直接提交而不先校验,也是安全的:不合格时服务端返回 422,message 就是那句配置好的失败信息,什么都不写。先校验的好处是能把每一项标在表单上,让用户改完再交。
async function submit(name, params) {
const action = client.action(name);
const check = await action.applyAction(params, { $validateOnly: true });
if (check.validation.result !== "VALID") return showProblems(check.validation); // 什么都没写
try {
const done = await action.applyAction(params, { $returnEdits: true });
ui.toast("已提交", { variant: "success", description: `新建 ${done.edits.addedObjectCount},修改 ${done.edits.modifiedObjectsCount}` });
await refresh(); // 「成功之后」的事件
} catch (err) {
ui.toast(err.message, { variant: "error" }); // 422、404、409:message 是可以直接给人看的话
}
}
没有配置 writeback webhook,提交成功后却提示「已同步到 ERP」。
未配置 writeback webhook 时,提示「已登记缺陷,记录在 Semantic 里」。要改 ERP,给 Action 配 writeback webhook。外部系统先接受,语义层才写入。外部系统拒绝或超时,整个 Action 不生效。界面提示要与实际行为一致。
谁能点,批量怎么办
应用只能执行清单 semantic.actions 登记过的 Action,访客的角色还要在 Action 的 roles 里(缺省是 developer、member、editor);只读访客,也就是公开链接和只读分享进来的人,永远不能写。真正的拦截在服务端,界面只负责别让人白点:
冲突也会以同样的方式回来:对象刚被别人改过,是 409;对象不存在,是 404;对象已经存在,是 409。message 都是可以直接给人看的话,例如「对象已被别人改过,刷新后再改」。界面上要做的只有一件事:把它显示出来,并提供「刷新」。
开了 Action Log 的 Action,每次成功提交都会记下执行人。在应用里,执行人是访客本人,不是应用,所以看板上谁登记了缺陷,日志里就是谁。
const me = await auth.me();
const canFlag = auth.can(me, { action: "flag-defect" }); // 没权限就隐藏按钮
批量对应官方的 Action 表格:普通 batchApplyAction 一次最多 20 个请求,放在一个事务里,任何一个失败全部回滚;配置 writeback webhook 的 Action 一次只能提交一个请求。一次 Action 最多改 10,000 个对象、涉及 50 个 Object Type。不带 writeback webhook 时,班组长给同一张工单登记三条缺陷,就是三个请求、一个事务:要么全登记,要么都不登。超过 20 个就得拆成几批,批与批之间不再是同一个事务。
要点
- 表单由 Action 的定义生成;规则只写在 Action 里,应用只把参数放到界面上。
- 先
$validateOnly再提交;参数问题标在输入框旁,提交条件的失败信息放在表单顶部原样显示。 - 直接提交不合格的内容会得到 422,
message就是配置好的失败信息,什么都不写。 - 普通批量用
batchApplyAction:最多 20 个请求,一个事务,一个失败全部回滚。配置 writeback webhook 的 Action 一次只能提交一个请求。 - 应用只能执行清单登记过的 Action,且角色要在 Action 的
roles里;只读访客永远不能写。
练一练
把 Action 放进界面
在你有权限的组织里做;只校验不会写任何东西。
选一个 Action,用 aidc semantic apply … --validate-only 故意填错参数,看返回;再写一段代码,把同样的信息显示出来。
为 flag-defect 写一个提交函数(校验、提交、刷新),并说出失败时用户会看到什么。
三个需求各该用什么:质检员登记 1 条缺陷;班组长放行 8 张工单;一张工单要登记 30 条缺陷。
小测
选一个答案,马上看解析。
Q1用户提交 flag-defect,提交条件没有通过。不带 $validateOnly 直接执行,会怎样?
提交是一个事务,校验不过就整体不写。
Q2flag-defect 未配置 writeback webhook。班组长要给同一张工单一次登记三条缺陷,要么全成功要么全失败。用什么?
单独的三次调用是三个事务,可能只成功一部分;批量才是一个事务。
Q3通过公开链接进来的只读访客打开了看板,「登记缺陷」按钮该怎么处理?
界面隐藏只是体验,权限由服务端裁决;也不能借更高的身份替人执行。