feat: add icon property to workflow node specifications and update related components
This commit is contained in:
@@ -13,6 +13,7 @@ export function buildFlowgramNodeRegistries(nodeSpecs: AIWorkflowNodeSpec[]): Wo
|
||||
type: "start",
|
||||
title: "开始",
|
||||
description: "流程入口",
|
||||
icon: "PlayCircleIcon",
|
||||
riskLevel: "low" as const,
|
||||
interruptible: false,
|
||||
requiresConfirmationPredecessor: false,
|
||||
@@ -21,6 +22,7 @@ export function buildFlowgramNodeRegistries(nodeSpecs: AIWorkflowNodeSpec[]): Wo
|
||||
type: "end",
|
||||
title: "结束",
|
||||
description: "流程结束",
|
||||
icon: "FlagIcon",
|
||||
riskLevel: "low" as const,
|
||||
interruptible: false,
|
||||
requiresConfirmationPredecessor: false,
|
||||
@@ -47,9 +49,10 @@ export function buildFlowgramNodeRegistries(nodeSpecs: AIWorkflowNodeSpec[]): Wo
|
||||
formMeta: {
|
||||
render: () => (
|
||||
<FlowgramNodeForm
|
||||
nodeType={spec.type}
|
||||
fallbackTitle={spec.title || spec.type}
|
||||
/>
|
||||
nodeType={spec.type}
|
||||
fallbackTitle={spec.title || spec.type}
|
||||
icon={spec.icon}
|
||||
/>
|
||||
),
|
||||
},
|
||||
}))
|
||||
@@ -58,9 +61,11 @@ export function buildFlowgramNodeRegistries(nodeSpecs: AIWorkflowNodeSpec[]): Wo
|
||||
function FlowgramNodeForm({
|
||||
nodeType,
|
||||
fallbackTitle,
|
||||
icon,
|
||||
}: {
|
||||
nodeType: string
|
||||
fallbackTitle: string
|
||||
icon: string
|
||||
}) {
|
||||
const { node, selected } = useNodeRender()
|
||||
const nodeId = String(node.id ?? "")
|
||||
@@ -69,8 +74,8 @@ function FlowgramNodeForm({
|
||||
<Field<string> name="title">
|
||||
{({ field }) => (
|
||||
<WorkflowNodeCard
|
||||
nodeType={nodeType}
|
||||
title={field.value || fallbackTitle}
|
||||
icon={icon}
|
||||
selected={selected}
|
||||
width={nodeType === "condition" ? "wide" : "normal"}
|
||||
>
|
||||
|
||||
@@ -4,14 +4,14 @@ import { cn } from "@/lib/utils"
|
||||
import { WorkflowNodeIcon } from "./workflow-node-icon"
|
||||
|
||||
export function WorkflowNodeCard({
|
||||
nodeType,
|
||||
title,
|
||||
icon,
|
||||
selected,
|
||||
width = "normal",
|
||||
children,
|
||||
}: {
|
||||
nodeType: string
|
||||
title: string
|
||||
icon: string
|
||||
selected: boolean
|
||||
width?: "normal" | "wide"
|
||||
children?: ReactNode
|
||||
@@ -28,7 +28,7 @@ export function WorkflowNodeCard({
|
||||
>
|
||||
<div className="overflow-hidden rounded-lg border border-transparent bg-background">
|
||||
<div className="flex items-center gap-2 px-3 pb-2 pt-3">
|
||||
<WorkflowNodeIcon type={nodeType} />
|
||||
<WorkflowNodeIcon icon={icon} />
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="truncate text-sm font-semibold leading-5 text-foreground">
|
||||
{title}
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
import { cn } from "@/lib/utils"
|
||||
import { getWorkflowNodeMeta } from "./workflow-node-meta"
|
||||
import { FileTextIcon, type LucideIcon } from "lucide-react"
|
||||
import * as LucideIcons from "lucide-react"
|
||||
|
||||
const lucideIconComponents = LucideIcons as unknown as Record<string, LucideIcon>
|
||||
|
||||
export function WorkflowNodeIcon({
|
||||
type,
|
||||
icon,
|
||||
size = "md",
|
||||
className,
|
||||
}: {
|
||||
type: string
|
||||
icon?: string
|
||||
size?: "sm" | "md"
|
||||
className?: string
|
||||
}) {
|
||||
const meta = getWorkflowNodeMeta(type)
|
||||
const Icon = meta.icon
|
||||
const Icon = icon ? lucideIconComponents[icon] ?? FileTextIcon : FileTextIcon
|
||||
|
||||
return (
|
||||
<span
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
import {
|
||||
BookOpenIcon,
|
||||
BotIcon,
|
||||
ClipboardListIcon,
|
||||
FileTextIcon,
|
||||
FlagIcon,
|
||||
GitBranchIcon,
|
||||
HeadphonesIcon,
|
||||
HelpCircleIcon,
|
||||
MessageCircleIcon,
|
||||
PlayCircleIcon,
|
||||
SearchIcon,
|
||||
SendIcon,
|
||||
ShieldCheckIcon,
|
||||
TicketIcon,
|
||||
UserCheckIcon,
|
||||
type LucideIcon,
|
||||
} from "lucide-react"
|
||||
|
||||
export type WorkflowNodeMeta = {
|
||||
icon: LucideIcon
|
||||
}
|
||||
|
||||
const workflowNodeMetaByType: Record<string, WorkflowNodeMeta> = {
|
||||
start: { icon: PlayCircleIcon },
|
||||
conversation_understanding: { icon: MessageCircleIcon },
|
||||
reply_policy: { icon: ShieldCheckIcon },
|
||||
knowledge_retrieve: { icon: BookOpenIcon },
|
||||
answerability_gate: { icon: HelpCircleIcon },
|
||||
llm_reply: { icon: BotIcon },
|
||||
condition: { icon: GitBranchIcon },
|
||||
analyze_conversation: { icon: SearchIcon },
|
||||
prepare_ticket_draft: { icon: ClipboardListIcon },
|
||||
human_confirm: { icon: UserCheckIcon },
|
||||
create_ticket: { icon: TicketIcon },
|
||||
handoff_to_human: { icon: HeadphonesIcon },
|
||||
send_reply: { icon: SendIcon },
|
||||
end: { icon: FlagIcon },
|
||||
}
|
||||
|
||||
export function getWorkflowNodeMeta(type: string): WorkflowNodeMeta {
|
||||
return workflowNodeMetaByType[type] ?? { icon: FileTextIcon }
|
||||
}
|
||||
@@ -24,7 +24,7 @@ export function WorkflowNodePalette({
|
||||
className="flex w-full items-start gap-2 rounded-md px-2 py-2 text-left text-sm transition-colors hover:bg-muted"
|
||||
onClick={() => onAddNode(spec)}
|
||||
>
|
||||
<WorkflowNodeIcon type={spec.type} size="sm" className="mt-0.5" />
|
||||
<WorkflowNodeIcon icon={spec.icon} size="sm" className="mt-0.5" />
|
||||
<span className="min-w-0">
|
||||
<span className="block truncate font-medium">{spec.title || spec.type}</span>
|
||||
<span className="line-clamp-2 text-xs text-muted-foreground">{spec.description}</span>
|
||||
|
||||
@@ -380,6 +380,7 @@ export type AIWorkflowNodeSpec = {
|
||||
type: string
|
||||
title: string
|
||||
description: string
|
||||
icon: string
|
||||
riskLevel: "low" | "medium" | "high"
|
||||
interruptible: boolean
|
||||
requiresConfirmationPredecessor: boolean
|
||||
|
||||
Reference in New Issue
Block a user