From a13580d53f5c8ef44a5a18c970eece91c26fdd5f Mon Sep 17 00:00:00 2001 From: fofolee Date: Tue, 7 Jan 2025 17:50:13 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=8F=82=E6=95=B0=E5=80=BC?= =?UTF-8?q?=E4=B8=BA=E7=A9=BA=E5=92=8C=E4=BC=A0=E9=80=92=E7=A9=BA=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E7=9A=84=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/composer/MultiParams.vue | 82 ++++- .../composer/common/NumberInput.vue | 8 +- src/components/composer/common/ParamInput.vue | 16 + src/js/composer/commands/dataCommands.js | 288 +++++++++--------- src/js/composer/commands/simulateCommands.js | 37 ++- src/js/composer/formatString.js | 29 +- 项目说明.json | 14 +- 7 files changed, 275 insertions(+), 199 deletions(-) diff --git a/src/components/composer/MultiParams.vue b/src/components/composer/MultiParams.vue index c0324b6..7904ba6 100644 --- a/src/components/composer/MultiParams.vue +++ b/src/components/composer/MultiParams.vue @@ -4,7 +4,7 @@ v-if="hasFunctionSelector" :model-value="funcName" @update:model-value="funcName = $event" - :options="localCommand.functionSelector?.options" + :options="localCommand.functionSelector" /> @@ -40,17 +40,22 @@ export default defineComponent({ }, // 特定函数独有参数配置 functionConfig() { - return ( - this.modelValue.functionSelector?.options.find( - (item) => item.value === this.funcName - )?.config || [] - ); + return this.getSelectFunction()?.config || []; }, localConfig() { return [...this.commonConfig, ...this.functionConfig].map((item) => { + const value = + item.type === "varInput" + ? item.defaultValue || { + value: "", + isString: true, + __varInputVal__: true, + } + : // 其他类型情况复杂,不做判断,没有默认值返回undefined + item.defaultValue; return { ...item, - value: item.defaultValue, + value, }; }); }, @@ -62,7 +67,20 @@ export default defineComponent({ return this.modelValue.value; }, set(value) { - this.updateModelValue(value, this.defaultArgvs); + // 构建新的参数数组 + const newArgvs = []; + + // 保留通用配置的参数值 + this.commonConfig.forEach((_, index) => { + newArgvs[index] = this.argvs[index]; + }); + + // 使用新选择的函数独有配置的默认值 + this.getSelectFunction(value)?.config?.forEach((config, index) => { + newArgvs[this.commonConfig.length + index] = config.defaultValue; + }); + + this.updateModelValue(value, newArgvs); }, }, argvs() { @@ -75,6 +93,11 @@ export default defineComponent({ }, }, methods: { + getSelectFunction(funcName = this.funcName) { + return this.modelValue.functionSelector?.find( + (item) => item.value === funcName + ); + }, updateArgv(index, value) { const newArgvs = [...this.argvs]; newArgvs[index] = value; @@ -82,10 +105,41 @@ export default defineComponent({ this.updateModelValue(this.funcName, newArgvs); }, generateCode(funcName, argvs) { - const newArgvs = argvs - .map((argv) => stringifyArgv(argv)) - .filter((item) => item != null && item !== ""); - return `${funcName}(${newArgvs.join(",")})`; + console.log("argvs", argvs); + /** + * 字符串模式stringfiy后,null会变成'"null"', ''变成'""' + * 变量模式stringify后,null变成'null', ''保持'' + */ + const stringifiedArgvs = argvs.map((argv) => stringifyArgv(argv)); + + /* 空值处理: + * 1. 去掉 undefined,'', null + * 2. varInput在字符串模式下,留空为'""',所以不会被处理 + * 3. 变量模式下,留空是'', 会被过滤 + * 4. 如果想传递空字符串,将varInput切为字符串模式并留空 + * 5. 如果不想传递对应参数,将varInput切为变量模式并留空 + * 6. 如果想传递空参数,将varInput切为变量模式并设置为null或undefined + + * [undefined, undefined] -> funcName() + * [undefined, 1] -> '' + * [1, undefined] -> funcName(1) + * [null, 1] -> funcName(null, 1) + * [1, 字符串模式下varInput留空] -> funcName(1, "") + * [1, 变量模式下varInput留空] -> funcName(1) + * [1, 变量模式下varInput设置为null] -> funcName(1, null) + */ + // 空参数后面跟着非空参数,不生成代码 + const isEmpty = (v) => v === undefined || v === "" || v === null; + for (let i = 0; i < stringifiedArgvs.length - 1; i++) { + if (isEmpty(stringifiedArgvs[i]) && !isEmpty(stringifiedArgvs[i + 1])) { + return ""; + } + } + + // 过滤空参数,由于前面已经对处于非空参数中间的空参数做了处理,这里直接过滤空参数不会对参数顺序造成影响 + const finalArgvs = stringifiedArgvs.filter((v) => !isEmpty(v)); + + return `${funcName}(${finalArgvs.join(",")})`; }, parseCodeToArgvs(code) { let argvs = window.lodashM.cloneDeep(this.defaultArgvs); @@ -110,9 +164,7 @@ export default defineComponent({ }, getSummary(argvs) { // 虽然header里对溢出做了处理,但是这里截断主要是为了节省存储空间 - const funcNameLabel = this.localCommand.functionSelector?.options.find( - (option) => option.value === this.funcName - )?.label; + const funcNameLabel = this.getSelectFunction()?.label; const subFeature = funcNameLabel ? `${funcNameLabel} ` : ""; const allArgvs = argvs .filter((item) => item != null && item != "") diff --git a/src/components/composer/common/NumberInput.vue b/src/components/composer/common/NumberInput.vue index 4645d97..17a74d3 100644 --- a/src/components/composer/common/NumberInput.vue +++ b/src/components/composer/common/NumberInput.vue @@ -67,13 +67,17 @@ export default defineComponent({ return this.modelValue; }, set(value) { - this.$emit("update:modelValue", value); + if (value === null || value === undefined || value === "") { + this.$emit("update:modelValue", null); + } else { + this.$emit("update:modelValue", value); + } }, }, }, methods: { updateNumber(delta) { - this.$emit("update:modelValue", this.localValue + delta); + this.$emit("update:modelValue", (this.localValue || 0) + delta); }, }, }); diff --git a/src/components/composer/common/ParamInput.vue b/src/components/composer/common/ParamInput.vue index 29fbf95..9f9ba04 100644 --- a/src/components/composer/common/ParamInput.vue +++ b/src/components/composer/common/ParamInput.vue @@ -43,6 +43,8 @@ * { + flex: 1; + min-width: 0; } @media (max-width: 600px) { .grid-item { width: 100% !important; + flex: 1 1 100% !important; } } diff --git a/src/js/composer/commands/dataCommands.js b/src/js/composer/commands/dataCommands.js index 41f72f0..10678d7 100644 --- a/src/js/composer/commands/dataCommands.js +++ b/src/js/composer/commands/dataCommands.js @@ -17,50 +17,48 @@ export const dataCommands = { type: "varInput", }, ], - functionSelector: { - options: [ - { - label: "Base64编码", - value: "quickcomposer.data.base64Encode", - icon: "title", - }, - { - label: "Base64解码", - value: "quickcomposer.data.base64Decode", - icon: "title", - }, - { - label: "十六进制编码", - value: "quickcomposer.data.hexEncode", - icon: "code", - }, - { - label: "十六进制解码", - value: "quickcomposer.data.hexDecode", - icon: "code", - }, - { - label: "URL编码", - value: "quickcomposer.data.urlEncode", - icon: "link", - }, - { - label: "URL解码", - value: "quickcomposer.data.urlDecode", - icon: "link", - }, - { - label: "HTML编码", - value: "quickcomposer.data.htmlEncode", - icon: "html", - }, - { - label: "HTML解码", - value: "quickcomposer.data.htmlDecode", - icon: "html", - }, - ], - }, + functionSelector: [ + { + label: "Base64编码", + value: "quickcomposer.data.base64Encode", + icon: "title", + }, + { + label: "Base64解码", + value: "quickcomposer.data.base64Decode", + icon: "title", + }, + { + label: "十六进制编码", + value: "quickcomposer.data.hexEncode", + icon: "code", + }, + { + label: "十六进制解码", + value: "quickcomposer.data.hexDecode", + icon: "code", + }, + { + label: "URL编码", + value: "quickcomposer.data.urlEncode", + icon: "link", + }, + { + label: "URL解码", + value: "quickcomposer.data.urlDecode", + icon: "link", + }, + { + label: "HTML编码", + value: "quickcomposer.data.htmlEncode", + icon: "html", + }, + { + label: "HTML解码", + value: "quickcomposer.data.htmlDecode", + icon: "html", + }, + ], }, { value: "quickcomposer.data.symmetricCrypto", @@ -90,35 +88,33 @@ export const dataCommands = { type: "varInput", }, ], - functionSelector: { - options: [ - { - label: "MD5", - value: "quickcomposer.data.md5Hash", - icon: "functions", - }, - { - label: "SHA1", - value: "quickcomposer.data.sha1Hash", - icon: "functions", - }, - { - label: "SHA256", - value: "quickcomposer.data.sha256Hash", - icon: "functions", - }, - { - label: "SHA512", - value: "quickcomposer.data.sha512Hash", - icon: "functions", - }, - { - label: "SM3", - value: "quickcomposer.data.sm3Hash", - icon: "functions", - }, - ], - }, + functionSelector: [ + { + label: "MD5", + value: "quickcomposer.data.md5Hash", + icon: "functions", + }, + { + label: "SHA1", + value: "quickcomposer.data.sha1Hash", + icon: "functions", + }, + { + label: "SHA256", + value: "quickcomposer.data.sha256Hash", + icon: "functions", + }, + { + label: "SHA512", + value: "quickcomposer.data.sha512Hash", + icon: "functions", + }, + { + label: "SM3", + value: "quickcomposer.data.sm3Hash", + icon: "functions", + }, + ], }, { value: "Math.sin", @@ -134,80 +130,78 @@ export const dataCommands = { type: "numInput", }, ], - functionSelector: { - options: [ - { - label: "正弦(sin)", - value: "Math.sin", - icon: "functions", - }, - { - label: "余弦(cos)", - value: "Math.cos", - icon: "functions", - }, - { - label: "正切(tan)", - value: "Math.tan", - icon: "functions", - }, - { - label: "反正弦(asin)", - value: "Math.asin", - icon: "functions", - }, - { - label: "反余弦(acos)", - value: "Math.acos", - icon: "functions", - }, - { - label: "反正切(atan)", - value: "Math.atan", - icon: "functions", - }, - { - label: "平方根(sqrt)", - value: "Math.sqrt", - icon: "functions", - }, - { - label: "自然对数(ln)", - value: "Math.log", - icon: "functions", - }, - { - label: "10对数(log10)", - value: "Math.log10", - icon: "functions", - }, - { - label: "绝对值(abs)", - value: "Math.abs", - icon: "functions", - }, - { - label: "向上取整(ceil)", - value: "Math.ceil", - icon: "functions", - }, - { - label: "向下取整(floor)", - value: "Math.floor", - icon: "functions", - }, - { - label: "四舍五入(round)", - value: "Math.round", - icon: "functions", - }, - { - label: "幂运算(pow)", - value: "Math.pow", - icon: "functions", - }, - ], - }, + functionSelector: [ + { + label: "正弦(sin)", + value: "Math.sin", + icon: "functions", + }, + { + label: "余弦(cos)", + value: "Math.cos", + icon: "functions", + }, + { + label: "正切(tan)", + value: "Math.tan", + icon: "functions", + }, + { + label: "反正弦(asin)", + value: "Math.asin", + icon: "functions", + }, + { + label: "反余弦(acos)", + value: "Math.acos", + icon: "functions", + }, + { + label: "反正切(atan)", + value: "Math.atan", + icon: "functions", + }, + { + label: "平方根(sqrt)", + value: "Math.sqrt", + icon: "functions", + }, + { + label: "自然对数(ln)", + value: "Math.log", + icon: "functions", + }, + { + label: "10对数(log10)", + value: "Math.log10", + icon: "functions", + }, + { + label: "绝对值(abs)", + value: "Math.abs", + icon: "functions", + }, + { + label: "向上取整(ceil)", + value: "Math.ceil", + icon: "functions", + }, + { + label: "向下取整(floor)", + value: "Math.floor", + icon: "functions", + }, + { + label: "四舍五入(round)", + value: "Math.round", + icon: "functions", + }, + { + label: "幂运算(pow)", + value: "Math.pow", + icon: "functions", + }, + ], }, { value: "quickcomposer.data.random", diff --git a/src/js/composer/commands/simulateCommands.js b/src/js/composer/commands/simulateCommands.js index f793065..646661c 100644 --- a/src/js/composer/commands/simulateCommands.js +++ b/src/js/composer/commands/simulateCommands.js @@ -27,26 +27,23 @@ export const simulateCommands = { width: 6, }, ], - functionSelector: { - options: [ - { - label: "单击", - value: "utools.simulateMouseClick", - icon: "mouse", - }, - { - label: "右击", - value: "utools.simulateMouseRightClick", - icon: "mouse", - }, - { - label: "双击", - value: "utools.simulateMouseDoubleClick", - icon: "mouse", - }, - ], - allowEmptyArgv: true, - }, + functionSelector: [ + { + label: "单击", + value: "utools.simulateMouseClick", + icon: "mouse", + }, + { + label: "右击", + value: "utools.simulateMouseRightClick", + icon: "mouse", + }, + { + label: "双击", + value: "utools.simulateMouseDoubleClick", + icon: "mouse", + }, + ], }, { value: "utools.simulateMouseMove", diff --git a/src/js/composer/formatString.js b/src/js/composer/formatString.js index ba79214..6360239 100644 --- a/src/js/composer/formatString.js +++ b/src/js/composer/formatString.js @@ -103,15 +103,19 @@ const stringifyObject = (jsonObj) => { * @returns {string} 格式化后的字符串 */ export const stringifyArgv = (argv) => { - // 处理普通字符串 + // 普通字符串加上引号 if (typeof argv === "string") { return `"${argv}"`; } - // 处理对象 + // null类型是Object,需要单独处理,返回原值 + if (argv === null) { + return null; + } + // 对象通过stringifyObject处理 if (typeof argv === "object") { return stringifyObject(argv); } - // 处理其他类型 + // 其他类型返回原值 return argv; }; @@ -270,12 +274,25 @@ export const parseFunction = (functionStr, options = {}) => { return shouldUseVariableFormat ? { value: node.value, isString: true, __varInputVal__: true } : node.value; + // 数字、布尔 case "NumericLiteral": - return node.value; case "BooleanLiteral": - return node.value; + return shouldUseVariableFormat + ? { + value: JSON.stringify(node.value), + isString: false, + __varInputVal__: true, + } + : node.value; + // null case "NullLiteral": - return null; + return shouldUseVariableFormat + ? { + value: "null", + isString: false, + __varInputVal__: true, + } + : null; case "Identifier": // 标识符(变量)总是不带引号的 return shouldUseVariableFormat diff --git a/项目说明.json b/项目说明.json index a3daf46..3db461b 100644 --- a/项目说明.json +++ b/项目说明.json @@ -28,15 +28,11 @@ } }, "functionSelector": { - "描述": "可选,函数选择器,用于选择函数,如果存在则使用MultiParams组件,用于一类参数类似,但函数名不同的命令", - "options": { - "描述": "必选,选项,一个数组,每个元素是一个对象,包含以下属性:", - "配置项属性": { - "label": "必选,显示的名称", - "value": "必选,生成代码时使用的函数名", - "icon": "可选,图标", - "config": "可选,特定函数独有参数配置,和MultiParams组件的config一样" - } + "配置项属性": { + "label": "必选,显示的名称", + "value": "必选,生成代码时使用的函数名", + "icon": "可选,图标", + "config": "可选,特定函数独有参数配置,和MultiParams组件的config一样" }, "value": "必选,默认值" }