refactor: workflow condition node
refactor: workflow condition node
This commit is contained in:
@@ -1,17 +1,14 @@
|
||||
import { memo, useRef, useState } from "react";
|
||||
import { MoreOutlined as MoreOutlinedIcon } from "@ant-design/icons";
|
||||
import { FilterFilled as FilterFilledIcon, FilterOutlined as FilterOutlinedIcon, MoreOutlined as MoreOutlinedIcon } from "@ant-design/icons";
|
||||
import { Button, Card, Popover } from "antd";
|
||||
import { produce } from "immer";
|
||||
|
||||
import type { Expr, WorkflowNodeIoValueType } from "@/domain/workflow";
|
||||
import { ExprType } from "@/domain/workflow";
|
||||
import { useZustandShallowSelector } from "@/hooks";
|
||||
import { useWorkflowStore } from "@/stores/workflow";
|
||||
|
||||
import SharedNode, { type SharedNodeProps } from "./_SharedNode";
|
||||
import AddNode from "./AddNode";
|
||||
import type { ConditionItem, ConditionNodeConfigFormFieldValues, ConditionNodeConfigFormInstance } from "./ConditionNodeConfigForm";
|
||||
import ConditionNodeConfigForm from "./ConditionNodeConfigForm";
|
||||
import ConditionNodeConfigForm, { type ConditionNodeConfigFormFieldValues, type ConditionNodeConfigFormInstance } from "./ConditionNodeConfigForm";
|
||||
|
||||
export type ConditionNodeProps = SharedNodeProps & {
|
||||
branchId: string;
|
||||
@@ -23,55 +20,9 @@ const ConditionNode = ({ node, disabled, branchId, branchIndex }: ConditionNodeP
|
||||
|
||||
const [formPending, setFormPending] = useState(false);
|
||||
const formRef = useRef<ConditionNodeConfigFormInstance>(null);
|
||||
|
||||
const [drawerOpen, setDrawerOpen] = useState(false);
|
||||
|
||||
const getFormValues = () => formRef.current!.getFieldsValue() as ConditionNodeConfigFormFieldValues;
|
||||
|
||||
// 将表单值转换为表达式结构
|
||||
const formToExpression = (values: ConditionNodeConfigFormFieldValues): Expr => {
|
||||
// 创建单个条件的表达式
|
||||
const createComparisonExpr = (condition: ConditionItem): Expr => {
|
||||
const selectors = condition.leftSelector.split("#");
|
||||
const t = selectors[2] as WorkflowNodeIoValueType;
|
||||
const left: Expr = {
|
||||
type: ExprType.Var,
|
||||
selector: {
|
||||
id: selectors[0],
|
||||
name: selectors[1],
|
||||
type: t,
|
||||
},
|
||||
};
|
||||
|
||||
const right: Expr = { type: ExprType.Const, value: condition.rightValue, valueType: t };
|
||||
|
||||
return {
|
||||
type: ExprType.Compare,
|
||||
op: condition.operator,
|
||||
left,
|
||||
right,
|
||||
};
|
||||
};
|
||||
|
||||
// 如果只有一个条件,直接返回比较表达式
|
||||
if (values.conditions.length === 1) {
|
||||
return createComparisonExpr(values.conditions[0]);
|
||||
}
|
||||
|
||||
// 多个条件,通过逻辑运算符连接
|
||||
let expr: Expr = createComparisonExpr(values.conditions[0]);
|
||||
|
||||
for (let i = 1; i < values.conditions.length; i++) {
|
||||
expr = {
|
||||
type: ExprType.Logical,
|
||||
op: values.logicalOperator,
|
||||
left: expr,
|
||||
right: createComparisonExpr(values.conditions[i]),
|
||||
};
|
||||
}
|
||||
|
||||
return expr;
|
||||
};
|
||||
const [drawerOpen, setDrawerOpen] = useState(false);
|
||||
|
||||
const handleDrawerConfirm = async () => {
|
||||
setFormPending(true);
|
||||
@@ -84,10 +35,9 @@ const ConditionNode = ({ node, disabled, branchId, branchIndex }: ConditionNodeP
|
||||
|
||||
try {
|
||||
const newValues = getFormValues();
|
||||
const expression = formToExpression(newValues);
|
||||
const newNode = produce(node, (draft) => {
|
||||
draft.config = {
|
||||
expression,
|
||||
...newValues,
|
||||
};
|
||||
draft.validated = true;
|
||||
});
|
||||
@@ -100,7 +50,7 @@ const ConditionNode = ({ node, disabled, branchId, branchIndex }: ConditionNodeP
|
||||
return (
|
||||
<>
|
||||
<Popover
|
||||
classNames={{ root: "shadow-md" }}
|
||||
classNames={{ root: "mt-20 shadow-md" }}
|
||||
styles={{ body: { padding: 0 } }}
|
||||
arrow={false}
|
||||
content={
|
||||
@@ -116,26 +66,35 @@ const ConditionNode = ({ node, disabled, branchId, branchIndex }: ConditionNodeP
|
||||
>
|
||||
<Card className="relative z-[1] mt-10 w-[256px] shadow-md" styles={{ body: { padding: 0 } }} hoverable onClick={() => setDrawerOpen(true)}>
|
||||
<div className="flex h-[48px] flex-col items-center justify-center truncate px-4 py-2">
|
||||
<SharedNode.Title
|
||||
className="focus:bg-background focus:text-foreground overflow-hidden outline-slate-200 focus:rounded-sm"
|
||||
node={node}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<div className="relative w-full overflow-hidden" onClick={(e) => e.stopPropagation()}>
|
||||
<SharedNode.Title
|
||||
className="focus:bg-background focus:text-foreground overflow-hidden outline-slate-200 focus:rounded-sm"
|
||||
node={node}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<div className="absolute right-0 top-1/2 -translate-y-1/2" onClick={() => setDrawerOpen(true)}>
|
||||
{node.config?.expression ? (
|
||||
<Button color="primary" icon={<FilterFilledIcon />} variant="link" />
|
||||
) : (
|
||||
<Button color="default" icon={<FilterOutlinedIcon />} variant="link" />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
<SharedNode.ConfigDrawer
|
||||
node={node}
|
||||
open={drawerOpen}
|
||||
pending={formPending}
|
||||
onConfirm={handleDrawerConfirm}
|
||||
onOpenChange={(open) => setDrawerOpen(open)}
|
||||
getFormValues={() => formRef.current!.getFieldsValue()}
|
||||
>
|
||||
<ConditionNodeConfigForm nodeId={node.id} ref={formRef} disabled={disabled} initialValues={node.config} />
|
||||
</SharedNode.ConfigDrawer>
|
||||
</Popover>
|
||||
|
||||
<SharedNode.ConfigDrawer
|
||||
getConfigNewValues={getFormValues}
|
||||
node={node}
|
||||
open={drawerOpen}
|
||||
pending={formPending}
|
||||
onConfirm={handleDrawerConfirm}
|
||||
onOpenChange={(open) => setDrawerOpen(open)}
|
||||
>
|
||||
<ConditionNodeConfigForm nodeId={node.id} ref={formRef} disabled={disabled} initialValues={node.config} />
|
||||
</SharedNode.ConfigDrawer>
|
||||
|
||||
<AddNode node={node} disabled={disabled} />
|
||||
</>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user