mcpField
F
fcode-ui-triggers

fcode-ui-triggers

github.com/factorialco开发1235 次安装今天更新
代码仓库

关于 fcode-ui-triggers

fcode-ui-triggers 说明如何将 Factorial Code 流程呈现为 Factorial 页面中的按钮,面向配置流程入口的应用开发者。内容涵盖上下文传递、同步结果、表单、授权和本地化标签。

主要功能

  1. 01在 Factorial 位置配置流程按钮
  2. 02传递页面上下文和可信身份参数
  3. 03支持同步结果与排队执行
  4. 04在 Factorial 对话框中打开流程表单
  5. 05配置本地化标签和允许列表中的图标

适用场景

  1. 01在 Factorial 页面添加流程按钮
  2. 02将当前记录 ID 传给流程
  3. 03从页面操作打开流程表单

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/factorialco/factorial-code-skills --skill fcode-ui-triggers

安装后在 Claude Code 中输入/fcode-ui-triggers确认已加载。

详细介绍

Factorial Code — UI 触发器

UI 触发器会将 marketplace 应用的流程公开为 Factorial 内的按钮(页面标题栏、操作下拉菜单等)。Factorial 页面会声明 位置;已安装应用的流程认领某个位置后,Factorial 就会为每个认领该位置的流程渲染一个按钮。点击按钮会运行流程,或打开其表单。这是 Factorial Action 的一个入口:其设置位于流程 metadata.json 的 factorial.uiTrigger 子块中,awaitResult 位于 factorial 块顶层(整个块、旧版镜像以及 Factorial One / 后端入口见 fcode-factorial-actions;字段参考见 fcode-cli)。

注意事项

  • 只有已安装的 marketplace 应用才会显示按钮。 Factorial 会从公司已安装应用的部署工作区读取并列出触发器。普通工作区中的流程不会显示;触发器要像应用的其他部分一样,通过发布版本从 dev → prod → deploy 到达客户。
  • 位置 ID 必须来自拥有该页面的 Factorial 团队。 位置在 Factorial 代码中声明(例如 calendar.header.admin),不在平台上声明。平台接受任何非空白的 locationId(≤ 200 个字符);未知位置会被静默地从列表中忽略,因此拼写错误意味着“没有按钮”,而不是报错。
  • 由位置决定契约,而不是流程:哪些上下文参数会转发给流程、同步结果中的哪些键会传回页面,以及该位置是否为 single(一次只能有一个已安装应用)。除了 ID,也要询问这三项。
  • awaitResult 位于 factorial 块中,默认值为 true(同步)。 旧版 uiTrigger.awaitResult 的默认行为是触发后不等待;镜像会将新值复制覆盖旧值。因此,移入 factorial 的按钮会同步运行,除非你写入 "awaitResult": false。只有在任务耗时较短(< 50 s),且用户必须看到结果时,才将其设为 true;设为 false 时,点击会将执行加入队列,用户会看到“操作已开始”,并且永远不会显示返回值。
  • 启用了表单的流程会打开表单,而不是运行流程。 启用 factorial.form.enabled(或旧版 form.enabled)后,按钮会在 Factorial 内的对话框中打开表单,并忽略 awaitResult。
  • 由触发器打开的表单会通过 Factorial,而不是直接连接平台。 对话框会读取架构,并通过 Factorial 自己的后端提交;该后端会携带点击用户的身份。表单自身的 authMode 仍适用于通过其公开 URL 访问表单的用户(fcode-forms),但不适用于对话框。
  • company_id、triggered_from_location 和 access_id 在两种路径中都可信。 Factorial 会在每次调用时于服务端注入这些字段,不论是否使用表单;位置转发的参数会覆盖浏览器发送的任何值。可以安全地基于这些字段进行授权。(旧表单路径并非如此,它会将这些字段作为客户端可编辑的预填字段传递。)
  • 谁可以点击由 requiredPolicies 决定,并会强制执行。 Factorial 会在运行任何内容之前,根据点击用户检查 factorial.requiredPolicies(fcode-factorial-actions);此外,还会按策略范围读取位置。未列出任何策略的操作,对任何能访问该按钮的人开放。
  • 未捕获的错误会显示通用消息。 抛出异常或崩溃时,用户会看到“The action could not be completed”,不会看到详情。对于任何应向用户展示的内容,请返回 { errors: [...] }。
  • 更改最多需要五分钟才会显示——Factorial 会在浏览器中缓存触发器列表。

声明触发器

在 processes/<slug>/metadata.json 中配置,然后运行 fcode push(或在控制台的流程页面中使用 Trigger from Factorial 部分):

