在应用里用 Action

第 4 课 · 共 6 课 约 8 分钟

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

本课目标

读完这一课,你将能够

  • 说出应用里一个 Action 的完整流程:填参数、只校验、提交、刷新
  • 用 $validateOnly 与错误信息,把参数问题和提交条件问题分别显示在界面上
  • 判断该用单个 Action 还是批量,并说出应用里谁能执行哪个 Action

表单从定义里长出来

上一节说,事件里最要紧的一类是「点一下,改一条数据」。在应用里,这件事有个好处:表单是根据 Action 的定义生成的,写数据的界面和写数据的规则不是两套东西。规则只写在 Action 里,应用只负责把参数放到界面上。

官方有两种放法。按钮一次触发一个 Action;行内 Action 有表单和表格两种:表单一次一个 Action,适合少量对象,表格适合大批量或从 CSV 来的数据,但批量调用有上限,改动之间不能冲突。参数还可以带默认值,例如绑定到「当前选中的工单」,并选择让它可见、隐藏或只读。

示例工厂看板的每一行有一个「登记缺陷」。flag-defect 有四个参数:检验(对象)、缺陷代码、严重程度、描述,规则是新建一个 defect。检验由程序填好,用户只填后三项。

  1. 01选中一行把对象填进参数
  2. 02填参数代码、严重程度、描述
  3. 03只校验逐项结果,什么都不写
  4. 04提交一个事务
  5. 05刷新并提示「成功之后」的事件

两种失败,两种样子

$validateOnly: true 返回每个参数和每条提交条件的结果,但一个字也不写。两种问题的来源不同,放在界面上的位置也应该不同:

参数不合格提交条件不满足
来自哪里参数的类型、必填、取值约束Action 作者写的提交条件
返回里在哪validation.parameters.{name}.messagevalidation.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 故意填错参数,看返回;再写一段代码,把同样的信息显示出来。

小测

选一个答案,马上看解析。

Q1用户提交 flag-defect,提交条件没有通过。不带 $validateOnly 直接执行,会怎样?

Q2flag-defect 未配置 writeback webhook。班组长要给同一张工单一次登记三条缺陷,要么全成功要么全失败。用什么?

Q3通过公开链接进来的只读访客打开了看板,「登记缺陷」按钮该怎么处理?

延伸阅读