---
title: Automation 自动化编排
description: 带流程画布、节点配置与运行日志的自动化编辑器
category: TemplateData
status: beta
since: 0.6.0
tags: [template, automation, workflow, flowchart, ocr]
syncStatus: reviewed
verified: false
---

## 用法

### 剪贴板截图翻译
:::TuffDemoWrapper{demo="TemplateAutomationDemo" code-lang="vue" description="进入视口后自动运行一次；改节点配置后再点「运行」。"}
---
code: |
  <script setup lang="ts">
  import { computed, reactive, ref } from 'vue'
  import TemplateFrame from './TemplateFrame.vue'

  const states = reactive({ trigger: 'idle', ocr: 'idle', fallback: 'idle', translate: 'idle', notify: 'idle' })
  const flight = ref<string | null>(null) // 正在传递数据的那条连线
  const config = reactive({ ocr: { engine: 'vision', minConfidence: 80 }, translate: { rateLimit: false } })

  const edges = computed(() => [
    ['trigger', 'ocr'], ['ocr', 'translate'], ['ocr', 'fallback'], ['fallback', 'translate'], ['translate', 'notify'],
  ].map(([from, to]) => ({ from, to, dashed: flight.value === `${from}>${to}` })))

  // 按下「运行」时按当前配置排好一条可取消的 setTimeout 链
  function run() {
    const reread = OCR_CONFIDENCE < config.ocr.minConfidence
    schedule(0, () => (states.trigger = 'running'))
    schedule(400, () => {
      states.trigger = 'done'
      flight.value = 'trigger>ocr'
    })
    // … 识别，然后要么走 AI 重读，要么 states.fallback = 'skipped' …
  }
  </script>

  <template>
    <TemplateFrame title="Automation" @enter="run">
      <template #default="{ width, height }">
        <TxFlowchart
          :nodes="layout(width, height)" :edges="edges" :height="height - 56"
          :node-width="212" draggable
          @node-move="keepOffset" @node-click="({ id }) => (selected = id)"
        >
          <template #node="{ node }">
            <div class="flow-node" :class="`is-${states[node.id]}`">
              <span class="flow-node__title">{{ titles[node.id] }}</span>
              <TxWorkingIndicator v-if="states[node.id] === 'running'" variant="dots" :show-elapsed="false" />
              <TxStatusBadge v-else-if="states[node.id] === 'done'" size="sm" status="success" text="完成" />
            </div>
          </template>
        </TxFlowchart>

        <aside class="flow__rail">
          <TxFlatSelect v-model="config.ocr.engine">
            <TxFlatSelectItem value="vision" label="Apple Vision" />
            <TxFlatSelectItem value="windows" label="Windows OCR" />
          </TxFlatSelect>
          <TxScrubField v-model="config.ocr.minConfidence" label="≥" :min="50" :max="99" suffix="%" />
          <TxTaskRows variant="list" :rows="taskRows" />
          <TxCodeStream :code="log" :revealed-lines="revealed" :min-height="0" />
        </aside>
      </template>
    </TemplateFrame>
  </template>

  <style scoped>
  /* TxFlowchart 的连线只有 dashed 一种变体，模板用它表示「正在传递」 */
  .flow :deep(.tx-bui-flowchart__edge.is-dashed) { stroke: var(--tx-bui-accent); }
  @media (prefers-reduced-motion: no-preference) {
    .flow :deep(.tx-bui-flowchart__edge.is-dashed) { animation: march 0.6s linear infinite; }
  }
  @keyframes march { to { stroke-dashoffset: -8; } }
  </style>
---
:::

## 概述

可编辑、可运行的 Tuff 截图 OCR 流程：原生 OCR 置信度不足时交给 AI 重读，再翻译并写回剪贴板。

- 首次进入视口时自动运行一次（约 3.3 秒），数据经过的连线会流动；减少动态效果时直接显示结果，不启动计时器。
- 点节点编辑配置，对下一次运行生效；把「原生 OCR」的最低置信度调到 94% 以上（样例为 93%），运行就会绕到 AI 重读。
- 「翻译」节点打开「模拟限流（429）」后，翻译先失败，600ms 后重试成功。
- 运行中可以「停止」：正在执行的节点标为已取消，日志补一行 `cancelled by user`。
- 节点可拖动并吸附点阵；拖动距离作为偏移保留，全屏后不丢。
- 宽屏（≥ 960px）显示运行记录、四步进度与日志分栏；列内与窄屏把「节点配置 / 本次运行」收进页签。

## 自定义

- 换成自己的流程：节点与连线都是普通数组，`flowNodes()` 只按画布尺寸算坐标；连线总从上一节点底边连到下一节点顶边，分支节点要横向错开。
- 接真实执行器时，把 `buildPlan()` 里的定时步骤换成后端事件（SSE / WebSocket），每个事件调用一次 `setNode()` 并追加一行日志。
- TxFlowchart 没有逐条连线的样式 API：模板借用 `dashed` 表示「正在传递」，颜色与流动写在 `prefers-reduced-motion: no-preference` 之内。
- TxFlatSelect 与微调卡片的类型菜单都不 teleport，要避开 `overflow: hidden` 的裁切，并远离容器底边。

## 相关组件

| 区域 | 组件 | 作用 |
|---|---|---|
| 顶栏 | [TxWorkingIndicator](/docs/dev/components/working-indicator)、[TxStatusBadge](/docs/dev/components/status-badge)、[TxSteps](/docs/dev/components/steps)、[TxSwitch](/docs/dev/components/switch)、[TxButton](/docs/dev/components/button) | 状态、进度与运行 / 停止 |
| 画布 | [TxFlowchart](/docs/dev/components/flowchart)、[TxStatusBadge](/docs/dev/components/status-badge)、[TxWorkingIndicator](/docs/dev/components/working-indicator)、[TxDotIndicator](/docs/dev/components/dot-indicator) | 五个节点与流动连线 |
| 节点配置 | [TxFlatSelect](/docs/dev/components/flat-select)、[TxScrubField](/docs/dev/components/scrub-field)、[TxSwitch](/docs/dev/components/switch)、[TxFineTuneCard](/docs/dev/components/fine-tune-card)、[TxToastPanel](/docs/dev/components/toast-panel) | 每个节点的表单 |
| 本次运行 | [TxTaskRows](/docs/dev/components/task-rows)、[TxCodeStream](/docs/dev/components/code-stream) | 步骤状态与运行日志 |
| 运行记录（宽屏） | [TxTimeline](/docs/dev/components/timeline) | 最近几次运行 |
| 日志分栏（宽屏） | [TxSplitter](/docs/dev/components/splitter) | 调整画布与日志高度 |
| 完成提示 | [TxToastPanel](/docs/dev/components/toast-panel) | 4 秒后收起的结果卡 |
