优化ArrayDict/DictEditor参数传递,修复formatString处理Array时的BUG

This commit is contained in:
fofolee
2025-01-10 18:54:11 +08:00
parent 41b3501945
commit 5e70c4c9a0
10 changed files with 372 additions and 371 deletions

View File

@@ -335,6 +335,7 @@ export const dataCommands = {
icon: "memory",
width: 12,
defaultValue: [newVarInputVal("var")],
defaultRowValue: newVarInputVal("var"),
disableToggleType: true,
},
{

View File

@@ -1,5 +1,109 @@
import { newVarInputVal } from "js/composer/varInputValManager";
const SAVE_DIALOG_PROPERTIES = {
component: "CheckGroup",
icon: "settings",
label: "选项",
width: 12,
options: [
{ label: "显示隐藏文件", value: "showHiddenFiles" },
{ label: "允许创建文件夹Mac", value: "createDirectory" },
{
label: "将.App作为目录Mac",
value: "treatPackageAsDirectory",
},
{
label: "显示覆盖确认Linux",
value: "showOverwriteConfirmation",
},
{ label: "不添加到最近Win", value: "dontAddToRecent" },
],
};
const OPEN_DIALOG_PROPERTIES = {
...SAVE_DIALOG_PROPERTIES,
options: [
{ label: "选择文件", value: "openFile" },
{ label: "选择文件夹", value: "openDirectory" },
{ label: "允许多选", value: "multiSelections" },
{ label: "显示隐藏文件", value: "showHiddenFiles" },
{ label: "提示新建路径Win", value: "promptToCreate" },
{ label: "不添加到最近Win", value: "dontAddToRecent" },
{ label: "允许创建文件夹Mac", value: "createDirectory" },
{ label: "不解析符号链接Mac", value: "noResolveAliases" },
{
label: "将.App作为目录Mac",
value: "treatPackageAsDirectory",
},
],
};
const DIALOG_CONFIG = {
options: {
title: {
label: "标题",
component: "VariableInput",
icon: "title",
width: 6,
},
defaultPath: {
label: "默认路径",
component: "VariableInput",
icon: "folder",
width: 6,
},
buttonLabel: {
label: "按钮文本",
component: "VariableInput",
icon: "text_fields",
width: 6,
},
message: {
label: "提示信息",
component: "VariableInput",
icon: "info",
width: 6,
},
filters: {
topLabel: "过滤器",
component: "ArrayEditor",
icon: "filter_list",
width: 12,
defaultRowValue: [newVarInputVal("str"), newVarInputVal("var", "")],
columns: {
name: {
label: "文件类型",
noIcon: true,
width: 4,
},
extensions: {
label: "扩展名",
noIcon: true,
width: 7,
disableToggleType: true,
options: {
items: ["*", "jpg", "png", "gif", "txt", "json", "exe"],
multiSelect: true,
},
},
},
},
},
defaultValue: {
title: newVarInputVal("str", "请选择"),
defaultPath: newVarInputVal("str"),
buttonLabel: newVarInputVal("str", "选择"),
message: newVarInputVal("str", "请选择"),
filters: [
{
name: newVarInputVal("str", "file"),
extensions: newVarInputVal("var", '["*"]'),
},
],
properties: ["openFile", "showHiddenFiles"],
},
};
export const uiCommands = {
label: "用户交互",
icon: "web",
@@ -19,6 +123,7 @@ export const uiCommands = {
newVarInputVal("str", "是"),
newVarInputVal("str", "否"),
],
defaultRowValue: newVarInputVal("str"),
},
],
},
@@ -33,17 +138,13 @@ export const uiCommands = {
label: "输入框",
component: "ArrayEditor",
width: 12,
options: {
keys: [
{
label: "标签",
value: "label",
},
{
label: "默认值",
value: "value",
},
],
columns: {
label: {
label: "标签",
},
value: {
label: "默认值",
},
},
defaultValue: [
{
@@ -163,106 +264,43 @@ export const uiCommands = {
],
},
{
value: "quickcomposer.ui.showOpenDialog",
value: "utools.showOpenDialog",
label: "文件选择框",
desc: "显示一个文件选择框,返回选择的文件路径",
outputVariable: "filePaths",
saveOutput: true,
config: [
{
label: "标题",
component: "VariableInput",
defaultValue: newVarInputVal("str", "请选择文件"),
width: 6,
},
{
label: "默认路径",
component: "VariableInput",
defaultValue: newVarInputVal("str"),
width: 6,
placeholder: "默认打开的路径",
},
{
label: "按钮文本",
component: "VariableInput",
defaultValue: newVarInputVal("str", "选择"),
width: 3,
},
{
label: "提示信息",
component: "VariableInput",
defaultValue: newVarInputVal("str"),
width: 3,
placeholder: "对话框底部的提示信息",
defaultValue: newVarInputVal("str", "请选择"),
},
{
label: "扩展名",
component: "VariableInput",
width: 6,
options: {
items: ["*", "jpg", "png", "gif", "txt", "json", "exe"],
multiSelect: true,
},
defaultValue: newVarInputVal("var", '["*"]'),
disableToggleType: true,
},
],
subCommands: [
{
value: "quickcomposer.ui.showOpenDialog",
value: "utools.showOpenDialog",
label: "打开文件对话框",
desc: "打开文件对话框",
icon: "folder_open",
config: [
{
label: "选择选项",
component: "CheckGroup",
icon: "settings",
width: 12,
options: [
{ label: "选择文件", value: "openFile" },
{ label: "选择文件夹", value: "openDirectory" },
{ label: "允许多选", value: "multiSelections" },
{ label: "显示隐藏文件", value: "showHiddenFiles" },
{ label: "提示新建路径Win", value: "promptToCreate" },
{ label: "不添加到最近Win", value: "dontAddToRecent" },
{ label: "允许创建文件夹Mac", value: "createDirectory" },
{ label: "不解析符号链接Mac", value: "noResolveAliases" },
{
label: "将.App作为目录Mac",
value: "treatPackageAsDirectory",
},
],
defaultValue: ["openFile", "showHiddenFiles"],
label: "选项",
component: "OptionEditor",
defaultValue: DIALOG_CONFIG.defaultValue,
options: {
...DIALOG_CONFIG.options,
properties: OPEN_DIALOG_PROPERTIES,
},
},
],
},
{
value: "quickcomposer.ui.showSaveDialog",
value: "utools.showSaveDialog",
label: "保存文件对话框",
desc: "保存文件对话框",
icon: "save",
config: [
{
label: "选择选项",
component: "CheckGroup",
icon: "settings",
width: 12,
options: [
{ label: "显示隐藏文件", value: "showHiddenFiles" },
{ label: "允许创建文件夹Mac", value: "createDirectory" },
{
label: "将.App作为目录Mac",
value: "treatPackageAsDirectory",
},
{
label: "显示覆盖确认Linux",
value: "showOverwriteConfirmation",
},
{ label: "不添加到最近Win", value: "dontAddToRecent" },
],
defaultValue: ["showHiddenFiles"],
label: "选项",
component: "OptionEditor",
defaultValue: DIALOG_CONFIG.defaultValue,
options: {
...DIALOG_CONFIG.options,
properties: SAVE_DIALOG_PROPERTIES,
},
},
],
},

View File

@@ -6,69 +6,101 @@ import {
} from "./varInputValManager";
/**
* 递归移除对象中的空值
* @param {Object} obj 要处理的对象
* @returns {Object} 处理后的对象
* 处理单个值,返回格式化后的字符串
*/
const removeEmptyValues = (obj) => {
return window.lodashM.omitBy(obj, (value) => {
// 如果value是VariableInput的输出则取其value值
const realValue = isVarInputVal(value) ? value.value : value;
if (window.lodashM.isNil(realValue) || realValue === "") return true;
// 如果value是对象并且不是VariableInput的输出则递归移除空值
if (typeof value === "object" && !isVarInputVal(value))
return window.lodashM.isEmpty(removeEmptyValues(value));
return false;
});
const processValue = (value, parentPath = "") => {
if (!value) return value;
if (typeof value === "object") {
if (isVarInputVal(value)) {
return stringifyVarInputVal(value);
}
return processObject(value, parentPath);
}
return typeof value === "string" ? `"${value}"` : value;
};
/**
* 格式化带缩进的值
*/
const formatWithIndent = (value, indent, isLast = true) => {
return `${indent}${value}${isLast ? "" : ","}`;
};
/**
* 递归处理对象的值并格式化成字符串
* @param {Object} obj 要处理的对象
* @param {string} parentPath 父路径(用于缩进)
* @returns {string} 处理后的字符串
*/
const processObject = (obj, parentPath = "") => {
// 移除空值
obj = removeEmptyValues(obj);
// 如果是 VariableInput 的输出,直接用 stringifyVarInputVal 处理
if (isVarInputVal(obj)) {
return stringifyVarInputVal(obj);
}
let result = "{\n";
const indentLevel = parentPath.split(".").length;
const indent = " ".repeat(indentLevel + 1);
const closingIndent = " ".repeat(indentLevel);
// 处理数组
if (Array.isArray(obj)) {
if (obj.length === 0) return "[]";
const items = obj.map((item, index) =>
formatWithIndent(
processValue(item, parentPath + " "),
indent,
index === obj.length - 1
)
);
return `[\n${items.join("\n")}\n${closingIndent}]`;
}
// 处理对象
const entries = Object.entries(obj);
if (entries.length === 0) return "{}";
entries.forEach(([key, value], index) => {
let valueStr = "";
const items = entries.map(([key, value], index) =>
formatWithIndent(
`"${key}": ${processValue(value, parentPath + " ")}`,
indent,
index === entries.length - 1
)
);
// 处理对象类型
if (value && typeof value === "object") {
// 如果是 VariableInput 的输出,直接用 stringifyVarInputVal 处理
if (isVarInputVal(value)) {
valueStr = stringifyVarInputVal(value);
} else {
valueStr = processObject(value, parentPath + " ");
}
}
// 处理其他类型
else if (value && typeof value === "string") {
valueStr = `"${value}"`;
} else {
valueStr = value;
return `{\n${items.join("\n")}\n${closingIndent}}`;
};
/**
* 递归移除对象中的空值
*/
const removeEmptyValues = (obj) => {
const isEmptyValue = (value) => {
const realValue = isVarInputVal(value) ? value.value : value;
return window.lodashM.isNil(realValue) || realValue === "";
};
const processObjectValue = (value) => {
if (typeof value === "object" && !isVarInputVal(value)) {
return removeEmptyValues(value);
}
return value;
};
// 添加缩进
const indent = " ".repeat(parentPath.split(".").length + 1);
result += `${indent}"${key}": ${valueStr}`;
if (index < entries.length - 1) result += ",";
result += "\n";
});
if (Array.isArray(obj)) {
return obj.filter((value) => !isEmptyValue(value)).map(processObjectValue);
}
// 闭合括号的缩进
const closingIndent = " ".repeat(parentPath.split(".").length);
result += `${closingIndent}}`;
return result;
return window.lodashM.omitBy(
obj,
(value) =>
isEmptyValue(value) ||
(typeof value === "object" &&
!isVarInputVal(value) &&
window.lodashM.isEmpty(removeEmptyValues(value)))
);
};
/**
@@ -264,9 +296,7 @@ export const parseFunction = (functionStr, options = {}) => {
: node.value;
// null
case "NullLiteral":
return shouldUseVariableFormat
? newVarInputVal("var", "null")
: null;
return shouldUseVariableFormat ? newVarInputVal("var", "null") : null;
case "Identifier":
// 标识符(变量)总是不带引号的
return shouldUseVariableFormat