ソースを参照

Merge branch 'feature-0123-Ai-workFlow' of https://git.shalu.com/Shalu/shalu-agent-workflow

lj1559651600@163.com 5 日 前
コミット
0290b48d9e

+ 1 - 0
.gitignore

@@ -6,6 +6,7 @@ node_modules
 .pnp.js
 .idea/
 .idea/shelf/
+.idea/workspace.xml
 
 # Local env files
 .env

+ 4 - 3
.idea/workspace.xml

@@ -6,7 +6,7 @@
   <component name="ChangeListManager">
     <list default="true" id="41cd2400-3735-4e1a-9a77-7ea2e4a1c041" name="更改" comment="update">
       <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/apps/web/src/components/SetterCommon/Code/TestConfig.vue" beforeDir="false" afterPath="$PROJECT_DIR$/apps/web/src/components/SetterCommon/Code/TestConfig.vue" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/apps/web/src/components/setter/ConditionSetter.vue" beforeDir="false" afterPath="$PROJECT_DIR$/apps/web/src/components/setter/ConditionSetter.vue" afterDir="false" />
     </list>
     <option name="SHOW_DIALOG" value="false" />
     <option name="HIGHLIGHT_CONFLICTS" value="true" />
@@ -41,14 +41,14 @@
   <component name="PropertiesComponent"><![CDATA[{
   "keyToString": {
     "RunOnceActivity.ShowReadmeOnStart": "true",
-    "git-widget-placeholder": "main",
+    "git-widget-placeholder": "feature-0123-Ai-workFlow",
     "last_opened_file_path": "/Users/liujie/Desktop/shalu/shalu-agent-workflow",
     "node.js.detected.package.eslint": "true",
     "node.js.detected.package.tslint": "true",
     "node.js.selected.package.eslint": "(autodetect)",
     "node.js.selected.package.tslint": "(autodetect)",
     "nodejs_package_manager_path": "pnpm",
-    "settings.editor.selected.configurable": "preferences.keymap",
+    "settings.editor.selected.configurable": "preferences.sourceCode.JavaScript",
     "ts.external.directory.path": "/Users/liujie/Desktop/shalu/shalu-agent-workflow/node_modules/typescript/lib",
     "vue.rearranger.settings.migration": "true"
   }
@@ -82,6 +82,7 @@
       <workItem from="1769518660683" duration="5115000" />
       <workItem from="1769525730430" duration="3654000" />
       <workItem from="1769529933165" duration="6257000" />
+      <workItem from="1769579076775" duration="529000" />
     </task>
     <task id="LOCAL-00001" summary="合并冲突">
       <option name="closed" value="true" />

+ 40 - 33
apps/web/src/components/SetterCommon/Code/CodeEditor.vue

@@ -1,12 +1,19 @@
+<!--
+ * @Author: liuJie
+ * @Date: 2026-01-28 02:04:56
+ * @LastEditors: liuJie
+ * @LastEditTime: 2026-01-28 16:55:30
+ * @Describe: 代码编辑器
+-->
 <template>
     <div class="space-y-4">
-<!--			<div class="flex items-center justify-between text-gray-800">-->
-<!--				<span class="w-[60px] text-sm">语法</span>-->
-<!--				<ElSelect v-model="selectedLanguageVal" @change="changeLanguage">-->
-<!--					<el-option v-for="li in language" :key="li" :value="li">{{li}}</el-option>-->
-<!--				</ElSelect>-->
-<!--			</div>-->
-			<div ref="editorContainer" style="height: 240px;"></div>
+        <!-- <div class="flex items-center justify-between text-gray-800">
+            <span class="w-[60px] text-sm">语法</span>
+            <ElSelect v-model="selectedLanguageVal" @change="changeLanguage">
+                <el-option v-for="li in language" :key="li" :value="li">{{li}}</el-option>
+            </ElSelect>
+        </div> -->
+        <div ref="editorContainer" style="height: 240px;"></div>
     </div>
 </template>
 
@@ -21,37 +28,37 @@ const editorContainer = ref<HTMLElement | null>(null)
 let editor = ref(null) as any;
 
 onMounted(() => {
-		try {
-				if(!editorContainer.value){
-					console.log('编辑器挂载节点没获取到')
-					return
-				}
-				editor.value = monaco.editor.create(editorContainer.value, {
-					value: [
-						'function x() {',
-						'    console.log("Hello world!");',
-						'}'
-					].join('\n'),
-					language: 'javascript',
-					theme: 'vs-dark',
-					automaticLayout: true,
-					fixedOverflowWidgets: true,
-				});
-				// 防止冒泡
-				editor.value.onKeyDown((e:Event) => {
-					e.stopPropagation();
-				});
+    try {
+        if (!editorContainer.value) {
+            console.log('编辑器挂载节点没获取到')
+            return
+        }
+        editor.value = monaco.editor.create(editorContainer.value, {
+            value: [
+                'function x() {',
+                '    console.log("Hello world!");',
+                '}'
+            ].join('\n'),
+            language: 'javascript',
+            theme: 'vs-dark',
+            automaticLayout: true,
+            fixedOverflowWidgets: true,
+        });
+        // 防止冒泡
+        editor.value.onKeyDown((e: Event) => {
+            e.stopPropagation();
+        });
 
-		}catch (err){
-				console.error("Monaco 创建失败:", err);
-		}
+    } catch (err) {
+        console.error("Monaco 创建失败:", err);
+    }
 
 });
 
 onUnmounted(() => {
-	if (editor.value) {
-		editor.dispose();
-	}
+    if (editor.value) {
+        editor.value.dispose();
+    }
 });
 
 // // 动态设置模型语言

+ 43 - 54
apps/web/src/components/SetterCommon/Code/InputVariables.vue

@@ -1,43 +1,32 @@
 <template>
-	<div class="space-y-3">
-		<div class="flex items-center justify-between">
-			<label class="text-sm font-medium text-gray-700">输入变量</label>
-			<ElButton
-					@click="addVariable"
-					class="p-1  rounded bg-gray-100 transition-colors"
-					title="添加变量">
-				<Icon icon="lucide:plus" :height="16" :width="16" class="text-gray-600" />
-			</ElButton>
-		</div>
+    <div class="space-y-3">
+        <div class="flex items-center justify-between">
+            <label class="text-sm font-medium text-gray-700">输入变量</label>
+            <ElButton @click="addVariable" class="p-1  rounded bg-gray-100 transition-colors" title="添加变量">
+                <Icon icon="lucide:plus" :height="16" :width="16" class="text-gray-600" />
+            </ElButton>
+        </div>
 
-		<div class="space-y-2">
-			<div
-				v-for="(variable, index) in variables"
-				:key="variable.name"
-				class="flex items-center gap-2 group"
-			>
-				<ElInput
-					v-model="variable.id"
-					type="text"
-					placeholder="变量名"
-					class="w-1/3 px-3 py-2 text-sm border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
-					@input="handleVariableChange"
-				/>
-				<ElInput  class="w-1/3" v-model="variable.name"  placeholder="设置变量值" />
-				<ElButton
-					@click="removeVariable(index)"
-					class="w-1/3 p-1 opacity-0 group-hover:opacity-100 hover:bg-red-50 rounded transition-all"
-					title="删除变量"
-				>
-					<Icon icon="lucide:trash-2" :height="16" :width="16" class="text-red-500" />
-				</ElButton>
-			</div>
+        <div class="space-y-2">
+            <div v-for="(variable, index) in variables" :key="variable.name" class="flex items-center gap-2 group">
+                <ElInput v-model="variable.id" type="text" placeholder="变量名"
+                    class="w-1/3 px-3 py-2 text-sm border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
+                    @input="handleVariableChange" />
+                <ElInput class="w-1/3" v-model="variable.name" placeholder="设置变量值" />
 
-			<div v-if="variables.length === 0" class="text-sm text-gray-400 text-center py-4">
-				暂无输入变量
-			</div>
-		</div>
-	</div>
+                <ElButton @click="removeVariable(index)"
+                    class="w-1/3 p-1 opacity-50 group-hover:opacity-100 hover:bg-red-50 rounded transition-all"
+                    title="删除变量">
+                    <Icon icon="lucide:trash-2" :height="16" :width="16" class="text-red-500" />
+                </ElButton>
+            </div>
+
+            <div v-if="variables.length === 0" class="text-sm text-gray-400 text-center py-4">
+                <Icon icon="lucide:circle-off" :height="24" :width="25"></Icon>
+                <p class="m-1">暂无输入变量</p>
+            </div>
+        </div>
+    </div>
 </template>
 
 <script setup lang="ts">
@@ -45,16 +34,16 @@ import { ref, watch } from 'vue'
 import { Icon } from '@iconify/vue'
 
 interface Variable {
-	name: string
-	id: string
+    name: string
+    id: string
 }
 
 interface Props {
-	modelValue: Variable[]
+    modelValue: Variable[]
 }
 
 interface Emits {
-	(e: 'update:modelValue', value: Variable[]): void
+    (e: 'update:modelValue', value: Variable[]): void
 }
 
 const props = defineProps<Props>()
@@ -63,27 +52,27 @@ const emit = defineEmits<Emits>()
 const variables = ref<Variable[]>(props.modelValue || [])
 
 watch(
-	() => props.modelValue,
-	(newVal) => {
-		variables.value = newVal || []
-	}
+    () => props.modelValue,
+    (newVal) => {
+        variables.value = newVal || []
+    }
 )
 
 const addVariable = () => {
-	const newVariable: Variable = {
-		id: `var_${Date.now()}`,
-		name: `arg${variables.value.length + 1}`
-	}
-	variables.value.push(newVariable)
-	handleVariableChange()
+    const newVariable: Variable = {
+        id: `var_${Date.now()}`,
+        name: `arg${variables.value.length + 1}`
+    }
+    variables.value.push(newVariable)
+    handleVariableChange()
 }
 
 const removeVariable = (index: number) => {
-	variables.value.splice(index, 1)
-	handleVariableChange()
+    variables.value.splice(index, 1)
+    handleVariableChange()
 }
 
 const handleVariableChange = () => {
-	emit('update:modelValue', variables.value)
+    emit('update:modelValue', variables.value)
 }
 </script>

+ 5 - 3
apps/web/src/components/SetterCommon/Code/OutputVariables.vue

@@ -2,7 +2,7 @@
  * @Author: liuJie
  * @Date: 2026-01-27 14:38:32
  * @LastEditors: liuJie
- * @LastEditTime: 2026-01-27 17:26:25
+ * @LastEditTime: 2026-01-28 17:18:55
  * @Describe: file describe
 -->
 <template>
@@ -31,13 +31,15 @@
                     <el-option value="Array">Array</el-option>
                 </ElSelect>
                 <ElButton @click="removeOutput(index)"
-                    class="w-1/3 p-1 opacity-0 group-hover:opacity-100 hover:bg-red-50 rounded transition-all" title="删除输出">
+                    class="w-1/3 p-1 opacity-50 group-hover:opacity-100 hover:bg-red-50 rounded transition-all"
+                    title="删除输出">
                     <Icon icon="lucide:trash-2" :height="16" :width="16" class="text-red-500" />
                 </ElButton>
             </div>
 
             <div v-if="outputs.length === 0" class="text-sm text-gray-400 text-center py-4">
-                请添加至少一个输出变量
+                <Icon icon="lucide:circle-off" :height="24" :width="25"></Icon>
+                <p class="m-1">请添加至少一个输出变量</p>
             </div>
         </div>
     </div>

+ 75 - 90
apps/web/src/components/SetterCommon/condition/BranchCard.vue

@@ -1,67 +1,52 @@
 <template>
-	<div
-		class="border rounded-lg transition-all"
-		:class="[
-      isActive ? 'border-blue-400 bg-blue-50/30' : 'border-gray-200 bg-white',
-      isDragging ? 'opacity-50' : ''
-    ]"
-	>
-		<!-- 分支头部 -->
-		<div
-			class="flex items-center justify-between px-4 py-3 cursor-pointer"
-			@click="toggleExpanded"
-		>
-			<div class="flex items-center gap-3">
-				<!-- 分支类型标签 -->
-				<div
-					class="px-2.5 py-1 rounded text-xs font-medium"
-					:class="branchTypeClass"
-				>
-					{{ branchTypeLabel }}
-				</div>
-
-				<!-- 分支标题 -->
-				<div class="flex flex-col">
-					<span class="text-sm font-medium text-gray-900">{{ branch.label }}</span>
-					<span v-if="branch.description" class="text-xs text-gray-500">
-            {{ branch.description }}
-          </span>
-				</div>
-			</div>
-
-			<div class="flex items-center gap-2">
-				<!-- 删除按钮 (只有 ELIF 可以删除) -->
-				<ElButton
-					v-if="branch.type === 'elif'"
-					@click.stop="handleRemove"
-					class="p-1.5 hover:bg-red-50 rounded transition-colors"
-					title="删除分支"
-				>
-					<Icon icon="lucide:trash-2" :height="16" :width="16" class="text-red-500" />
-				</ElButton>
-
-				<!-- 展开/收起图标 -->
-				<Icon
-					:icon="isExpanded ? 'lucide:chevron-up' : 'lucide:chevron-down'"
-					:height="18"
-					:width="18"
-					class="text-gray-400"
-				/>
-			</div>
-		</div>
-
-		<!-- 分支内容 -->
-		<div
-			v-show="isExpanded"
-			class="px-4 pb-4 space-y-3 border-t border-gray-100"
-		>
-			<!-- IF 和 ELIF 的条件配置 -->
-			<div v-if="branch.type !== 'else'" class="pt-3">
-				<slot name="condition"></slot>
-			</div>
-
-		</div>
-	</div>
+    <!-- :class="[
+        isActive ? 'border-blue-400 bg-blue-50/30' : 'border-gray-200',
+        isDragging ? 'opacity-50' : ''
+    ]" -->
+    <div class="border transition-all">
+        <!-- 分支头部 -->
+        <div class="flex items-center justify-between px-4 py-3 cursor-pointer bg-white"
+            style="border-bottom: 1px solid #eee;" @click="toggleExpanded">
+            <div class="flex items-center gap-3">
+                <!-- 分支类型标签 -->
+                <div class="px-2.5 py-1 rounded text-xs font-bold" :class="branchTypeClass">
+                    {{ branchTypeLabel }}
+                </div>
+
+                <!-- 分支标题 -->
+                <div class="flex flex-col">
+                    <span class="text-sm font-medium text-gray-900">{{ branch.label }}</span>
+                    <span v-if="branch.description" class="text-xs text-gray-500">
+                        {{ branch.description }}
+                    </span>
+                </div>
+            </div>
+
+            <div class="flex items-center gap-2">
+                <!-- 删除按钮 (只有 ELIF 可以删除) -->
+                <ElButton v-if="branch.type === 'elif'" @click.stop="handleRemove"
+                    class="p-1.5 hover:bg-red-50 rounded transition-colors" title="删除分支">
+                    <Icon icon="lucide:trash-2" :height="16" :width="16" class="text-red-500" />
+                </ElButton>
+
+                <!-- 展开/收起图标 -->
+                <Icon :icon="isExpanded ? 'lucide:chevron-up' : 'lucide:chevron-down'" :height="18" :width="18"
+                    class="text-gray-400" />
+            </div>
+        </div>
+
+        <!-- 分支内容 -->
+        <div v-show="isExpanded" class="px-4 pb-4 space-y-3 border-t border-gray-100 bg-orange-50"
+            :class="{ '!bg-gray-100': branch.type === 'else' }">
+            <!-- IF 和 ELIF 的条件配置 -->
+            <div v-if="branch.type !== 'else'" class="pt-3">
+                <slot name="condition"></slot>
+            </div>
+            <div v-else-if="branch.type === 'else'" class="pt-3">
+                <slot name="else"></slot>
+            </div>
+        </div>
+    </div>
 </template>
 
 <script setup lang="ts">
@@ -69,27 +54,27 @@ import { ref, computed } from 'vue'
 import { Icon } from '@iconify/vue'
 
 interface Branch {
-	id: string
-	type: 'if' | 'elif' | 'else'
-	label: string
-	description?: string
-	conditions?: any[]
+    id: string
+    type: 'if' | 'elif' | 'else'
+    label: string
+    description?: string
+    conditions?: any[]
 }
 
 interface Props {
-	branch: Branch
-	isActive?: boolean
-	isDragging?: boolean
+    branch: Branch
+    isActive?: boolean
+    isDragging?: boolean
 }
 
 interface Emits {
-	(e: 'remove'): void
-	(e: 'toggle'): void
+    (e: 'remove'): void
+    (e: 'toggle'): void
 }
 
 const props = withDefaults(defineProps<Props>(), {
-	isActive: false,
-	isDragging: false
+    isActive: false,
+    isDragging: false
 })
 
 const emit = defineEmits<Emits>()
@@ -97,29 +82,29 @@ const emit = defineEmits<Emits>()
 const isExpanded = ref(true)
 
 const branchTypeLabel = computed(() => {
-	const labels: Record<string, string> = {
-		if: 'IF',
-		elif: 'ELIF',
-		else: 'ELSE'
-	}
-	return labels[props.branch.type] || 'IF'
+    const labels: Record<string, string> = {
+        if: 'IF',
+        elif: 'ELIF',
+        else: 'ELSE'
+    }
+    return labels[props.branch.type] || 'IF'
 })
 
 const branchTypeClass = computed(() => {
-	const classes: Record<string, string> = {
-		if: 'bg-blue-100 text-blue-700',
-		elif: 'bg-purple-100 text-purple-700',
-		else: 'bg-gray-100 text-gray-700'
-	}
-	return classes[props.branch.type] || 'bg-blue-100 text-blue-700'
+    const classes: Record<string, string> = {
+        if: 'bg-orange-500 text-white',
+        elif: 'bg-orange-500 text-white',
+        else: 'bg-gray-900 text-white'
+    }
+    return classes[props.branch.type] || 'bg-blue-100 text-blue-700'
 })
 
 const toggleExpanded = () => {
-	isExpanded.value = !isExpanded.value
-	emit('toggle')
+    isExpanded.value = !isExpanded.value
+    emit('toggle')
 }
 
 const handleRemove = () => {
-	emit('remove')
+    emit('remove')
 }
 </script>

+ 106 - 115
apps/web/src/components/SetterCommon/condition/ConditionBuilder.vue

@@ -1,85 +1,44 @@
 <template>
-	<div class="space-y-2">
-		<!-- 条件行 -->
-		<div
-			v-for="(condition, index) in conditions"
-			:key="condition.id"
-			class="flex items-center"
-		>
-			<!-- 左侧变量选择 -->
-			<div class="relative w-3/4">
-					<ElSelect placeholder="选择变量" v-model="condition.leftValue">
-						<el-option></el-option>
-					</ElSelect>
-<!--				<ElButton-->
-<!--					@click="openVariablePicker(index, 'left')"-->
-<!--					class="w-full px-3 py-2 text-sm text-left border border-gray-200 rounded-lg bg-white flex items-center justify-between group"-->
-<!--				>-->
-<!--          <span v-if="condition.leftValue" class="flex items-center gap-1">-->
-<!--            <Icon icon="lucide:at-sign" :height="14" :width="14" class="text-red-500" />-->
-<!--            <span class="text-red-600">{{ condition.leftValue }}</span>-->
-<!--          </span>-->
-<!--					<span v-else class="text-gray-400">选择变量</span>-->
-<!--					<Icon icon="lucide:chevron-down" :height="14" :width="14" class="text-gray-400" />-->
-<!--				</ElButton>-->
-			</div>
-
-			<!-- 运算符选择 -->
-			<ElSelect
-				v-model="condition.operator"
-				@change="handleConditionChange"
-				class="w-[60px] px-3 py-2 text-sm border border-gray-200 rounded-lg  bg-white ">
-				<el-option value="equals">等于</el-option>
-				<el-option value="notEquals">不等于</el-option>
-				<el-option value="contains">包含</el-option>
-				<el-option value="notContains">不包含</el-option>
-				<el-option value="greaterThan">大于</el-option>
-				<el-option value="lessThan">小于</el-option>
-				<el-option value="greaterOrEqual">大于等于</el-option>
-				<el-option value="lessOrEqual">小于等于</el-option>
-			</ElSelect>
-
-			<!-- 右侧值输入 -->
-			<div class="relative w-3/4">
-				<ElInput
-					v-model="condition.rightValue"
-					type="text"
-					placeholder="输入值"
-					@input="handleConditionChange"
-					class="w-full px-3 py-2 text-sm border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
-				/>
-			</div>
-
-			<!-- 删除按钮 -->
-			<ElButton
-				v-if="conditions.length > 1"
-				@click="removeCondition(index)"
-				class="p-2 w-1/4 opacity-0 hover:opacity-100 hover:bg-red-50 rounded transition-all"
-				title="删除条件">
-					<Icon icon="lucide:trash-2" :height="16" :width="16" class="text-red-500" />
-			</ElButton>
-		</div>
-
-		<!-- AND 连接符 -->
-<!--		<div v-if="showAndButton" class="flex items-center gap-2 pl-3">-->
-<!--			<div class="flex items-center gap-2 px-3 py-1.5 bg-blue-50 text-blue-600 text-xs font-medium rounded">-->
-<!--				<Icon icon="lucide:link" :height="12" :width="12" />-->
-<!--				AND-->
-<!--			</div>-->
-<!--		</div>-->
-
-		<!-- 添加条件按钮 -->
-		<div class="text-center">
-			<ElButton
-				@click="addCondition"
-				class="flex items-center gap-2 px-3 py-2 text-sm text-blue-600 hover:bg-blue-50 rounded-lg transition-colors"
-			>
-				<Icon icon="lucide:plus" :height="16" :width="16" />
-				添加条件
-			</ElButton>
-		</div>
-
-	</div>
+    <div class="space-y-2">
+        <!-- 条件行 -->
+        <div v-for="(condition, index) in conditions" :key="condition.id" class="flex items-center gap-1">
+            <!-- 左侧变量选择 -->
+            <div class="relative w-3/4">
+                <ElSelect placeholder="选择变量" v-model="condition.leftValue">
+                    <ElOption v-for="variable in availableVariables" :key="variable.id" :value="variable.name"
+                        :label="variable.name" />
+                </ElSelect>
+            </div>
+
+            <!-- 运算符选择 -->
+            <ElSelect v-model="condition.operator" @change="handleConditionChange"
+                class="w-1/4 text-sm border border-gray-200 rounded-lg  bg-white ">
+                <ElOption v-for="li in operators" :key="li.value" :value="li.value" :label="li.label" />
+            </ElSelect>
+
+            <!-- 右侧值输入 -->
+            <div class="relative w-3/4">
+                <ElInput v-model="condition.rightValue" type="text" placeholder="输入值" @input="handleConditionChange"
+                    class="w-full text-sm border border-gray-200 rounded-lg" />
+            </div>
+
+            <!-- 删除按钮 -->
+            <ElButton v-if="conditions.length > 1" @click="removeCondition(index)"
+                class="p-2 w-1/4 opacity-50 hover:opacity-100 hover:bg-red-50 rounded transition-all" title="删除条件">
+                <Icon icon="lucide:trash-2" :height="16" :width="16" class="text-red-500" />
+            </ElButton>
+        </div>
+
+        <!-- 添加条件按钮 -->
+        <div class="text-right" v-if="conditions[0]?.id !== 'else'">
+            <ElButton @click="addCondition"
+                class="flex items-center gap-2 px-3 py-2 text-sm text-blue-600 hover:bg-blue-50 rounded-lg transition-colors">
+                <Icon icon="lucide:git-branch-plus" :height="16" :width="16" />
+                添加条件
+            </ElButton>
+        </div>
+
+    </div>
 </template>
 
 <script setup lang="ts">
@@ -87,65 +46,97 @@ import { ref, computed, watch } from 'vue'
 import { Icon } from '@iconify/vue'
 
 interface Condition {
-	id: string
-	leftValue: string
-	operator: string
-	rightValue: string
+    id: string
+    leftValue: string
+    operator: string
+    rightValue: string
 }
 
 interface Props {
-	modelValue: Condition[]
+    modelValue: Condition[]
 }
 
 interface Emits {
-	(e: 'update:modelValue', value: Condition[]): void
-	(e: 'openVariablePicker', index: number, side: 'left' | 'right'): void
+    (e: 'update:modelValue', value: Condition[]): void
+    (e: 'openVariablePicker', index: number, side: 'left' | 'right'): void
 }
+interface Variable {
+    id: string
+    name: string
+    type: string
+    source: string
+}
+// 可用变量列表
+const availableVariables: Variable[] = [
+    { id: 'var_1', name: 'sys.user_id', type: 'String', source: 'HTTP 请求' },
+    { id: 'var_2', name: 'sys.app_id', type: 'Number', source: 'HTTP 请求' },
+    { id: 'var_3', name: 'result', type: 'String', source: '代码执行' },
+    { id: 'var_4', name: 'output_format', type: 'String', source: 'SQL查询' },
+    { id: 'var_5', name: 'user_name', type: 'String', source: 'HTTP 请求' },
+    { id: 'var_6', name: 'user_email', type: 'String', source: 'HTTP 请求' },
+]
+
+interface OperatorsType {
+    value: string
+    label: string
+}
+// 运算符列表
+const operators: OperatorsType[] = [
+    { value: 'equals', label: '等于' },
+    { value: 'notEquals', label: '不等于' },
+    { value: 'contains', label: '包含' },
+    { value: 'notContains', label: '不包含' },
+    { value: 'greaterThan', label: '大于' },
+    { value: 'lessThan', label: '小于' },
+    { value: 'greaterOrEqual', label: '大于等于' },
+    { value: 'lessOrEqual', label: '小于等于' }
+]
 
 const props = defineProps<Props>()
 const emit = defineEmits<Emits>()
 
+
+
 const conditions = ref<Condition[]>(props.modelValue || [
-	{
-		id: `condition_${Date.now()}`,
-		leftValue: '',
-		operator: 'equals',
-		rightValue: ''
-	}
+    {
+        id: `condition_${Date.now()}`,
+        leftValue: '',
+        operator: '',
+        rightValue: ''
+    }
 ])
 
-const showAndButton = computed(() => conditions.value.length > 1)
 
 watch(
-	() => props.modelValue,
-	(newVal) => {
-		if (newVal && newVal.length > 0) {
-			conditions.value = newVal
-		}
-	},
-	{ deep: true }
+    () => props.modelValue,
+    (newVal) => {
+        if (newVal && newVal.length > 0) {
+            conditions.value = newVal
+        }
+    },
+    { deep: true }
 )
 
 const addCondition = () => {
-	conditions.value.push({
-		id: `condition_${Date.now()}`,
-		leftValue: '',
-		operator: 'equals',
-		rightValue: ''
-	})
-	handleConditionChange()
+    conditions.value.push({
+        id: `condition_${Date.now()}`,
+        leftValue: '',
+        operator: '',
+        rightValue: ''
+    })
+    handleConditionChange()
 }
 
 const removeCondition = (index: number) => {
-	conditions.value.splice(index, 1)
-	handleConditionChange()
+    conditions.value.splice(index, 1)
+    handleConditionChange()
 }
 
 const handleConditionChange = () => {
-	emit('update:modelValue', conditions.value)
+    emit('update:modelValue', conditions.value)
 }
 
-const openVariablePicker = (index: number, side: 'left' | 'right') => {
-	emit('openVariablePicker', index, side)
-}
+// const openVariablePicker = (index: number, side: 'left' | 'right') => {
+//     emit('openVariablePicker', index, side)
+// }
 </script>

+ 0 - 159
apps/web/src/components/SetterCommon/condition/VariablePicker.vue

@@ -1,159 +0,0 @@
-<template>
-	<div
-		v-if="isOpen"
-		class="fixed inset-0 bg-black bg-opacity-30 flex items-center justify-center z-50"
-		@click.self="handleClose"
-	>
-		<div class="bg-white rounded-lg shadow-xl w-full max-w-md">
-			<!-- 头部 -->
-			<div class="flex items-center justify-between px-4 py-3 border-b border-gray-200">
-				<h3 class="text-sm font-semibold text-gray-900">选择变量</h3>
-				<ElButton
-					@click="handleClose"
-					class="p-1 hover:bg-gray-100 rounded transition-colors"
-				>
-					<Icon icon="lucide:x" :height="18" :width="18" class="text-gray-500" />
-				</ElButton>
-			</div>
-
-			<!-- 搜索框 -->
-			<div class="p-4 border-b border-gray-100">
-				<div class="relative">
-					<Icon
-						icon="lucide:search"
-						:height="16"
-						:width="16"
-						class="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400"
-					/>
-					<ElInput
-						v-model="searchQuery"
-						type="text"
-						placeholder="搜索变量..."
-						class="w-full pl-10 pr-4 py-2 text-sm border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
-					/>
-				</div>
-			</div>
-
-			<!-- 变量列表 -->
-			<div class="max-h-96 overflow-y-auto">
-				<div v-if="filteredVariables.length === 0" class="px-4 py-8 text-center">
-					<Icon icon="lucide:inbox" :height="48" :width="48" class="mx-auto mb-2 text-gray-300" />
-					<p class="text-sm text-gray-500">没有找到变量</p>
-				</div>
-
-				<div v-else class="py-2">
-					<ElButton
-						v-for="variable in filteredVariables"
-						:key="variable.id"
-						@click="selectVariable(variable)"
-						class="w-full px-4 py-2.5 text-left hover:bg-gray-50 transition-colors flex items-center gap-3 group"
-					>
-						<div
-							class="w-8 h-8 rounded-lg flex items-center justify-center"
-							:class="getVariableIconBg(variable.source)"
-						>
-							<Icon
-								:icon="getVariableIcon(variable.source)"
-								:height="16"
-								:width="16"
-								:class="getVariableIconColor(variable.source)"
-							/>
-						</div>
-						<div class="flex-1">
-							<div class="flex items-center gap-2">
-								<span class="text-sm font-medium text-gray-900">{{ variable.name }}</span>
-								<span class="text-xs px-2 py-0.5 bg-gray-100 text-gray-600 rounded">
-                  {{ variable.type }}
-                </span>
-							</div>
-							<p class="text-xs text-gray-500 mt-0.5">{{ variable.source }}</p>
-						</div>
-						<Icon
-							icon="lucide:chevron-right"
-							:height="16"
-							:width="16"
-							class="text-gray-400 opacity-0 group-hover:opacity-100 transition-opacity"
-						/>
-					</ElButton>
-				</div>
-			</div>
-		</div>
-	</div>
-</template>
-
-<script setup lang="ts">
-import { ref, computed } from 'vue'
-import { Icon } from '@iconify/vue'
-
-interface Variable {
-	id: string
-	name: string
-	type: string
-	source: string
-}
-
-interface Props {
-	isOpen: boolean
-	variables: Variable[]
-}
-
-interface Emits {
-	(e: 'close'): void
-	(e: 'select', variable: Variable): void
-}
-
-const props = defineProps<Props>()
-const emit = defineEmits<Emits>()
-
-const searchQuery = ref('')
-
-const filteredVariables = computed(() => {
-	if (!searchQuery.value) return props.variables
-
-	const query = searchQuery.value.toLowerCase()
-	return props.variables.filter(v =>
-		v.name.toLowerCase().includes(query) ||
-		v.source.toLowerCase().includes(query)
-	)
-})
-
-const getVariableIcon = (source: string) => {
-	const icons: Record<string, string> = {
-		'HTTP 请求': 'lucide:globe',
-		'代码执行': 'lucide:code-2',
-		'SQL查询': 'lucide:database',
-		'条件分支': 'lucide:git-branch'
-	}
-	return icons[source] || 'lucide:box'
-}
-
-const getVariableIconBg = (source: string) => {
-	const colors: Record<string, string> = {
-		'HTTP 请求': 'bg-purple-100',
-		'代码执行': 'bg-blue-100',
-		'SQL查询': 'bg-green-100',
-		'条件分支': 'bg-orange-100'
-	}
-	return colors[source] || 'bg-gray-100'
-}
-
-const getVariableIconColor = (source: string) => {
-	const colors: Record<string, string> = {
-		'HTTP 请求': 'text-purple-600',
-		'代码执行': 'text-blue-600',
-		'SQL查询': 'text-green-600',
-		'条件分支': 'text-orange-600'
-	}
-	return colors[source] || 'text-gray-600'
-}
-
-const selectVariable = (variable: Variable) => {
-	emit('select', variable)
-	handleClose()
-}
-
-const handleClose = () => {
-	searchQuery.value = ''
-	emit('close')
-}
-</script>

+ 145 - 183
apps/web/src/components/setter/ConditionSetter.vue

@@ -1,68 +1,40 @@
 <template>
-	<div class="bg-white w-full">
-		<div class="w-full">
-			<!-- Content -->
-				<!-- 设置标签页 -->
-				<div class="space-y-4">
-					<!-- IF 分支 -->
-					<BranchCard
-						:branch="branches.if"
-						:is-active="activeBranchId === branches.if.id"
-					>
-						<template #condition>
-							<ConditionBuilder
-								v-model="branches.if.conditions"
-								@open-variable-picker="openVariablePicker"
-							/>
-						</template>
-					</BranchCard>
-
-					<!-- ELIF 分支列表 -->
-					<BranchCard
-						v-for="(elifBranch, index) in branches.elifs"
-						:key="elifBranch.id"
-						:branch="elifBranch"
-						:is-active="activeBranchId === elifBranch.id"
-						@remove="removeElifBranch(index)"
-					>
-						<template #condition>
-							<ConditionBuilder
-								v-model="elifBranch.conditions"
-								@open-variable-picker="openVariablePicker"
-							/>
-						</template>
-					</BranchCard>
-
-					<!-- 添加 ELIF 按钮 -->
-					<div class="text-center">
-						<ElButton @click="addElifBranch" class="gap-2 px-4 py-3">
-							<Icon icon="lucide:plus" :height="16" :width="16" />
-							添加 ELIF
-						</ElButton>
-					</div>
-
-
-					<!-- ELSE 分支 -->
-					<BranchCard
-						:branch="branches.else"
-						:is-active="activeBranchId === branches.else.id"
-					>
-						<template #condition>
-							<!-- ELSE 没有条件配置 -->
-						</template>
-					</BranchCard>
-				</div>
-
-		</div>
-
-		<!-- 变量选择器弹窗 -->
-<!--		<VariablePicker-->
-<!--			:is-open="showVariablePicker"-->
-<!--			:variables="availableVariables"-->
-<!--			@close="closeVariablePicker"-->
-<!--			@select="handleVariableSelect"-->
-<!--		/>-->
-	</div>
+    <div class="bg-white w-full pb-22">
+        <div class="w-full">
+            <!-- Content -->
+            <!-- 设置标签页 -->
+            <div class="space-y-4">
+                <!-- IF 分支 -->
+                <BranchCard :branch="branches.if" :is-active="activeBranchId === branches.if.id">
+                    <template #condition>
+                        <ConditionBuilder v-model="branches.if.conditions" />
+                    </template>
+                </BranchCard>
+
+                <!-- ELIF 分支列表 -->
+                <BranchCard v-for="(elifBranch, index) in branches.elifs" :key="elifBranch.id" :branch="elifBranch"
+                    :is-active="activeBranchId === elifBranch.id" @remove="removeElifBranch(index)">
+                    <template #condition>
+                        <ConditionBuilder v-model="elifBranch.conditions" />
+                    </template>
+                </BranchCard>
+
+                <!-- ELSE 分支 -->
+                <BranchCard :branch="branches.else" :is-active="activeBranchId === branches.else.id">
+                    <template #else>
+                        <ConditionBuilder v-model="branches.else.conditions" />
+                    </template>
+                </BranchCard>
+                <!-- 添加 ELIF按钮 -->
+                <div class="text-center">
+                    <ElButton @click="addElifBranch" type="primary" class="gap-2 px-4 py-3">
+                        <Icon icon="lucide:grid-2x2-plus" :height="16" :width="16" />
+                        添加 ELIF {{ activeBranchId }}
+                    </ElButton>
+                </div>
+            </div>
+        </div>
+    </div>
 </template>
 
 <script setup lang="ts">
@@ -70,149 +42,139 @@ import { ref, reactive } from 'vue'
 import { Icon } from '@iconify/vue'
 import BranchCard from '@/components/SetterCommon/condition/BranchCard.vue'
 import ConditionBuilder from '@/components/SetterCommon/condition/ConditionBuilder.vue'
-import VariablePicker from '@/components/SetterCommon/condition/VariablePicker.vue'
+import { ElMessageBox } from 'element-plus'
 
 interface Condition {
-	id: string
-	leftValue: string
-	operator: string
-	rightValue: string
+    id: string
+    leftValue: string
+    operator: string
+    rightValue: string
 }
 
 interface Branch {
-	id: string
-	type: 'if' | 'elif' | 'else'
-	label: string
-	description?: string
-	conditions: Condition[]
+    id: string
+    type: 'if' | 'elif' | 'else'
+    label: string
+    description?: string
+    conditions: Condition[]
 }
 
-interface Variable {
-	id: string
-	name: string
-	type: string
-	source: string
-}
+
 
 interface Emits {
-	(e: 'close'): void
-	(e: 'save', data: any): void
+    (e: 'close'): void
+    (e: 'save', data: any): void
 }
 
 const emit = defineEmits<Emits>()
 
-const nodeName = ref('条件分支')
-const activeTab = ref('settings')
 const activeBranchId = ref<string | null>(null)
-const showVariablePicker = ref(false)
-const currentPickerContext = ref<{ branchId?: string; conditionIndex?: number; side?: 'left' | 'right' }>({})
 
-const tabs = [
-	{ label: '设置', value: 'settings' },
-	{ label: '上次运行', value: 'lastRun' }
-]
 
 // 分支数据
 const branches = reactive({
-	if: {
-		id: 'if_1',
-		type: 'if' as const,
-		label: 'CASE 1',
-		description: '条件未设置',
-		conditions: [
-			{
-				id: 'condition_1',
-				leftValue: 'sys.user_id',
-				operator: 'equals',
-				rightValue: '1323'
-			}
-		]
-	},
-	elifs: [] as Branch[],
-	else: {
-		id: 'else_1',
-		type: 'else' as const,
-		label: 'ELSE',
-		description: '用于定义当 if 条件不满足且没有匹配的逻辑时。',
-		conditions: []
-	}
+    if: {
+        id: 'if_1',
+        type: 'if' as const,
+        label: 'CASE 1',
+        description: '选择变量名称,设置条件和值',
+        conditions: [
+            {
+                id: 'condition_1',
+                leftValue: '',
+                operator: '',
+                rightValue: ''
+            }
+        ]
+    },
+    elifs: [] as Branch[],
+    else: {
+        id: 'else_1',
+        type: 'else' as const,
+        label: 'ELSE',
+        description: '当if条件不满足且没有匹配的逻辑时。',
+        conditions: [
+            {
+                id: 'else',
+                leftValue: '',
+                operator: '',
+                rightValue: ''
+            }
+        ]
+    }
 })
 
-// 可用变量列表
-const availableVariables: Variable[] = [
-	{ id: 'var_1', name: 'sys.user_id', type: 'String', source: 'HTTP 请求' },
-	{ id: 'var_2', name: 'sys.app_id', type: 'Number', source: 'HTTP 请求' },
-	{ id: 'var_3', name: 'result', type: 'String', source: '代码执行' },
-	{ id: 'var_4', name: 'output_format', type: 'String', source: 'SQL查询' },
-	{ id: 'var_5', name: 'user_name', type: 'String', source: 'HTTP 请求' },
-	{ id: 'var_6', name: 'user_email', type: 'String', source: 'HTTP 请求' },
-]
 
+// 添加else if
 const addElifBranch = () => {
-	const newElif: Branch = {
-		id: `elif_${Date.now()}`,
-		type: 'elif',
-		label: `CASE ${branches.elifs.length + 2}`,
-		description: '条件未设置',
-		conditions: [
-			{
-				id: `condition_${Date.now()}`,
-				leftValue: '',
-				operator: 'equals',
-				rightValue: ''
-			}
-		]
-	}
-	branches.elifs.push(newElif)
+    if (branches.elifs.length >= 7) {
+        ElMessageBox.alert('ELSE-IF数量不能超过8个')
+        return
+    }
+    const newElif: Branch = {
+        id: `elif_${Date.now()}`,
+        type: 'elif',
+        label: `CASE ${branches.elifs.length + 2}`,
+        description: '条件未设置',
+        conditions: [
+            {
+                id: `condition_${Date.now()}`,
+                leftValue: '',
+                operator: '',
+                rightValue: ''
+            }
+        ]
+    }
+    branches.elifs.push(newElif)
 }
 
 const removeElifBranch = (index: number) => {
-	branches.elifs.splice(index, 1)
-	// 重新编号 CASE
-	branches.elifs.forEach((branch, idx) => {
-		branch.label = `CASE ${idx + 2}`
-	})
-}
-
-const openVariablePicker = (conditionIndex: number, side: 'left' | 'right') => {
-	currentPickerContext.value = { conditionIndex, side }
-	showVariablePicker.value = true
-}
-
-const closeVariablePicker = () => {
-	showVariablePicker.value = false
-	currentPickerContext.value = {}
-}
-
-const handleVariableSelect = (variable: Variable) => {
-	const { conditionIndex, side } = currentPickerContext.value
-
-	if (conditionIndex !== undefined && side) {
-		// 更新对应条件的值
-		if (side === 'left') {
-			branches.if.conditions[conditionIndex].leftValue = variable.name
-		}
-	}
-}
-
-const handleTest = () => {
-	console.log('Testing condition branch...', branches)
+    branches.elifs.splice(index, 1)
+    // 重新编号 CASE
+    branches.elifs.forEach((branch, idx) => {
+        branch.label = `CASE ${idx + 2}`
+    })
 }
 
-const handleClose = () => {
-	emit('close')
-}
-
-const handleSave = () => {
-	const data = {
-		name: nodeName.value,
-		branches: {
-			if: branches.if,
-			elifs: branches.elifs,
-			else: branches.else
-		}
-	}
-	emit('save', data)
-	console.log('Saved:', data)
-}
-</script>
+// const openVariablePicker = (conditionIndex: number, side: 'left' | 'right') => {
+//     currentPickerContext.value = { conditionIndex, side }
+//     showVariablePicker.value = true
+// }
+
+// const closeVariablePicker = () => {
+//     showVariablePicker.value = false
+//     currentPickerContext.value = {}
+// }
+
+// const handleVariableSelect = (variable: Variable) => {
+//     const { conditionIndex, side } = currentPickerContext.value
+
+//     if (conditionIndex !== undefined && side) {
+//         // 更新对应条件的值
+//         if (side === 'left') {
+//             branches.if.conditions[conditionIndex].leftValue = variable.name
+//         }
+//     }
+// }
+
+// const handleTest = () => {
+//     console.log('Testing condition branch...', branches)
+// }
+
+// const handleClose = () => {
+//     emit('close')
+// }
+
+// const handleSave = () => {
+//     const data = {
+//         name: nodeName.value,
+//         branches: {
+//             if: branches.if,
+//             elifs: branches.elifs,
+//             else: branches.else
+//         }
+//     }
+//     emit('save', data)
+//     console.log('Saved:', data)
+// }
+</script>

+ 133 - 173
packages/workflow/src/components/elements/node-temp/ConditionNode.vue

@@ -11,208 +11,168 @@ import CanvasHandle from '../handles/CanvasHandle.vue'
 import { Icon } from '@repo/ui'
 
 interface Condition {
-	id: string
-	name: string
-	expression: string
-	priority?: number
+    id: string
+    name: string
+    expression: string
+    priority?: number
 }
 
 interface Props {
-	data: {
-		label?: string
-		description?: string
-		conditions?: Condition[]
-		defaultBranch?: string
-		[key: string]: any
-	}
-	selected?: boolean
+    data: {
+        label?: string
+        description?: string
+        conditions?: Condition[]
+        defaultBranch?: string
+        [key: string]: any
+    }
+    selected?: boolean
 }
 
 const props = withDefaults(defineProps<Props>(), {
-	selected: false
+    selected: false
 })
 
 // 如果没有条件,至少显示默认分支
 const branches =
-	props.data.conditions && props.data.conditions.length > 0
-		? props.data.conditions
-		: [{ id: 'default', name: '默认分支', expression: 'true' }]
+    props.data.conditions && props.data.conditions.length > 0
+        ? props.data.conditions
+        : [{ id: 'default', name: '默认分支', expression: 'true' }]
 
 // 计算每个分支 Handle 的位置
 const getBranchPosition = (index: number, total: number) => {
-	if (total === 1) return 50
-	const spacing = 70 / (total - 1) // 从 20% 到 90% 分布
-	return 15 + index * spacing
+    if (total === 1) return 50
+    const spacing = 70 / (total - 1) // 从 20% 到 90% 分布
+    return 15 + index * spacing
 }
 </script>
 
 <template>
-	<div
-		class="relative min-w-[260px] transition-all duration-300 ease-out hover:-translate-y-0.5"
-		:class="{ 'scale-105': selected }"
-	>
-		<!-- 节点主体 -->
-		<div
-			class="bg-gradient-to-br from-white to-orange-50 border-2 rounded-xl shadow-md transition-all duration-300 relative overflow-hidden"
-			:class="
-				selected
-					? 'border-orange-500 shadow-orange-200 shadow-lg'
-					: 'border-orange-300 hover:shadow-lg hover:shadow-orange-100'
-			"
-		>
-			<!-- 左侧装饰条 -->
-			<div
-				class="absolute left-0 top-0 bottom-0 w-1 bg-gradient-to-b from-orange-500 to-orange-400 rounded-l-xl"
-			></div>
-
-			<!-- 头部 -->
-			<div class="flex items-center gap-3 px-4 py-3 border-b border-orange-100">
-				<!-- 图标 - 菱形形状 -->
-				<div
-					class="relative flex-shrink-0 flex items-center justify-center w-10 h-10 bg-gradient-to-br from-orange-500 to-orange-400 rounded-lg shadow-md shadow-orange-200 rotate-45"
-				>
-					<div
-						class="absolute inset-0 bg-gradient-to-br from-white/30 to-transparent rounded-lg"
-					></div>
-					<div class="-rotate-45">
-						<Icon icon="lucide:git-branch" color="#ffffff" class="relative z-10" :size="20" />
-					</div>
-				</div>
-
-				<!-- 标题 -->
-				<div class="flex-1 min-w-0">
-					<div class="text-sm font-semibold text-gray-800 truncate">
-						{{ data.label || '条件分支' }}
-					</div>
-					<div v-if="data.description" class="text-xs text-gray-500 mt-0.5 truncate">
-						{{ data.description }}
-					</div>
-				</div>
-
-				<!-- 分支数量标签 -->
-				<div
-					class="flex-shrink-0 flex items-center gap-1 px-2 py-1 bg-orange-100 rounded text-xs font-medium text-orange-700"
-				>
-					<Icon icon="lucide:split" color="#ea580c" :size="12" />
-					<span>{{ branches.length }}</span>
-				</div>
-			</div>
-
-			<!-- 分支列表 -->
-			<div class="px-4 py-3 space-y-2 max-h-[200px] overflow-y-auto">
-				<div
-					v-for="(condition, index) in branches"
-					:key="condition.id"
-					class="flex items-start gap-2 p-2 rounded-lg bg-orange-50/50 hover:bg-orange-100/50 transition-colors group"
-				>
-					<!-- 分支序号 -->
-					<div
-						class="flex-shrink-0 flex items-center justify-center w-5 h-5 bg-orange-500 text-white text-xs font-bold rounded-full"
-					>
-						{{ index + 1 }}
-					</div>
-
-					<!-- 分支信息 -->
-					<div class="flex-1 min-w-0">
-						<div class="flex items-center gap-1.5 mb-1">
-							<span class="text-xs font-medium text-gray-700 truncate">
-								{{ condition.name }}
-							</span>
-							<Icon
-								v-if="condition.priority"
-								icon="lucide:star"
-								color="#f97316"
-								:size="12"
-								class="flex-shrink-0"
-							/>
-						</div>
-						<div class="text-xs text-gray-500 font-mono bg-white px-2 py-1 rounded truncate">
-							{{ condition.expression }}
-						</div>
-					</div>
-
-					<!-- 分支指示箭头 -->
-					<div class="flex-shrink-0 opacity-0 group-hover:opacity-100 transition-opacity">
-						<Icon icon="lucide:arrow-right" color="#f97316" :size="14" />
-					</div>
-				</div>
-
-				<!-- 默认分支提示 -->
-				<div
-					v-if="data.defaultBranch"
-					class="flex items-center gap-2 p-2 rounded-lg bg-gray-50 border border-dashed border-gray-300"
-				>
-					<Icon icon="lucide:shield-check" color="#94a3b8" :size="14" />
-					<span class="text-xs text-gray-500">
-						默认: <span class="font-medium text-gray-700">{{ data.defaultBranch }}</span>
-					</span>
-				</div>
-			</div>
-
-			<!-- 底部状态栏 -->
-			<div
-				class="flex items-center justify-between px-4 py-2 bg-orange-50/50 border-t border-orange-100"
-			>
-				<div class="flex items-center gap-1.5">
-					<Icon icon="lucide:zap" color="#f97316" :size="12" />
-					<span class="text-xs text-gray-500">条件判断</span>
-				</div>
-				<Icon
-					icon="lucide:settings"
-					color="#94a3b8"
-					:size="14"
-					class="cursor-pointer hover:text-orange-500 transition-colors"
-				/>
-			</div>
-		</div>
-
-		<!-- 输入连接点 -->
-		<CanvasHandle
-			handle-id="condition-node-input"
-			type="target"
-			:connections-count="1"
-			:position="Position.Left"
-		/>
-
-		<!-- 输出连接点 - 为每个分支创建一个 -->
-		<CanvasHandle
-			v-for="(condition, index) in branches"
-			:key="condition.id"
-			:id="`branch-${condition.id}`"
-			:handle-id="`condition-node-id-${index}`"
-			:connections-count="branches.length"
-			type="source"
-			:position="Position.Right"
-			:style="{
-				top: `${getBranchPosition(index, branches.length)}%`
-			}"
-		>
-			<!-- 多个分支标签提示 -->
-			<div
-				class="absolute left-5 top-1/2 -translate-y-1/2 px-2 py-0.5 bg-orange-500 text-white text-xs rounded whitespace-nowrap opacity-0 hover:opacity-100 transition-opacity pointer-events-none"
-			>
-				{{ condition.name }}
-			</div>
-		</CanvasHandle>
-	</div>
+    <div class="relative min-w-[260px] transition-all duration-300 ease-out hover:-translate-y-0.5"
+        :class="{ 'scale-105': selected }">
+        <!-- 节点主体 -->
+        <div class="bg-gradient-to-br from-white to-orange-50 border-2 rounded-xl shadow-md transition-all duration-300 relative overflow-hidden"
+            :class="selected
+                    ? 'border-orange-500 shadow-orange-200 shadow-lg'
+                    : 'border-orange-300 hover:shadow-lg hover:shadow-orange-100'
+                ">
+            <!-- 左侧装饰条 -->
+            <div class="absolute left-0 top-0 bottom-0 w-1 bg-gradient-to-b from-orange-500 to-orange-400 rounded-l-xl">
+            </div>
+
+            <!-- 头部 -->
+            <div class="flex items-center gap-3 px-4 py-3 border-b border-orange-100">
+                <!-- 图标 - 菱形形状 -->
+                <div
+                    class="relative flex-shrink-0 flex items-center justify-center w-10 h-10 bg-gradient-to-br from-orange-500 to-orange-400 rounded-lg shadow-md shadow-orange-200 rotate-45">
+                    <div class="absolute inset-0 bg-gradient-to-br from-white/30 to-transparent rounded-lg"></div>
+                    <div class="-rotate-45">
+                        <Icon icon="lucide:git-branch" color="#ffffff" class="relative z-10" :size="20" />
+                    </div>
+                </div>
+
+                <!-- 标题 -->
+                <div class="flex-1 min-w-0">
+                    <div class="text-sm font-semibold text-gray-800 truncate">
+                        {{ data.label || '条件分支' }}
+                    </div>
+                    <div v-if="data.description" class="text-xs text-gray-500 mt-0.5 truncate">
+                        {{ data.description }}
+                    </div>
+                </div>
+
+                <!-- 分支数量标签 -->
+                <div
+                    class="flex-shrink-0 flex items-center gap-1 px-2 py-1 bg-orange-100 rounded text-xs font-medium text-orange-700">
+                    <Icon icon="lucide:split" color="#ea580c" :size="12" />
+                    <span>{{ branches.length }}</span>
+                </div>
+            </div>
+
+            <!-- 分支列表 -->
+            <div class="px-4 py-3 space-y-2 max-h-[200px] overflow-y-auto">
+                <div v-for="(condition, index) in branches" :key="condition.id"
+                    class="flex items-start gap-2 p-2 rounded-lg bg-orange-50/50 hover:bg-orange-100/50 transition-colors group">
+                    <!-- 分支序号 -->
+                    <div
+                        class="flex-shrink-0 flex items-center justify-center w-5 h-5 bg-orange-500 text-white text-xs font-bold rounded-full">
+                        {{ index + 1 }}
+                    </div>
+
+                    <!-- 分支信息 -->
+                    <div class="flex-1 min-w-0">
+                        <div class="flex items-center gap-1.5 mb-1">
+                            <span class="text-xs font-medium text-gray-700 truncate">
+                                {{ condition.name }}
+                            </span>
+                            <Icon v-if="condition.priority" icon="lucide:star" color="#f97316" :size="12"
+                                class="flex-shrink-0" />
+                        </div>
+                        <div class="text-xs text-gray-500 font-mono bg-white px-2 py-1 rounded truncate">
+                            {{ condition.expression }}
+                        </div>
+                    </div>
+
+                    <!-- 分支指示箭头 -->
+                    <div class="flex-shrink-0 opacity-0 group-hover:opacity-100 transition-opacity">
+                        <Icon icon="lucide:arrow-right" color="#f97316" :size="14" />
+                    </div>
+                </div>
+
+                <!-- 默认分支提示 -->
+                <div v-if="data.defaultBranch"
+                    class="flex items-center gap-2 p-2 rounded-lg bg-gray-50 border border-dashed border-gray-300">
+                    <Icon icon="lucide:shield-check" color="#94a3b8" :size="14" />
+                    <span class="text-xs text-gray-500">
+                        默认: <span class="font-medium text-gray-700">{{ data.defaultBranch }}</span>
+                    </span>
+                </div>
+            </div>
+
+            <!-- 底部状态栏 -->
+            <div class="flex items-center justify-between px-4 py-2 bg-orange-50/50 border-t border-orange-100">
+                <div class="flex items-center gap-1.5">
+                    <Icon icon="lucide:zap" color="#f97316" :size="12" />
+                    <span class="text-xs text-gray-500">条件判断</span>
+                </div>
+                <Icon icon="lucide:settings" color="#94a3b8" :size="14"
+                    class="cursor-pointer hover:text-orange-500 transition-colors" />
+            </div>
+        </div>
+
+        <!-- 输入连接点 -->
+        <CanvasHandle handle-id="condition-node-input" type="target" :connections-count="1" :position="Position.Left" />
+
+        <!-- 输出连接点 - 为每个分支创建一个 -->
+        <CanvasHandle v-for="(condition, index) in branches" :key="condition.id" :id="`branch-${condition.id}`"
+            :handle-id="`condition-node-id-${index}`" :connections-count="branches.length" type="source"
+            :position="Position.Right" :style="{
+                top: `${getBranchPosition(index, branches.length)}%`
+            }">
+            <!-- 多个分支标签提示 -->
+            <div
+                class="absolute left-5 top-1/2 -translate-y-1/2 px-2 py-0.5 bg-orange-500 text-white text-xs rounded whitespace-nowrap opacity-0 hover:opacity-100 transition-opacity pointer-events-none">
+                {{ condition.name }}
+            </div>
+        </CanvasHandle>
+    </div>
 </template>
 
 <style scoped>
 .overflow-y-auto::-webkit-scrollbar {
-	width: 4px;
+    width: 4px;
 }
 
 .overflow-y-auto::-webkit-scrollbar-track {
-	background: #fed7aa;
-	border-radius: 4px;
+    background: #fed7aa;
+    border-radius: 4px;
 }
 
 .overflow-y-auto::-webkit-scrollbar-thumb {
-	background: #f97316;
-	border-radius: 4px;
+    background: #f97316;
+    border-radius: 4px;
 }
 
 .overflow-y-auto::-webkit-scrollbar-thumb:hover {
-	background: #ea580c;
+    background: #ea580c;
 }
 </style>