编排UI新增输入框;调整了showInputBox接口,以方便可视化编排调用

This commit is contained in:
fofolee 2025-01-07 11:08:25 +08:00
parent b6bdb88fe9
commit 53a411c664
8 changed files with 167 additions and 33 deletions

View File

@ -5,13 +5,14 @@
:model-value="funcName" :model-value="funcName"
@update:model-value="funcName = $event" @update:model-value="funcName = $event"
:options="localCommand.functionSelector?.options" :options="localCommand.functionSelector?.options"
class="width-12"
/> />
<div class="flex-container"> <div class="flex-container">
<div <div
v-for="(item, index) in localConfig" v-for="(item, index) in localConfig"
:key="index" :key="index"
class="flex-item" class="grid-item"
:style="{ flex: item.width || 12 }" :style="getColumnStyle(item.width)"
> >
<VariableInput <VariableInput
v-if="item.type === 'varInput'" v-if="item.type === 'varInput'"
@ -49,23 +50,25 @@
/> />
<q-select <q-select
v-else-if="item.type === 'select'" v-else-if="item.type === 'select'"
filled
:model-value="argvs[index]" :model-value="argvs[index]"
@update:model-value="updateArgv(index, $event)" @update:model-value="updateArgv(index, $event)"
:options="item.options" :options="item.options"
> >
<template v-slot:prepend> <template v-slot:prepend>
<q-icon :name="item.icon" /> <q-icon :name="item.icon || 'code'" />
</template> </template>
</q-select> </q-select>
<q-input <q-input
v-else-if="item.type === 'input'" v-else-if="item.type === 'input'"
filled
:model-value="argvs[index]" :model-value="argvs[index]"
@update:model-value="updateArgv(index, $event)" @update:model-value="updateArgv(index, $event)"
:label="item.label" :label="item.label"
:icon="item.icon" :icon="item.icon"
> >
<template v-slot:prepend> <template v-slot:prepend>
<q-icon :name="item.icon" /> <q-icon :name="item.icon || 'code'" />
</template> </template>
</q-input> </q-input>
<q-checkbox <q-checkbox
@ -197,6 +200,12 @@ export default defineComponent({
code: this.generateCode(funcName, argvs), code: this.generateCode(funcName, argvs),
}); });
}, },
getColumnStyle(width = 12) {
const columnWidth = (width / 12) * 100;
return {
width: `calc(${columnWidth}% - var(--grid-gap))`,
};
},
}, },
mounted() { mounted() {
if (!this.modelValue.argvs && !this.modelValue.code) { if (!this.modelValue.argvs && !this.modelValue.code) {
@ -210,17 +219,19 @@ export default defineComponent({
.flex-container { .flex-container {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
gap: 8px; gap: 12px;
width: 100%; width: 100%;
--grid-gap: 8px;
} }
.flex-item { .grid-item {
min-width: 100px; min-width: 50px;
margin-bottom: 0;
} }
@media (max-width: 600px) { @media (max-width: 600px) {
.flex-item { .grid-item {
flex: 1 1 100% !important; width: 100% !important;
} }
} }

View File

@ -8,8 +8,8 @@
:class="['col', options.keys.length > 1 ? 'q-pr-sm' : '']" :class="['col', options.keys.length > 1 ? 'q-pr-sm' : '']"
> >
<VariableInput <VariableInput
:model-value="item[key]" :model-value="item[key.value || key]"
:label="key" :label="key.label || key"
:icon="icon || 'code'" :icon="icon || 'code'"
@update:model-value="(val) => updateItemKeyValue(index, key, val)" @update:model-value="(val) => updateItemKeyValue(index, key, val)"
/> />

View File

@ -57,6 +57,18 @@ export default {
}, },
mounted() { mounted() {
const quickcommandUI = { const quickcommandUI = {
/**
* 显示一个输入框组对话框并返回用户输入的所有值
*
* @param options 数组如果元素为字符串则作为输入框的标签名如果元素为对象则作为输入框的属性可为对象包含labelvaluehint三个属性
*
* @example options = ["请输入", "请输入2"]
* @example options = [{label: "请输入", value: "", hint: ""}, {label: "请输入2", value: "", hint: ""}]
* @example options = {labels: ["请输入", "请输入2"], values: ["", ""], hints: ["", ""]}
*
* @param title 窗口标题默认为空
*
*/
showInputBox: (options = ["请输入"], title = "") => showInputBox: (options = ["请输入"], title = "") =>
new Promise((reslove, reject) => { new Promise((reslove, reject) => {
let props = { let props = {
@ -67,11 +79,31 @@ export default {
}; };
if (!window.lodashM.isObject(options)) if (!window.lodashM.isObject(options))
return reject(new TypeError(`应为 Object, 而非 ${typeof options}`)); return reject(new TypeError(`应为 Object, 而非 ${typeof options}`));
if (window.lodashM.isArray(options)) props.labels = options; if (window.lodashM.isArray(options)) {
else Object.assign(props, options); options.forEach((item) => {
if (typeof item === "string") {
props.labels.push(item);
props.values.push("");
props.hints.push("");
} else {
props.labels.push(item.label);
props.values.push(item.value);
props.hints.push(item.hint);
}
});
} else {
//
Object.assign(props, options);
}
this.showUI(InputBox, props, false, reslove); this.showUI(InputBox, props, false, reslove);
}), }),
/**
* 显示一个按钮组对话框并返回用户点击的按钮的标签
*
* @param labels 按钮标签数组默认为["确定"]
* @param title 窗口标题默认为空
*/
showButtonBox: (labels = ["确定"], title = "") => showButtonBox: (labels = ["确定"], title = "") =>
new Promise((reslove, reject) => { new Promise((reslove, reject) => {
if (!window.lodashM.isArray(labels)) if (!window.lodashM.isArray(labels))
@ -79,6 +111,14 @@ export default {
this.showUI(ButtonBox, { labels, title }, false, reslove); this.showUI(ButtonBox, { labels, title }, false, reslove);
}), }),
/**
* 显示一个确认对话框并返回用户点击的按钮的标签
*
* @param message 确认消息默认为空
* @param title 窗口标题默认为空
* @param isHtml 是否为html消息默认为false
* @param width 窗口宽度默认为300
*/
showConfirmBox: (message = "", title = "提示", isHtml = false, width) => showConfirmBox: (message = "", title = "提示", isHtml = false, width) =>
new Promise((reslove, reject) => { new Promise((reslove, reject) => {
this.showUI( this.showUI(
@ -89,6 +129,14 @@ export default {
); );
}), }),
/**
* 显示一个消息框并返回用户点击的按钮的标签
*
* @param message 消息内容默认为空
* @param icon 消息图标默认为"success"
* @param time 消息显示时间默认为消息内容长度乘以120毫秒
* @param position 消息显示位置默认为"top"
*/
showMessageBox: (message, icon = "success", time, position = "top") => { showMessageBox: (message, icon = "success", time, position = "top") => {
message = window.lodashM.truncate(message, { length: 1200 }); message = window.lodashM.truncate(message, { length: 1200 });
if (icon === "success") icon = "positive"; if (icon === "success") icon = "positive";
@ -112,11 +160,23 @@ export default {
}); });
}, },
/**
* 显示一个文本区域对话框并返回用户输入的文本
*
* @param placeholder 文本区域提示默认为空
* @param value 文本区域默认值默认为空
*/
showTextArea: (placeholder = "", value = "") => showTextArea: (placeholder = "", value = "") =>
new Promise((reslove, reject) => { new Promise((reslove, reject) => {
this.showUI(TextArea, { placeholder, value }, true, reslove); this.showUI(TextArea, { placeholder, value }, true, reslove);
}), }),
/**
* 显示一个支持搜索的且可以动态更新的选项列表选项类型为文本或html
*
* @param initItems 初始选项数组默认为空
* @param options 选项列表配置默认为空
*/
showSelectList: (initItems, options = {}) => showSelectList: (initItems, options = {}) =>
new Promise((reslove, reject) => { new Promise((reslove, reject) => {
if (!window.lodashM.isArray(initItems)) if (!window.lodashM.isArray(initItems))
@ -134,27 +194,50 @@ export default {
this.showUI(SelectList, { initItems, options }, true, reslove); this.showUI(SelectList, { initItems, options }, true, reslove);
}), }),
/**
* 显示一个等待按钮并返回用户点击的按钮的标签
*
* @param callback 等待回调函数
* @param label 按钮标签默认为"确定"
*/
showWaitButton: (callback, label = "确定") => { showWaitButton: (callback, label = "确定") => {
this.wbLabel = label; this.wbLabel = label;
this.showWb = true; this.showWb = true;
this.wbEvent = callback; this.wbEvent = callback;
}, },
/**
* 关闭等待按钮
*/
closeWaitButton: () => { closeWaitButton: () => {
this.showWb = false; this.showWb = false;
}, },
/**
* 更新选项列表
*
* @param opt 新选项
* @param id 选项索引默认为undefined
*/
updateSelectList: (opt, id) => { updateSelectList: (opt, id) => {
if (this.currentUI !== SelectList) throw "请先创建 selectList"; if (this.currentUI !== SelectList) throw "请先创建 selectList";
if (typeof id === "undefined") this.$refs.ui.items.push(opt); if (typeof id === "undefined") this.$refs.ui.items.push(opt);
else this.$refs.ui.items[id] = opt; else this.$refs.ui.items[id] = opt;
}, },
/**
* 监听全局快捷键
*
* @param callback 快捷键回调函数
*/
listenKeydown: (callback) => { listenKeydown: (callback) => {
this.listeners.push(callback); this.listeners.push(callback);
document.addEventListener("keydown", callback); document.addEventListener("keydown", callback);
}, },
/**
* 移除全局快捷键
*/
removeListener: () => { removeListener: () => {
this.listeners.forEach((listener) => { this.listeners.forEach((listener) => {
document.removeEventListener("keydown", listener); document.removeEventListener("keydown", listener);

View File

@ -220,19 +220,19 @@ export const dataCommands = {
label: "整数", label: "整数",
type: "switch", type: "switch",
defaultValue: false, defaultValue: false,
width: 1, width: 2,
}, },
{ {
label: "起始值", label: "起始值",
icon: "last_page", icon: "last_page",
type: "numInput", type: "numInput",
width: 10, width: 5,
}, },
{ {
label: "结束值", label: "结束值",
icon: "first_page", icon: "first_page",
type: "numInput", type: "numInput",
width: 10, width: 5,
}, },
], ],
outputVariable: "randomNumber", outputVariable: "randomNumber",

View File

@ -18,13 +18,13 @@ export const simulateCommands = {
label: "X坐标留空则原地点击", label: "X坐标留空则原地点击",
icon: "drag_handle", icon: "drag_handle",
type: "numInput", type: "numInput",
width: 8, width: 6,
}, },
{ {
label: "Y坐标留空则原地点击", label: "Y坐标留空则原地点击",
icon: "drag_handle", icon: "drag_handle",
type: "numInput", type: "numInput",
width: 8, width: 6,
}, },
], ],
functionSelector: { functionSelector: {
@ -33,17 +33,19 @@ export const simulateCommands = {
{ {
label: "单击", label: "单击",
value: "utools.simulateMouseClick", value: "utools.simulateMouseClick",
icon: "mouse",
}, },
{ {
label: "右击", label: "右击",
value: "utools.simulateMouseRightClick", value: "utools.simulateMouseRightClick",
icon: "mouse",
}, },
{ {
label: "双击", label: "双击",
value: "utools.simulateMouseDoubleClick", value: "utools.simulateMouseDoubleClick",
icon: "mouse",
}, },
], ],
width: 2,
allowEmptyArgv: true, allowEmptyArgv: true,
}, },
}, },
@ -56,14 +58,14 @@ export const simulateCommands = {
icon: "drag_handle", icon: "drag_handle",
defaultValue: 0, defaultValue: 0,
type: "numInput", type: "numInput",
width: 8, width: 6,
}, },
{ {
label: "Y坐标", label: "Y坐标",
icon: "drag_handle", icon: "drag_handle",
defaultValue: 0, defaultValue: 0,
type: "numInput", type: "numInput",
width: 8, width: 6,
}, },
], ],
}, },

View File

@ -5,7 +5,7 @@ export const uiCommands = {
commands: [ commands: [
{ {
value: "quickcommand.showButtonBox", value: "quickcommand.showButtonBox",
label: "按钮组弹窗", label: "按钮组",
isAsync: true, isAsync: true,
outputVariable: "{id,text}", outputVariable: "{id,text}",
saveOutput: true, saveOutput: true,
@ -15,12 +15,12 @@ export const uiCommands = {
type: "arrayEditor", type: "arrayEditor",
defaultValue: [ defaultValue: [
{ {
value: "按钮1", value: "",
isString: true, isString: true,
__varInputVal__: true, __varInputVal__: true,
}, },
{ {
value: "按钮2", value: "",
isString: true, isString: true,
__varInputVal__: true, __varInputVal__: true,
}, },
@ -28,5 +28,45 @@ export const uiCommands = {
}, },
], ],
}, },
{
value: "quickcommand.showInputBox",
label: "输入框",
isAsync: true,
outputVariable: "[inputValue1]",
saveOutput: true,
config: [
{
label: "输入框",
type: "arrayEditor",
width: 12,
options: {
keys: [
{
label: "标签",
value: "label",
},
{
label: "默认值",
value: "value",
},
],
},
defaultValue: [
{
label: {
value: "请输入",
isString: true,
__varInputVal__: true,
},
value: {
value: "",
isString: true,
__varInputVal__: true,
},
},
],
},
],
},
], ],
}; };

View File

@ -114,7 +114,7 @@ export function processVariable({ value, existingVars }) {
key, key,
processedName, processedName,
needsRename: processedName !== varName, needsRename: processedName !== varName,
hasRename: parts.length > 1 hasRename: parts.length > 1,
}; };
}); });
@ -135,9 +135,9 @@ export function processVariable({ value, existingVars }) {
const format = const format =
destructured.format === "array" destructured.format === "array"
? `[${processedVars.map((v) => v.key).join(", ")}]` ? `[${processedVars.map((v) => v.key).join(", ")}]`
: `{${processedVars.map((v) => : `{${processedVars
v.hasRename ? `${v.key}:${v.processedName}` : v.key .map((v) => (v.hasRename ? `${v.key}:${v.processedName}` : v.key))
).join(", ")}}`; .join(", ")}}`;
return { return {
isValid: true, isValid: true,

View File

@ -25,18 +25,16 @@ interface quickcommandApi {
* console.log(`输入的内容分别为${values}`) * console.log(`输入的内容分别为${values}`)
* }) * })
* *
* quickcommand.showInputBox({labels:["输入框标签"],values:["默认值"],hints:["输入框提示"]}).then(values => { * quickcommand.showInputBox([{label:"输入框标签",value:"默认值",hint:"输入框提示"},{label:"输入框标签2",value:"默认值2",hint:"输入框提示2"}]).then(values => {
* console.log(`输入的内容分别为${values}`) * console.log(`输入的内容分别为${values}`)
* }) * })
* ``` * ```
* *
* * @param options labelvaluehint三个属性
*
* @param options
* @param title * @param title
*/ */
showInputBox( showInputBox(
options: string[] | { labels: string[]; values: string[]; hints: string[] }, options: string[] | { labels: string; values: string; hints: string }[],
title?: string title?: string
): Promise<string[]>; ): Promise<string[]>;