mirror of
https://github.com/fofolee/uTools-quickcommand.git
synced 2025-06-08 22:51:25 +08:00
271 lines
6.4 KiB
Vue
271 lines
6.4 KiB
Vue
<template>
|
|
<div class="command-composer">
|
|
<!-- 主体内容 -->
|
|
<div class="composer-body row no-wrap">
|
|
<!-- 左侧命令列表 -->
|
|
<div class="col-3 command-section command-list">
|
|
<!-- <div class="section-header">
|
|
<q-icon name="list" size="20px" class="q-mr-sm text-primary" />
|
|
<span class="text-subtitle1">可用命令</span>
|
|
</div> -->
|
|
<q-scroll-area class="command-scroll">
|
|
<ComposerList
|
|
:commands="availableCommands"
|
|
@add-command="addCommand"
|
|
/>
|
|
</q-scroll-area>
|
|
</div>
|
|
|
|
<!-- 右侧命令流程 -->
|
|
<div class="col command-section command-flow">
|
|
<div class="section-header">
|
|
<q-icon name="timeline" size="20px" class="q-mr-sm text-primary" />
|
|
<span class="text-subtitle1">命令流程</span>
|
|
<q-space />
|
|
<ComposerButtons
|
|
:generate-code="generateFlowCode"
|
|
@action="handleComposer"
|
|
/>
|
|
</div>
|
|
<q-scroll-area class="command-scroll">
|
|
<ComposerFlow v-model="commandFlow" @add-command="addCommand" />
|
|
</q-scroll-area>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { defineComponent, provide, ref } from "vue";
|
|
import ComposerList from "./ComposerList.vue";
|
|
import ComposerFlow from "./ComposerFlow.vue";
|
|
import ComposerButtons from "./ComposerButtons.vue";
|
|
import { commandCategories } from "js/composer/composerConfig";
|
|
import { generateCode } from "js/composer/generateCode";
|
|
// 从commandCategories中提取所有命令
|
|
const availableCommands = commandCategories.reduce((commands, category) => {
|
|
return commands.concat(
|
|
category.commands.map((cmd) => ({
|
|
type: category.label,
|
|
...cmd,
|
|
}))
|
|
);
|
|
}, []);
|
|
|
|
export default defineComponent({
|
|
name: "CommandComposer",
|
|
components: {
|
|
ComposerList,
|
|
ComposerFlow,
|
|
ComposerButtons,
|
|
},
|
|
setup() {
|
|
const variables = ref([]);
|
|
|
|
const addVariable = (name, command) => {
|
|
if (!variables.value.find((v) => v.name === name)) {
|
|
variables.value.push({
|
|
name,
|
|
sourceCommand: command,
|
|
});
|
|
}
|
|
};
|
|
|
|
const removeVariable = (name) => {
|
|
const index = variables.value.findIndex((v) => v.name === name);
|
|
if (index !== -1) {
|
|
variables.value.splice(index, 1);
|
|
}
|
|
};
|
|
|
|
provide("composerVariables", variables);
|
|
provide("addVariable", addVariable);
|
|
provide("removeVariable", removeVariable);
|
|
|
|
return {
|
|
variables,
|
|
addVariable,
|
|
removeVariable,
|
|
};
|
|
},
|
|
data() {
|
|
return {
|
|
commandFlow: [],
|
|
nextId: 1,
|
|
availableCommands,
|
|
};
|
|
},
|
|
emits: ["use-composer", "update:modelValue"],
|
|
methods: {
|
|
addCommand(action) {
|
|
this.commandFlow.push({
|
|
...action,
|
|
id: this.nextId++,
|
|
argv: "",
|
|
argvType: "string",
|
|
saveOutput: false,
|
|
outputVariable: null,
|
|
cmd: action.value || action.cmd,
|
|
value: action.value || action.cmd,
|
|
});
|
|
},
|
|
generateFlowCode() {
|
|
return generateCode(this.commandFlow);
|
|
},
|
|
handleComposer(type) {
|
|
const code = this.generateFlowCode();
|
|
this.$emit("use-composer", { type, code });
|
|
if (type !== "run") this.$emit("update:modelValue", false);
|
|
},
|
|
},
|
|
});
|
|
</script>
|
|
|
|
<style scoped>
|
|
.command-composer {
|
|
display: flex;
|
|
flex-direction: column;
|
|
height: 100%;
|
|
background-color: #f4f4f4;
|
|
}
|
|
|
|
.body--dark .command-composer {
|
|
background-color: #303132;
|
|
}
|
|
|
|
.composer-body {
|
|
flex: 1;
|
|
overflow: hidden;
|
|
gap: 8px;
|
|
padding: 8px;
|
|
}
|
|
|
|
.command-section {
|
|
display: flex;
|
|
flex-direction: column;
|
|
height: 100%;
|
|
background: white;
|
|
border-radius: 8px;
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
|
}
|
|
|
|
.body--dark .command-section {
|
|
background: #1d1d1d;
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
|
|
}
|
|
|
|
.section-header {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 12px 16px;
|
|
height: 28px;
|
|
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
|
}
|
|
|
|
.body--dark .section-header {
|
|
border-bottom-color: rgba(255, 255, 255, 0.1);
|
|
}
|
|
|
|
.command-scroll {
|
|
flex: 1;
|
|
overflow: hidden;
|
|
border-radius: 8px;
|
|
padding-bottom: 8px;
|
|
}
|
|
|
|
/* 滚动美化 */
|
|
:deep(.q-scrollarea__thumb) {
|
|
width: 2px;
|
|
opacity: 0.4;
|
|
transition: opacity 0.3s ease;
|
|
}
|
|
|
|
:deep(.q-scrollarea__thumb:hover) {
|
|
opacity: 0.8;
|
|
}
|
|
|
|
/* 动画效果 */
|
|
.command-section {
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.command-section:hover {
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
|
}
|
|
|
|
.body--dark .command-section:hover {
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
|
}
|
|
|
|
/* 布局更加紧凑 */
|
|
/* 输入框高度及字体 */
|
|
.command-composer :deep(.q-field--filled .q-field__control),
|
|
.command-composer :deep(.q-field--filled .q-field__control > *),
|
|
.command-composer
|
|
:deep(.q-field--filled.q-select--with-input .q-field__native) {
|
|
border-radius: 5px;
|
|
font-size: 12px;
|
|
max-height: 36px !important;
|
|
min-height: 36px !important;
|
|
}
|
|
|
|
/* 输入框图标大小 */
|
|
.command-composer :deep(.q-field--filled .q-field__control .q-icon) {
|
|
font-size: 18px;
|
|
}
|
|
|
|
/* 输入框标签字体大小,占位时的位置 */
|
|
.command-composer :deep(.q-field--filled .q-field__label) {
|
|
font-size: 11px;
|
|
top: 8px;
|
|
}
|
|
|
|
/* 输入框标签悬浮的位置 */
|
|
.command-composer :deep(.q-field--filled .q-field--float .q_field__label) {
|
|
transform: translateY(-35%) scale(0.7);
|
|
}
|
|
|
|
/* 去除filled输入框边框 */
|
|
.command-composer :deep(.q-field--filled .q-field__control:before) {
|
|
border: none;
|
|
}
|
|
|
|
/* 去除filled输入框下划线 */
|
|
.command-composer :deep(.q-field--filled .q-field__control:after) {
|
|
height: 0;
|
|
border-bottom: none;
|
|
}
|
|
|
|
/* 输入框背景颜色 */
|
|
.command-composer :deep(.q-field--filled .q-field__control) {
|
|
background: rgba(0, 0, 0, 0.03);
|
|
}
|
|
|
|
/* 输入框聚焦时的背景颜色 */
|
|
.command-composer
|
|
:deep(.q-field--filled.q-field--highlighted .q-field__control) {
|
|
background: rgba(0, 0, 0, 0.03);
|
|
}
|
|
|
|
/* 暗黑模式下的输入框背景颜色 */
|
|
.body--dark .command-composer :deep(.q-field--filled .q-field__control) {
|
|
background: rgba(255, 255, 255, 0.04);
|
|
}
|
|
|
|
/* 暗黑模式下输入框聚焦时的背景颜色 */
|
|
.body--dark
|
|
.command-composer
|
|
:deep(.q-field--filled.q-field--highlighted .q-field__control) {
|
|
background: rgba(255, 255, 255, 0.08);
|
|
}
|
|
|
|
/* checkbox大小及字体 */
|
|
.command-composer :deep(.q-checkbox__label) {
|
|
font-size: 12px;
|
|
}
|
|
|
|
.command-composer :deep(.q-checkbox__inner) {
|
|
font-size: 24px;
|
|
}
|
|
</style>
|