{
  "name": "Sync report",
  "tags": ["acme"],
  "factorial": {
    "enabled": true,
    "uiTrigger": {
      "enabled": true,
      "locationId": "compensations.cycle.header",
      "label": "Sync to Acme",
      "icon": "Refresh"
    }
  }
}
字段含义
factorial.enabled整个操作的总开关;按钮需要启用此项
factorial.awaitResult默认为 true:同步运行并显示结果。设为 false 可不等待结果
uiTrigger.enabled启用按钮。设为 true 时必须提供 locationId
uiTrigger.locationId按钮显示所在的 Factorial 位置,由页面所属团队指定
uiTrigger.label按钮文字。可使用纯文本或 fcode.i18n("key") 标记(见下文);这是此区块中唯一支持 i18n 的字段
uiTrigger.icon使用允许列表中的名称之一(见下文);省略时按钮仅显示文字

旧版顶层 uiTrigger 区块(enabled、locationId、label、icon、 awaitResult)仍可往返读写,并会与 factorial.uiTrigger 保持镜像同步;旧文件仍可正常使用,而 fcode pull 仍会在每个流程中写入 "uiTrigger": { "enabled": false }。新代码请使用 factorial;如果两者同时存在,fcode push 会发送 factorial(镜像规则见 fcode-factorial-actions)。

一个应用可在同一位置声明多个触发器,每个触发器都会显示为一个按钮;但在 Factorial 中标记为 single 的位置只允许安装一个应用:如果安装第二个声明了该位置的应用,安装会因冲突而失败,并指出第一个应用。若应用需要与其他应用共存,请勿声明 single 位置。

流程接收的内容

点击按钮会运行流程,并将 fcode.context.parameters 设为:

  • 该位置的转发上下文参数,例如页面所显示记录的 ID(cycle_id),具体包含哪些键取决于该位置的允许列表;
  • company_id — 点击按钮的 Factorial 用户所属的公司(可信:在共享密钥下注入,会覆盖浏览器发送的任何内容);
  • triggered_from_location — 位置 ID(可信,注入方式相同);
  • access_id — Factorial 访问权限(即点击用户在该公司中的成员身份),以字符串形式传入(可信,注入方式相同)。

没有上下文的位置(例如未关联任何记录的页眉按钮)不会转发任何参数,只传递三个可信键。点击用户的区域设置会作为执行区域设置传入,因此流程中的 fcode.i18n 会使用其语言(fcode-i18n)。

const { company_id, access_id, triggered_from_location, cycle_id } = fcode.context.parameters;
if (!cycle_id) throw new Error("cycle_id is required");

返回结果(同步触发器)

当 awaitResult: true 时,Factorial 会等待执行完成,并将你返回的内容原样交给页面。无需用封装结构包装,也不会在传递过程中筛除任何内容。

// Success — the whole object reaches the page's onSuccess handler.
return { synced: 42, report_url: "https://acme.example/reports/7" };
  • 成功状态始终表示成功,无论响应正文的内容是什么。返回包含 errors 键的对象不会导致失败。
  • 需要表示预期失败时,应使用错误状态,而不是通过响应正文表示。可抛出 fcode.error(...),或在类 HTTP 流程中返回错误状态;响应正文会原样传递,以便页面读取其中的消息。
  • 抛出未附带消息的错误,或超出同步执行时限(约 50 秒;执行可能仍会在后台完成),都会向用户显示无法采取后续操作的通用错误。

流程作者有责任让返回值符合入口点的预期:表单会读取自身约定的字段(message、formErrors、nextProcessId),而普通按钮只会显示提示,因此同时面向两者的流程无法使用一种通用的结果结构。位置上的 result_keys 仅供参考,用于描述页面打算读取哪些字段;它不会筛选任何内容。

当 awaitResult 关闭时,返回值只会显示在执行日志中;长时间运行的任务应放在日志中处理,或通过快速同步触发器调用 fcode.processes.run(...) 后在后台执行(参见 fcode-javascript / fcode-python)。

基于表单的触发器

照常启用表单(fcode-forms),按钮会在 Factorial 内以对话框形式打开表单,使用 f0 主题渲染,并预填转发的参数。点击后是打开对话框还是运行流程,取决于操作的入口:同时声明 form 和 uiTrigger 会打开表单;仅声明 uiTrigger 则会运行流程。

