mirror of
https://github.com/fofolee/uTools-quickcommand.git
synced 2025-06-08 22:51:25 +08:00
使用组件而非插件的形式重写 quickcommandUI
This commit is contained in:
parent
b0d06875b3
commit
6d8034d950
@ -476,7 +476,6 @@ let getSandboxFuns = () => {
|
||||
var sandbox = {
|
||||
fetch: fetch.bind(window),
|
||||
utools: getuToolsLite(),
|
||||
quickcommand: _.cloneDeep(quickcommand),
|
||||
electron,
|
||||
axios,
|
||||
Audio,
|
||||
@ -503,17 +502,17 @@ let liteErr = e => {
|
||||
utools.isDev() && (window.godMode = code => eval(code))
|
||||
|
||||
// vm 模块将无法在渲染进程中使用,改用 ses 来执行代码
|
||||
window.evalCodeInSandbox = (code, userVars = {}) => {
|
||||
let sandboxWithUV = Object.assign(userVars, getSandboxFuns())
|
||||
window.evalCodeInSandbox = (code, addVars = {}) => {
|
||||
let sandboxWithAD = Object.assign(addVars, getSandboxFuns())
|
||||
try {
|
||||
return new Compartment(sandboxWithUV).evaluate(code);
|
||||
return new Compartment(sandboxWithAD).evaluate(code);
|
||||
} catch (error) {
|
||||
throw liteErr(error)
|
||||
}
|
||||
}
|
||||
|
||||
let isWatchingError = false
|
||||
window.runCodeInSandbox = (code, callback, userVars = {}) => {
|
||||
window.runCodeInSandbox = (code, callback, addVars = {}) => {
|
||||
let sandbox = getSandboxFuns()
|
||||
sandbox.console = {
|
||||
log: (...stdout) => {
|
||||
@ -524,9 +523,9 @@ window.runCodeInSandbox = (code, callback, userVars = {}) => {
|
||||
callback(null, parseStdout(stderr))
|
||||
}
|
||||
}
|
||||
let sandboxWithUV = Object.assign(userVars, sandbox)
|
||||
let sandboxWithAD = Object.assign(addVars, sandbox)
|
||||
try {
|
||||
new Compartment(sandboxWithUV).evaluate(code)
|
||||
new Compartment(sandboxWithAD).evaluate(code)
|
||||
} catch (e) {
|
||||
console.log('Error: ', e)
|
||||
callback(null, liteErr(e))
|
||||
@ -629,7 +628,7 @@ window.quickcommandHttpServer = () => {
|
||||
// 错误返回 500
|
||||
if (stderr) return httpResponse(res, 500, stderr)
|
||||
return httpResponse(res, 200, stdout)
|
||||
}, userVars)
|
||||
}, Object.assign(userVars, _.cloneDeep(quickcommand)))
|
||||
}
|
||||
httpServer = http.createServer()
|
||||
httpServer.on('request', (req, res) => {
|
||||
|
@ -117,7 +117,7 @@ module.exports = configure(function(ctx) {
|
||||
// directives: [],
|
||||
|
||||
// Quasar plugins
|
||||
plugins: ['Dialog', 'Notify']
|
||||
plugins: ['Notify']
|
||||
},
|
||||
|
||||
// animations: 'all', // --- includes all animations
|
||||
|
13
src/App.vue
13
src/App.vue
@ -2,6 +2,7 @@
|
||||
<router-view v-slot="{ Component }">
|
||||
<component ref="view" :is="Component" />
|
||||
</router-view>
|
||||
<QuickCommand />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@ -11,8 +12,10 @@ import UTOOLS from "./js/utools.js";
|
||||
import programmings from "./js/options/programs.js";
|
||||
import defaultProfile from "./js/options/defaultProfile.js";
|
||||
import Cron from "croner";
|
||||
import QuickCommand from "components/quickcommandUI/QuickCommand";
|
||||
|
||||
export default defineComponent({
|
||||
components: { QuickCommand },
|
||||
name: "App",
|
||||
data() {
|
||||
return {
|
||||
@ -21,6 +24,7 @@ export default defineComponent({
|
||||
profile: defaultProfile,
|
||||
utools: UTOOLS,
|
||||
cronJobs: {},
|
||||
enterData: {},
|
||||
};
|
||||
},
|
||||
computed: {},
|
||||
@ -82,8 +86,7 @@ export default defineComponent({
|
||||
// 使用情况统计
|
||||
this.usageStatistics(enter.code, this.parseDate(new Date()));
|
||||
this.$q.dark.set(utools.isDarkColors());
|
||||
quickcommand.enterData = enter;
|
||||
quickcommand.payload = enter.payload;
|
||||
this.enterData = enter;
|
||||
this.$router.push(enter.code);
|
||||
},
|
||||
outPlugin() {
|
||||
@ -91,7 +94,7 @@ export default defineComponent({
|
||||
_.cloneDeep(this.profile),
|
||||
this.utools.DBPRE.CFG + "preferences"
|
||||
);
|
||||
this.$refs.view.$refs?.commandEditor?.saveCodeHistory()
|
||||
this.$refs.view.$refs?.commandEditor?.saveCodeHistory();
|
||||
this.$router.push("/");
|
||||
},
|
||||
runCronTask(featureCode, cronExp) {
|
||||
@ -102,7 +105,9 @@ export default defineComponent({
|
||||
runCommandSilently(featureCode) {
|
||||
let command = this.utools.getDB(this.utools.DBPRE.QC + featureCode);
|
||||
if (command.program === "quickcommand") {
|
||||
window.runCodeInSandbox(command.cmd, () => {});
|
||||
window.runCodeInSandbox(command.cmd, () => {}, {
|
||||
quickcommand: _.cloneDeep(quickcommand),
|
||||
});
|
||||
} else {
|
||||
let option =
|
||||
command.program === "custom"
|
||||
|
@ -113,14 +113,21 @@ export default {
|
||||
utools.outPlugin();
|
||||
}, 500);
|
||||
if (currentCommand.program === "quickcommand") {
|
||||
window.runCodeInSandbox(currentCommand.cmd, (stdout, stderr) => {
|
||||
let qc = _.cloneDeep(quickcommand);
|
||||
qc.enterData = this.$root.enterData;
|
||||
qc.type = this.$root.enterData.type;
|
||||
window.runCodeInSandbox(
|
||||
currentCommand.cmd,
|
||||
(stdout, stderr) => {
|
||||
if (stderr) {
|
||||
return quitBeforeShowResult
|
||||
? alert(stderr)
|
||||
: this.showRunResult(stderr, false, action);
|
||||
}
|
||||
!outPlugin && this.showRunResult(stdout, true, action);
|
||||
});
|
||||
},
|
||||
{ quickcommand: qc }
|
||||
);
|
||||
} else if (currentCommand.program === "html") {
|
||||
this.showRunResult(currentCommand.cmd, true, action);
|
||||
} else {
|
||||
@ -150,7 +157,9 @@ export default {
|
||||
let spVars = _.filter(specialVars, (sp) => sp.repl);
|
||||
_.forIn(spVars, (val, key) => {
|
||||
if (cmd.includes(val.label.slice(0, -2))) {
|
||||
cmd = cmd.replace(val.match, (x) => val.repl(x));
|
||||
cmd = cmd.replace(val.match, (x) =>
|
||||
val.repl(x, this.$root.enterData)
|
||||
);
|
||||
}
|
||||
});
|
||||
return cmd;
|
||||
@ -208,7 +217,7 @@ export default {
|
||||
if (!this.needTempPayload) return;
|
||||
let type =
|
||||
currentCommand.cmdType || currentCommand.features?.cmds[0].type;
|
||||
quickcommand.enterData = {
|
||||
this.$root.enterData = {
|
||||
type: type || "text",
|
||||
payload: await commandTypes[type]?.tempPayload?.(),
|
||||
};
|
||||
@ -255,14 +264,11 @@ export default {
|
||||
this.clear();
|
||||
},
|
||||
clear() {
|
||||
if (!!this.quickcommandListener) {
|
||||
document.removeEventListener("keydown", this.quickcommandListener);
|
||||
}
|
||||
if (!!this.childProcess) {
|
||||
quickcommand.kill(this.childProcess.pid);
|
||||
}
|
||||
quickcommand.closeWaitBtn?.();
|
||||
quickcommand.closeWaitBtn = () => {};
|
||||
quickcommand.removeListener();
|
||||
quickcommand.closeWaitButton();
|
||||
},
|
||||
frameLoad(initHeight) {
|
||||
this.outputAutoHeight(this.fromUtools);
|
||||
@ -272,11 +278,5 @@ export default {
|
||||
unmounted() {
|
||||
this.stopRun();
|
||||
},
|
||||
mounted() {
|
||||
quickcommand.listenKeydown = (callback) => {
|
||||
this.quickcommandListener = callback;
|
||||
document.addEventListener("keydown", callback);
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
@ -2,7 +2,7 @@
|
||||
export default {
|
||||
mounted() {
|
||||
utools.setExpendHeight(0);
|
||||
quickcommand.enterData.payload.forEach((file) => {
|
||||
this.$root.payload.forEach((file) => {
|
||||
let uid = this.getUid();
|
||||
let fileInfo = window.getFileInfo({
|
||||
type: "file",
|
||||
|
@ -24,7 +24,7 @@ export default {
|
||||
);
|
||||
url = choise.text + "://" + url;
|
||||
}
|
||||
let title = quickcommand.enterData.payload.title
|
||||
let title = this.$root.payload.title
|
||||
.replace(/和另外 \d+ 个页面.*/, "")
|
||||
.replace(/[-|—] .*?[Edge|Firefox|Chrome].*/, "")
|
||||
.trim();
|
||||
|
@ -1,21 +1,20 @@
|
||||
<template>
|
||||
<q-dialog ref="dialog" @hide="onDialogHide">
|
||||
<q-card class="q-dialog-plugin">
|
||||
<q-card-section>
|
||||
<div class="text-h5" align="center" v-text="title"></div>
|
||||
<div class="text-h5" align="center" v-text="options.title"></div>
|
||||
</q-card-section>
|
||||
<q-card-section class="q-gutter-lg">
|
||||
<div v-for="(label, index) in labels" :key="index">
|
||||
<div v-for="(label, index) in options.labels" :key="index">
|
||||
<q-btn
|
||||
class="full-width"
|
||||
color="primary"
|
||||
:label="label"
|
||||
@click="onOKClick(label, index)"
|
||||
v-close-popup
|
||||
@click="clickOK(label, index)"
|
||||
/>
|
||||
</div>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@ -26,29 +25,11 @@ export default {
|
||||
};
|
||||
},
|
||||
props: {
|
||||
labels: Array,
|
||||
title: String,
|
||||
options: Object,
|
||||
},
|
||||
emits: ["ok", "hide"],
|
||||
methods: {
|
||||
show() {
|
||||
this.$refs.dialog.show();
|
||||
},
|
||||
hide() {
|
||||
this.$refs.dialog.hide();
|
||||
},
|
||||
|
||||
onDialogHide() {
|
||||
this.$emit("hide");
|
||||
},
|
||||
|
||||
onOKClick(label, index) {
|
||||
this.$emit("ok", { id: index, text: label });
|
||||
this.hide();
|
||||
},
|
||||
|
||||
onCancelClick() {
|
||||
this.hide();
|
||||
clickOK(label, index) {
|
||||
this.$emit("clickOK", { id: index, text: label });
|
||||
},
|
||||
},
|
||||
};
|
||||
|
34
src/components/quickcommandUI/ConfirmBox.vue
Normal file
34
src/components/quickcommandUI/ConfirmBox.vue
Normal file
@ -0,0 +1,34 @@
|
||||
<template>
|
||||
<q-card class="q-dialog-plugin">
|
||||
<q-card-section>
|
||||
<div class="text-h5" align="left" v-text="options.title"></div>
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
{{ options.message }}
|
||||
</q-card-section>
|
||||
<q-card-section class="flex justify-end q-gutter-sm">
|
||||
<q-btn flat label="取消" color="grey" v-close-popup />
|
||||
<q-btn
|
||||
flat
|
||||
autofocus
|
||||
label="确定"
|
||||
color="primary"
|
||||
v-close-popup
|
||||
@click="clickOK()"
|
||||
/>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
methods: {
|
||||
clickOK() {
|
||||
this.$emit("clickOK");
|
||||
},
|
||||
},
|
||||
props: {
|
||||
options: Object,
|
||||
},
|
||||
};
|
||||
</script>
|
@ -1,63 +1,41 @@
|
||||
<template>
|
||||
<q-dialog ref="dialog" @hide="onDialogHide">
|
||||
<q-card class="q-dialog-plugin">
|
||||
<q-card-section>
|
||||
<div class="text-h5" align="center" v-text="title"></div>
|
||||
<div class="text-h5" align="center" v-text="options.title"></div>
|
||||
</q-card-section>
|
||||
<q-card-section class="q-gutter-sm">
|
||||
<div v-for="(label, index) in labels" :key="index">
|
||||
<div v-for="(label, index) in options.labels" :key="index">
|
||||
<q-input
|
||||
outlined
|
||||
v-model="results[index]"
|
||||
:label="label"
|
||||
:hint="hints[index]"
|
||||
:hint="options.hints[index]"
|
||||
hide-hint
|
||||
autofocus
|
||||
@keyup.enter="onOKClick"
|
||||
@keyup.enter="clickOK"
|
||||
/>
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-actions align="right">
|
||||
<q-btn color="blue-9" label="确定" @click="onOKClick" />
|
||||
<q-btn color="negative" label="取消" @click="onCancelClick" />
|
||||
<q-btn color="blue-9" label="确定" @click="clickOK" v-close-popup />
|
||||
<q-btn color="negative" label="取消" v-close-popup />
|
||||
</q-card-actions>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
results: this.values,
|
||||
results: this.options.values,
|
||||
};
|
||||
},
|
||||
props: {
|
||||
labels: Array,
|
||||
title: String,
|
||||
hints: Array,
|
||||
values: Array
|
||||
options: Object,
|
||||
},
|
||||
emits: ["ok", "hide"],
|
||||
methods: {
|
||||
show() {
|
||||
this.$refs.dialog.show();
|
||||
},
|
||||
hide() {
|
||||
this.$refs.dialog.hide();
|
||||
},
|
||||
|
||||
onDialogHide() {
|
||||
this.$emit("hide");
|
||||
},
|
||||
|
||||
onOKClick() {
|
||||
this.$emit("ok", this.results);
|
||||
this.hide();
|
||||
},
|
||||
|
||||
onCancelClick() {
|
||||
this.hide();
|
||||
clickOK() {
|
||||
this.$emit("clickOK", this.results);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
156
src/components/quickcommandUI/QuickCommand.vue
Normal file
156
src/components/quickcommandUI/QuickCommand.vue
Normal file
@ -0,0 +1,156 @@
|
||||
<template>
|
||||
<q-dialog
|
||||
v-model="showDialog"
|
||||
:maximized="maximized"
|
||||
:transition-show="maximized ? 'fade' : 'scale'"
|
||||
:transition-hide="maximized ? 'fade' : 'scale'"
|
||||
>
|
||||
<component
|
||||
ref="ui"
|
||||
:is="currentUI"
|
||||
:options="options"
|
||||
@clickOK="clickOK"
|
||||
@hide="showDialog = false"
|
||||
/>
|
||||
</q-dialog>
|
||||
<!-- waitButton 单独一个 -->
|
||||
<q-dialog seamless position="right" style="z-index: 9999" v-model="showWb">
|
||||
<q-card>
|
||||
<q-btn color="primary" :label="wbLabel" @click="wbEvent" v-close-popup />
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Notify } from "quasar";
|
||||
import { markRaw } from "vue";
|
||||
import InputBox from "components/quickcommandUI/InputBox";
|
||||
import ButtonBox from "components/quickcommandUI/ButtonBox";
|
||||
import ConfirmBox from "components/quickcommandUI/ConfirmBox";
|
||||
import TextArea from "components/quickcommandUI/TextArea";
|
||||
import SelectList from "components/quickcommandUI/SelectList";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
InputBox: markRaw(InputBox),
|
||||
ButtonBox: markRaw(ButtonBox),
|
||||
ConfirmBox: markRaw(ConfirmBox),
|
||||
TextArea: markRaw(TextArea),
|
||||
SelectList: markRaw(SelectList),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentUI: null,
|
||||
options: {},
|
||||
showDialog: false,
|
||||
maximized: false,
|
||||
showWb: false,
|
||||
wbLabel: "",
|
||||
listeners: [],
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
const quickcommandUI = {
|
||||
showInputBox: (options = ["请输入"], title = "") =>
|
||||
new Promise((reslove, reject) => {
|
||||
let props = {
|
||||
labels: [],
|
||||
values: [],
|
||||
hints: [],
|
||||
title: title,
|
||||
};
|
||||
if (!_.isObject(options))
|
||||
return reject(new TypeError(`应为 Object, 而非 ${typeof options}`));
|
||||
if (_.isArray(options)) props.labels = options;
|
||||
else Object.assign(props, options);
|
||||
this.showUI(InputBox, props, false, reslove);
|
||||
}),
|
||||
|
||||
showButtonBox: (labels = ["确定"], title = "") =>
|
||||
new Promise((reslove, reject) => {
|
||||
if (!_.isArray(labels))
|
||||
return reject(new TypeError(`应为 Array, 而非 ${typeof labels}`));
|
||||
this.showUI(ButtonBox, { labels, title }, false, reslove);
|
||||
}),
|
||||
|
||||
showConfirmBox: (message = "", title = "提示") =>
|
||||
new Promise((reslove, reject) => {
|
||||
this.showUI(ConfirmBox, { message, title }, false, reslove);
|
||||
}),
|
||||
|
||||
showMessageBox: (message, icon = "success", time = 3000) => {
|
||||
if (icon === "success") icon = "positive";
|
||||
if (icon === "error") icon = "negative";
|
||||
Notify.create({
|
||||
type: icon,
|
||||
message: message,
|
||||
timeout: time,
|
||||
position: "top",
|
||||
});
|
||||
},
|
||||
|
||||
showTextArea: (placeholder = "", value = "") =>
|
||||
new Promise((reslove, reject) => {
|
||||
this.showUI(TextArea, { placeholder, value }, true, reslove);
|
||||
}),
|
||||
|
||||
showSelectList: (initItems, options = {}) =>
|
||||
new Promise((reslove, reject) => {
|
||||
if (!_.isArray(initItems))
|
||||
return reject(
|
||||
new TypeError(`应为 Array, 而非 ${typeof initItems}`)
|
||||
);
|
||||
let defaultOptions = {
|
||||
placeholder: "输入进行筛选,支持拼音",
|
||||
optionType: "plaintext",
|
||||
enableSearch: true,
|
||||
showCancelButton: false,
|
||||
closeOnSelect: true,
|
||||
};
|
||||
options = Object.assign(defaultOptions, options);
|
||||
this.showUI(SelectList, { initItems, options }, true, reslove);
|
||||
}),
|
||||
|
||||
showWaitButton: (callback, label = "确定") => {
|
||||
this.wbLabel = label;
|
||||
this.showWb = true;
|
||||
this.wbEvent = callback;
|
||||
},
|
||||
|
||||
closeWaitButton: () => {
|
||||
this.showWb = false;
|
||||
},
|
||||
|
||||
updateSelectList: (opt, id) => {
|
||||
if (this.currentUI !== SelectList) throw "请先创建 selectList";
|
||||
if (typeof id === "undefined") this.$refs.ui.items.push(opt);
|
||||
else this.$refs.ui.items[id] = opt;
|
||||
},
|
||||
|
||||
listenKeydown: (callback) => {
|
||||
this.listeners.push(callback);
|
||||
document.addEventListener("keydown", callback);
|
||||
},
|
||||
|
||||
removeListener: () => {
|
||||
this.listeners.forEach((listener) => {
|
||||
document.removeEventListener("keydown", listener);
|
||||
});
|
||||
},
|
||||
};
|
||||
Object.assign(window.quickcommand, quickcommandUI);
|
||||
Object.freeze(quickcommand);
|
||||
},
|
||||
methods: {
|
||||
clickOK() {},
|
||||
wbEvent() {},
|
||||
showUI(uiComponent, options, maximized, reslove) {
|
||||
this.showDialog = true;
|
||||
this.options = options;
|
||||
this.maximized = maximized;
|
||||
this.currentUI = uiComponent;
|
||||
this.clickOK = reslove;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
@ -1,13 +1,5 @@
|
||||
<template>
|
||||
<q-dialog
|
||||
@keydown="keyEvent"
|
||||
maximized
|
||||
ref="dialog"
|
||||
transition-show="fade"
|
||||
transition-hide="fade"
|
||||
@hide="onDialogHide"
|
||||
>
|
||||
<q-card>
|
||||
<q-card @keydown="keyEvent">
|
||||
<q-virtual-scroll
|
||||
ref="scrollBar"
|
||||
:style="{ maxHeight: listMaxHeight + 'px', height: '100vh' }"
|
||||
@ -22,7 +14,7 @@
|
||||
clickable
|
||||
v-ripple
|
||||
@mousemove="currentIndex = index"
|
||||
@click="onOKClick"
|
||||
@click="clickOK"
|
||||
manual-focus
|
||||
:focused="index === currentIndex"
|
||||
:active="index === currentIndex"
|
||||
@ -33,10 +25,7 @@
|
||||
<q-item-section v-if="isText">
|
||||
<q-item-label lines="1">{{ item }}</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section
|
||||
v-else-if="isJson"
|
||||
class="content-start q-gutter-md"
|
||||
>
|
||||
<q-item-section v-else-if="isJson" class="content-start q-gutter-md">
|
||||
<q-avatar size="40px" v-if="item.icon">
|
||||
<q-img :src="item.icon" />
|
||||
</q-avatar>
|
||||
@ -57,10 +46,9 @@
|
||||
round
|
||||
color="primary"
|
||||
icon="close"
|
||||
@click="onCancelClick"
|
||||
@click="hide"
|
||||
/>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@ -69,7 +57,7 @@ import pinyinMatch from "pinyin-match";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
items: this.initItems,
|
||||
items: this.options.initItems,
|
||||
listMaxHeight: 500,
|
||||
currentIndex: 0,
|
||||
itemHeight: 50,
|
||||
@ -78,11 +66,7 @@ export default {
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
quickcommand.updateSelectList = (opt, id) => {
|
||||
if (typeof id === "undefined") this.items.push(opt);
|
||||
else this.items[id] = opt;
|
||||
};
|
||||
this.options.enableSearch && this.setSubInput();
|
||||
this.options.options.enableSearch && this.setSubInput();
|
||||
this.setUtoolsHeight(this.itemHeight * this.matchedItemsSize);
|
||||
},
|
||||
unmounted() {
|
||||
@ -102,48 +86,33 @@ export default {
|
||||
return this.matchedItems.length;
|
||||
},
|
||||
isJson() {
|
||||
return this.options.optionType === "json";
|
||||
return this.options.options.optionType === "json";
|
||||
},
|
||||
isHtml() {
|
||||
return this.options.optionType === "html";
|
||||
return this.options.options.optionType === "html";
|
||||
},
|
||||
isText() {
|
||||
return this.options.optionType === "plaintext";
|
||||
return this.options.options.optionType === "plaintext";
|
||||
},
|
||||
},
|
||||
props: {
|
||||
options: Object,
|
||||
initItems: Array,
|
||||
},
|
||||
emits: ["ok", "hide"],
|
||||
methods: {
|
||||
show() {
|
||||
this.$refs.dialog.show();
|
||||
},
|
||||
|
||||
hide() {
|
||||
this.$refs.dialog.hide();
|
||||
},
|
||||
|
||||
onDialogHide() {
|
||||
this.clear();
|
||||
this.$emit("hide");
|
||||
},
|
||||
|
||||
onOKClick() {
|
||||
let selected =
|
||||
this.options.optionType === "json"
|
||||
clickOK() {
|
||||
let selected = this.isJson
|
||||
? this.matchedItems[this.currentIndex]
|
||||
: {
|
||||
id: this.currentIndex,
|
||||
text: this.matchedItems[this.currentIndex],
|
||||
};
|
||||
this.$emit("ok", selected);
|
||||
this.options.closeOnSelect && this.hide();
|
||||
},
|
||||
|
||||
onCancelClick() {
|
||||
this.hide();
|
||||
this.$emit("clickOK", selected);
|
||||
this.options.options.closeOnSelect && this.hide();
|
||||
},
|
||||
|
||||
keyEvent(e) {
|
||||
@ -159,7 +128,7 @@ export default {
|
||||
);
|
||||
break;
|
||||
case 13:
|
||||
this.onOKClick();
|
||||
this.clickOK();
|
||||
return;
|
||||
}
|
||||
this.$refs.scrollBar.scrollTo(this.currentIndex);
|
||||
@ -181,7 +150,7 @@ export default {
|
||||
setSubInput() {
|
||||
utools.setSubInput(({ text }) => {
|
||||
this.searchWords = text;
|
||||
}, this.options.placeholder);
|
||||
}, this.options.options.placeholder);
|
||||
},
|
||||
|
||||
setUtoolsHeight(height) {
|
||||
@ -191,8 +160,13 @@ export default {
|
||||
clear() {
|
||||
utools.removeSubInput();
|
||||
this.setUtoolsHeight(this.listMaxHeight);
|
||||
quickcommand.updateSelectList = () => {};
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.q-card--dark {
|
||||
background: var(--q-dark-page);
|
||||
}
|
||||
</style>
|
||||
|
@ -1,9 +1,8 @@
|
||||
<template>
|
||||
<q-dialog maximized ref="dialog" @hide="onDialogHide">
|
||||
<q-card class="q-dialog-plugin">
|
||||
<textarea
|
||||
v-model="result"
|
||||
:placeholder="placeholder"
|
||||
:placeholder="options.placeholder"
|
||||
autofocus
|
||||
class="fixed"
|
||||
:style="{
|
||||
@ -19,47 +18,26 @@
|
||||
borderRadius: '5px',
|
||||
}"
|
||||
/>
|
||||
<div
|
||||
class="fixed-bottom-right q-pa-md q-gutter-sm"
|
||||
>
|
||||
<q-btn round color="blue-grey" icon="arrow_back" @click="onCancelClick" />
|
||||
<q-btn round color="primary" icon="done" @click="onOKClick" />
|
||||
<div class="fixed-bottom-right q-pa-md q-gutter-sm">
|
||||
<q-btn round color="blue-grey" icon="arrow_back" v-close-popup />
|
||||
<q-btn round color="primary" icon="done" @click="clickOK" />
|
||||
</div>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
result: this.value,
|
||||
result: this.options.value,
|
||||
};
|
||||
},
|
||||
props: {
|
||||
placeholder: String,
|
||||
value: String,
|
||||
options: Object,
|
||||
},
|
||||
emits: ["ok", "hide"],
|
||||
methods: {
|
||||
show() {
|
||||
this.$refs.dialog.show();
|
||||
},
|
||||
hide() {
|
||||
this.$refs.dialog.hide();
|
||||
},
|
||||
|
||||
onDialogHide() {
|
||||
this.$emit("hide");
|
||||
},
|
||||
|
||||
onOKClick() {
|
||||
this.$emit("ok", this.result);
|
||||
this.hide();
|
||||
},
|
||||
|
||||
onCancelClick() {
|
||||
this.hide();
|
||||
clickOK() {
|
||||
this.$emit("clickOK", this.result);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -1,47 +0,0 @@
|
||||
<template>
|
||||
<q-dialog
|
||||
ref="dialog"
|
||||
seamless
|
||||
position="right"
|
||||
@hide="onDialogHide"
|
||||
style="z-index: 9999"
|
||||
>
|
||||
<q-card>
|
||||
<q-btn color="primary" :label="label" @click="onOKClick" v-close-popup />
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
label: String,
|
||||
},
|
||||
mounted() {
|
||||
quickcommand.closeWaitBtn = () => {
|
||||
this.$refs?.dialog?.hide();
|
||||
};
|
||||
},
|
||||
emits: ["ok", "hide"],
|
||||
methods: {
|
||||
show() {
|
||||
this.$refs.dialog.show();
|
||||
},
|
||||
hide() {
|
||||
this.$refs.dialog.hide();
|
||||
},
|
||||
|
||||
onDialogHide() {
|
||||
this.$emit("hide");
|
||||
},
|
||||
|
||||
onOKClick() {
|
||||
this.$emit("ok");
|
||||
},
|
||||
|
||||
onCancelClick() {
|
||||
this.hide();
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
@ -8,10 +8,10 @@ let escapeItem = item => {
|
||||
return item.replace('$', '$$$')
|
||||
}
|
||||
|
||||
let handlingJsonVar = (jsonVar, name) => {
|
||||
let handlingJsonVar = (jsonVar, name, payload) => {
|
||||
try {
|
||||
return escapeItem(window.evalCodeInSandbox(jsonVar.slice(2, -2), {
|
||||
[name]: quickcommand.enterData.payload
|
||||
[name]: payload
|
||||
}))
|
||||
} catch (e) {
|
||||
return utools.showNotification(e)
|
||||
@ -73,7 +73,7 @@ const specialVars = {
|
||||
label: "{{input}}",
|
||||
desc: "主输入框的文本",
|
||||
match: /{{input}}/mg,
|
||||
repl: () => quickcommand.enterData.payload
|
||||
repl: (text, enterData) => enterData.payload
|
||||
},
|
||||
pwd: {
|
||||
name: "pwd",
|
||||
@ -88,21 +88,21 @@ const specialVars = {
|
||||
desc: "当前窗口信息,JSON格式,可以指定键值,如{{WindowInfo.id}}",
|
||||
type: "json",
|
||||
match: /{{WindowInfo(.*?)}}/mg,
|
||||
repl: jsonVar => handlingJsonVar(jsonVar, "WindowInfo")
|
||||
repl: (jsonVar, enterData) => handlingJsonVar(jsonVar, "WindowInfo", enterData.payload)
|
||||
},
|
||||
MatchImage: {
|
||||
name: "MatchImage",
|
||||
label: "{{MatchImage}}",
|
||||
desc: "匹配到图片的 DataUrl",
|
||||
match: /{{MatchImage}}/mg,
|
||||
repl: () => quickcommand.enterData.payload
|
||||
repl: (text, enterData) => enterData.payload
|
||||
},
|
||||
SelectFile: {
|
||||
name: "SelectFile",
|
||||
label: "{{SelectFile}}",
|
||||
desc: "文件管理器选中的文件,不支持Linux",
|
||||
match: /{{SelectFile}}/mg,
|
||||
repl: () => window.getSelectFile(quickcommand.enterData.payload.id)
|
||||
repl: (text, enterData) => window.getSelectFile(enterData.payload.id)
|
||||
},
|
||||
MatchedFiles: {
|
||||
name: "MatchedFiles",
|
||||
@ -110,14 +110,14 @@ const specialVars = {
|
||||
desc: "匹配的文件,JSON格式,可以指定键值,如{{MatchedFiles[0].path}}",
|
||||
type: "json",
|
||||
match: /{{MatchedFiles(.*?)}}/mg,
|
||||
repl: jsonVar => handlingJsonVar(jsonVar, "MatchedFiles")
|
||||
repl: (jsonVar, enterData) => handlingJsonVar(jsonVar, "MatchedFiles", enterData.payload)
|
||||
},
|
||||
type: {
|
||||
name: "type",
|
||||
label: "{{type}}",
|
||||
desc: "onPluginEnter的type,匹配的类型",
|
||||
match: /{{type}}/mg,
|
||||
repl: () => quickcommand.enterData.type
|
||||
repl: (text, enterData) => enterData.type
|
||||
},
|
||||
payload: {
|
||||
name: "payload",
|
||||
@ -125,7 +125,7 @@ const specialVars = {
|
||||
desc: "onPluginEnter的payload,当为JSON时可以指定键值,如{{payload.id}}",
|
||||
type: "json",
|
||||
match: /{{payload(.*?)}}/mg,
|
||||
repl: jsonVar => handlingJsonVar(jsonVar, "payload")
|
||||
repl: (jsonVar, enterData) => handlingJsonVar(jsonVar, "payload", enterData.payload)
|
||||
},
|
||||
js: {
|
||||
name: "js",
|
||||
|
@ -1,131 +0,0 @@
|
||||
/**
|
||||
* 通过quickcommand的api,快速生成可交互的UI界面
|
||||
* UI界面基于quasar
|
||||
*/
|
||||
|
||||
import {
|
||||
Dialog,
|
||||
Notify
|
||||
} from 'quasar'
|
||||
import inputBox from "../components/quickcommandUI/InputBox"
|
||||
import buttonBox from "../components/quickcommandUI/ButtonBox"
|
||||
import TextArea from "../components/quickcommandUI/TextArea"
|
||||
import SelectList from "../components/quickcommandUI/SelectList"
|
||||
import WaitButton from "../components/quickcommandUI/waitButton"
|
||||
|
||||
const quickcommand = {
|
||||
showInputBox: (options = ["请输入"], title = "") => new Promise((reslove, reject) => {
|
||||
let props = {
|
||||
labels: [],
|
||||
values: [],
|
||||
hints: [],
|
||||
title: title
|
||||
}
|
||||
if (!_.isObject(options)) return reject(new TypeError(`应为 Object, 而非 ${typeof options}`))
|
||||
if (_.isArray(options)) props.labels = options
|
||||
else Object.assign(props, options)
|
||||
Dialog.create({
|
||||
component: inputBox,
|
||||
componentProps: props
|
||||
}).onOk(results => {
|
||||
reslove(Array.from(results))
|
||||
}).onCancel(() => {
|
||||
console.log('取消')
|
||||
})
|
||||
}),
|
||||
|
||||
showButtonBox: (labels = ["确定"], title = "") => new Promise((reslove, reject) => {
|
||||
if (!_.isArray(labels)) return reject(new TypeError(`应为 Array, 而非 ${typeof labels}`))
|
||||
let props = {
|
||||
labels: labels,
|
||||
title: title
|
||||
}
|
||||
Dialog.create({
|
||||
component: buttonBox,
|
||||
componentProps: props
|
||||
}).onOk(results => {
|
||||
reslove(results)
|
||||
}).onCancel(() => {
|
||||
console.log('取消')
|
||||
})
|
||||
}),
|
||||
|
||||
|
||||
showConfirmBox: (message = "", title = "提示") => new Promise((reslove, reject) => {
|
||||
Dialog.create({
|
||||
title: title,
|
||||
message: message,
|
||||
cancel: true,
|
||||
persistent: true
|
||||
}).onOk(() => {
|
||||
reslove(true)
|
||||
}).onCancel(() => {
|
||||
reslove(false)
|
||||
})
|
||||
}),
|
||||
|
||||
showMessageBox: (message, icon = 'success', time = 3000) => {
|
||||
if (icon === 'success') icon = 'positive'
|
||||
if (icon === 'error') icon = 'negative'
|
||||
Notify.create({
|
||||
type: icon,
|
||||
message: message,
|
||||
timeout: time,
|
||||
position: 'top',
|
||||
})
|
||||
},
|
||||
|
||||
showTextArea: (placeholder = "", value = "") => new Promise((reslove, reject) => {
|
||||
let props = {
|
||||
placeholder: placeholder,
|
||||
value: value
|
||||
}
|
||||
Dialog.create({
|
||||
component: TextArea,
|
||||
componentProps: props
|
||||
}).onOk(results => {
|
||||
reslove(results)
|
||||
}).onCancel(() => {
|
||||
console.log('取消')
|
||||
})
|
||||
}),
|
||||
|
||||
showSelectList: (selects, options = {}) => new Promise((reslove, reject) => {
|
||||
if (!_.isArray(selects)) return reject(new TypeError(`应为 Array, 而非 ${typeof selects}`))
|
||||
let defaultOptions = {
|
||||
placeholder: "输入进行筛选,支持拼音",
|
||||
optionType: "plaintext",
|
||||
enableSearch: true,
|
||||
showCancelButton: false,
|
||||
closeOnSelect: true
|
||||
}
|
||||
Object.assign(defaultOptions, options)
|
||||
let props = {
|
||||
initItems: selects,
|
||||
options: defaultOptions
|
||||
}
|
||||
Dialog.create({
|
||||
component: SelectList,
|
||||
componentProps: props
|
||||
}).onOk(results => {
|
||||
reslove(results)
|
||||
}).onCancel(() => {
|
||||
console.log('取消')
|
||||
})
|
||||
}),
|
||||
|
||||
showWaitButton: (callback, label = "确定") => {
|
||||
Dialog.create({
|
||||
component: WaitButton,
|
||||
componentProps: {
|
||||
label
|
||||
}
|
||||
}).onOk(() => {
|
||||
callback()
|
||||
}).onCancel(() => {
|
||||
console.log('取消')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default quickcommand
|
@ -315,8 +315,8 @@ export default {
|
||||
initPage() {
|
||||
// 如果从 newcommand 进入则直接新建命令
|
||||
if (this.newCommandDirect) {
|
||||
if (quickcommand.enterData.type === "text") this.addNewCommand();
|
||||
else this.editCommand(JSON.parse(quickcommand.enterData.payload));
|
||||
if (this.$root.enterData.type === "text") this.addNewCommand();
|
||||
else this.editCommand(JSON.parse(this.$root.enterData.payload));
|
||||
this.$router.push("/configuration");
|
||||
}
|
||||
// 已启用的 features
|
||||
|
11
src/plugins/monaco/types/quickcommand.api.d.ts
vendored
11
src/plugins/monaco/types/quickcommand.api.d.ts
vendored
@ -174,8 +174,10 @@ interface quickcommandApi {
|
||||
|
||||
/**
|
||||
* 关掉现有等待操作按钮
|
||||
*
|
||||
* 正常会在退出运行结果界面后自动关闭,也可手动关闭
|
||||
*/
|
||||
closeWaitBtn(): void;
|
||||
closeWaitButton(): void;
|
||||
|
||||
/**
|
||||
* 监听用户按键,并执行回调函数
|
||||
@ -192,6 +194,13 @@ interface quickcommandApi {
|
||||
*/
|
||||
listenKeydown(callback: (event) => void): void;
|
||||
|
||||
/**
|
||||
* 移除所有按键监听
|
||||
*
|
||||
* 正常会在退出运行结果界面后自动移除,也可手动移除
|
||||
*/
|
||||
removeListener(): void;
|
||||
|
||||
/**
|
||||
* 同步等待,会阻塞进程
|
||||
* @param ms 等待的毫秒数
|
||||
|
@ -1,9 +1,6 @@
|
||||
import { route } from 'quasar/wrappers'
|
||||
import { createRouter, createMemoryHistory, createWebHistory, createWebHashHistory } from 'vue-router'
|
||||
import routes from './routes'
|
||||
import quickcommandUI from '../js/quickcommand'
|
||||
|
||||
Object.assign(window.quickcommand, quickcommandUI)
|
||||
|
||||
/*
|
||||
* If not building with SSR mode, you can
|
||||
@ -14,10 +11,10 @@ Object.assign(window.quickcommand, quickcommandUI)
|
||||
* with the Router instance.
|
||||
*/
|
||||
|
||||
export default route(function (/* { store, ssrContext } */) {
|
||||
const createHistory = process.env.SERVER
|
||||
? createMemoryHistory
|
||||
: (process.env.VUE_ROUTER_MODE === 'history' ? createWebHistory : createWebHashHistory)
|
||||
export default route(function( /* { store, ssrContext } */ ) {
|
||||
const createHistory = process.env.SERVER ?
|
||||
createMemoryHistory :
|
||||
(process.env.VUE_ROUTER_MODE === 'history' ? createWebHistory : createWebHashHistory)
|
||||
|
||||
const Router = createRouter({
|
||||
scrollBehavior: () => ({ left: 0, top: 0 }),
|
||||
|
Loading…
x
Reference in New Issue
Block a user