277 lines
7.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div
class="composer-card"
:class="{
collapsed: localCommand.isCollapsed && !localCommand.isControlFlow,
}"
v-bind="$attrs"
>
<q-card class="command-item">
<q-card-section
class="card-section"
:class="{
collapsed: localCommand.isCollapsed || localCommand.isControlFlow,
}"
>
<CommandHead
:command="localCommand"
@update:outputVariable="handleOutputVariableUpdate"
@toggle-output="handleToggleOutput"
@toggle-collapse="handleToggleCollapse"
@run="runCommand"
@remove="$emit('remove')"
>
<!-- 控制流程组件直接把组件放在head中 -->
<template v-if="localCommand.isControlFlow">
<component
:is="localCommand.component"
v-model="localCommand"
v-bind="localCommand.componentProps || {}"
class="control-component"
@addBranch="(event) => $emit('addBranch', event)"
/>
</template>
<!-- 非控制流程组件使用正常布局 -->
<template v-else>
<q-space />
</template>
</CommandHead>
<!-- 非控制流程组件的参数输入 -->
<div
v-if="!localCommand.isControlFlow"
class="command-content-wrapper"
:class="{ collapsed: localCommand.isCollapsed }"
>
<div class="command-content">
<component
v-if="!!localCommand.component"
:is="localCommand.component"
v-model="localCommand"
class="col q-mt-sm"
v-bind="localCommand.componentProps || {}"
/>
<MultiParams
v-else
v-model="localCommand"
:class="localCommand.config?.length ? 'col q-mt-sm' : 'col'"
/>
</div>
</div>
</q-card-section>
</q-card>
</div>
</template>
<script>
import { defineComponent, inject } from "vue";
import { validateVariableName } from "js/common/variableValidator";
import VariableInput from "components/composer/common/VariableInput.vue";
import MultiParams from "components/composer/MultiParams.vue";
import CommandHead from "components/composer/card/CommandHead.vue";
import * as CardComponents from "js/composer/cardComponents";
export default defineComponent({
name: "ComposerCard",
components: {
VariableInput,
MultiParams,
CommandHead,
...CardComponents,
},
props: {
modelValue: {
type: Object,
required: true,
},
},
emits: ["remove", "run", "addBranch", "toggle-collapse", "update:modelValue"],
computed: {
localCommand: {
get() {
return this.modelValue || {};
},
set(value) {
this.$emit("update:modelValue", value);
},
},
showRunBtn() {
return !this.command.isControlFlow;
},
showOutputBtn() {
return !this.command.isControlFlow;
},
isLastCommandInChain() {
if (!this.command.commandChain) return false;
return (
this.command.commandType === this.command.commandChain?.slice(-1)[0]
);
},
},
setup() {
const addVariable = inject("addVariable");
const removeVariable = inject("removeVariable");
const variables = inject("composerVariables", []);
return {
addVariable,
removeVariable,
variables,
};
},
methods: {
handleOutputVariableUpdate(value) {
// 检查变量名是否合法
const validation = validateVariableName(value);
if (!validation.isValid) {
quickcommand.showMessageBox(validation.error, "warning");
return;
}
// 检查变量名是否重复
if (this.variables.some((v) => v.name === value)) {
quickcommand.showMessageBox(`变量名 "${value}" 已经存在`, "warning");
return;
}
// 处理变量管理
if (this.localCommand.outputVariable) {
this.removeVariable(this.localCommand.outputVariable);
}
if (value) {
this.addVariable(value, this.localCommand);
}
this.localCommand.outputVariable = value;
},
handleToggleOutput() {
this.localCommand.saveOutput = !this.localCommand.saveOutput;
// 如果关闭输出,清空变量名
if (!this.localCommand.saveOutput && this.localCommand.outputVariable) {
this.removeVariable(this.localCommand.outputVariable);
this.localCommand.outputVariable = null;
}
},
runCommand() {
// 创建一个带临时变量的命令副本
const tempCommand = {
...this.localCommand,
outputVariable:
this.localCommand.outputVariable || `temp_${Date.now()}`,
saveOutput: true,
};
this.$emit("run", tempCommand);
},
handleToggleCollapse() {
if (this.localCommand.isControlFlow) {
// 控制命令的折叠,直接传递给父组件处理
this.$emit("toggle-collapse", {
isCollapsed: this.localCommand.isCollapsed,
chainId: this.localCommand.chainId,
});
} else {
// 非控制命令的折叠,更新自身状态
this.localCommand.isCollapsed = !this.localCommand.isCollapsed;
}
},
},
});
</script>
<style scoped>
/* 卡片基础样式 */
.composer-card {
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
transform-origin: center;
opacity: 1;
transform: translateY(0) scale(1);
border-radius: inherit;
position: relative;
}
/* 控制流程组件样式 */
.control-component {
flex: 1;
display: flex;
align-items: center;
width: 100%;
}
.composer-card,
.composer-card::before,
.composer-card .command-item {
transition: none !important;
transform: none !important;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05) !important;
}
.command-item {
transition: all 0.3s ease;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
border: 1px solid rgba(0, 0, 0, 0.05);
border-radius: inherit;
user-select: none;
transform: translateZ(0);
will-change: transform;
}
/* 暗色模式适配 */
.body--dark .command-item {
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}
.body--dark .composer-card.drag-handle:hover::before {
background: rgba(255, 255, 255, 0.1);
}
.body--dark .composer-card.drag-handle:active::before {
background: rgba(255, 255, 255, 0.15);
}
/* 收起状态样式 */
.composer-card.collapsed {
transform-origin: top;
}
.composer-card.collapsed .command-item {
min-height: 20px;
}
/* 卡片内容区域动画 */
.card-section {
transition: padding 0.2s cubic-bezier(0.4, 0, 0.2, 1);
padding: 8px;
}
.card-section.collapsed {
padding: 2px 8px;
}
/* 命令内容动画 */
.command-content-wrapper {
display: grid;
grid-template-rows: 1fr;
transition: grid-template-rows 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}
.command-content {
min-height: 0;
overflow: hidden;
}
.command-content-wrapper.collapsed {
grid-template-rows: 0fr;
margin-top: 0;
}
.command-content-wrapper.collapsed .command-content {
opacity: 0;
}
/* 调整控制流程组件的样式 */
.command-item :deep(.condition-type-btn) {
margin-left: -8px;
}
</style>