onCreate(ev)}>
- {(Array.from(instructions.getValues()) as Instruction[]).map(item => item.options
- ? (
-
- {item.options.map(option => (
- {option.label}
+ {groups.map(group => (
+
+ {instructionList.filter(item => item.group === group.value).map(item => item.options
+ ? (
+
+ {item.options.map(option => (
+ {option.label}
+ ))}
+
+ )
+ : (
+ {item.title}
))}
-
- )
- : (
- {item.title}
+
))}
}>
diff --git a/packages/client/src/workflow/calculators.tsx b/packages/client/src/workflow/calculators.tsx
index a4096948d..45ebee120 100644
--- a/packages/client/src/workflow/calculators.tsx
+++ b/packages/client/src/workflow/calculators.tsx
@@ -1,10 +1,13 @@
import React from "react";
-import { Input, Select } from "antd";
+import { Cascader, DatePicker, Input, InputNumber, Select } from "antd";
import { css } from "@emotion/css";
-import { useNodeContext } from "./nodes";
-
+import { instructions, useNodeContext } from "./nodes";
+import { useFlowContext } from "./WorkflowCanvas";
+function NullRender() {
+ return null;
+}
export const calculators = [
{ value: 'equal', name: '等于' },
@@ -13,67 +16,219 @@ export const calculators = [
const JT_VALUE_RE = /^\s*\{\{([\s\S]*)\}\}\s*$/;
-function JobSelect({ value, onChange }) {
- const node = useNodeContext();
- const stack = [];
- for (let current = node.upstream; current; current = current.upstream) {
- stack.push(current);
+export function parseStringValue(value: string, Types) {
+ const matcher = value.match(JT_VALUE_RE);
+ if (!matcher) {
+ return { type: 'constant', value, options: { type: 'string' } };
}
- return (
-
- );
+
+ const [type, ...paths] = matcher[1].split('.');
+
+ return {
+ type,
+ options: paths.length ? (Types || VariableTypes)[type].parse(paths) : {}
+ };
}
-function ContextSelect({ value, onChange }) {
- return (
-
- );
-}
-
-const VariableTypeComponent = {
- constant({ onChange, ...props }) {
- return onChange(ev.target.value)} />
+const ConstantTypes = {
+ string: {
+ title: '字符串',
+ value: 'string',
+ component({ onChange, type, options, ...props }) {
+ return onChange(ev.target.value)} />;
+ },
+ default: ''
},
- job: JobSelect,
- context: ContextSelect,
+ number: {
+ title: '数字',
+ value: 'number',
+ component({ type, options, ...props }) {
+ return ;
+ },
+ default: 0
+ },
+ boolean: {
+ title: '逻辑值',
+ value: 'boolean',
+ component({ type, options, ...props }) {
+ return (
+
+ );
+ },
+ default: false
+ },
+ // date: {
+ // title: '日期',
+ // value: 'date',
+ // component({ type, options, ...props }) {
+ // return ;
+ // },
+ // default: new Date()
+ // }
+};
+
+export const VariableTypes = {
+ constant: {
+ title: '常量',
+ value: 'constant',
+ options: Object.values(ConstantTypes).map(item => ({
+ value: item.value,
+ label: item.title
+ })),
+ component({ options: { type } = { type: 'string' } }) {
+ return type ? ConstantTypes[type].component : NullRender;
+ },
+ appendTypeValue({ options = { type: 'string' } }) {
+ return options?.type ? [options.type] : [];
+ },
+ onTypeChange(props, [type, optionsType], onChange) {
+ const { default: value } = ConstantTypes[optionsType];
+ onChange({
+ value,
+ type,
+ options: { ...props.options, type: optionsType }
+ });
+ },
+ parse(path) {
+ return { path };
+ }
+ },
+ job: {
+ title: '节点数据',
+ value: 'job',
+ options() {
+ const node = useNodeContext();
+ const stack = [];
+ for (let current = node.upstream; current; current = current.upstream) {
+ const { getter } = instructions.get(current.type);
+ // consider `getter` as the key of a value available node
+ if (getter) {
+ stack.push({
+ value: current.id,
+ label: current.title ?? `#${current.id}`
+ });
+ }
+ }
+
+ return stack;
+ },
+ component({ options }) {
+ const { nodes } = useFlowContext();
+ if (!options?.nodeId) {
+ return NullRender;
+ }
+ const node = nodes.find(n => n.id == options.nodeId);
+ if (!node) {
+ return NullRender;
+ }
+ const instruction = instructions.get(node.type);
+ return instruction?.getter ?? NullRender;
+ },
+ appendTypeValue({ options = {} }: { type: string, options: any }) {
+ return options.nodeId ? [Number.parseInt(options.nodeId, 10)] : [];
+ },
+ onTypeChange(props, [type, nodeId], onChange) {
+ onChange({
+ ...props,
+ type,
+ options: { ...props.options, nodeId }
+ });
+ },
+ parse([nodeId, ...path]) {
+ return { nodeId, path: path.join('.') };
+ },
+ stringify({ options }) {
+ const stack = ['job'];
+ if (options.nodeId) {
+ stack.push(options.nodeId);
+ if (options.path) {
+ stack.push(options.path);
+ }
+ }
+ return `{{${stack.join('.')}}}`;
+ }
+ },
+ // context: ContextSelect,
// calculation: Calculation
};
-function OperandTypeSelect({ value, onChange }) {
- return (
-
- );
+interface OperandProps {
+ value: {
+ type: string;
+ value?: any;
+ options?: any;
+ };
+ onChange(v: any): void
}
-export function Operand({ value: operand = { type: 'constant', value: '' }, onChange }) {
- const { value } = operand;
- let { type = 'constant' } = operand;
- if (typeof value === 'string') {
- const matcher = value.match(JT_VALUE_RE);
+export function Operand({ onChange, value: operand = { type: 'constant', value: '', options: { type: 'string' } } }: OperandProps) {
+ const { type } = operand;
- if (matcher) {
- console.log(matcher);
- }
- }
-
- const VariableComponent = VariableTypeComponent[type];
+ const { component, appendTypeValue } = VariableTypes[type];
+ const VariableComponent = typeof component === 'function' ? component(operand) : component;
return (
- onChange({ ...operand, type: v })} />
- onChange({ ...operand, value: v })} />
+ {
+ const children = typeof item.options === 'function' ? item.options() : item.options;
+ return {
+ label: item.title,
+ value: item.value,
+ children,
+ disabled: children && !children.length
+ };
+ })}
+ onChange={(t: Array) => {
+ const { onTypeChange } = VariableTypes[t[0]];
+ if (typeof onTypeChange === 'function') {
+ onTypeChange(operand, t, onChange);
+ } else {
+ if (t[0] !== type) {
+ onChange({ type: t[0], value: null });
+ }
+ }
+ }}
+ />
+ onChange({ ...operand, value: v })} />
+
+ );
+}
+
+export function Calculation({ calculator, operands, onChange }) {
+ return (
+
+ onChange({ calculator, operands: [v, operands[1]] }))} />
+ {operands[0]
+ ? (
+ <>
+
+ onChange({ calculator, operands: [operands[0], v] }))} />
+ >
+ )
+ : null
+ }
);
}
diff --git a/packages/client/src/workflow/nodes/condition.tsx b/packages/client/src/workflow/nodes/condition.tsx
index f540a0058..a438af99d 100644
--- a/packages/client/src/workflow/nodes/condition.tsx
+++ b/packages/client/src/workflow/nodes/condition.tsx
@@ -7,7 +7,7 @@ import { Trans } from "react-i18next";
import { NodeDefaultView } from ".";
import { Branch, useFlowContext } from "../WorkflowCanvas";
import { branchBlockClass, nodeSubtreeClass } from "../style";
-import { calculators, Operand } from "../calculators";
+import { Calculation } from "../calculators";
// import { SchemaComponent } from "../../schema-component";
function CalculationItem({ value, onChange, onRemove }) {
@@ -30,24 +30,7 @@ function CalculationItem({ value, onChange, onRemove }) {
onChange={group => onChange({ ...value, group })}
/>
)
- : (
-
- onChange({ ...value, operands: [v, operands[1]] })} />
-
- onChange({ ...value, operands: [operands[0], v] })} />
-
- )
+ :
}
} />