index.vue 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. <script setup lang="ts">
  2. import type { NodeVar } from '@/types/var'
  3. import type { Ref } from 'vue'
  4. import { computed, inject } from 'vue'
  5. import { nodeMap } from '@/nodes'
  6. import { Icon } from '@repo/ui'
  7. const props = defineProps<{
  8. label: string
  9. nodeVars?: NodeVar[]
  10. }>()
  11. const injectedNodeVars = inject<Ref<NodeVar[]>>('nodeVars')
  12. const valueInfo = computed(() => {
  13. // 根据#{xxx.var}解析变量
  14. // 解析格式 #{env.xxx} 或 #{nodeId.xxx}
  15. if (!props.label?.startsWith('#{') || !props.label?.endsWith('}')) {
  16. return {
  17. type: 'env',
  18. name: props.label || '',
  19. value: props.label || ''
  20. }
  21. }
  22. const expr = props.label.slice(2, -1) // 去掉 #{ 和 }
  23. const [prefix, ...rest] = expr.split('.')
  24. const varName = rest.join('.')
  25. if (!prefix || !varName) {
  26. return {
  27. type: 'env',
  28. name: props.label || '',
  29. value: props.label || ''
  30. }
  31. }
  32. if (prefix === 'env') {
  33. // 环境变量
  34. return {
  35. type: 'env',
  36. name: 'env',
  37. value: varName
  38. }
  39. } else if (prefix.startsWith('sys')) {
  40. // 系统变量
  41. return {
  42. type: 'sys',
  43. name: 'sys',
  44. value: varName
  45. }
  46. } else {
  47. // 节点变量,需要解析节点类型名称
  48. const availableNodeVars = props.nodeVars ?? injectedNodeVars?.value
  49. if (availableNodeVars?.length) {
  50. const node = availableNodeVars.find((item) => item.id === prefix)
  51. return {
  52. type: 'node',
  53. icon: nodeMap?.[node?.type!]?.icon,
  54. nodeType: node?.type || '',
  55. nodeName: node?.name || '',
  56. name: varName,
  57. value: varName
  58. }
  59. } else {
  60. return {
  61. type: 'node',
  62. nodeType: '',
  63. nodeName: '',
  64. name: varName,
  65. value: varName
  66. }
  67. }
  68. }
  69. })
  70. </script>
  71. <template>
  72. <div class="var-label" :key="valueInfo.type + valueInfo.value">
  73. <div v-if="valueInfo.type === 'env'" class="flex gap-1 items-center truncate">
  74. <span class="var-select__item-prefix env text-6px">
  75. <span>ENV</span>
  76. </span>
  77. <span class="text-gray-600">{{ valueInfo.value }}</span>
  78. </div>
  79. <div v-else-if="valueInfo.type === 'sys'" class="flex gap-1 items-center truncate">
  80. <span class="var-select__item-prefix sys text-6px">
  81. <span>SYS</span>
  82. </span>
  83. <span class="text-gray-600">{{ valueInfo.value }}</span>
  84. </div>
  85. <div
  86. v-else
  87. class="flex gap-1 items-center truncate"
  88. :title="valueInfo.nodeName + ' / ' + valueInfo.value"
  89. >
  90. <span
  91. class="var-select__item-prefix env text-10px"
  92. :style="{ background: nodeMap[valueInfo?.nodeType ?? '']?.iconColor ?? '' }"
  93. >
  94. <Icon v-if="valueInfo?.icon" :icon="valueInfo?.icon!" :size="18" />
  95. <span v-else class="text-6px">VAR</span>
  96. </span>
  97. {{ valueInfo.nodeName }}
  98. {{ valueInfo.nodeName ? '/' : '' }}
  99. <span class="text-gray-600">{{ valueInfo.value }}</span>
  100. <Icon icon="lucide:circle-alert" color="red" />
  101. </div>
  102. </div>
  103. </template>
  104. <style lang="less" scoped>
  105. .var-label {
  106. --el-tag-font-size: 12px;
  107. --el-tag-border-radius: 4px;
  108. --el-tag-bg-color: #f2f2f5;
  109. background-color: var(--el-tag-bg-color);
  110. vertical-align: middle;
  111. height: 24px;
  112. font-size: var(--el-tag-font-size);
  113. border-radius: var(--el-tag-border-radius);
  114. box-sizing: border-box;
  115. white-space: nowrap;
  116. border-width: 1px;
  117. justify-content: center;
  118. align-items: center;
  119. padding: 0 4px;
  120. line-height: 1;
  121. display: inline-flex;
  122. }
  123. .var-select__item-prefix {
  124. display: inline-flex;
  125. align-items: center;
  126. justify-content: center;
  127. width: 20px;
  128. height: 20px;
  129. border-radius: 6px;
  130. color: #fff;
  131. flex-shrink: 0;
  132. &.env {
  133. background: #6366f1;
  134. }
  135. &.sys {
  136. background: #f97316;
  137. }
  138. }
  139. .node-name {
  140. max-width: 120px;
  141. overflow: hidden;
  142. text-overflow: ellipsis;
  143. white-space: nowrap;
  144. }
  145. </style>