diff --git a/public/locales/en.json b/public/locales/en.json
index 4a61d56..296c631 100644
--- a/public/locales/en.json
+++ b/public/locales/en.json
@@ -121,7 +121,7 @@
"node.name": "Node name",
"node.noNodeSelected": "No node selected",
"node.notFound": "Node '{{name}}' not found",
- "node.oneof.error": "Only one is allowed between input '{{input}}' and argument '{{arg}}({{desc}})'",
+ "node.oneof.error": "Only one is allowed between input '{{input}}' and argument '{{desc}}({{arg}})'",
"node.oneof.inputNotfound": "Input '{{input}}' not found",
"node.outputVariable": "Output variables",
"node.pasteDataError": "Paste data error",
diff --git a/public/locales/zh.json b/public/locales/zh.json
index c63f668..46496f1 100644
--- a/public/locales/zh.json
+++ b/public/locales/zh.json
@@ -121,7 +121,7 @@
"node.name": "节点名称",
"node.noNodeSelected": "未选择任务节点",
"node.notFound": "节点 “{{name}}” 不存在",
- "node.oneof.error": "输入项 “{{input}}” 和参数 “{{arg}}({{desc}})” 之中,只能选择设置其中之一",
+ "node.oneof.error": "输入项 “{{input}}” 和参数 “{{desc}}({{arg}})” 之中,只能选择设置其中之一",
"node.oneof.inputNotfound": "输入项“{{input}}”不存在",
"node.outputVariable": "输出变量",
"node.pasteDataError": "粘贴数据出错",
diff --git a/sample/node-config.b3-setting b/sample/node-config.b3-setting
index b6d24c2..a17a21e 100644
--- a/sample/node-config.b3-setting
+++ b/sample/node-config.b3-setting
@@ -416,5 +416,19 @@
}
],
"desc": "等待"
+ },
+ {
+ "name": "TestOneof",
+ "desc": "测试oneof",
+ "type": "Action",
+ "input": ["选项?"],
+ "args": [
+ {
+ "name": "option",
+ "desc": "选项",
+ "type": "int[]?",
+ "oneof": "选项"
+ }
+ ]
}
]
diff --git a/sample/vars/test-vars.json b/sample/vars/test-vars.json
index 0897ee5..fe04aec 100644
--- a/sample/vars/test-vars.json
+++ b/sample/vars/test-vars.json
@@ -104,6 +104,15 @@
"args": {
"builtin": "afterRunFailure"
}
+ },
+ {
+ "id": "13",
+ "name": "TestOneof",
+ "input": [
+ "context"
+ ],
+ "output": [],
+ "args": {}
}
]
}
diff --git a/src/components/inspector.tsx b/src/components/inspector.tsx
index f619b2b..eea441c 100644
--- a/src/components/inspector.tsx
+++ b/src/components/inspector.tsx
@@ -760,7 +760,7 @@ const NodeInspector: FC = () => {
}
});
}
- data.args[arg.name] = arr;
+ data.args[arg.name] = !isNodeArgOptional(arg) ? arr : arr.length ? arr : undefined;
} else if (isJsonType(type)) {
try {
data.args[arg.name] = value === "null" ? null : JSON.parse(value);
@@ -1070,7 +1070,7 @@ const NodeInspector: FC = () => {
setFieldValue(`input.${i}`, value);
validateFields([argName]);
}
- if (!checkOneof(getFieldValue(argName) ?? "", value)) {
+ if (!checkOneof(arg, getFieldValue(argName), value)) {
return Promise.reject(
new Error(
t("node.oneof.error", {
@@ -1116,118 +1116,148 @@ const NodeInspector: FC = () => {
const type = getNodeArgRawType(arg);
if (isNodeArgArray(arg)) {
return (
-
-
- {(items, { add, remove }, { errors }) => (
-
- {items.map((item, idx) => (
-
- input.replace("?", "") === arg.oneof
+ );
+ if (idx === undefined || idx < 0) {
+ return Promise.reject(
+ new Error(t("node.oneof.inputNotfound", { input: arg.oneof }))
+ );
+ }
+ const inputName = `input.${idx}`;
+ if (!form.isFieldValidating(inputName)) {
+ form.setFieldValue(`args.${arg.name}`, value);
+ form.validateFields([inputName]);
+ }
+ if (!checkOneof(arg, value, form.getFieldValue(inputName))) {
+ return Promise.reject(
+ new Error(
+ t("node.oneof.error", {
+ input: def.input![idx],
+ arg: arg.name,
+ desc: arg.desc ?? "",
+ })
+ )
+ );
+ } else {
+ return Promise.resolve();
+ }
+ },
+ },
+ ]}
+ >
+ {(items, { add, remove }, { errors }) => (
+
+ {items.map((item, idx) => (
+
+ ({
+ validator(_, value) {
+ return validateArg(
+ editingNode.data,
+ arg,
+ value,
+ workspace.usingVars
+ );
},
- () => ({
- validator(_, value) {
- return validateArg(
- editingNode.data,
- arg,
- value,
- workspace.usingVars
- );
- },
- }),
- ]}
- >
- {!hasArgOptions(arg) && isStringType(type) && (
-
- )}
- {!hasArgOptions(arg) && isJsonType(type) && (
-
- )}
- {!hasArgOptions(arg) && isIntType(type) && (
-
- )}
- {!hasArgOptions(arg) && isFloatType(type) && (
-
- )}
- {!hasArgOptions(arg) && isBoolType(type) && (
-
- )}
- {!hasArgOptions(arg) && isExprType(type) && (
-
- )}
- {hasArgOptions(arg) && (
-
- {
- remove(item.name);
- submit();
- }}
- />
-
- ))}
-
-
-
-
-
- )}
-
-
+ {!hasArgOptions(arg) && isStringType(type) && (
+
+ )}
+ {!hasArgOptions(arg) && isJsonType(type) && (
+
+ )}
+ {!hasArgOptions(arg) && isIntType(type) && (
+
+ )}
+ {!hasArgOptions(arg) && isFloatType(type) && (
+
+ )}
+ {!hasArgOptions(arg) && isBoolType(type) && (
+
+ )}
+ {!hasArgOptions(arg) && isExprType(type) && (
+
+ )}
+ {hasArgOptions(arg) && (
+
+ ))}
+
+
+
+
+
+ )}
+
);
} else {
return (
@@ -1264,7 +1294,7 @@ const NodeInspector: FC = () => {
setFieldValue(`args.${arg.name}`, value);
validateFields([inputName]);
}
- if (!checkOneof(getFieldValue(inputName) ?? "", value)) {
+ if (!checkOneof(arg, value, form.getFieldValue(inputName))) {
return Promise.reject(
new Error(
t("node.oneof.error", {
diff --git a/src/misc/b3util.ts b/src/misc/b3util.ts
index 8ea6bf4..fbdda0e 100644
--- a/src/misc/b3util.ts
+++ b/src/misc/b3util.ts
@@ -307,7 +307,7 @@ export const checkNodeArg = (data: NodeData, conf: NodeDef, i: number, verbose?:
}
if (arg.oneof !== undefined) {
const idx = conf.input?.findIndex((v) => v.startsWith(arg.oneof!)) ?? -1;
- if (!checkOneof(data.args?.[arg.name], data.input?.[idx])) {
+ if (!checkOneof(arg, data.args?.[arg.name], data.input?.[idx])) {
if (verbose) {
error(
data,
@@ -321,7 +321,12 @@ export const checkNodeArg = (data: NodeData, conf: NodeDef, i: number, verbose?:
return !hasError;
};
-export const checkOneof = (argValue: unknown, inputValue: unknown) => {
+export const checkOneof = (arg: NodeArg, argValue: unknown, inputValue: unknown) => {
+ if (isNodeArgArray(arg)) {
+ if (argValue instanceof Array && argValue.length === 0) {
+ argValue = undefined;
+ }
+ }
argValue = argValue === undefined ? "" : argValue;
inputValue = inputValue ?? "";
return (argValue !== "" && inputValue === "") || (argValue === "" && inputValue !== "");