diff --git a/packages/client/src/workflow/calculators.tsx b/packages/client/src/workflow/calculators.tsx
index 45ebee120..8239eceec 100644
--- a/packages/client/src/workflow/calculators.tsx
+++ b/packages/client/src/workflow/calculators.tsx
@@ -10,8 +10,46 @@ function NullRender() {
}
export const calculators = [
- { value: 'equal', name: '等于' },
- { value: 'notEqual', name: '不等于' }
+ {
+ value: 'boolean',
+ title: '值比较',
+ children: [
+ { value: 'equal', name: '=' },
+ { value: 'notEqual', name: '≠' },
+ { value: 'gt', name: '>' },
+ { value: 'gte', name: '≥' },
+ { value: 'lt', name: '<' },
+ { value: 'lte', name: '≤' }
+ ]
+ },
+ {
+ value: 'number',
+ title: '算术运算',
+ children: [
+ { value: 'add', name: '+' },
+ { value: 'minus', name: '-' },
+ { value: 'multipe', name: '*' },
+ { value: 'divide', name: '/' },
+ { value: 'mod', name: '%' },
+ ]
+ },
+ {
+ value: 'string',
+ title: '字符串',
+ children: [
+ { value: 'includes', name: '包含' },
+ { value: 'notIncludes', name: '不包含' },
+ { value: 'startsWith', name: '开头是' },
+ { value: 'notStartsWith', name: '开头不是' },
+ { value: 'endsWith', name: '结尾是' },
+ { value: 'notEndsWith', name: '结尾不是' }
+ ]
+ },
+ {
+ value: 'date',
+ title: '日期',
+ children: []
+ }
];
const JT_VALUE_RE = /^\s*\{\{([\s\S]*)\}\}\s*$/;
@@ -79,17 +117,17 @@ export const VariableTypes = {
label: item.title
})),
component({ options: { type } = { type: 'string' } }) {
- return type ? ConstantTypes[type].component : NullRender;
+ return ConstantTypes[type]?.component ?? NullRender;
},
appendTypeValue({ options = { type: 'string' } }) {
return options?.type ? [options.type] : [];
},
- onTypeChange(props, [type, optionsType], onChange) {
+ onTypeChange(old, [type, optionsType], onChange) {
const { default: value } = ConstantTypes[optionsType];
onChange({
value,
type,
- options: { ...props.options, type: optionsType }
+ options: { ...old.options, type: optionsType }
});
},
parse(path) {
@@ -104,7 +142,7 @@ export const VariableTypes = {
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
+ // Note: consider `getter` as the key of a value available node
if (getter) {
stack.push({
value: current.id,
@@ -130,11 +168,11 @@ export const VariableTypes = {
appendTypeValue({ options = {} }: { type: string, options: any }) {
return options.nodeId ? [Number.parseInt(options.nodeId, 10)] : [];
},
- onTypeChange(props, [type, nodeId], onChange) {
+ onTypeChange(old, [type, nodeId], onChange) {
onChange({
- ...props,
+ // ...old,
type,
- options: { ...props.options, nodeId }
+ options: { nodeId }
});
},
parse([nodeId, ...path]) {
@@ -155,6 +193,12 @@ export const VariableTypes = {
// calculation: Calculation
};
+export const VariableTypesContext = React.createContext(null);
+
+export function useVariableTypes() {
+ return React.useContext(VariableTypesContext);
+}
+
interface OperandProps {
value: {
type: string;
@@ -165,10 +209,12 @@ interface OperandProps {
}
export function Operand({ onChange, value: operand = { type: 'constant', value: '', options: { type: 'string' } } }: OperandProps) {
+ const Types = useVariableTypes();
+
const { type } = operand;
- const { component, appendTypeValue } = VariableTypes[type];
- const VariableComponent = typeof component === 'function' ? component(operand) : component;
+ const { component, appendTypeValue } = Types[type];
+ const VariableComponent = typeof component === 'function' ? component(operand) : NullRender;
return (
{
+ options={Object.values(Types).map((item: any) => {
const children = typeof item.options === 'function' ? item.options() : item.options;
return {
label: item.title,
value: item.value,
children,
- disabled: children && !children.length
+ disabled: children && !children.length,
+ isLeaf: !children
};
})}
- onChange={(t: Array) => {
- const { onTypeChange } = VariableTypes[t[0]];
+ onChange={(next: Array) => {
+ const { onTypeChange } = Types[next[0]];
if (typeof onTypeChange === 'function') {
- onTypeChange(operand, t, onChange);
+ onTypeChange(operand, next, onChange);
} else {
- if (t[0] !== type) {
- onChange({ type: t[0], value: null });
+ if (next[0] !== type) {
+ onChange({ type: next[0], value: null });
}
}
}}
/>
- onChange({ ...operand, value: v })} />
+ onChange({ ...op })} />
);
}
-export function Calculation({ calculator, operands, onChange }) {
+export function Calculation({ calculator, operands = [], onChange }) {
return (
-
+
- onChange({ calculator, operands: [v, operands[1]] }))} />
- {operands[0]
- ? (
- <>
-
- onChange({ calculator, operands: [operands[0], v] }))} />
- >
- )
- : null
- }
-
+ .ant-select{
+ width: auto;
+ min-width: 6em;
+ }
+ `}>
+
onChange({ calculator, operands: [v, operands[1]] }))} />
+ {operands[0]
+ ? (
+ <>
+
+ onChange({ calculator, operands: [operands[0], v] }))} />
+ >
+ )
+ : null
+ }
+
+
);
}
diff --git a/packages/client/src/workflow/nodes/calculation.tsx b/packages/client/src/workflow/nodes/calculation.tsx
new file mode 100644
index 000000000..522db142a
--- /dev/null
+++ b/packages/client/src/workflow/nodes/calculation.tsx
@@ -0,0 +1,31 @@
+import React from 'react';
+import { Calculation } from '../calculators';
+
+export default {
+ title: '运算',
+ type: 'calculation',
+ group: 'control',
+ fieldset: {
+ calculation: {
+ type: 'object',
+ title: '配置计算',
+ name: 'calculation',
+ required: true,
+ 'x-decorator': 'FormItem',
+ 'x-component': 'CalculationConfig',
+ }
+ },
+ view: {
+
+ },
+ components: {
+ CalculationConfig({ value, onChange }) {
+ return (
+
+ );
+ }
+ },
+ getter() {
+ return 计算值
;
+ }
+};
diff --git a/packages/client/src/workflow/nodes/index.tsx b/packages/client/src/workflow/nodes/index.tsx
index 3c93aabcf..e55185d6e 100644
--- a/packages/client/src/workflow/nodes/index.tsx
+++ b/packages/client/src/workflow/nodes/index.tsx
@@ -14,6 +14,7 @@ import { nodeClass, nodeCardClass, nodeHeaderClass, nodeTitleClass, nodeBlockCla
import query from './query';
import condition from './condition';
import parallel from './parallel';
+import calculation from './calculation';
function useUpdateConfigAction() {
@@ -60,6 +61,7 @@ export const instructions = new Registry();
instructions.register('query', query);
instructions.register('condition', condition);
instructions.register('parallel', parallel);
+instructions.register('calculation', calculation);
const NodeContext = React.createContext(null);
diff --git a/packages/client/src/workflow/nodes/query.tsx b/packages/client/src/workflow/nodes/query.tsx
index e362e7924..7c754c3ef 100644
--- a/packages/client/src/workflow/nodes/query.tsx
+++ b/packages/client/src/workflow/nodes/query.tsx
@@ -5,10 +5,10 @@ import { Cascader, Select } from 'antd';
import { t } from 'i18next';
import { css } from '@emotion/css';
-import { useRequest, useCollectionManager } from '../..';
+import { useCollectionManager } from '../..';
import { useCollectionFilterOptions } from '../../collection-manager/action-hooks';
import { useFlowContext } from '../WorkflowCanvas';
-import { parseStringValue, VariableTypes } from '../calculators';
+import { Operand, parseStringValue, VariableTypes, VariableTypesContext } from '../calculators';
const BaseTypeSet = new Set(['boolean', 'number', 'string', 'date']);
@@ -56,12 +56,10 @@ export default {
},
'x-component': 'Filter',
'x-component-props': {
- useDataSource(options) {
+ useProps() {
const { values } = useForm();
- const data = useCollectionFilterOptions(values.collection);
- return useRequest(() => Promise.resolve({
- data
- }), options)
+ const options = useCollectionFilterOptions(values.collection);
+ return { options };
},
dynamicComponent: 'VariableComponent'
}
@@ -91,7 +89,10 @@ export default {
constant: {
title: '常量',
value: 'constant',
- options: undefined
+ options: undefined,
+ component() {
+ return renderSchemaComponent;
+ }
}
};
@@ -99,59 +100,33 @@ export default {
? parseStringValue(value, VTypes)
: { type: 'constant', value };
- const { component, appendTypeValue } = VTypes[operand.type];
- const [types, setTypes] = useState([operand.type, ...(appendTypeValue ? appendTypeValue(operand) : [])]);
- const [type] = types;
-
- const VariableComponent = typeof component === 'function' ? component(operand) : component;
-
return (
-
-
({
- label: item.title,
- value: item.value,
- children: typeof item.options === 'function' ? item.options() : item.options
- }))}
- onChange={(next: Array) => {
- const { onTypeChange, stringify } = VTypes[next[0]];
- setTypes(next);
- if (typeof onTypeChange === 'function') {
- onTypeChange(operand, next, (op) => {
- onChange(stringify(op));
- });
+
+ {
+ if (next.type !== operand.type && next.type === 'constant') {
+ onChange(null);
} else {
- if (next[0] !== type) {
- onChange(null);
- }
+ const { stringify } = VTypes[next.type];
+ onChange(stringify(next));
}
}}
/>
- {type === 'constant'
- ? renderSchemaComponent()
- : {
- const { stringify } = VTypes[type];
- onChange(stringify(v));
- }} />
- }
-
+
);
}
},
- getter({ options, onChange }) {
+ getter({ type, options, onChange }) {
const { collections = [] } = useCollectionManager();
const { nodes } = useFlowContext();
const { config } = nodes.find(n => n.id == options.nodeId);
const collection = collections.find(item => item.name === config.collection) ?? { fields: [] };
return (
-