---
order: 5
navTitle: 程序流脚本节点
---
# 前端程序流脚本节点

前端程序流脚本节点运行在浏览器端，用于在页面内程序流中调用 `custom.ts` 或页面同名 `.ts` 中的自定义脚本函数。它适合处理页面交互、组件联动、当前行上下文、浏览器事件和前端可访问的数据。

如果脚本需要访问数据库、文件系统、服务端权限上下文，或需要作为独立 `.afl` 程序流执行，改用[后端程序流脚本节点](../backend/action-flow-script-node.md)。

::: tip 提示
前端脚本节点只能用于嵌入在 SuperPage、仪表板等页面内的前端程序流，不能用于独立后端程序流 `.afl` 文件。
:::

## 写在哪里{#where}

按复用范围选择脚本位置：只给一个页面使用，写在页面同目录的同名 `.ts`；应用或项目内多个页面复用，写到对应层级的 `custom.ts`；多个项目复用时，再考虑系统级脚本。具体路径、加载范围和优先级见[脚本文件组织](../file-organization.md#front-script)。

## 编写脚本函数{#usage}

前端程序流脚本函数必须 `export`，并且函数名以 `action_` 开头。函数可以同步返回结果，也可以返回 `Promise`；返回 `Promise` 时，程序流会等待异步结果完成后再执行后续节点。

```ts
export async function action_buildOrderTip(
  args: { orderNo: string; status: string },
  ctx: succ.script.ActionFunctionContext
): Promise<string> {
  if (!args.orderNo) {
    return '';
  }

  const rowLabel = ctx.currentRow ? '当前行' : '当前页面';
  return `${rowLabel}：订单 ${args.orderNo} 当前状态为 ${args.status || '未知'}`;
}
```

写法要求：

1. 必须 `export` 函数，否则页面脚本服务无法发现它。
2. 函数名必须以 `action_` 开头。
3. 第一个参数使用对象接收节点参数，属性名和节点上配置的参数名一致。
4. 第二个参数是 `succ.script.ActionFunctionContext`，用于读取页面、组件、当前行和浏览器事件上下文。
5. 函数返回值会作为当前脚本节点的执行结果，可在后续节点中通过该节点的 `$result` 输出变量继续使用。

前端上下文 `ctx` 常用字段包括：

| 字段 | 说明 |
| :--- | :--- |
| `pageDataModel` | 当前页面数据对象。 |
| `component` | 触发脚本调用的组件 UI 对象。 |
| `currentRow` | 触发事件的数据行。 |
| `componentDataModel` | 没有 UI 对象时传入的组件数据对象。 |
| `srcEvent` | 浏览器原生事件。 |

## 配置节点{#configure}

在页面内程序流中添加**执行前端脚本**节点后，按下面方式配置：

1. 选择执行函数。节点会从当前页面已加载的前端脚本中列出 `action_` 开头的函数。
2. 设置参数。参数值可以写常量，也可以写表达式引用页面参数、组件值、当前行数据或前序节点结果。
3. 设置输出变量。需要给后续节点使用返回值时，在节点输出变量中保存 `$result`。

如果直接编辑元数据，`executeBrowserScript.method` 写去掉 `action_` 前缀后的名称，例如 `buildOrderTip`。

例如节点参数配置为：

| 参数名 | 参数值 |
| :--- | :--- |
| `orderNo` | `params.orderNo` |
| `status` | `[订单].[状态]` |

脚本函数会收到：

```ts
{
  orderNo: 'SO-20260628-001',
  status: '待审核'
}
```

参数名应保持稳定。已经被程序流节点引用的参数，不要随意改名；确需调整时，同步修改节点参数配置和后续引用。

## 返回值和异常{#result-error}

前端脚本函数可以返回字符串、数值、布尔值、对象或数组，也可以返回 `Promise`。返回值会进入当前脚本节点的 `$result`，后续节点可以用表达式读取。

```ts
export async function action_loadOptions(args: { keyword: string }, ctx: succ.script.ActionFunctionContext) {
  const response = await fetch(`/api/options?keyword=${encodeURIComponent(args.keyword || '')}`);
  return await response.json();
}
```

如果函数没有返回值，`$result` 为空。需要让后续分支根据执行结果判断时，建议显式返回状态对象，而不是只依赖异常。

```ts
export function action_validateSelection(args: { selectedIds: string[] }, ctx: succ.script.ActionFunctionContext) {
  if (!args.selectedIds?.length) {
    return { success: false, message: '请至少选择一条数据' };
  }
  return { success: true };
}
```

脚本函数中抛出的异常，或异步函数返回的 `Promise` 被 reject，都会导致脚本节点执行失败。面向终端用户的页面中，应优先处理可预期异常并返回可判断的状态对象。

## 加载范围和优先级{#scope}

前端程序流脚本函数按当前页面加载到的脚本范围生效。同一个函数被多个页面使用时，不要复制到每个页面脚本里，应上移到应用或项目的 `custom.ts`；只在一个页面临时使用时，不要放到项目级或系统级脚本里。

`custom.ts` 的基础写法见 [custom.ts](./custom-ts.md)。

## 相关类型{#types}

需要核对字段或运行环境时，可查看以下类型声明：

- 程序流执行脚本概念：[`types/internal/succ.concepts.d.ts`](../../../../dev-types/types/internal/succ.concepts.d.ts)
- 前端脚本函数上下文：[`types/api/succ.script.d.ts`](../../../../dev-types/types/api/succ.script.d.ts)
- 执行前端脚本节点元数据：[`types/meta/actionComponent/executeBrowserScript.d.ts`](../../../../dev-types/types/meta/actionComponent/executeBrowserScript.d.ts)

更多程序流节点结构见 [.afl 程序流元数据](../../meta/file-types/backend/afl.md)。
