《60天AI学习计划启动 | Day 44: 工作流可视化配置(简单 DAG / 步骤 UI)》
Day 44:工作流可视化配置(简单 DAG / 步骤 UI)
学习目标
- 理解 “AI 工作流 = 多步骤 + Agent/工具 + 线性/分支关系” 的前端抽象
- 掌握 用简单步骤列表模拟「线性工作流」的配置方式
- 会写 一个最小可用的“工作流编辑器”数据结构 + React 组件雏形
核心知识点
-
1. 工作流模型(简化版,先线性后再考虑 DAG)
- Workflow:
id / name / steps[] - Step:
id / name / type(collect/analyze/report/notify等) / agentId / config config里放参数,如时间范围、要分析的指标等- 将 Day 43 的任务(collect→analyze→report)抽象成“可配置模板”
- Workflow:
-
2. 可视化编辑的基本形态
- 左侧:步骤列表(可添加/删除/上下移动)
- 中间:选中步骤的配置表单(type/agent/参数)
- 右侧(可选):预览 JSON(方便对接后端)
实战作业(附代码)
作业 1:定义工作流 & 步骤 TS 类型
// workflowTypes.ts
export type WorkflowStepType = 'collect' | 'analyze' | 'report' | 'notify'
export interface WorkflowStep {
id: string
name: string
type: WorkflowStepType
agentId: string
config: Record<string, any>
}
export interface Workflow {
id: string
name: string
steps: WorkflowStep[]
}
作业 2:最小“工作流编辑器”组件雏形(线性步骤)
// WorkflowEditor.tsx
import React, { useState } from 'react'
import type { Workflow, WorkflowStep, WorkflowStepType } from './workflowTypes'
const STEP_TYPES: WorkflowStepType[] = ['collect', 'analyze', 'report', 'notify']
const AGENT_OPTIONS = [
{ id: 'frontend', label: '前端专家 Agent' },
{ id: 'analytics', label: '报表分析 Agent' },
{ id: 'doc', label: '文档助手 Agent' }
]
function createEmptyStep(): WorkflowStep {
return {
id: crypto.randomUUID(),
name: '新步骤',
type: 'collect',
agentId: 'analytics',
config: {}
}
}
export const WorkflowEditor: React.FC = () => {
const [wf, setWf] = useState<Workflow>({
id: 'wf_demo',
name: '每日巡检工作流模板',
steps: [createEmptyStep()]
})
const [selectedStepId, setSelectedStepId] = useState<string | null>(
wf.steps[0]?.id ?? null
)
const updateStep = (id: string, patch: Partial<WorkflowStep>) => {
setWf(prev => ({
...prev,
steps: prev.steps.map(s => (s.id === id ? { ...s, ...patch } : s))
}))
}
const addStep = () => {
const step = createEmptyStep()
setWf(prev => ({ ...prev, steps: [...prev.steps, step] }))
setSelectedStepId(step.id)
}
const removeStep = (id: string) => {
setWf(prev => ({ ...prev, steps: prev.steps.filter(s => s.id !== id) }))
if (selectedStepId === id) setSelectedStepId(null)
}
const moveStep = (id: string, dir: -1 | 1) => {
setWf(prev => {
const idx = prev.steps.findIndex(s => s.id === id)
if (idx < 0) return prev
const target = idx + dir
if (target < 0 || target >= prev.steps.length) return prev
const arr = [...prev.steps]
const [step] = arr.splice(idx, 1)
arr.splice(target, 0, step)
return { ...prev, steps: arr }
})
}
const selected = wf.steps.find(s => s.id === selectedStepId) || null
return (
<div style={{ display:'flex', gap:16 }}>
{/* 左侧:步骤列表 */}
<div style={{ width:220 }}>
<h4>步骤列表</h4>
<button onClick={addStep}>+ 添加步骤</button>
<ul>
{wf.steps.map((s, idx) => (
<li
key={s.id}
style={{
cursor:'pointer',
padding:4,
background: s.id === selectedStepId ? '#eef' : 'transparent'
}}
onClick={() => setSelectedStepId(s.id)}
>
{idx + 1}. {s.name} ({s.type})
<button onClick={e => { e.stopPropagation(); moveStep(s.id, -1) }}>↑</button>
<button onClick={e => { e.stopPropagation(); moveStep(s.id, 1) }}>↓</button>
<button onClick={e => { e.stopPropagation(); removeStep(s.id) }}>删</button>
</li>
))}
</ul>
</div>
{/* 中间:选中步骤配置 */}
<div style={{ flex:1 }}>
<h4>步骤配置</h4>
{selected ? (
<>
<div>
名称:
<input
value={selected.name}
onChange={e => updateStep(selected.id, { name: e.target.value })}
/>
</div>
<div>
类型:
<select
value={selected.type}
onChange={e => updateStep(selected.id, { type: e.target.value as WorkflowStepType })}
>
{STEP_TYPES.map(t => (
<option key={t} value={t}>{t}</option>
))}
</select>
</div>
<div>
Agent:
<select
value={selected.agentId}
onChange={e => updateStep(selected.id, { agentId: e.target.value })}
>
{AGENT_OPTIONS.map(a => (
<option key={a.id} value={a.id}>{a.label}</option>
))}
</select>
</div>
{/* 简单 config 示例:collect 步骤配置时间范围 */}
{selected.type === 'collect' && (
<div>
时间范围:
<input
placeholder="如 last_7_days"
value={selected.config.range || ''}
onChange={e =>
updateStep(selected.id, {
config: { ...selected.config, range: e.target.value }
})
}
/>
</div>
)}
</>
) : (
<div>请选择一个步骤</div>
)}
</div>
{/* 右侧:JSON 预览 */}
<div style={{ width:280 }}>
<h4>JSON 预览</h4>
<pre style={{ fontSize:12, whiteSpace:'pre-wrap' }}>
{JSON.stringify(wf, null, 2)}
</pre>
</div>
</div>
)
}
明日学习计划预告(Day 45)
- 主题:将工作流能力嵌入前端产品 + 运行监控页面
- 方向:
- 把今天配置好的 Workflow 作为“模板”,真正触发执行并查看运行记录
- 在前端做一个简单的「任务实例列表 + 状态 + 查看报告」页

浙公网安备 33010602011771号