mirror of
https://github.com/APIParkLab/APIPark.git
synced 2026-07-06 16:11:56 +08:00
feat: model
This commit is contained in:
@@ -1,7 +1,17 @@
|
||||
'use client'
|
||||
|
||||
import { useFetch } from '@common/hooks/http'
|
||||
import { addEdge, NodeTypes, ReactFlow, useEdgesState, useNodesState } from '@xyflow/react'
|
||||
import {
|
||||
addEdge,
|
||||
Connection,
|
||||
Edge,
|
||||
Node,
|
||||
NodeTypes,
|
||||
PanOnScrollMode,
|
||||
ReactFlow,
|
||||
useEdgesState,
|
||||
useNodesState
|
||||
} from '@xyflow/react'
|
||||
import '@xyflow/react/dist/style.css'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { KeyStatusNode } from './components/KeyStatusNode'
|
||||
@@ -23,6 +33,18 @@ interface ApiResponse {
|
||||
success: string
|
||||
}
|
||||
|
||||
interface NodeData {
|
||||
title?: string
|
||||
status?: string
|
||||
defaultModel?: string
|
||||
logo?: string
|
||||
keys?: Array<{
|
||||
id: string
|
||||
status: string
|
||||
priority: number
|
||||
}>
|
||||
}
|
||||
|
||||
const calculateNodePositions = (models: ModelData[], startY = LAYOUT.NODE_START_Y, gap = LAYOUT.NODE_GAP) => {
|
||||
return models.reduce(
|
||||
(acc, model, index) => {
|
||||
@@ -48,8 +70,8 @@ const nodeTypes: NodeTypes = {
|
||||
|
||||
const AIFlowChart = () => {
|
||||
const [modelData, setModelData] = useState<ModelData[]>([])
|
||||
const [nodes, setNodes, onNodesChange] = useNodesState([])
|
||||
const [edges, setEdges, onEdgesChange] = useEdgesState([])
|
||||
const [nodes, setNodes, onNodesChange] = useNodesState<Node>([])
|
||||
const [edges, setEdges, onEdgesChange] = useEdgesState<Edge>([])
|
||||
const { fetchData } = useFetch()
|
||||
|
||||
useEffect(() => {
|
||||
@@ -68,7 +90,7 @@ const AIFlowChart = () => {
|
||||
|
||||
const newNodes = [
|
||||
{
|
||||
id: 'service',
|
||||
id: 'apiService',
|
||||
type: 'serviceCard',
|
||||
position: { x: LAYOUT.SERVICE_NODE_X, y: LAYOUT.NODE_START_Y },
|
||||
data: {}
|
||||
@@ -123,10 +145,10 @@ const AIFlowChart = () => {
|
||||
setEdges(newEdges)
|
||||
}, [modelData])
|
||||
|
||||
const onConnect = useCallback((params: any) => setEdges((eds) => addEdge(params, eds)), [setEdges])
|
||||
const onConnect = useCallback((params: Connection) => setEdges((eds) => addEdge(params, eds)), [setEdges])
|
||||
|
||||
const onNodeDrag = useCallback(
|
||||
(_: any, node: any) => {
|
||||
const onNodeDrag: any = useCallback(
|
||||
(_: MouseEvent, node: Node<any>) => {
|
||||
if (node.type !== 'modelCard') return
|
||||
|
||||
setNodes((nds) => {
|
||||
@@ -147,8 +169,8 @@ const AIFlowChart = () => {
|
||||
[setNodes]
|
||||
)
|
||||
|
||||
const onNodeDragStop = useCallback(
|
||||
(_: any, node: any) => {
|
||||
const onNodeDragStop: any = useCallback(
|
||||
(_, node: Node<any>) => {
|
||||
if (node.type !== 'modelCard') return
|
||||
|
||||
setNodes((nds) => {
|
||||
@@ -174,7 +196,7 @@ const AIFlowChart = () => {
|
||||
)
|
||||
|
||||
return (
|
||||
<div className="w-full h-full">
|
||||
<div className="overflow-y-auto w-full h-full" style={{ height: '100vh' }}>
|
||||
<ReactFlow
|
||||
nodes={nodes}
|
||||
edges={edges}
|
||||
@@ -184,8 +206,13 @@ const AIFlowChart = () => {
|
||||
onNodeDrag={onNodeDrag}
|
||||
onNodeDragStop={onNodeDragStop}
|
||||
nodeTypes={nodeTypes}
|
||||
fitView
|
||||
attributionPosition="bottom-left"
|
||||
maxZoom={1}
|
||||
minZoom={1}
|
||||
zoomOnScroll={false}
|
||||
zoomOnPinch={false}
|
||||
zoomOnDoubleClick={false}
|
||||
panOnScroll={true}
|
||||
panOnScrollMode={PanOnScrollMode.Vertical}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Icon } from '@iconify/react'
|
||||
import { Handle, Position } from '@xyflow/react'
|
||||
import { Avatar } from 'antd'
|
||||
import { t } from 'i18next'
|
||||
import React from 'react'
|
||||
import { ModelStatus } from './types'
|
||||
@@ -29,25 +28,13 @@ export const ModelCardNode: React.FC<{ data: ModelCardNodeData }> = ({ data }) =
|
||||
<div>
|
||||
<div className="flex justify-between items-center">
|
||||
<div className="flex gap-2 items-center">
|
||||
<Avatar
|
||||
shape="square"
|
||||
size={50}
|
||||
className={`rounded-[12px] border-none ${logo ? 'bg-[linear-gradient(135deg,white,#f0f0f0)]' : 'bg-theme'}`}
|
||||
src={
|
||||
logo ? (
|
||||
<img
|
||||
src={logo}
|
||||
alt="Logo"
|
||||
style={{ maxWidth: '200px', width: '45px', height: '45px', objectFit: 'unset' }}
|
||||
/>
|
||||
) : undefined
|
||||
}
|
||||
// TODO use https://www.npmjs.com/package/@icon-park/react
|
||||
icon={logo ? '' : <iconpark-icon name="auto-generate-api"></iconpark-icon>}
|
||||
>
|
||||
{' '}
|
||||
</Avatar>
|
||||
<span className="text-base text-gray-900">{title}</span>
|
||||
<div className="flex flex-1 overflow-hidden items-center gap-[4px]">
|
||||
<span
|
||||
className=" flex items-center h-[22px] ai-setting-svg-container"
|
||||
dangerouslySetInnerHTML={{ __html: logo }}
|
||||
></span>
|
||||
</div>
|
||||
<span className="text-base text-gray-900 max-w-[180px] truncate">{title}</span>
|
||||
<Icon
|
||||
icon={status === 'enable' ? 'mdi:check-circle' : 'mdi:close-circle'}
|
||||
className={`text-xl ${status === 'enable' ? 'text-green-500' : 'text-red-500'}`}
|
||||
|
||||
Reference in New Issue
Block a user