mirror of
https://github.com/APIParkLab/APIPark.git
synced 2026-07-06 16:11:56 +08:00
feat: apikey
This commit is contained in:
@@ -15,7 +15,9 @@ import {
|
||||
useNodesState
|
||||
} from '@xyflow/react'
|
||||
import '@xyflow/react/dist/style.css'
|
||||
import { Button, Space } from 'antd'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import CustomEdge from './components/CustomEdge'
|
||||
import { KeyStatusNode } from './components/KeyStatusNode'
|
||||
import { ModelCardNode } from './components/ModelCardNode'
|
||||
@@ -68,11 +70,13 @@ const AIFlowChart = () => {
|
||||
const [edges, setEdges, onEdgesChange] = useEdgesState<Edge>([])
|
||||
const { fetchData } = useFetch()
|
||||
const { aiConfigFlushed } = useGlobalContext()
|
||||
const navigate = useNavigate()
|
||||
|
||||
useEffect(() => {
|
||||
fetchData<ApiResponse>('ai/providers/configured', {
|
||||
method: 'GET',
|
||||
eoTransformKeys: ['default_llm']
|
||||
// eoApiPrefix: 'http://uat.apikit.com:11204/mockApi/aoplatform/api/v1/'
|
||||
}).then((response) => {
|
||||
const mockApiResponse: ApiResponse = response as ApiResponse
|
||||
setModelData(mockApiResponse.data.providers)
|
||||
@@ -207,26 +211,35 @@ const AIFlowChart = () => {
|
||||
|
||||
return (
|
||||
<div className="w-full h-full">
|
||||
<ReactFlow
|
||||
nodes={nodes}
|
||||
edges={edges}
|
||||
onNodesChange={onNodesChange}
|
||||
onEdgesChange={onEdgesChange}
|
||||
onNodeDragStop={onNodeDragStop}
|
||||
proOptions={{ hideAttribution: true }}
|
||||
draggable={false}
|
||||
nodeTypes={nodeTypes}
|
||||
edgeTypes={edgeTypes}
|
||||
zoomOnScroll={false}
|
||||
zoomOnPinch={false}
|
||||
zoomOnDoubleClick={false}
|
||||
panOnScroll={true}
|
||||
panOnScrollMode={PanOnScrollMode.Vertical}
|
||||
defaultEdgeOptions={{
|
||||
type: 'custom'
|
||||
}}
|
||||
translateExtent={calculateExtent()}
|
||||
/>
|
||||
{modelData.length === 0 ? (
|
||||
<Space className="flex flex-col justify-center items-center h-[200px]">
|
||||
<div>No AI model configured</div>
|
||||
<Button type="primary" onClick={() => navigate('/aisetting?status=unconfigure')}>
|
||||
Go to Settings
|
||||
</Button>
|
||||
</Space>
|
||||
) : (
|
||||
<ReactFlow
|
||||
nodes={nodes}
|
||||
edges={edges}
|
||||
onNodesChange={onNodesChange}
|
||||
onEdgesChange={onEdgesChange}
|
||||
onNodeDragStop={onNodeDragStop}
|
||||
proOptions={{ hideAttribution: true }}
|
||||
draggable={false}
|
||||
nodeTypes={nodeTypes}
|
||||
edgeTypes={edgeTypes}
|
||||
zoomOnScroll={false}
|
||||
zoomOnPinch={false}
|
||||
zoomOnDoubleClick={false}
|
||||
panOnScroll={true}
|
||||
panOnScrollMode={PanOnScrollMode.Vertical}
|
||||
defaultEdgeOptions={{
|
||||
type: 'custom'
|
||||
}}
|
||||
translateExtent={calculateExtent()}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -6,16 +6,17 @@ import { useFetch } from '@common/hooks/http'
|
||||
import { $t } from '@common/locales'
|
||||
import { App, Button, Card, Empty, Spin, Tag } from 'antd'
|
||||
import { memo, useEffect, useState } from 'react'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { useAiSetting } from './contexts/AiSettingContext'
|
||||
import { AiSettingListItem } from './types'
|
||||
|
||||
const CardBox = memo(({ provider }: { provider: AiSettingListItem }) => {
|
||||
const { openConfigModal } = useAiSetting()
|
||||
const { aiConfigFlushed, setAiConfigFlushed } = useGlobalContext()
|
||||
const navigate = useNavigate()
|
||||
|
||||
const handleOpenModal = async (provider: AiSettingListItem) => {
|
||||
await openConfigModal(provider)
|
||||
setAiConfigFlushed(!aiConfigFlushed)
|
||||
navigate('/aisetting?status=configure')
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import InsidePage from '@common/components/aoplatform/InsidePage'
|
||||
import { $t } from '@common/locales'
|
||||
import { Tabs } from 'antd'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useSearchParams } from 'react-router-dom'
|
||||
import AIFlowChart from './AIFlowChart'
|
||||
import AIUnConfigure from './AIUnconfigure'
|
||||
import { AiSettingProvider } from './contexts/AiSettingContext'
|
||||
@@ -8,6 +10,14 @@ import { AiSettingProvider } from './contexts/AiSettingContext'
|
||||
const CONTENT_STYLE = { height: 'calc(-300px + 100vh)' } as const
|
||||
|
||||
const AiSettingContent = () => {
|
||||
const [searchParams, setSearchParams] = useSearchParams()
|
||||
const [activeKey, setActiveKey] = useState(searchParams.get('status') === 'unconfigure' ? 'config' : 'flow')
|
||||
|
||||
useEffect(() => {
|
||||
const newActiveKey = searchParams.get('status') === 'unconfigure' ? 'config' : 'flow'
|
||||
setActiveKey(newActiveKey)
|
||||
}, [searchParams])
|
||||
|
||||
return (
|
||||
<InsidePage
|
||||
className="h-full pb-PAGE_INSIDE_B"
|
||||
@@ -18,6 +28,11 @@ const AiSettingContent = () => {
|
||||
>
|
||||
<div className="flex flex-col h-full">
|
||||
<Tabs
|
||||
activeKey={activeKey}
|
||||
onChange={(key) => {
|
||||
setActiveKey(key)
|
||||
setSearchParams({ status: key === 'config' ? 'unconfigure' : 'configure' })
|
||||
}}
|
||||
className="sticky top-0 flex-shrink-0"
|
||||
items={[
|
||||
{
|
||||
|
||||
@@ -5,10 +5,10 @@ import { useFetch } from '@common/hooks/http'
|
||||
import { $t } from '@common/locales'
|
||||
import { App, Form, InputNumber, Select, Switch, Tag, Tooltip } from 'antd'
|
||||
import { forwardRef, useEffect, useImperativeHandle, useState } from 'react'
|
||||
import { AiProviderConfig, AiProviderLlmsItems, ModelDetailData } from './types'
|
||||
import { AiProviderLlmsItems, ModelDetailData } from './types'
|
||||
|
||||
export type AiSettingModalContentProps = {
|
||||
entity: AiProviderConfig & { defaultLlm: string }
|
||||
entity: ModelDetailData & { defaultLlm: string }
|
||||
readOnly: boolean
|
||||
}
|
||||
|
||||
@@ -173,7 +173,7 @@ const AiSettingModalContent = forwardRef<AiSettingModalContentHandle, AiSettingM
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
{entity.id && (
|
||||
{entity.configured && (
|
||||
<Form.Item className="p-4 bg-white rounded-lg" label={$t('LLM 状态管理')}>
|
||||
<div className="flex justify-between items-center">
|
||||
<div>
|
||||
|
||||
@@ -44,7 +44,7 @@ export const ModelCardNode: React.FC<{ data: ModelCardNodeData }> = ({ data }) =
|
||||
></span>
|
||||
</div>
|
||||
<span className="text-base text-gray-900 max-w-[180px] truncate">{name}</span>
|
||||
<Icon icon={statusConfig.icon} className={`text-xl ${statusConfig.color}`} />
|
||||
<Icon icon={statusConfig?.icon} className={`text-xl ${statusConfig?.color}`} />
|
||||
</div>
|
||||
|
||||
{/* Action buttons */}
|
||||
|
||||
@@ -7,7 +7,7 @@ import { checkAccess } from '@common/utils/permission'
|
||||
import { App } from 'antd'
|
||||
import { createContext, useContext, useRef } from 'react'
|
||||
import AiSettingModalContent, { AiSettingModalContentHandle } from '../AiSettingModal'
|
||||
import { AiProviderConfig, AiSettingListItem } from '../types'
|
||||
import { AiSettingListItem, ModelDetailData } from '../types'
|
||||
|
||||
interface AiSettingContextType {
|
||||
openConfigModal: (entity: AiSettingListItem) => Promise<void>
|
||||
@@ -23,7 +23,7 @@ export const AiSettingProvider: React.FC<{ children: React.ReactNode }> = ({ chi
|
||||
|
||||
const openConfigModal = async (entity: AiSettingListItem) => {
|
||||
message.loading($t(RESPONSE_TIPS.loading))
|
||||
const { code, data, msg } = await fetchData<BasicResponse<{ provider: AiProviderConfig }>>('ai/provider/config', {
|
||||
const { code, data, msg } = await fetchData<BasicResponse<{ provider: ModelDetailData }>>('ai/provider/config', {
|
||||
method: 'GET',
|
||||
eoParams: { provider: entity!.id },
|
||||
eoTransformKeys: ['get_apikey_url']
|
||||
|
||||
@@ -21,6 +21,9 @@ export interface ModelDetailData extends ModelListData{
|
||||
enable:boolean
|
||||
config: string,
|
||||
priority?: number
|
||||
getApikeyUrl: string
|
||||
status: ModelStatus
|
||||
configured: boolean
|
||||
}
|
||||
|
||||
|
||||
@@ -51,12 +54,4 @@ export type AiProviderDefaultConfig = {
|
||||
scopes: string[]
|
||||
}
|
||||
|
||||
export interface AiProviderConfig {
|
||||
id: string
|
||||
name: string
|
||||
config: string
|
||||
getApikeyUrl: string
|
||||
priority: number
|
||||
enable: boolean
|
||||
status: ModelStatus
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user