mirror of
https://github.com/fofolee/uTools-quickcommand.git
synced 2025-06-29 20:32:44 +08:00
优化ArrayDict/DictEditor参数传递,修复formatString处理Array时的BUG
This commit is contained in:
parent
41b3501945
commit
5e70c4c9a0
@ -6,7 +6,6 @@ const quickcomposer = {
|
|||||||
network: require("./quickcomposer/network"),
|
network: require("./quickcomposer/network"),
|
||||||
coding: require("./quickcomposer/coding"),
|
coding: require("./quickcomposer/coding"),
|
||||||
math: require("./quickcomposer/math"),
|
math: require("./quickcomposer/math"),
|
||||||
ui: require("./quickcomposer/ui"),
|
|
||||||
audio: require("./quickcomposer/audio"),
|
audio: require("./quickcomposer/audio"),
|
||||||
image: require("./quickcomposer/image"),
|
image: require("./quickcomposer/image"),
|
||||||
};
|
};
|
||||||
|
@ -1,50 +0,0 @@
|
|||||||
const showSaveDialog = (
|
|
||||||
title,
|
|
||||||
defaultPath,
|
|
||||||
buttonLabel,
|
|
||||||
message,
|
|
||||||
extensions,
|
|
||||||
properties
|
|
||||||
) => {
|
|
||||||
return window.utools.showSaveDialog({
|
|
||||||
title,
|
|
||||||
defaultPath,
|
|
||||||
buttonLabel,
|
|
||||||
message,
|
|
||||||
properties,
|
|
||||||
filters: [
|
|
||||||
{
|
|
||||||
name: "文件",
|
|
||||||
extensions,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const showOpenDialog = (
|
|
||||||
title,
|
|
||||||
defaultPath,
|
|
||||||
buttonLabel,
|
|
||||||
message,
|
|
||||||
extensions,
|
|
||||||
properties
|
|
||||||
) => {
|
|
||||||
return window.utools.showOpenDialog({
|
|
||||||
title,
|
|
||||||
defaultPath,
|
|
||||||
buttonLabel,
|
|
||||||
message,
|
|
||||||
properties,
|
|
||||||
filters: [
|
|
||||||
{
|
|
||||||
name: "文件",
|
|
||||||
extensions,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
showSaveDialog,
|
|
||||||
showOpenDialog,
|
|
||||||
};
|
|
@ -1,6 +0,0 @@
|
|||||||
const { showSaveDialog, showOpenDialog } = require("./dialog");
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
showSaveDialog,
|
|
||||||
showOpenDialog,
|
|
||||||
};
|
|
@ -96,7 +96,7 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
saveFlow() {
|
saveFlow() {
|
||||||
const flow = window.lodashM.cloneDeep(this.commandFlow);
|
const flow = window.lodashM.cloneDeep(this.commandFlow);
|
||||||
const uselessProps = ["config", "argvs", "label", "type"];
|
const uselessProps = ["config", "argvs", "label", "component", "subCommands", "options", "defaultValue"];
|
||||||
// 移除不必要属性
|
// 移除不必要属性
|
||||||
flow.forEach((cmd) => {
|
flow.forEach((cmd) => {
|
||||||
for (const props of uselessProps) {
|
for (const props of uselessProps) {
|
||||||
|
@ -6,25 +6,21 @@
|
|||||||
:model-value="isCollapse"
|
:model-value="isCollapse"
|
||||||
>
|
>
|
||||||
<div class="array-editor">
|
<div class="array-editor">
|
||||||
<div v-for="(item, index) in items" :key="index" class="row items-center">
|
<div v-for="(row, index) in rows" :key="index" class="row items-center">
|
||||||
<template v-if="optionsKeys.length">
|
<template v-if="columns">
|
||||||
<div
|
<div
|
||||||
v-for="key in optionsKeys"
|
v-for="column in processedColumns"
|
||||||
:key="key.value"
|
:key="column.key"
|
||||||
:class="[
|
:class="[
|
||||||
key.width ? `col-${key.width}` : 'col',
|
column.width ? `col-${column.width}` : 'col',
|
||||||
optionsKeys.length > 1 ? 'q-pr-sm' : '',
|
Object.keys(columns).length > 1 ? 'q-pr-sm' : '',
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
<VariableInput
|
<VariableInput
|
||||||
:model-value="item[key.value] || key.defaultValue"
|
:model-value="row[column.key]"
|
||||||
:label="key.label"
|
v-bind="column"
|
||||||
:no-icon="true"
|
|
||||||
:placeholder="key.placeholder"
|
|
||||||
:options="key.options"
|
|
||||||
:disable-toggle-type="key.disableToggleType"
|
|
||||||
@update:model-value="
|
@update:model-value="
|
||||||
(val) => updateItemKeyValue(index, key.value, val)
|
(val) => updateColumn(index, column.key, val)
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -32,38 +28,32 @@
|
|||||||
<template v-else>
|
<template v-else>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<VariableInput
|
<VariableInput
|
||||||
:model-value="item"
|
:model-value="row"
|
||||||
:label="`${label || '项目'} ${index + 1}`"
|
v-bind="$attrs"
|
||||||
:icon="icon || 'code'"
|
@update:model-value="(val) => updateValue(index, val)"
|
||||||
:placeholder="placeholder"
|
|
||||||
:options="{
|
|
||||||
items: options.items,
|
|
||||||
}"
|
|
||||||
:disable-toggle-type="disableToggleType"
|
|
||||||
@update:model-value="(val) => updateItemValue(index, val)"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<div class="col-auto">
|
<div class="col-auto">
|
||||||
<div class="btn-container">
|
<div class="btn-container">
|
||||||
<template v-if="items.length === 1">
|
<template v-if="rows.length === 1">
|
||||||
<q-btn
|
<q-btn
|
||||||
flat
|
flat
|
||||||
dense
|
dense
|
||||||
size="sm"
|
size="sm"
|
||||||
icon="add"
|
icon="add"
|
||||||
class="center-btn"
|
class="center-btn"
|
||||||
@click="addItem"
|
@click="addRow"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="index === items.length - 1">
|
<template v-else-if="index === rows.length - 1">
|
||||||
<q-btn
|
<q-btn
|
||||||
flat
|
flat
|
||||||
dense
|
dense
|
||||||
size="sm"
|
size="sm"
|
||||||
icon="remove"
|
icon="remove"
|
||||||
class="top-btn"
|
class="top-btn"
|
||||||
@click="removeItem(index)"
|
@click="removeRow(index)"
|
||||||
/>
|
/>
|
||||||
<q-btn
|
<q-btn
|
||||||
flat
|
flat
|
||||||
@ -71,7 +61,7 @@
|
|||||||
size="sm"
|
size="sm"
|
||||||
icon="add"
|
icon="add"
|
||||||
class="bottom-btn"
|
class="bottom-btn"
|
||||||
@click="addItem"
|
@click="addRow"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
@ -81,7 +71,7 @@
|
|||||||
size="sm"
|
size="sm"
|
||||||
icon="remove"
|
icon="remove"
|
||||||
class="center-btn"
|
class="center-btn"
|
||||||
@click="removeItem(index)"
|
@click="removeRow(index)"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
@ -94,63 +84,62 @@
|
|||||||
<script>
|
<script>
|
||||||
/**
|
/**
|
||||||
* 数组编辑器组件
|
* 数组编辑器组件
|
||||||
* @description 支持单值数组和多键对象数组的编辑
|
* @description 支持简单数组和对象数组的编辑
|
||||||
*
|
*
|
||||||
* @property {Array} modelValue - 绑定的数组值
|
* @property {Array} modelValue - 绑定的数组值
|
||||||
* @property {String} label - 输入框标签
|
* @property {Object} columns - 列配置(可选)
|
||||||
* @property {String} icon - 输入框图标
|
|
||||||
* @property {Object} options - 配置选项
|
|
||||||
*
|
*
|
||||||
* @property {String[]} [options.keys] - 多键对象模式的键名列表
|
* // 1. 简单数组(不传 columns)
|
||||||
* @property {String[]} [options.keys.value] - 元素为对象时,对象的键名
|
* // 值示例:
|
||||||
* @property {String[]} [options.keys.label] - 对应varInput的label
|
|
||||||
* @property {String[]} [options.keys.placeholder] - 对应varInput的placeholder
|
|
||||||
* @property {String[]} [options.keys.defaultValue] - 对应varInput的defaultValue
|
|
||||||
* @property {Object} [options.keys.options] - 对应varInput的options
|
|
||||||
*
|
|
||||||
* @property {String[]} [options.items] - 下拉选择模式的选项列表
|
|
||||||
* @property {Object} [options.defaultValue] - 初始化时,默认的值,决定显示几个元素,对应元素内容
|
|
||||||
* @example
|
|
||||||
* // 基础数组
|
|
||||||
* [
|
* [
|
||||||
* newVarInputVal("str", "张三")
|
* newVarInputVal('str', '选项1'),
|
||||||
|
* newVarInputVal('str', '选项2')
|
||||||
* ]
|
* ]
|
||||||
*
|
*
|
||||||
* // 多键对象数组
|
* 属性透传:
|
||||||
* options.keys = ['name', 'age', 'email']
|
* ArrayEditor属性全部透传给VariableInput
|
||||||
*
|
*
|
||||||
* options.keys= [
|
* 初始值:
|
||||||
* {
|
* 使用defaultValue属性设置初始值
|
||||||
* label: "姓名",
|
* 使用defaultRowValue属性设置新增行时的初始值
|
||||||
* value: "name",
|
*
|
||||||
* placeholder: "姓名",
|
* // 2. 对象数组(传入 columns)
|
||||||
|
* columns = {
|
||||||
|
* name: {
|
||||||
|
* label: '姓名',
|
||||||
|
* placeholder: '请输入姓名',
|
||||||
|
* width: 6,
|
||||||
* options: {
|
* options: {
|
||||||
* items: ["张三", "李四", "王五"],
|
* items: ['张三', '李四', '王五']
|
||||||
* multiSelect: true,
|
|
||||||
* },
|
* },
|
||||||
|
* defaultValue: newVarInputVal('str', '张三')
|
||||||
|
* },
|
||||||
|
* age: {
|
||||||
|
* label: '年龄',
|
||||||
|
* placeholder: '请输入年龄',
|
||||||
|
* width: 4,
|
||||||
|
* defaultValue: newVarInputVal('str', '18')
|
||||||
* }
|
* }
|
||||||
* ]
|
* }
|
||||||
*
|
* // 值示例:
|
||||||
* [
|
* [
|
||||||
* {
|
* {
|
||||||
* name: newVarInputVal("str", "张三"),
|
* name: newVarInputVal('str', '张三'),
|
||||||
* age: newVarInputVal("str", "18"),
|
* age: newVarInputVal('str', '18')
|
||||||
* email: newVarInputVal("str", "zhangsan@example.com")
|
|
||||||
* }
|
* }
|
||||||
* ]
|
* ]
|
||||||
*
|
*
|
||||||
* // 下拉选择模式
|
* 属性透传:
|
||||||
* options.items = ['选项1', '选项2', '选项3']
|
* columns的每一个对象的值的属性全部透传给VariableInput
|
||||||
* [
|
*
|
||||||
* newVarInputVal("str", "选项1"),
|
* 初始值:
|
||||||
* newVarInputVal("str", "选项2"),
|
* 使用defaultValue属性设置初始的每一行
|
||||||
* newVarInputVal("str", "选项3")
|
* columns的每一个对象的defaultValue属性设置新增行时的初始值
|
||||||
* ]
|
|
||||||
*/
|
*/
|
||||||
import { defineComponent } from "vue";
|
import { defineComponent } from "vue";
|
||||||
import VariableInput from "components/composer/common/VariableInput.vue";
|
import VariableInput from "./VariableInput.vue";
|
||||||
import { newVarInputVal } from "js/composer/varInputValManager";
|
import { newVarInputVal } from "js/composer/varInputValManager";
|
||||||
import BorderLabel from "components/composer/common/BorderLabel.vue";
|
import BorderLabel from "./BorderLabel.vue";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "ArrayEditor",
|
name: "ArrayEditor",
|
||||||
@ -164,9 +153,17 @@ export default defineComponent({
|
|||||||
required: true,
|
required: true,
|
||||||
default: () => [],
|
default: () => [],
|
||||||
},
|
},
|
||||||
label: {
|
columns: {
|
||||||
type: String,
|
type: Object,
|
||||||
default: "",
|
default: null,
|
||||||
|
},
|
||||||
|
defaultValue: {
|
||||||
|
type: [Object, Array],
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
defaultRowValue: {
|
||||||
|
type: [Object, String],
|
||||||
|
default: null,
|
||||||
},
|
},
|
||||||
topLabel: {
|
topLabel: {
|
||||||
type: String,
|
type: String,
|
||||||
@ -180,103 +177,89 @@ export default defineComponent({
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
options: {
|
|
||||||
type: Object,
|
|
||||||
default: () => ({}),
|
|
||||||
},
|
|
||||||
placeholder: {
|
|
||||||
type: String,
|
|
||||||
default: "",
|
|
||||||
},
|
|
||||||
disableToggleType: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
emits: ["update:modelValue"],
|
emits: ["update:modelValue"],
|
||||||
computed: {
|
computed: {
|
||||||
items() {
|
rows() {
|
||||||
return this.modelValue.length ? this.modelValue : this.initializeItems();
|
return this.modelValue.length ? this.modelValue : this.initializeRow();
|
||||||
},
|
},
|
||||||
optionsKeys() {
|
processedColumns() {
|
||||||
return (
|
if (!this.columns) return null;
|
||||||
this.options?.keys?.map((key) => {
|
|
||||||
return {
|
return Object.entries(this.columns).map(([key, config]) => ({
|
||||||
...key,
|
key,
|
||||||
value: key.value || key,
|
...config,
|
||||||
label: key.label || key,
|
width: config.width || null,
|
||||||
};
|
defaultValue: config.defaultValue || newVarInputVal("str"),
|
||||||
}) || []
|
}));
|
||||||
);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
initializeItems() {
|
initializeRow() {
|
||||||
if (this.optionsKeys?.length) {
|
if (!this.columns) {
|
||||||
const item = {};
|
// 简单数组模式:使用 defaultValue 或创建新的 VarInputVal
|
||||||
this.optionsKeys.forEach((key) => {
|
return this.defaultValue || [newVarInputVal("str")];
|
||||||
item[key] = newVarInputVal("str");
|
|
||||||
});
|
|
||||||
return [item];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return [newVarInputVal("str")];
|
// 对象数组模式
|
||||||
},
|
if (this.defaultValue) {
|
||||||
/**
|
return [this.defaultValue];
|
||||||
* 添加新的数组项
|
|
||||||
* 根据配置创建相应的数据结构
|
|
||||||
*/
|
|
||||||
addItem() {
|
|
||||||
let newItems = [];
|
|
||||||
if (this.options.keys) {
|
|
||||||
const newItem = {};
|
|
||||||
this.options.keys.forEach((key) => {
|
|
||||||
newItem[key] = newVarInputVal("str");
|
|
||||||
});
|
|
||||||
newItems = [...this.items, newItem];
|
|
||||||
} else {
|
|
||||||
newItems = [...this.items, newVarInputVal("str")];
|
|
||||||
}
|
}
|
||||||
this.$emit("update:modelValue", newItems);
|
|
||||||
|
const row = {};
|
||||||
|
Object.entries(this.columns).forEach(([key, config]) => {
|
||||||
|
row[key] = config.defaultValue || newVarInputVal("str");
|
||||||
|
});
|
||||||
|
return [row];
|
||||||
},
|
},
|
||||||
/**
|
getNewRowValue() {
|
||||||
* 移除指定索引的数组项
|
if (!this.columns) {
|
||||||
* 如果移除后数组为空,则创建一个新的空项
|
// 简单数组模式:使用 defaultRowValue 或创建新的 VarInputVal
|
||||||
*/
|
return this.defaultRowValue || newVarInputVal("str");
|
||||||
removeItem(index) {
|
}
|
||||||
const newItems = [...this.items];
|
|
||||||
newItems.splice(index, 1);
|
// 对象数组模式
|
||||||
if (newItems.length === 0) {
|
if (this.defaultRowValue) {
|
||||||
if (this.options.keys) {
|
return this.defaultRowValue;
|
||||||
const newItem = {};
|
}
|
||||||
this.options.keys.forEach((key) => {
|
|
||||||
newItem[key] = newVarInputVal("str");
|
const row = {};
|
||||||
});
|
Object.entries(this.columns).forEach(([key, config]) => {
|
||||||
newItems.push(newItem);
|
row[key] = config.defaultValue || newVarInputVal("str");
|
||||||
} else {
|
});
|
||||||
newItems.push(newVarInputVal("str"));
|
return row;
|
||||||
|
},
|
||||||
|
addRow() {
|
||||||
|
const newRows = [...this.rows, this.getNewRowValue()];
|
||||||
|
this.$emit("update:modelValue", newRows);
|
||||||
|
},
|
||||||
|
removeRow(index) {
|
||||||
|
const newRows = [...this.rows];
|
||||||
|
newRows.splice(index, 1);
|
||||||
|
if (newRows.length === 0) {
|
||||||
|
newRows.push(this.initializeRow()[0]);
|
||||||
|
}
|
||||||
|
this.$emit("update:modelValue", newRows);
|
||||||
|
},
|
||||||
|
updateValue(index, value) {
|
||||||
|
const newRows = [...this.rows];
|
||||||
|
newRows[index] = value;
|
||||||
|
this.$emit("update:modelValue", newRows);
|
||||||
|
},
|
||||||
|
updateColumn(index, columnKey, value) {
|
||||||
|
// 创建一个新的行数组
|
||||||
|
const newRows = this.rows.map((row, i) => {
|
||||||
|
// 只更新指定索引的行
|
||||||
|
if (i === index) {
|
||||||
|
return {
|
||||||
|
...row,
|
||||||
|
[columnKey]: value,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
return row;
|
||||||
this.$emit("update:modelValue", newItems);
|
});
|
||||||
},
|
|
||||||
/**
|
this.$emit("update:modelValue", newRows);
|
||||||
* 更新单值模式下的值
|
|
||||||
*/
|
|
||||||
updateItemValue(index, value) {
|
|
||||||
const newItems = [...this.items];
|
|
||||||
newItems[index] = value;
|
|
||||||
this.$emit("update:modelValue", newItems);
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 更新多键模式下指定键的值
|
|
||||||
*/
|
|
||||||
updateItemKeyValue(index, key, value) {
|
|
||||||
const newItems = [...this.items];
|
|
||||||
newItems[index] = {
|
|
||||||
...newItems[index],
|
|
||||||
[key]: value,
|
|
||||||
};
|
|
||||||
this.$emit("update:modelValue", newItems);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -157,7 +157,7 @@ import BorderLabel from "components/composer/common/BorderLabel.vue";
|
|||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* // 下拉选择模式
|
* // 下拉选择模式
|
||||||
* options.items = ['User-Agent', 'Content-Type', 'Accept']
|
* options.optionKeys = ['User-Agent', 'Content-Type', 'Accept']
|
||||||
* {
|
* {
|
||||||
* "User-Agent": newVarInputVal("str", "Mozilla/5.0"),
|
* "User-Agent": newVarInputVal("str", "Mozilla/5.0"),
|
||||||
* "Content-Type": newVarInputVal("str", "text/html"),
|
* "Content-Type": newVarInputVal("str", "text/html"),
|
||||||
|
@ -130,23 +130,8 @@
|
|||||||
<template v-if="argvs.optionType === 'json'">
|
<template v-if="argvs.optionType === 'json'">
|
||||||
<ArrayEditor
|
<ArrayEditor
|
||||||
:model-value="argvs.selects"
|
:model-value="argvs.selects"
|
||||||
:options="{
|
:columns="arrayEditorColumns"
|
||||||
keys: [
|
:default-row-value="arrayEditorDefaultRowValue"
|
||||||
{
|
|
||||||
value: 'id',
|
|
||||||
label: 'id',
|
|
||||||
width: 3,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'title',
|
|
||||||
label: '标题',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'description',
|
|
||||||
label: '描述',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}"
|
|
||||||
@update:model-value="updateArgvs('selects', $event)"
|
@update:model-value="updateArgvs('selects', $event)"
|
||||||
>
|
>
|
||||||
<template #header>
|
<template #header>
|
||||||
@ -178,8 +163,7 @@ import VariableInput from "../common/VariableInput.vue";
|
|||||||
import ArrayEditor from "../common/ArrayEditor.vue";
|
import ArrayEditor from "../common/ArrayEditor.vue";
|
||||||
import OperationCard from "../common/OperationCard.vue";
|
import OperationCard from "../common/OperationCard.vue";
|
||||||
import { parseFunction, stringifyArgv } from "js/composer/formatString";
|
import { parseFunction, stringifyArgv } from "js/composer/formatString";
|
||||||
import { newVarInputVal, isVarInputVal} from "js/composer/varInputValManager";
|
import { newVarInputVal, isVarInputVal } from "js/composer/varInputValManager";
|
||||||
|
|
||||||
|
|
||||||
const jsonDefaultSelects = new Array(3).fill().map((_, index) => ({
|
const jsonDefaultSelects = new Array(3).fill().map((_, index) => ({
|
||||||
id: newVarInputVal("var", index),
|
id: newVarInputVal("var", index),
|
||||||
@ -226,6 +210,28 @@ export default defineComponent({
|
|||||||
showCancelButton: false,
|
showCancelButton: false,
|
||||||
closeOnSelect: true,
|
closeOnSelect: true,
|
||||||
},
|
},
|
||||||
|
arrayEditorDefaultRowValue: {
|
||||||
|
id: newVarInputVal("var"),
|
||||||
|
title: newVarInputVal("str"),
|
||||||
|
description: newVarInputVal("str"),
|
||||||
|
},
|
||||||
|
arrayEditorColumns: {
|
||||||
|
id: {
|
||||||
|
label: "id",
|
||||||
|
width: 3,
|
||||||
|
noIcon: true,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
label: "标题",
|
||||||
|
width: 4,
|
||||||
|
noIcon: true,
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
label: "描述",
|
||||||
|
width: 4,
|
||||||
|
noIcon: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -335,6 +335,7 @@ export const dataCommands = {
|
|||||||
icon: "memory",
|
icon: "memory",
|
||||||
width: 12,
|
width: 12,
|
||||||
defaultValue: [newVarInputVal("var")],
|
defaultValue: [newVarInputVal("var")],
|
||||||
|
defaultRowValue: newVarInputVal("var"),
|
||||||
disableToggleType: true,
|
disableToggleType: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,109 @@
|
|||||||
import { newVarInputVal } from "js/composer/varInputValManager";
|
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 = {
|
export const uiCommands = {
|
||||||
label: "用户交互",
|
label: "用户交互",
|
||||||
icon: "web",
|
icon: "web",
|
||||||
@ -19,6 +123,7 @@ export const uiCommands = {
|
|||||||
newVarInputVal("str", "是"),
|
newVarInputVal("str", "是"),
|
||||||
newVarInputVal("str", "否"),
|
newVarInputVal("str", "否"),
|
||||||
],
|
],
|
||||||
|
defaultRowValue: newVarInputVal("str"),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -33,17 +138,13 @@ export const uiCommands = {
|
|||||||
label: "输入框",
|
label: "输入框",
|
||||||
component: "ArrayEditor",
|
component: "ArrayEditor",
|
||||||
width: 12,
|
width: 12,
|
||||||
options: {
|
columns: {
|
||||||
keys: [
|
label: {
|
||||||
{
|
label: "标签",
|
||||||
label: "标签",
|
},
|
||||||
value: "label",
|
value: {
|
||||||
},
|
label: "默认值",
|
||||||
{
|
},
|
||||||
label: "默认值",
|
|
||||||
value: "value",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
defaultValue: [
|
defaultValue: [
|
||||||
{
|
{
|
||||||
@ -163,106 +264,43 @@ export const uiCommands = {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "quickcomposer.ui.showOpenDialog",
|
value: "utools.showOpenDialog",
|
||||||
label: "文件选择框",
|
label: "文件选择框",
|
||||||
desc: "显示一个文件选择框,返回选择的文件路径",
|
desc: "显示一个文件选择框,返回选择的文件路径",
|
||||||
outputVariable: "filePaths",
|
outputVariable: "filePaths",
|
||||||
saveOutput: true,
|
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: [
|
subCommands: [
|
||||||
{
|
{
|
||||||
value: "quickcomposer.ui.showOpenDialog",
|
value: "utools.showOpenDialog",
|
||||||
label: "打开文件对话框",
|
label: "打开文件对话框",
|
||||||
desc: "打开文件对话框",
|
desc: "打开文件对话框",
|
||||||
icon: "folder_open",
|
icon: "folder_open",
|
||||||
config: [
|
config: [
|
||||||
{
|
{
|
||||||
label: "选择选项",
|
label: "选项",
|
||||||
component: "CheckGroup",
|
component: "OptionEditor",
|
||||||
icon: "settings",
|
defaultValue: DIALOG_CONFIG.defaultValue,
|
||||||
width: 12,
|
options: {
|
||||||
options: [
|
...DIALOG_CONFIG.options,
|
||||||
{ label: "选择文件", value: "openFile" },
|
properties: OPEN_DIALOG_PROPERTIES,
|
||||||
{ 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"],
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "quickcomposer.ui.showSaveDialog",
|
value: "utools.showSaveDialog",
|
||||||
label: "保存文件对话框",
|
label: "保存文件对话框",
|
||||||
desc: "保存文件对话框",
|
desc: "保存文件对话框",
|
||||||
icon: "save",
|
icon: "save",
|
||||||
config: [
|
config: [
|
||||||
{
|
{
|
||||||
label: "选择选项",
|
label: "选项",
|
||||||
component: "CheckGroup",
|
component: "OptionEditor",
|
||||||
icon: "settings",
|
defaultValue: DIALOG_CONFIG.defaultValue,
|
||||||
width: 12,
|
options: {
|
||||||
options: [
|
...DIALOG_CONFIG.options,
|
||||||
{ label: "显示隐藏文件", value: "showHiddenFiles" },
|
properties: SAVE_DIALOG_PROPERTIES,
|
||||||
{ label: "允许创建文件夹(Mac)", value: "createDirectory" },
|
},
|
||||||
{
|
|
||||||
label: "将.App作为目录(Mac)",
|
|
||||||
value: "treatPackageAsDirectory",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "显示覆盖确认(Linux)",
|
|
||||||
value: "showOverwriteConfirmation",
|
|
||||||
},
|
|
||||||
{ label: "不添加到最近(Win)", value: "dontAddToRecent" },
|
|
||||||
],
|
|
||||||
defaultValue: ["showHiddenFiles"],
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -6,69 +6,101 @@ import {
|
|||||||
} from "./varInputValManager";
|
} from "./varInputValManager";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 递归移除对象中的空值
|
* 处理单个值,返回格式化后的字符串
|
||||||
* @param {Object} obj 要处理的对象
|
|
||||||
* @returns {Object} 处理后的对象
|
|
||||||
*/
|
*/
|
||||||
const removeEmptyValues = (obj) => {
|
const processValue = (value, parentPath = "") => {
|
||||||
return window.lodashM.omitBy(obj, (value) => {
|
if (!value) return value;
|
||||||
// 如果value是VariableInput的输出,则取其value值
|
|
||||||
const realValue = isVarInputVal(value) ? value.value : value;
|
if (typeof value === "object") {
|
||||||
if (window.lodashM.isNil(realValue) || realValue === "") return true;
|
if (isVarInputVal(value)) {
|
||||||
// 如果value是对象,并且不是VariableInput的输出,则递归移除空值
|
return stringifyVarInputVal(value);
|
||||||
if (typeof value === "object" && !isVarInputVal(value))
|
}
|
||||||
return window.lodashM.isEmpty(removeEmptyValues(value));
|
return processObject(value, parentPath);
|
||||||
return false;
|
}
|
||||||
});
|
|
||||||
|
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 = "") => {
|
const processObject = (obj, parentPath = "") => {
|
||||||
// 移除空值
|
// 移除空值
|
||||||
obj = removeEmptyValues(obj);
|
obj = removeEmptyValues(obj);
|
||||||
// 如果是 VariableInput 的输出,直接用 stringifyVarInputVal 处理
|
|
||||||
if (isVarInputVal(obj)) {
|
if (isVarInputVal(obj)) {
|
||||||
return stringifyVarInputVal(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);
|
const entries = Object.entries(obj);
|
||||||
|
if (entries.length === 0) return "{}";
|
||||||
|
|
||||||
entries.forEach(([key, value], index) => {
|
const items = entries.map(([key, value], index) =>
|
||||||
let valueStr = "";
|
formatWithIndent(
|
||||||
|
`"${key}": ${processValue(value, parentPath + " ")}`,
|
||||||
|
indent,
|
||||||
|
index === entries.length - 1
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
// 处理对象类型
|
return `{\n${items.join("\n")}\n${closingIndent}}`;
|
||||||
if (value && typeof value === "object") {
|
};
|
||||||
// 如果是 VariableInput 的输出,直接用 stringifyVarInputVal 处理
|
|
||||||
if (isVarInputVal(value)) {
|
/**
|
||||||
valueStr = stringifyVarInputVal(value);
|
* 递归移除对象中的空值
|
||||||
} else {
|
*/
|
||||||
valueStr = processObject(value, parentPath + " ");
|
const removeEmptyValues = (obj) => {
|
||||||
}
|
const isEmptyValue = (value) => {
|
||||||
}
|
const realValue = isVarInputVal(value) ? value.value : value;
|
||||||
// 处理其他类型
|
return window.lodashM.isNil(realValue) || realValue === "";
|
||||||
else if (value && typeof value === "string") {
|
};
|
||||||
valueStr = `"${value}"`;
|
|
||||||
} else {
|
const processObjectValue = (value) => {
|
||||||
valueStr = value;
|
if (typeof value === "object" && !isVarInputVal(value)) {
|
||||||
|
return removeEmptyValues(value);
|
||||||
}
|
}
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
// 添加缩进
|
if (Array.isArray(obj)) {
|
||||||
const indent = " ".repeat(parentPath.split(".").length + 1);
|
return obj.filter((value) => !isEmptyValue(value)).map(processObjectValue);
|
||||||
result += `${indent}"${key}": ${valueStr}`;
|
}
|
||||||
if (index < entries.length - 1) result += ",";
|
|
||||||
result += "\n";
|
|
||||||
});
|
|
||||||
|
|
||||||
// 闭合括号的缩进
|
return window.lodashM.omitBy(
|
||||||
const closingIndent = " ".repeat(parentPath.split(".").length);
|
obj,
|
||||||
result += `${closingIndent}}`;
|
(value) =>
|
||||||
return result;
|
isEmptyValue(value) ||
|
||||||
|
(typeof value === "object" &&
|
||||||
|
!isVarInputVal(value) &&
|
||||||
|
window.lodashM.isEmpty(removeEmptyValues(value)))
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -264,9 +296,7 @@ export const parseFunction = (functionStr, options = {}) => {
|
|||||||
: node.value;
|
: node.value;
|
||||||
// null
|
// null
|
||||||
case "NullLiteral":
|
case "NullLiteral":
|
||||||
return shouldUseVariableFormat
|
return shouldUseVariableFormat ? newVarInputVal("var", "null") : null;
|
||||||
? newVarInputVal("var", "null")
|
|
||||||
: null;
|
|
||||||
case "Identifier":
|
case "Identifier":
|
||||||
// 标识符(变量)总是不带引号的
|
// 标识符(变量)总是不带引号的
|
||||||
return shouldUseVariableFormat
|
return shouldUseVariableFormat
|
||||||
|
Loading…
x
Reference in New Issue
Block a user