ConditionBuilder.vue 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. <template>
  2. <div class="space-y-2">
  3. <!-- 条件行 -->
  4. <div
  5. v-for="(condition, index) in conditions"
  6. :key="condition.id"
  7. class="flex items-center"
  8. >
  9. <!-- 左侧变量选择 -->
  10. <div class="relative w-3/4">
  11. <ElSelect placeholder="选择变量" v-model="condition.leftValue">
  12. <el-option></el-option>
  13. </ElSelect>
  14. <!-- <ElButton-->
  15. <!-- @click="openVariablePicker(index, 'left')"-->
  16. <!-- 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"-->
  17. <!-- >-->
  18. <!-- <span v-if="condition.leftValue" class="flex items-center gap-1">-->
  19. <!-- <Icon icon="lucide:at-sign" :height="14" :width="14" class="text-red-500" />-->
  20. <!-- <span class="text-red-600">{{ condition.leftValue }}</span>-->
  21. <!-- </span>-->
  22. <!-- <span v-else class="text-gray-400">选择变量</span>-->
  23. <!-- <Icon icon="lucide:chevron-down" :height="14" :width="14" class="text-gray-400" />-->
  24. <!-- </ElButton>-->
  25. </div>
  26. <!-- 运算符选择 -->
  27. <ElSelect
  28. v-model="condition.operator"
  29. @change="handleConditionChange"
  30. class="w-[60px] px-3 py-2 text-sm border border-gray-200 rounded-lg bg-white ">
  31. <el-option value="equals">等于</el-option>
  32. <el-option value="notEquals">不等于</el-option>
  33. <el-option value="contains">包含</el-option>
  34. <el-option value="notContains">不包含</el-option>
  35. <el-option value="greaterThan">大于</el-option>
  36. <el-option value="lessThan">小于</el-option>
  37. <el-option value="greaterOrEqual">大于等于</el-option>
  38. <el-option value="lessOrEqual">小于等于</el-option>
  39. </ElSelect>
  40. <!-- 右侧值输入 -->
  41. <div class="relative w-3/4">
  42. <ElInput
  43. v-model="condition.rightValue"
  44. type="text"
  45. placeholder="输入值"
  46. @input="handleConditionChange"
  47. 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"
  48. />
  49. </div>
  50. <!-- 删除按钮 -->
  51. <ElButton
  52. v-if="conditions.length > 1"
  53. @click="removeCondition(index)"
  54. class="p-2 w-1/4 opacity-0 hover:opacity-100 hover:bg-red-50 rounded transition-all"
  55. title="删除条件">
  56. <Icon icon="lucide:trash-2" :height="16" :width="16" class="text-red-500" />
  57. </ElButton>
  58. </div>
  59. <!-- AND 连接符 -->
  60. <!-- <div v-if="showAndButton" class="flex items-center gap-2 pl-3">-->
  61. <!-- <div class="flex items-center gap-2 px-3 py-1.5 bg-blue-50 text-blue-600 text-xs font-medium rounded">-->
  62. <!-- <Icon icon="lucide:link" :height="12" :width="12" />-->
  63. <!-- AND-->
  64. <!-- </div>-->
  65. <!-- </div>-->
  66. <!-- 添加条件按钮 -->
  67. <div class="text-center">
  68. <ElButton
  69. @click="addCondition"
  70. class="flex items-center gap-2 px-3 py-2 text-sm text-blue-600 hover:bg-blue-50 rounded-lg transition-colors"
  71. >
  72. <Icon icon="lucide:plus" :height="16" :width="16" />
  73. 添加条件
  74. </ElButton>
  75. </div>
  76. </div>
  77. </template>
  78. <script setup lang="ts">
  79. import { ref, computed, watch } from 'vue'
  80. import { Icon } from '@iconify/vue'
  81. interface Condition {
  82. id: string
  83. leftValue: string
  84. operator: string
  85. rightValue: string
  86. }
  87. interface Props {
  88. modelValue: Condition[]
  89. }
  90. interface Emits {
  91. (e: 'update:modelValue', value: Condition[]): void
  92. (e: 'openVariablePicker', index: number, side: 'left' | 'right'): void
  93. }
  94. const props = defineProps<Props>()
  95. const emit = defineEmits<Emits>()
  96. const conditions = ref<Condition[]>(props.modelValue || [
  97. {
  98. id: `condition_${Date.now()}`,
  99. leftValue: '',
  100. operator: 'equals',
  101. rightValue: ''
  102. }
  103. ])
  104. const showAndButton = computed(() => conditions.value.length > 1)
  105. watch(
  106. () => props.modelValue,
  107. (newVal) => {
  108. if (newVal && newVal.length > 0) {
  109. conditions.value = newVal
  110. }
  111. },
  112. { deep: true }
  113. )
  114. const addCondition = () => {
  115. conditions.value.push({
  116. id: `condition_${Date.now()}`,
  117. leftValue: '',
  118. operator: 'equals',
  119. rightValue: ''
  120. })
  121. handleConditionChange()
  122. }
  123. const removeCondition = (index: number) => {
  124. conditions.value.splice(index, 1)
  125. handleConditionChange()
  126. }
  127. const handleConditionChange = () => {
  128. emit('update:modelValue', conditions.value)
  129. }
  130. const openVariablePicker = (index: number, side: 'left' | 'right') => {
  131. emit('openVariablePicker', index, side)
  132. }
  133. </script>