/
githubmirror
/
ChatDev
Обзор
Документация
Войти
/
githubmirror
/
ChatDev
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
frontend/src/components/WorkflowNode.vue
192 строки
5 KB
laansdole
feat: move enable help tooltips default true to setting
10 фев 2026, 19:12
10 фев 2026, 19:12
5e27466
Код
Авторство
О чём код?
<script setup> import { computed, ref, onMounted, onUnmounted, watch } from 'vue' import { Handle, Position } from '@vue-flow/core' import { getNodeStyles } from '../utils/colorUtils.js' import { spriteFetcher } from '../utils/spriteFetcher.js' import RichTooltip from './RichTooltip.vue' import { getNodeHelp } from '../utils/helpContent.js' import { configStore } from '../utils/configStore.js' const props = defineProps({ id: { type: String, required: true, }, data: { type: Object, required: true, }, isActive: { type: Boolean, default: false, }, sprite: { type: String, default: '', }, }) // Expose hover events so parent can highlight edges defineEmits(['hover', 'leave']) // Walking animation state const walkingFrame = ref(2) // Start with frame 2 let walkingInterval = null // Compute properties for reactivity const nodeType = computed(() => props.data?.type || 'unknown') const nodeId = computed(() => props.data?.id || props.id) const nodeDescription = computed(() => props.data?.description || '') const isActive = computed(() => props.isActive) const dynamicStyles = computed(() => getNodeStyles(nodeType.value)) const nodeHelpContent = computed(() => getNodeHelp(nodeType.value)) const shouldShowTooltip = computed(() => configStore.ENABLE_HELP_TOOLTIPS && nodeHelpContent.value) // Compute the current sprite path based on active state and walking frame const currentSprite = computed(() => { if (!props.sprite) return '' if (isActive.value) { // When active, use walking frames (2 and 3) return spriteFetcher.fetchSprite(nodeId.value, 'D', walkingFrame.value) } else { // When not active, use the original frame (1) return props.sprite } }) // Start/stop walking animation based on active state const startWalking = () => { if (walkingInterval) return walkingInterval = setInterval(() => { walkingFrame.value = walkingFrame.value === 2 ? 3 : 2 }, 500) // Alternate every 500ms } const stopWalking = () => { if (walkingInterval) { clearInterval(walkingInterval) walkingInterval = null } walkingFrame.value = 2 // Reset to frame 2 } // Watch for active state changes watch(isActive, (newActive) => { if (newActive) { startWalking() } else { stopWalking() } }) // Cleanup on unmount onUnmounted(() => { stopWalking() }) </script> <template> <RichTooltip v-if="shouldShowTooltip" :content="nodeHelpContent" placement="top"> <div class="workflow-node-container"> <div v-if="props.sprite" class="workflow-node-sprite"> <img :src="currentSprite" :alt="`${nodeId} sprite`" class="node-sprite-image" /> </div> <div class="workflow-node" :class="{ 'workflow-node-active': isActive }" :data-type="nodeType" :style="dynamicStyles" @mouseenter="$emit('hover', nodeId)" @mouseleave="$emit('leave', nodeId)" > <div class="workflow-node-header"> <span class="workflow-node-type">{{ nodeType }}</span> <span class="workflow-node-id">{{ nodeId }}</span> </div> <div v-if="nodeDescription" class="workflow-node-description"> {{ nodeDescription }} </div> <Handle id="source" type="source" :position="Position.Right" class="workflow-node-handle" /> <Handle id="target" type="target" :position="Position.Left" class="workflow-node-handle" /> </div> </div> </RichTooltip> <div v-else class="workflow-node-container"> <div v-if="props.sprite" class="workflow-node-sprite"> <img :src="currentSprite" :alt="`${nodeId} sprite`" class="node-sprite-image" /> </div> <div class="workflow-node" :class="{ 'workflow-node-active': isActive }" :data-type="nodeType" :style="dynamicStyles" @mouseenter="$emit('hover', nodeId)" @mouseleave="$emit('leave', nodeId)" > <div class="workflow-node-header"> <span class="workflow-node-type">{{ nodeType }}</span> <span class="workflow-node-id">{{ nodeId }}</span> </div> <div v-if="nodeDescription" class="workflow-node-description"> {{ nodeDescription }} </div> <Handle id="source" type="source" :position="Position.Right" class="workflow-node-handle" /> <Handle id="target" type="target" :position="Position.Left" class="workflow-node-handle" /> </div> </div> </template> <style scoped> .workflow-node-container { position: relative; } .workflow-node-description { /* Ensure long descriptions wrap instead of overflowing */ white-space: normal; word-break: break-word; overflow-wrap: anywhere; max-width: 200px; display: block; } .workflow-node-sprite { position: absolute; top: -25px; left: 50%; transform: translateX(-50%); z-index: 10; } .node-sprite-image { width: 32px; height: 40px; object-fit: contain; } </style>