mirror of
https://github.com/fofolee/uTools-quickcommand.git
synced 2025-12-20 10:55:43 +08:00
365 lines
9.7 KiB
Vue
365 lines
9.7 KiB
Vue
<template>
|
||
<div class="command-language-bar">
|
||
<q-select
|
||
class="q-pl-xs"
|
||
dense
|
||
options-dense
|
||
borderless
|
||
square
|
||
hide-bottom-space
|
||
color="primary"
|
||
transition-show="jump-down"
|
||
transition-hide="jump-up"
|
||
:model-value="currentCommand.program"
|
||
@update:model-value="handleProgramChange"
|
||
:options="Object.keys(programs)"
|
||
>
|
||
<template v-slot:prepend>
|
||
<q-badge
|
||
label="环境"
|
||
color="primary"
|
||
text-color="white"
|
||
class="q-ml-sm"
|
||
style="height: 20px"
|
||
/>
|
||
</template>
|
||
<template v-slot:append>
|
||
<q-avatar size="20px" square v-if="isRunCodePage">
|
||
<img :src="programs[currentCommand.program].icon" />
|
||
</q-avatar>
|
||
</template>
|
||
<template v-slot:option="scope">
|
||
<q-item v-bind="scope.itemProps">
|
||
<q-item-section avatar>
|
||
<img width="32" :src="programs[scope.opt].icon" />
|
||
</q-item-section>
|
||
<q-item-section>
|
||
<q-item-label v-html="scope.opt" />
|
||
</q-item-section>
|
||
</q-item>
|
||
</template>
|
||
</q-select>
|
||
<q-btn-group unelevated class="button-group">
|
||
<q-btn-dropdown
|
||
class="special-var-btn"
|
||
dense
|
||
flat
|
||
label="变量"
|
||
color="primary"
|
||
icon="data_object"
|
||
>
|
||
<q-list>
|
||
<q-item
|
||
v-for="(item, index) in Object.values(specialVars)"
|
||
:key="index"
|
||
clickable
|
||
v-close-popup
|
||
@click="handleSpecialVarClick(item)"
|
||
>
|
||
<q-item-section>
|
||
<q-item-label class="row items-center justify-between">
|
||
<div v-text="item.label" />
|
||
<div v-if="item.onlyCmdTypes" class="row">
|
||
<q-badge color="grey-9" class="q-ml-xs"> 仅 </q-badge>
|
||
<q-badge
|
||
v-for="type in item.onlyCmdTypes"
|
||
:key="type"
|
||
class="q-ml-xs"
|
||
v-text="commandTypes[type].label"
|
||
color="grey-9"
|
||
/>
|
||
</div>
|
||
</q-item-label>
|
||
<q-tooltip v-if="item.tooltip">
|
||
{{ item.tooltip }}
|
||
</q-tooltip>
|
||
<q-item-label caption>{{ item.desc }}</q-item-label>
|
||
</q-item-section>
|
||
</q-item>
|
||
</q-list>
|
||
</q-btn-dropdown>
|
||
|
||
<template v-if="currentCommand.program === 'quickcommand'">
|
||
<q-btn
|
||
v-for="(item, index) in ['help_center', 'view_timeline']"
|
||
:key="index"
|
||
dense
|
||
flat
|
||
color="primary"
|
||
class="settings-btn"
|
||
:label="['文档', '可视化'][index]"
|
||
:icon="item"
|
||
@click="handleQuickCommandAction(index)"
|
||
>
|
||
</q-btn>
|
||
</template>
|
||
|
||
<q-btn-dropdown
|
||
v-model="isSettingsVisible"
|
||
v-else-if="currentCommand.program !== 'html'"
|
||
class="settings-btn"
|
||
dense
|
||
flat
|
||
label="设置"
|
||
color="primary"
|
||
icon="settings"
|
||
>
|
||
<q-list>
|
||
<!-- 自定义解释器 -->
|
||
<q-item
|
||
v-for="(item, index) in Object.keys(currentCommand.customOptions)"
|
||
:key="index"
|
||
v-show="currentCommand.program === 'custom'"
|
||
>
|
||
<q-input
|
||
stack-label
|
||
autofocus
|
||
dense
|
||
outlined
|
||
class="full-width"
|
||
:label="
|
||
[
|
||
'解释器路径,如:/opt/python',
|
||
'运行参数,如:-u',
|
||
'脚本后缀,不含点,如:py',
|
||
][index]
|
||
"
|
||
:model-value="currentCommand.customOptions[item]"
|
||
@update:model-value="
|
||
(val) => updateModelValue(`customOptions.${item}`, val)
|
||
"
|
||
>
|
||
<template v-slot:prepend>
|
||
<q-icon name="code" />
|
||
</template>
|
||
</q-input>
|
||
</q-item>
|
||
<!-- 脚本参数 -->
|
||
<q-item v-show="currentCommand.program !== 'quickcommand'">
|
||
<q-input
|
||
dense
|
||
stack-label
|
||
outlined
|
||
label="脚本参数"
|
||
class="full-width"
|
||
:model-value="currentCommand.scptarg"
|
||
@update:model-value="updateModelValue('scptarg', $event)"
|
||
>
|
||
<template v-slot:prepend>
|
||
<q-icon name="input" />
|
||
</template>
|
||
</q-input>
|
||
</q-item>
|
||
<!-- 编码设置 -->
|
||
<q-item
|
||
v-for="(item, index) in Object.keys(currentCommand.charset)"
|
||
:key="index"
|
||
v-show="currentCommand.program !== 'quickcommand'"
|
||
>
|
||
<q-select
|
||
dense
|
||
outlined
|
||
stack-label
|
||
clearable
|
||
class="full-width"
|
||
:label="['脚本编码', '输出编码'][index]"
|
||
:model-value="currentCommand.charset[item]"
|
||
@update:model-value="
|
||
(val) => updateModelValue(`charset.${item}`, val)
|
||
"
|
||
:options="['GBK', 'utf8', 'Big5']"
|
||
type="text"
|
||
>
|
||
<template v-slot:prepend>
|
||
<q-icon :name="['format_size', 'output'][index]" />
|
||
</template>
|
||
</q-select>
|
||
</q-item>
|
||
</q-list>
|
||
</q-btn-dropdown>
|
||
<q-separator vertical inset />
|
||
<q-btn
|
||
v-if="!isRunCodePage"
|
||
class="action-btn run-btn"
|
||
dense
|
||
flat
|
||
color="primary"
|
||
icon="arrow_back"
|
||
label="退出"
|
||
@click="$emit('action', 'back')"
|
||
></q-btn>
|
||
<q-btn
|
||
class="action-btn run-btn"
|
||
dense
|
||
flat
|
||
color="primary"
|
||
icon="play_arrow"
|
||
:label="`运行(${ctrlKey}B)`"
|
||
@click="$emit('action', 'run')"
|
||
></q-btn>
|
||
<q-btn
|
||
v-if="!isRunCodePage"
|
||
:disable="!canCommandSave"
|
||
:color="canCommandSave ? 'primary' : 'grey'"
|
||
class="action-btn save-btn"
|
||
flat
|
||
dense
|
||
icon="save"
|
||
:label="`保存(${ctrlKey}S)`"
|
||
@click="$emit('action', 'save')"
|
||
></q-btn>
|
||
</q-btn-group>
|
||
<q-dialog v-model="showUserData">
|
||
<UserData
|
||
@insertText="
|
||
insertSpecialVar($event);
|
||
showUserData = false;
|
||
"
|
||
:showInsertBtn="true"
|
||
/>
|
||
</q-dialog>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import programs from "js/options/programs.js";
|
||
import specialVars from "js/options/specialVars.js";
|
||
import commandTypes from "js/options/commandTypes.js";
|
||
import UserData from "components/popup/UserData.vue";
|
||
|
||
export default {
|
||
name: "CommandLanguageBar",
|
||
props: {
|
||
modelValue: {
|
||
type: Object,
|
||
required: true,
|
||
},
|
||
canCommandSave: {
|
||
type: Boolean,
|
||
default: true,
|
||
},
|
||
isRunCodePage: {
|
||
type: Boolean,
|
||
default: false,
|
||
},
|
||
},
|
||
emits: ["update:modelValue", "action"],
|
||
components: {
|
||
UserData,
|
||
},
|
||
data() {
|
||
return {
|
||
programs,
|
||
specialVars,
|
||
commandTypes,
|
||
isSettingsVisible: false,
|
||
showUserData: false,
|
||
ctrlKey: utools.isMacOs ? "⌘" : "⌃",
|
||
};
|
||
},
|
||
computed: {
|
||
currentCommand() {
|
||
return this.modelValue;
|
||
},
|
||
},
|
||
methods: {
|
||
handleProgramChange(newProgram) {
|
||
const newCommand = { ...this.currentCommand };
|
||
newCommand.program = newProgram;
|
||
if (newProgram === "custom") {
|
||
this.isSettingsVisible = true;
|
||
}
|
||
if (newProgram === "html") {
|
||
newCommand.output = "html";
|
||
}
|
||
const featuresIcon = this.currentCommand.features.icon || "";
|
||
if (featuresIcon.slice(0, 10) !== "data:image") {
|
||
newCommand.features.icon = this.programs[newProgram].icon;
|
||
}
|
||
this.$emit("update:modelValue", newCommand);
|
||
},
|
||
updateModelValue(keyPath, value) {
|
||
const newModelValue = { ...this.modelValue };
|
||
const keys = keyPath.split(".");
|
||
const lastKey = keys.pop();
|
||
const target = keys.reduce((obj, key) => obj[key], newModelValue);
|
||
target[lastKey] = value;
|
||
this.$emit("update:modelValue", newModelValue);
|
||
},
|
||
handleQuickCommandAction(index) {
|
||
const actions = [
|
||
() => this.showHelp(),
|
||
() => this.$emit("action", "show-composer"),
|
||
];
|
||
actions[index]();
|
||
},
|
||
showHelp() {
|
||
window.showUb.docs();
|
||
},
|
||
handleSpecialVarClick(item) {
|
||
if (item.label === "{{usr:}}") this.showUserData = true;
|
||
else this.insertSpecialVar(item.label);
|
||
},
|
||
insertSpecialVar(text) {
|
||
if (!text) return;
|
||
this.$emit("action", "insert-text", `"${text}"`);
|
||
},
|
||
},
|
||
};
|
||
</script>
|
||
|
||
<style scoped>
|
||
.button-group {
|
||
padding: 0 5px;
|
||
}
|
||
|
||
.button-group :deep(.q-focus-helper) {
|
||
display: none;
|
||
}
|
||
|
||
.button-group :deep(.q-btn__content) {
|
||
font-size: 12px;
|
||
}
|
||
|
||
.button-group :deep(.q-btn-dropdown__arrow) {
|
||
margin-left: 0;
|
||
}
|
||
|
||
.button-group .q-btn:hover {
|
||
filter: brightness(1.2);
|
||
transition: all 0.2s ease;
|
||
}
|
||
|
||
/* 运行按钮动画 */
|
||
.run-btn:hover :deep(.q-icon) {
|
||
display: inline-block;
|
||
animation: leftRight 1.5s infinite;
|
||
}
|
||
|
||
/* 保存按钮动画 */
|
||
.save-btn:not([disabled]):hover :deep(.q-icon) {
|
||
display: inline-block;
|
||
animation: upDown 1.2s infinite;
|
||
}
|
||
|
||
.command-language-bar {
|
||
background-color: #fffffe;
|
||
height: 30px;
|
||
margin-bottom: 2px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
}
|
||
|
||
.body--dark .command-language-bar {
|
||
background-color: #1e1e1e;
|
||
}
|
||
|
||
.command-language-bar :deep(.q-field__control),
|
||
.command-language-bar :deep(.q-field__control > *),
|
||
.command-language-bar :deep(.q-field__native) {
|
||
max-height: 30px;
|
||
min-height: 30px;
|
||
}
|
||
</style>
|