mirror of
https://github.com/APIParkLab/APIPark.git
synced 2026-06-14 20:41:15 +08:00
feat: add priority
This commit is contained in:
@@ -140,7 +140,6 @@ const AIFlowChart = () => {
|
||||
animated: true
|
||||
}))
|
||||
]
|
||||
|
||||
setNodes(newNodes)
|
||||
setEdges(newEdges)
|
||||
}, [modelData])
|
||||
@@ -156,78 +155,65 @@ const AIFlowChart = () => {
|
||||
] as CoordinateExtent
|
||||
}, [modelData.length])
|
||||
|
||||
const onNodeDrag: any = useCallback(
|
||||
(_: MouseEvent, node: Node<any>) => {
|
||||
if (node.type !== 'modelCard') return
|
||||
const updateProviderOrder = async (sortedProviderIds: string[]) => {
|
||||
await fetchData('ai/provider/sort', {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify({
|
||||
providers: sortedProviderIds
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
setNodes((nds) => {
|
||||
return nds.map((n) => {
|
||||
if (n.type === 'keyCard' && n.id === `${node.id}-keys`) {
|
||||
const onNodeDragStop: any = useCallback((_: any, node: Node<any>) => {
|
||||
if (node.type !== 'modelCard') return
|
||||
|
||||
setNodes((nds) => {
|
||||
const modelNodes = nds.filter((n) => n.type === 'modelCard')
|
||||
const sortedNodes = [...modelNodes].sort((a, b) => a.position.y - b.position.y)
|
||||
const sortedProviderIds = sortedNodes.map((node) => node.id)
|
||||
|
||||
// Update provider order outside of setNodes callback
|
||||
updateProviderOrder(sortedProviderIds)
|
||||
// Update all node positions in a single pass
|
||||
return nds.map((n) => {
|
||||
if (n.type === 'modelCard') {
|
||||
const index = sortedNodes.findIndex((sn) => sn.id === n.id)
|
||||
return {
|
||||
...n,
|
||||
position: {
|
||||
x: LAYOUT.MODEL_NODE_X,
|
||||
y: LAYOUT.NODE_START_Y + index * LAYOUT.NODE_GAP
|
||||
}
|
||||
}
|
||||
}
|
||||
if (n.type === 'keyCard') {
|
||||
const modelId = n.id.replace('-keys', '')
|
||||
const modelNode = sortedNodes.find((mn) => mn.id === modelId)
|
||||
if (modelNode) {
|
||||
const index = sortedNodes.findIndex((sn) => sn.id === modelId)
|
||||
return {
|
||||
...n,
|
||||
position: {
|
||||
x: LAYOUT.KEY_NODE_X,
|
||||
y: node.position.y
|
||||
y: LAYOUT.NODE_START_Y + index * LAYOUT.NODE_GAP + 16
|
||||
}
|
||||
}
|
||||
}
|
||||
return n
|
||||
})
|
||||
}
|
||||
return n
|
||||
})
|
||||
},
|
||||
[setNodes]
|
||||
)
|
||||
|
||||
const onNodeDragStop: any = useCallback(
|
||||
(_: any, node: Node<any>) => {
|
||||
if (node.type !== 'modelCard') return
|
||||
|
||||
setNodes((nds) => {
|
||||
const modelNodes = nds.filter((n) => n.type === 'modelCard')
|
||||
const sortedNodes = [...modelNodes].sort((a, b) => a.position.y - b.position.y)
|
||||
|
||||
return nds.map((n) => {
|
||||
if (n.type === 'modelCard') {
|
||||
const index = sortedNodes.findIndex((sn) => sn.id === n.id)
|
||||
return {
|
||||
...n,
|
||||
position: {
|
||||
x: LAYOUT.MODEL_NODE_X,
|
||||
y: LAYOUT.NODE_START_Y + index * LAYOUT.NODE_GAP
|
||||
}
|
||||
}
|
||||
}
|
||||
if (n.type === 'keyCard') {
|
||||
const modelId = n.id.replace('-keys', '')
|
||||
const modelNode = sortedNodes.find((mn) => mn.id === modelId)
|
||||
if (modelNode) {
|
||||
const index = sortedNodes.findIndex((sn) => sn.id === modelId)
|
||||
return {
|
||||
...n,
|
||||
position: {
|
||||
x: LAYOUT.KEY_NODE_X,
|
||||
y: LAYOUT.NODE_START_Y + index * LAYOUT.NODE_GAP + 16
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return n
|
||||
})
|
||||
})
|
||||
},
|
||||
[setNodes]
|
||||
)
|
||||
})
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="w-full" style={{ height: 'calc(-300px + 100vh)' }}>
|
||||
<div className="w-full h-full">
|
||||
<ReactFlow
|
||||
nodes={nodes}
|
||||
edges={edges}
|
||||
onNodesChange={onNodesChange}
|
||||
onEdgesChange={onEdgesChange}
|
||||
onNodeDrag={onNodeDrag}
|
||||
proOptions={{ hideAttribution: true }}
|
||||
onNodeDragStop={onNodeDragStop}
|
||||
proOptions={{ hideAttribution: true }}
|
||||
draggable={false}
|
||||
nodeTypes={nodeTypes}
|
||||
edgeTypes={edgeTypes}
|
||||
|
||||
@@ -5,10 +5,12 @@ import AIFlowChart from './AIFlowChart'
|
||||
import AIUnConfigure from './AIUnconfigure'
|
||||
import { AiSettingProvider } from './contexts/AiSettingContext'
|
||||
|
||||
const CONTENT_STYLE = { height: 'calc(-300px + 100vh)' } as const
|
||||
|
||||
const AiSettingContent = () => {
|
||||
return (
|
||||
<InsidePage
|
||||
className="overflow-y-auto pb-PAGE_INSIDE_B"
|
||||
className="h-full pb-PAGE_INSIDE_B"
|
||||
pageTitle={$t('AI 模型')}
|
||||
description={$t('配置好 AI 模型后,你可以使用对应的大模型来创建 AI 服务')}
|
||||
showBorder={false}
|
||||
@@ -16,18 +18,22 @@ const AiSettingContent = () => {
|
||||
>
|
||||
<div className="flex flex-col h-full">
|
||||
<Tabs
|
||||
className="flex-shrink-0"
|
||||
className="sticky top-0 flex-shrink-0"
|
||||
items={[
|
||||
{
|
||||
key: 'flow',
|
||||
label: $t('已设置'),
|
||||
children: <AIFlowChart />
|
||||
children: (
|
||||
<div className="overflow-auto" style={CONTENT_STYLE}>
|
||||
<AIFlowChart />
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
key: 'config',
|
||||
label: $t('未设置'),
|
||||
children: (
|
||||
<div className="overflow-auto flex-grow">
|
||||
<div className="overflow-auto" style={CONTENT_STYLE}>
|
||||
<AIUnConfigure />
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { QuestionCircleOutlined } from '@ant-design/icons'
|
||||
import { Codebox } from '@common/components/postcat/api/Codebox'
|
||||
import { BasicResponse, PLACEHOLDER, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const'
|
||||
import { useFetch } from '@common/hooks/http'
|
||||
import { $t } from '@common/locales'
|
||||
import { App, Form, InputNumber, Select, Tag } from 'antd'
|
||||
import { App, Form, InputNumber, Select, Tag, Tooltip } from 'antd'
|
||||
import { forwardRef, useEffect, useImperativeHandle, useState } from 'react'
|
||||
import { AiProviderConfig, AiProviderLlmsItems } from './AiSettingList'
|
||||
|
||||
@@ -130,7 +131,16 @@ const AiSettingModalContent = forwardRef<AiSettingModalContentHandle, AiSettingM
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item<AiSettingModalContentField>
|
||||
label={$t('优先级')}
|
||||
label={
|
||||
<span className="flex items-center">
|
||||
{$t('负载优先级')}
|
||||
<Tooltip
|
||||
title={$t('负载优先级决定在原供应商异常或停用后,优先使用哪一个供应商。优先级数字越小,优先级越高。')}
|
||||
>
|
||||
<QuestionCircleOutlined className="ml-1 text-gray-500" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
name="priority"
|
||||
rules={[
|
||||
{ required: true },
|
||||
|
||||
Reference in New Issue
Block a user