第一次提交

This commit is contained in:
rjb
2026-01-19 00:09:36 +08:00
parent de4b5059e9
commit 6674060f2f
191 changed files with 40940 additions and 0 deletions

View File

@@ -0,0 +1,493 @@
/**
* 自定义节点类型定义
*/
import { defineComponent, h } from 'vue'
import { Handle, Position } from '@vue-flow/core'
// 开始节点(只有输出)
export const StartNode = defineComponent({
name: 'StartNode',
props: {
data: {
type: Object,
default: () => ({})
}
},
setup(props, { attrs }) {
const nodeClass = (attrs.class as string) || ''
const executionClass = props.data?.executionClass || ''
const allClasses = ['custom-node', 'start-node', nodeClass, executionClass].filter(Boolean).join(' ')
return () => {
// 根据执行状态动态设置样式
const isExecuting = allClasses.includes('executing')
const isExecuted = allClasses.includes('executed')
const isFailed = allClasses.includes('failed')
const baseStyle: any = {
padding: '8px 16px',
borderRadius: '6px',
background: '#67c23a',
color: 'white',
textAlign: 'center',
minWidth: '100px',
fontSize: '13px',
fontWeight: '500',
boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
position: 'relative',
border: '2px solid transparent',
transition: 'all 0.3s ease-in-out'
}
// 执行状态样式(覆盖基础样式)
if (isExecuting) {
baseStyle.border = '3px solid #409eff'
baseStyle.boxShadow = '0 0 0 3px rgba(64, 158, 255, 0.5), 0 0 20px rgba(64, 158, 255, 0.8)'
baseStyle.transform = 'scale(1.05)'
} else if (isExecuted) {
baseStyle.border = '3px solid #67c23a'
baseStyle.boxShadow = '0 0 0 3px rgba(103, 194, 58, 0.5), 0 2px 8px rgba(103, 194, 58, 0.3)'
} else if (isFailed) {
baseStyle.border = '3px solid #f56c6c'
baseStyle.boxShadow = '0 0 0 3px rgba(245, 108, 108, 0.5), 0 2px 8px rgba(245, 108, 108, 0.3)'
}
const errorMessage = props.data?.errorMessage
return h('div', {
class: allClasses,
style: baseStyle,
title: isFailed && errorMessage ? errorMessage : undefined
}, [
h(Handle, {
type: 'source',
position: Position.Bottom,
id: 'bottom',
style: {
background: '#67c23a',
width: '8px',
height: '8px'
}
}),
h(Handle, {
type: 'source',
position: Position.Right,
id: 'right',
style: {
background: '#67c23a',
width: '8px',
height: '8px'
}
}),
h('div', {
style: {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: '4px'
}
}, [
props.data.label || '开始',
isFailed ? h('span', {
style: {
fontSize: '12px',
marginLeft: '4px'
}
}, '❌') : null
])
])
}
}
})
// LLM节点有输入和输出
export const LLMNode = defineComponent({
name: 'LLMNode',
props: {
data: {
type: Object,
default: () => ({})
}
},
setup(props, { attrs }) {
const nodeClass = (attrs.class as string) || ''
const executionClass = props.data?.executionClass || ''
const allClasses = ['custom-node', 'llm-node', nodeClass, executionClass].filter(Boolean).join(' ')
return () => {
// 根据执行状态动态设置样式
const isExecuting = allClasses.includes('executing')
const isExecuted = allClasses.includes('executed')
const isFailed = allClasses.includes('failed')
const baseStyle: any = {
padding: '8px 16px',
borderRadius: '6px',
background: '#409eff',
color: 'white',
textAlign: 'center',
minWidth: '100px',
fontSize: '13px',
fontWeight: '500',
boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
position: 'relative',
border: '2px solid transparent',
transition: 'all 0.3s ease-in-out'
}
// 执行状态样式(覆盖基础样式)
if (isExecuting) {
baseStyle.border = '3px solid #409eff'
baseStyle.boxShadow = '0 0 0 3px rgba(64, 158, 255, 0.5), 0 0 20px rgba(64, 158, 255, 0.8)'
baseStyle.transform = 'scale(1.05)'
baseStyle.animation = 'pulse-blue 1.5s infinite'
} else if (isExecuted) {
baseStyle.border = '3px solid #67c23a'
baseStyle.boxShadow = '0 0 0 3px rgba(103, 194, 58, 0.5), 0 2px 8px rgba(103, 194, 58, 0.3)'
} else if (isFailed) {
baseStyle.border = '3px solid #f56c6c'
baseStyle.boxShadow = '0 0 0 3px rgba(245, 108, 108, 0.5), 0 2px 8px rgba(245, 108, 108, 0.3)'
}
return h('div', {
class: allClasses,
style: baseStyle
}, [
h(Handle, {
type: 'target',
position: Position.Top,
id: 'top',
style: {
background: '#409eff',
width: '8px',
height: '8px'
}
}),
h(Handle, {
type: 'target',
position: Position.Left,
id: 'left',
style: {
background: '#409eff',
width: '8px',
height: '8px'
}
}),
h('div', {
style: {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: '4px'
}
}, [
props.data.label || 'LLM',
isFailed ? h('span', {
style: {
fontSize: '12px',
marginLeft: '4px'
}
}, '❌') : null
]),
h(Handle, {
type: 'source',
position: Position.Bottom,
id: 'bottom',
style: {
background: '#409eff',
width: '8px',
height: '8px'
}
}),
h(Handle, {
type: 'source',
position: Position.Right,
id: 'right',
style: {
background: '#409eff',
width: '8px',
height: '8px'
}
})
])
}
}
})
// 条件节点有输入和两个输出true/false
export const ConditionNode = defineComponent({
name: 'ConditionNode',
props: {
data: {
type: Object,
default: () => ({})
}
},
setup(props, { attrs }) {
const nodeClass = (attrs.class as string) || ''
const executionClass = props.data?.executionClass || ''
const allClasses = ['custom-node', 'condition-node', nodeClass, executionClass].filter(Boolean).join(' ')
return () => {
const isExecuting = allClasses.includes('executing')
const isExecuted = allClasses.includes('executed')
const isFailed = allClasses.includes('failed')
const baseStyle: any = {
padding: '8px 16px',
borderRadius: '6px',
background: '#e6a23c',
color: 'white',
textAlign: 'center',
minWidth: '100px',
fontSize: '13px',
fontWeight: '500',
boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
position: 'relative',
border: '2px solid transparent',
transition: 'all 0.3s ease-in-out'
}
if (isExecuting) {
baseStyle.border = '3px solid #409eff'
baseStyle.boxShadow = '0 0 0 3px rgba(64, 158, 255, 0.5), 0 0 20px rgba(64, 158, 255, 0.8)'
baseStyle.transform = 'scale(1.05)'
baseStyle.animation = 'pulse-blue 1.5s infinite'
} else if (isExecuted) {
baseStyle.border = '3px solid #67c23a'
baseStyle.boxShadow = '0 0 0 3px rgba(103, 194, 58, 0.5), 0 2px 8px rgba(103, 194, 58, 0.3)'
} else if (isFailed) {
baseStyle.border = '3px solid #f56c6c'
baseStyle.boxShadow = '0 0 0 3px rgba(245, 108, 108, 0.5), 0 2px 8px rgba(245, 108, 108, 0.3)'
}
return h('div', {
class: allClasses,
style: baseStyle
}, [
h(Handle, {
type: 'target',
position: Position.Top,
id: 'top',
style: {
background: '#e6a23c',
width: '8px',
height: '8px'
}
}),
h(Handle, {
type: 'target',
position: Position.Left,
id: 'left',
style: {
background: '#e6a23c',
width: '8px',
height: '8px'
}
}),
props.data.label || '条件',
h(Handle, {
type: 'source',
position: Position.Bottom,
id: 'true',
style: {
background: '#67c23a',
width: '8px',
height: '8px',
left: '30%'
}
}),
h(Handle, {
type: 'source',
position: Position.Bottom,
id: 'false',
style: {
background: '#f56c6c',
width: '8px',
height: '8px',
right: '30%'
}
}),
h(Handle, {
type: 'source',
position: Position.Right,
id: 'right',
style: {
background: '#e6a23c',
width: '8px',
height: '8px'
}
})
])
}
}
})
// 结束节点(只有输入)
export const EndNode = defineComponent({
name: 'EndNode',
props: {
data: {
type: Object,
default: () => ({})
}
},
setup(props, { attrs }) {
const nodeClass = (attrs.class as string) || ''
const executionClass = props.data?.executionClass || ''
const allClasses = ['custom-node', 'end-node', nodeClass, executionClass].filter(Boolean).join(' ')
return () => {
const isExecuting = allClasses.includes('executing')
const isExecuted = allClasses.includes('executed')
const isFailed = allClasses.includes('failed')
const baseStyle: any = {
padding: '8px 16px',
borderRadius: '6px',
background: '#f56c6c',
color: 'white',
textAlign: 'center',
minWidth: '100px',
fontSize: '13px',
fontWeight: '500',
boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
position: 'relative',
border: '2px solid transparent',
transition: 'all 0.3s ease-in-out'
}
if (isExecuting) {
baseStyle.border = '3px solid #409eff'
baseStyle.boxShadow = '0 0 0 3px rgba(64, 158, 255, 0.5), 0 0 20px rgba(64, 158, 255, 0.8)'
baseStyle.transform = 'scale(1.05)'
baseStyle.animation = 'pulse-blue 1.5s infinite'
} else if (isExecuted) {
baseStyle.border = '3px solid #67c23a'
baseStyle.boxShadow = '0 0 0 3px rgba(103, 194, 58, 0.5), 0 2px 8px rgba(103, 194, 58, 0.3)'
} else if (isFailed) {
baseStyle.border = '3px solid #f56c6c'
baseStyle.boxShadow = '0 0 0 3px rgba(245, 108, 108, 0.5), 0 2px 8px rgba(245, 108, 108, 0.3)'
}
return h('div', {
class: allClasses,
style: baseStyle
}, [
h(Handle, {
type: 'target',
position: Position.Top,
id: 'top',
style: {
background: '#f56c6c',
width: '8px',
height: '8px'
}
}),
h(Handle, {
type: 'target',
position: Position.Left,
id: 'left',
style: {
background: '#f56c6c',
width: '8px',
height: '8px'
}
}),
props.data.label || '结束'
])
}
}
})
// 默认节点(有输入和输出)
export const DefaultNode = defineComponent({
name: 'DefaultNode',
props: {
data: {
type: Object,
default: () => ({})
}
},
setup(props, { attrs }) {
const nodeClass = (attrs.class as string) || ''
const executionClass = props.data?.executionClass || ''
const allClasses = ['custom-node', 'default-node', nodeClass, executionClass].filter(Boolean).join(' ')
return () => {
const isExecuting = allClasses.includes('executing')
const isExecuted = allClasses.includes('executed')
const isFailed = allClasses.includes('failed')
const baseStyle: any = {
padding: '8px 16px',
borderRadius: '6px',
background: '#909399',
color: 'white',
textAlign: 'center',
minWidth: '100px',
fontSize: '13px',
fontWeight: '500',
boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
position: 'relative',
border: '2px solid transparent',
transition: 'all 0.3s ease-in-out'
}
if (isExecuting) {
baseStyle.border = '3px solid #409eff'
baseStyle.boxShadow = '0 0 0 3px rgba(64, 158, 255, 0.5), 0 0 20px rgba(64, 158, 255, 0.8)'
baseStyle.transform = 'scale(1.05)'
baseStyle.animation = 'pulse-blue 1.5s infinite'
} else if (isExecuted) {
baseStyle.border = '3px solid #67c23a'
baseStyle.boxShadow = '0 0 0 3px rgba(103, 194, 58, 0.5), 0 2px 8px rgba(103, 194, 58, 0.3)'
} else if (isFailed) {
baseStyle.border = '3px solid #f56c6c'
baseStyle.boxShadow = '0 0 0 3px rgba(245, 108, 108, 0.5), 0 2px 8px rgba(245, 108, 108, 0.3)'
}
return h('div', {
class: allClasses,
style: baseStyle
}, [
h(Handle, {
type: 'target',
position: Position.Top,
id: 'top',
style: {
background: '#909399',
width: '8px',
height: '8px'
}
}),
h(Handle, {
type: 'target',
position: Position.Left,
id: 'left',
style: {
background: '#909399',
width: '8px',
height: '8px'
}
}),
props.data.label || '节点',
h(Handle, {
type: 'source',
position: Position.Bottom,
id: 'bottom',
style: {
background: '#909399',
width: '8px',
height: '8px'
}
}),
h(Handle, {
type: 'source',
position: Position.Right,
id: 'right',
style: {
background: '#909399',
width: '8px',
height: '8px'
}
})
])
}
}
})

File diff suppressed because it is too large Load Diff