refactor(web): 优化节点展现
This commit is contained in:
@@ -104,14 +104,13 @@ export function inputsFormColumns(
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
export function outputsFormColumns(editable: boolean = false, required: boolean = false, preload?: any): Schema[] {
|
export function outputsFormColumns(editable: boolean = false, required: boolean = false): Schema[] {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
disabled: !editable,
|
disabled: !editable,
|
||||||
type: 'input-kvs',
|
type: 'input-kvs',
|
||||||
name: 'outputs',
|
name: 'outputs',
|
||||||
label: '输出变量',
|
label: '输出变量',
|
||||||
value: preload,
|
|
||||||
addButtonText: '新增输出',
|
addButtonText: '新增输出',
|
||||||
draggable: false,
|
draggable: false,
|
||||||
keyItem: {
|
keyItem: {
|
||||||
@@ -155,7 +154,7 @@ type AmisNodeProps = {
|
|||||||
nodeProps: NodeProps
|
nodeProps: NodeProps
|
||||||
defaultNodeName: String
|
defaultNodeName: String
|
||||||
defaultNodeDescription?: String
|
defaultNodeDescription?: String
|
||||||
extraNodeDescription?: (nodeData: any) => JSX.Element
|
extraNodeDescription?: JSX.Element
|
||||||
handler: JSX.Element
|
handler: JSX.Element
|
||||||
columnSchema?: () => Schema[]
|
columnSchema?: () => Schema[]
|
||||||
}
|
}
|
||||||
@@ -338,7 +337,7 @@ const AmisNode: (props: AmisNodeProps) => JSX.Element = ({
|
|||||||
>
|
>
|
||||||
<div className="card-description p-2 text-secondary text-sm">
|
<div className="card-description p-2 text-secondary text-sm">
|
||||||
{nodeDescription}
|
{nodeDescription}
|
||||||
{extraNodeDescription?.(nodeData)}
|
{extraNodeDescription}
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
{handler}
|
{handler}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type {NodeProps} from '@xyflow/react'
|
import type {NodeProps} from '@xyflow/react'
|
||||||
import React from 'react'
|
import React, {useCallback, useEffect} from 'react'
|
||||||
import {useContextStore} from '../store/ContextStore.ts'
|
import {useContextStore} from '../store/ContextStore.ts'
|
||||||
import {useDataStore} from '../store/DataStore.ts'
|
import {useDataStore} from '../store/DataStore.ts'
|
||||||
import {useFlowStore} from '../store/FlowStore.ts'
|
import {useFlowStore} from '../store/FlowStore.ts'
|
||||||
@@ -7,53 +7,68 @@ import AmisNode, {inputsFormColumns, NormalNodeHandler, outputsFormColumns} from
|
|||||||
|
|
||||||
const CodeNode = (props: NodeProps) => {
|
const CodeNode = (props: NodeProps) => {
|
||||||
const {getNodes, getEdges} = useFlowStore()
|
const {getNodes, getEdges} = useFlowStore()
|
||||||
const {getData} = useDataStore()
|
const {getData, mergeDataById} = useDataStore()
|
||||||
const {getInputSchema} = useContextStore()
|
const {getInputSchema} = useContextStore()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
mergeDataById(
|
||||||
|
props.id,
|
||||||
|
{
|
||||||
|
outputs: {
|
||||||
|
result: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}, [props.id])
|
||||||
|
|
||||||
|
const columnsSchema = useCallback(() => [
|
||||||
|
...inputsFormColumns(props.id, getInputSchema(), getNodes(), getEdges(), getData()),
|
||||||
|
{
|
||||||
|
type: 'divider',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
name: 'type',
|
||||||
|
label: '代码类型',
|
||||||
|
required: true,
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
value: 'javascript',
|
||||||
|
label: 'JavaScript',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'python',
|
||||||
|
label: 'Python',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'lua',
|
||||||
|
label: 'Lua',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'editor',
|
||||||
|
required: true,
|
||||||
|
label: '代码内容',
|
||||||
|
name: 'content',
|
||||||
|
language: '${type}',
|
||||||
|
options: {
|
||||||
|
wordWrap: 'bounded',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'divider',
|
||||||
|
},
|
||||||
|
...outputsFormColumns(true, true),
|
||||||
|
], [props.id])
|
||||||
return (
|
return (
|
||||||
<AmisNode
|
<AmisNode
|
||||||
nodeProps={props}
|
nodeProps={props}
|
||||||
defaultNodeName="代码执行"
|
defaultNodeName="代码执行"
|
||||||
defaultNodeDescription="执行自定义的处理代码"
|
defaultNodeDescription="执行自定义的处理代码"
|
||||||
columnSchema={() => [
|
columnSchema={columnsSchema}
|
||||||
...inputsFormColumns(props.id, getInputSchema(), getNodes(), getEdges(), getData()),
|
|
||||||
{
|
|
||||||
type: 'divider',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'select',
|
|
||||||
name: 'type',
|
|
||||||
label: '代码类型',
|
|
||||||
required: true,
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
value: 'javascript',
|
|
||||||
label: 'JavaScript',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'python',
|
|
||||||
label: 'Python',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'lua',
|
|
||||||
label: 'Lua',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'editor',
|
|
||||||
required: true,
|
|
||||||
label: '代码内容',
|
|
||||||
name: 'content',
|
|
||||||
language: '${type}',
|
|
||||||
options: {
|
|
||||||
wordWrap: 'bounded',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'divider',
|
|
||||||
},
|
|
||||||
...outputsFormColumns(true, true, {result: {type: 'string'}}),
|
|
||||||
]}
|
|
||||||
handler={<NormalNodeHandler/>}
|
handler={<NormalNodeHandler/>}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type {NodeProps} from '@xyflow/react'
|
import type {NodeProps} from '@xyflow/react'
|
||||||
import React from 'react'
|
import React, {useCallback, useEffect} from 'react'
|
||||||
import {commonInfo} from '../../../util/amis.tsx'
|
import {commonInfo} from '../../../util/amis.tsx'
|
||||||
import {useContextStore} from '../store/ContextStore.ts'
|
import {useContextStore} from '../store/ContextStore.ts'
|
||||||
import {useDataStore} from '../store/DataStore.ts'
|
import {useDataStore} from '../store/DataStore.ts'
|
||||||
@@ -8,66 +8,81 @@ import AmisNode, {inputsFormColumns, NormalNodeHandler, outputsFormColumns} from
|
|||||||
|
|
||||||
const KnowledgeNode = (props: NodeProps) => {
|
const KnowledgeNode = (props: NodeProps) => {
|
||||||
const {getNodes, getEdges} = useFlowStore()
|
const {getNodes, getEdges} = useFlowStore()
|
||||||
const {getData} = useDataStore()
|
const {getData, mergeDataById} = useDataStore()
|
||||||
const {getInputSchema} = useContextStore()
|
const {getInputSchema} = useContextStore()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
mergeDataById(
|
||||||
|
props.id,
|
||||||
|
{
|
||||||
|
outputs: {
|
||||||
|
result: {
|
||||||
|
type: 'array-string',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}, [props.id])
|
||||||
|
|
||||||
|
const columnsSchema = useCallback(() => [
|
||||||
|
...inputsFormColumns(props.id, getInputSchema(), getNodes(), getEdges(), getData()),
|
||||||
|
{
|
||||||
|
type: 'divider',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
name: 'knowledgeId',
|
||||||
|
label: '知识库',
|
||||||
|
required: true,
|
||||||
|
options: [],
|
||||||
|
source: {
|
||||||
|
method: 'get',
|
||||||
|
url: `${commonInfo.baseAiUrl}/knowledge/list`,
|
||||||
|
// @ts-ignore
|
||||||
|
adaptor: (payload, response, api, context) => {
|
||||||
|
return {
|
||||||
|
...payload,
|
||||||
|
data: {
|
||||||
|
items: payload.data.items.map((item: any) => ({value: item['id'], label: item['name']})),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'input-text',
|
||||||
|
name: 'query',
|
||||||
|
label: '查询文本',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'input-range',
|
||||||
|
name: 'count',
|
||||||
|
label: '返回数量',
|
||||||
|
required: true,
|
||||||
|
value: 3,
|
||||||
|
max: 10,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'input-range',
|
||||||
|
name: 'score',
|
||||||
|
label: '匹配阀值',
|
||||||
|
required: true,
|
||||||
|
value: 0.6,
|
||||||
|
max: 1,
|
||||||
|
step: 0.05,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'divider',
|
||||||
|
},
|
||||||
|
...outputsFormColumns(false, true),
|
||||||
|
], [props.id])
|
||||||
return (
|
return (
|
||||||
<AmisNode
|
<AmisNode
|
||||||
nodeProps={props}
|
nodeProps={props}
|
||||||
defaultNodeName="知识库"
|
defaultNodeName="知识库"
|
||||||
defaultNodeDescription="查询知识库获取外部知识"
|
defaultNodeDescription="查询知识库获取外部知识"
|
||||||
columnSchema={() => [
|
columnSchema={columnsSchema}
|
||||||
...inputsFormColumns(props.id, getInputSchema(), getNodes(), getEdges(), getData()),
|
|
||||||
{
|
|
||||||
type: 'divider',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'select',
|
|
||||||
name: 'knowledgeId',
|
|
||||||
label: '知识库',
|
|
||||||
required: true,
|
|
||||||
options: [],
|
|
||||||
source: {
|
|
||||||
method: 'get',
|
|
||||||
url: `${commonInfo.baseAiUrl}/knowledge/list`,
|
|
||||||
// @ts-ignore
|
|
||||||
adaptor: (payload, response, api, context) => {
|
|
||||||
return {
|
|
||||||
...payload,
|
|
||||||
data: {
|
|
||||||
items: payload.data.items.map((item: any) => ({value: item['id'], label: item['name']})),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'input-text',
|
|
||||||
name: 'query',
|
|
||||||
label: '查询文本',
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'input-range',
|
|
||||||
name: 'count',
|
|
||||||
label: '返回数量',
|
|
||||||
required: true,
|
|
||||||
value: 3,
|
|
||||||
max: 10,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'input-range',
|
|
||||||
name: 'score',
|
|
||||||
label: '匹配阀值',
|
|
||||||
required: true,
|
|
||||||
value: 0.6,
|
|
||||||
max: 1,
|
|
||||||
step: 0.05,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'divider',
|
|
||||||
},
|
|
||||||
...outputsFormColumns(false, true, {result: {type: 'array-string'}}),
|
|
||||||
]}
|
|
||||||
handler={<NormalNodeHandler/>}
|
handler={<NormalNodeHandler/>}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type {NodeProps} from '@xyflow/react'
|
import type {NodeProps} from '@xyflow/react'
|
||||||
import {Tag} from 'antd'
|
import {Tag} from 'antd'
|
||||||
import React from 'react'
|
import React, {useCallback, useEffect, useState} from 'react'
|
||||||
import {useContextStore} from '../store/ContextStore.ts'
|
import {useContextStore} from '../store/ContextStore.ts'
|
||||||
import {useDataStore} from '../store/DataStore.ts'
|
import {useDataStore} from '../store/DataStore.ts'
|
||||||
import {useFlowStore} from '../store/FlowStore.ts'
|
import {useFlowStore} from '../store/FlowStore.ts'
|
||||||
@@ -13,46 +13,63 @@ const modelMap: Record<string, string> = {
|
|||||||
|
|
||||||
const LlmNode = (props: NodeProps) => {
|
const LlmNode = (props: NodeProps) => {
|
||||||
const {getNodes, getEdges} = useFlowStore()
|
const {getNodes, getEdges} = useFlowStore()
|
||||||
const {getData} = useDataStore()
|
const {getData, mergeDataById, getDataById} = useDataStore()
|
||||||
const {getInputSchema} = useContextStore()
|
const {getInputSchema} = useContextStore()
|
||||||
|
|
||||||
|
const [nodeData, setNodeData] = useState<any>()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
mergeDataById(
|
||||||
|
props.id,
|
||||||
|
{
|
||||||
|
outputs: {
|
||||||
|
text: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
setNodeData(getDataById(props.id))
|
||||||
|
}, [props.id])
|
||||||
|
|
||||||
|
const columnsSchema = useCallback(() => [
|
||||||
|
...inputsFormColumns(props.id, getInputSchema(), getNodes(), getEdges(), getData()),
|
||||||
|
{
|
||||||
|
type: 'divider',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
name: 'model',
|
||||||
|
label: '大模型',
|
||||||
|
required: true,
|
||||||
|
selectFirst: true,
|
||||||
|
options: Object.keys(modelMap).map(key => ({label: modelMap[key], value: key})),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'textarea',
|
||||||
|
name: 'systemPrompt',
|
||||||
|
label: '系统提示词',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'divider',
|
||||||
|
},
|
||||||
|
...outputsFormColumns(false, true),
|
||||||
|
], [props.id])
|
||||||
return (
|
return (
|
||||||
<AmisNode
|
<AmisNode
|
||||||
nodeProps={props}
|
nodeProps={props}
|
||||||
defaultNodeName="大模型"
|
defaultNodeName="大模型"
|
||||||
defaultNodeDescription="使用大模型对话"
|
defaultNodeDescription="使用大模型对话"
|
||||||
extraNodeDescription={nodeData => {
|
extraNodeDescription={
|
||||||
const model = nodeData?.model as string | undefined
|
nodeData?.model
|
||||||
return model
|
|
||||||
? <div className="mt-2 flex justify-between">
|
? <div className="mt-2 flex justify-between">
|
||||||
<span>大模型</span>
|
<span>大模型</span>
|
||||||
<Tag className="m-0" color="blue">{modelMap[model]}</Tag>
|
<Tag className="m-0" color="blue">{modelMap[nodeData.model]}</Tag>
|
||||||
</div>
|
</div>
|
||||||
: <></>
|
: <></>
|
||||||
}}
|
}
|
||||||
columnSchema={() => [
|
columnSchema={columnsSchema}
|
||||||
...inputsFormColumns(props.id, getInputSchema(), getNodes(), getEdges(), getData()),
|
|
||||||
{
|
|
||||||
type: 'divider',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'select',
|
|
||||||
name: 'model',
|
|
||||||
label: '大模型',
|
|
||||||
required: true,
|
|
||||||
selectFirst: true,
|
|
||||||
options: Object.keys(modelMap).map(key => ({label: modelMap[key], value: key})),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'textarea',
|
|
||||||
name: 'systemPrompt',
|
|
||||||
label: '系统提示词',
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'divider',
|
|
||||||
},
|
|
||||||
...outputsFormColumns(false, true, {text: {type: 'string'}}),
|
|
||||||
]}
|
|
||||||
handler={<NormalNodeHandler/>}
|
handler={<NormalNodeHandler/>}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
import type {NodeProps} from '@xyflow/react'
|
import type {NodeProps} from '@xyflow/react'
|
||||||
import React from 'react'
|
import React, {useCallback} from 'react'
|
||||||
import AmisNode, {EndNodeHandler, outputsFormColumns} from './AmisNode.tsx'
|
import AmisNode, {EndNodeHandler, outputsFormColumns} from './AmisNode.tsx'
|
||||||
|
|
||||||
const OutputNode = (props: NodeProps) => {
|
const OutputNode = (props: NodeProps) => {
|
||||||
|
const columnsSchema = useCallback(() => outputsFormColumns(true), [props.id])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AmisNode
|
<AmisNode
|
||||||
nodeProps={props}
|
nodeProps={props}
|
||||||
defaultNodeName="输出节点"
|
defaultNodeName="输出节点"
|
||||||
defaultNodeDescription="定义输出变量"
|
defaultNodeDescription="定义输出变量"
|
||||||
columnSchema={() => outputsFormColumns(true)}
|
columnSchema={columnsSchema}
|
||||||
handler={<EndNodeHandler/>}
|
handler={<EndNodeHandler/>}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -21,17 +21,15 @@ const SwitchNode = (props: NodeProps) => {
|
|||||||
nodeProps={props}
|
nodeProps={props}
|
||||||
defaultNodeName="分支节点"
|
defaultNodeName="分支节点"
|
||||||
defaultNodeDescription="根据不同的情况前往不同的分支"
|
defaultNodeDescription="根据不同的情况前往不同的分支"
|
||||||
extraNodeDescription={() => {
|
extraNodeDescription={
|
||||||
return (
|
<div className="mt-2">
|
||||||
<div className="mt-2">
|
{cases.map(item => (
|
||||||
{cases.map(item => (
|
<div key={item.index} className="mt-1">
|
||||||
<div key={item.index} className="mt-1">
|
<Tag className="m-0" color="blue">分支 {item.index}</Tag>
|
||||||
<Tag className="m-0" color="blue">分支 {item.index}</Tag>
|
</div>
|
||||||
</div>
|
))}
|
||||||
))}
|
</div>
|
||||||
</div>
|
}
|
||||||
)
|
|
||||||
}}
|
|
||||||
handler={
|
handler={
|
||||||
<>
|
<>
|
||||||
<Handle type="target" position={Position.Left}/>
|
<Handle type="target" position={Position.Left}/>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ export type DataStoreState = {
|
|||||||
setData: (data: Record<string, any>) => void,
|
setData: (data: Record<string, any>) => void,
|
||||||
getDataById: (id: string) => any,
|
getDataById: (id: string) => any,
|
||||||
setDataById: (id: string, data: any) => void,
|
setDataById: (id: string, data: any) => void,
|
||||||
|
mergeDataById: (id: string, data: any) => void,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useDataStore = create<DataStoreState>((set, get) => ({
|
export const useDataStore = create<DataStoreState>((set, get) => ({
|
||||||
@@ -22,4 +23,14 @@ export const useDataStore = create<DataStoreState>((set, get) => ({
|
|||||||
data: updateData,
|
data: updateData,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
mergeDataById: (id, data) => {
|
||||||
|
let updateData = get().data
|
||||||
|
updateData[id] = {
|
||||||
|
...(updateData[id] ?? {}),
|
||||||
|
...data,
|
||||||
|
}
|
||||||
|
set({
|
||||||
|
data: updateData,
|
||||||
|
})
|
||||||
|
},
|
||||||
}))
|
}))
|
||||||
Reference in New Issue
Block a user