提交会经由 Factorial 的后端处理,后端会在服务端注入 company_id、triggered_from_location 和 access_id——如果流程会读取这些参数,请在 parametersSchema.json 中声明它们(使用 hidden 小组件)。结果遵循表单约定(message、formErrors、nextProcessId 等);多步骤表单会在同一对话框中依次遵循每个步骤的 nextProcessId。

{
  "name": "Export cycle",
  "factorial": {
    "enabled": true,
    "form": { "enabled": true },
    "uiTrigger": { "enabled": true, "locationId": "compensations.cycle.header", "label": "Export…", "icon": "Download" }
  }
}
触发器表单中的文件

文件字段可用,文件不会经由 Factorial 传输。使用 x-fcode-file 声明参数,并列出其接受的扩展名:

"msj_file": {
  "title": "FIE file",
  "type": "string",
  "x-fcode-file": { "accept": [".msj"] },
  "ui": { "ui:widget": "file", "ui:options": { "accept": ".msj" } }
}

提交时,Factorial 会为每个文件向平台申请上传授权,将文件直接 PUT 到 Factorial Code 存储,并将生成的 fcode.storage:// 路径作为参数值发送。流程读取此值的方式与读取任何已存储文件相同(fcode-javascript / fcode-python)。

  • 授权在提交时发放,而非随架构发放——平台会根据实际文件名检查 accept,并为其内容类型签名;在用户选择文件之前,这两者都尚不可知。名称不符合 accept 的文件会在此处被拒绝。
  • 上传的文件在存储满 48 小时后会被移除。如果流程需要长期使用某个文件,请将其复制到其他存储位置。

标签和 i18n

label 可包含 fcode.i18n("key") 标记——与表单架构使用的标记相同——系统会根据每位用户的区域设置,从工作区的区域设置文件中解析,并回退到主要区域设置;标签不会为空(模型、文件和语法见 fcode-i18n):

"factorial": {
  "enabled": true,
  "uiTrigger": { "enabled": true, "locationId": "calendar.header.admin", "label": "fcode.i18n(\"acme.sync.button\")" }
}

图标

Factorial 只会渲染以下名称(不区分大小写);其他名称都会回退为纯文本按钮,控制台也会显示相同的列表供选择:

Bell、Calendar、Chart、Document、Download、ExternalLink、Globe、 Graph、Link、Play、Refresh、Send、Settings、Sparkles、Star、 Upload。

Factorial 如何渲染它们(供 Factorial 工程师参考)

Factorial 端采用通用实现——没有针对各应用的代码。在 factorial monolith 中:

  • 位置是组件 app/fcode_locations/ 目录下的 YAML 文件(包含 id,以及可选的 resource 和 param_key,用于指定当前记录;forward_params、result_keys、single、legacy_ui),并由 CI 规范验证。calendar/header_admin.yml 是参考示例。
  • 页面会从 frontend/src/modules/factorialCode/components/FactorialCodeTrigger 渲染 <FactorialCodeTrigger locationId="…" params={{ cycle_id }} onSuccess onError />。它会为每个声明该位置的触发器绘制一个按钮(F0 outline 按钮,或用于 legacy_ui 位置的旧版设计系统按钮);加载期间或没有已安装的应用声明该位置时不渲染任何内容,并负责管理表单对话框。底层钩子(用于列表的 useFactorialCodeTriggers,以及用于点击的 useFactorialCodeTriggerActivation)也会导出,供下拉菜单等数据驱动的宿主使用。
  • 点击会通过 FactorialCode::Interactors::InvokeAction 处理:它会检查操作的 requiredPolicies(RequiredPoliciesAuthorization,由多个 AND 组构成 OR),并在策略范围内读取该位置的 resource;只转发 forward_params;覆盖浏览器发送的任何同名值,注入 company_id / access_id / triggered_from_location;并原样返回流程的答复。SPA 使用不透明的 action_id 标识操作;流程 slug 不会传到浏览器。所有功能均受 Factorial Code 功能标志控制。

应用开发者无需处理这些内容;只需从负责该页面的团队获取位置 ID 和约定即可。

发布前检查清单

  1. 与负责的 Factorial 团队确认位置 id、转发参数和是否为 single。
  2. 明确决定 factorial.awaitResult 的取值——仅在结果快速且对用户可见时设为 true(默认值),其他情况设为 false。
  3. 填写 factorial.requiredPolicies;如果任何能够访问此按钮的人都可以使用,则有意留空。
  4. 基于表单的触发器声明其读取的预填键,且任何文件参数都带有 x-fcode-file。
  5. 先在 Factorial 的开发安装中测试,然后升级到 prod- 并发布,以便部署工作区获取更新(fcode-release、fcode-ama)。

评论

支持 Markdown