mirror of
https://github.com/APIParkLab/APIPark.git
synced 2026-06-14 20:41:15 +08:00
Merge branch 'feature/1.4' into 'main'
feat: aiApi detail page See merge request apipark/APIPark!147
This commit is contained in:
+3
-2
@@ -9,8 +9,9 @@ const PromptEditorResizable = (props: {
|
||||
onChange?: (value: string) => void
|
||||
variablesChange?: (keys: string[]) => void
|
||||
promptVariables: VariableItems[]
|
||||
disabled?: boolean
|
||||
}) => {
|
||||
const { value, onChange, variablesChange, promptVariables } = props
|
||||
const { value, onChange, variablesChange, promptVariables, disabled } = props
|
||||
const minHeight = 68
|
||||
const [editorHeight, setEditorHeight] = useState(minHeight)
|
||||
const [previousKeys, setPreviousKeys] = useState<string[]>([])
|
||||
@@ -82,7 +83,7 @@ const PromptEditorResizable = (props: {
|
||||
setPreviousKeys(keys)
|
||||
}
|
||||
}}
|
||||
editable={true}
|
||||
editable={disabled ? false : true}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
|
||||
@@ -157,7 +157,7 @@ const mockData = [
|
||||
{
|
||||
name: 'AI API',
|
||||
key: 'aiApiList',
|
||||
path: '/aiapis',
|
||||
path: '/aiApis',
|
||||
icon: 'ic:baseline-api'
|
||||
// access: 'system.settings.ai_api.view'
|
||||
}
|
||||
|
||||
@@ -92,10 +92,10 @@ const mockData = {
|
||||
},
|
||||
{
|
||||
driver: 'apipark.builtIn.component',
|
||||
name: 'aiapis',
|
||||
name: 'aiApis',
|
||||
router: [
|
||||
{
|
||||
path: 'aiapis',
|
||||
path: 'aiApis',
|
||||
type: 'normal'
|
||||
}
|
||||
]
|
||||
|
||||
@@ -468,10 +468,29 @@ export const routerMap: Map<string, RouterMapConfig> = new Map([
|
||||
}
|
||||
],
|
||||
[
|
||||
'aiapis',
|
||||
'aiApis',
|
||||
{
|
||||
type: 'component',
|
||||
lazy: lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiApis/index.tsx'))
|
||||
lazy: lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiApis/aiApisLayout.tsx')),
|
||||
key: 'aiApis',
|
||||
provider: AiServiceProvider,
|
||||
children: [
|
||||
{
|
||||
path: 'list',
|
||||
key: 'apiList',
|
||||
lazy: lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiApis/index.tsx')),
|
||||
},
|
||||
{
|
||||
path: 'service/:teamId/aiInside/:serviceId/route/:routeId/:type',
|
||||
key: 'apiDetail',
|
||||
lazy: lazy(
|
||||
() =>
|
||||
import(
|
||||
/* webpackChunkName: "[request]" */ '@core/pages/aiService/api/AiServiceInsideRouterCreate.tsx'
|
||||
)
|
||||
)
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
[
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import { useEffect } from "react";
|
||||
import { Outlet, useLocation, useNavigate } from "react-router-dom";
|
||||
|
||||
export default function GlobalPolicyLayout(){
|
||||
const location = useLocation()
|
||||
const pathName = location.pathname
|
||||
const navigator = useNavigate()
|
||||
useEffect(()=>{
|
||||
if(pathName === '/aiApis'){
|
||||
navigator('/aiApis/list')
|
||||
}
|
||||
},[pathName])
|
||||
return (<Outlet></Outlet>)
|
||||
}
|
||||
@@ -22,6 +22,7 @@ const ApiSettings: React.FC = () => {
|
||||
const [provider, setProvider] = useState<AIProvider | undefined>()
|
||||
const { fetchData } = useFetch()
|
||||
const [searchWord, setSearchWord] = useState<string>('')
|
||||
const [columns, setColumns] = useState<PageProColumns<APIs>[]>([])
|
||||
const [total, setTotal] = useState<number>(0)
|
||||
const [timeButton, setTimeButton] = useState<TimeRangeButton>('day')
|
||||
const navigate = useNavigate()
|
||||
@@ -36,9 +37,14 @@ const ApiSettings: React.FC = () => {
|
||||
}, [selectedProvider])
|
||||
|
||||
const handlePreview = (record: APIs) => {
|
||||
navigate(`service/${record.team.id}/aiInside/${record.service.id}/route/${record.id}`)
|
||||
navigate(`../service/${record.team.id}/aiInside/${record.service.id}/route/${record.id}/apiDetail`)
|
||||
}
|
||||
const requestApis = async (params: any) => {
|
||||
const requestApis = async (params: any & {
|
||||
pageSize: number;
|
||||
current: number;
|
||||
},
|
||||
sort: Record<string, string>,
|
||||
filter: Record<string, string>) => {
|
||||
if (!selectedProvider) return
|
||||
setQueryBtnLoading(true)
|
||||
try {
|
||||
@@ -46,6 +52,11 @@ const ApiSettings: React.FC = () => {
|
||||
provider: selectedProvider,
|
||||
page_size: params.pageSize,
|
||||
keyword: searchWord,
|
||||
sort: Object.keys(sort)?.length > 0 ? 'use_token' : undefined,
|
||||
asc: Object.keys(sort)?.length > 0 ? Object.values(sort)?.[0] === 'ascend' : undefined,
|
||||
models: filter?.model && filter?.model?.length ? JSON.stringify(filter.model) : undefined,
|
||||
services: filter?.name && filter?.name?.length ? JSON.stringify(filter.name) : undefined,
|
||||
disabled: filter?.disable && filter?.disable?.length ? filter.disable[0] : undefined,
|
||||
page: params.current,
|
||||
start: timeRange.start,
|
||||
end: timeRange.end
|
||||
@@ -62,8 +73,21 @@ const ApiSettings: React.FC = () => {
|
||||
setQueryBtnLoading(false)
|
||||
if (response.code === STATUS_CODE.SUCCESS) {
|
||||
setTotal(response.data.total)
|
||||
const modalMap: {
|
||||
[key: string]: string
|
||||
} = response.data?.condition?.models.reduce((acc: { [key: string]: string }, item: { id: string; name: string }) => {
|
||||
acc[item.id] = $t(item.name)
|
||||
return acc
|
||||
}, {})
|
||||
const serviceMap: {
|
||||
[key: string]: string
|
||||
} = response.data?.condition?.services.reduce((acc: { [key: string]: string }, item: { id: string; name: string }) => {
|
||||
acc[item.id] = $t(item.name)
|
||||
return acc
|
||||
}, {})
|
||||
setTableColumns(modalMap, serviceMap)
|
||||
return {
|
||||
data: response.data.apis,
|
||||
data: response.data.apis || [],
|
||||
success: true,
|
||||
total: response.data.total
|
||||
}
|
||||
@@ -83,7 +107,74 @@ const ApiSettings: React.FC = () => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const setTableColumns = (modalMap: {
|
||||
[key: string]: string
|
||||
}, serviceMap: {
|
||||
[key: string]: string
|
||||
}) => {
|
||||
setColumns([
|
||||
{
|
||||
title: $t('AI 服务'),
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
width: 180,
|
||||
filters: true,
|
||||
valueEnum: serviceMap || {}
|
||||
},
|
||||
{
|
||||
title: 'API URL',
|
||||
dataIndex: 'request_path',
|
||||
key: 'request_path',
|
||||
ellipsis: true,
|
||||
render: (text: string, record: APIs) => (
|
||||
<p>
|
||||
<Typography.Text type="success">{record.method}</Typography.Text>
|
||||
<span className="ml-1">{text}</span>
|
||||
</p>
|
||||
)
|
||||
},
|
||||
{
|
||||
title: $t('模型'),
|
||||
dataIndex: ['model', 'name'],
|
||||
key: 'model',
|
||||
width: 150,
|
||||
filters: true,
|
||||
onFilter: true,
|
||||
valueType: 'select',
|
||||
valueEnum: modalMap || {}
|
||||
},
|
||||
{
|
||||
title: $t('已用 Token'),
|
||||
dataIndex: 'use_token',
|
||||
key: 'use_token',
|
||||
width: 120,
|
||||
sorter: (a: any, b: any) => {
|
||||
return (a.priority as number) - (b.priority as number)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: $t('是否放行'),
|
||||
dataIndex: 'disable',
|
||||
ellipsis: true,
|
||||
width: 120,
|
||||
filters: true,
|
||||
onFilter: true,
|
||||
valueType: 'select',
|
||||
valueEnum: {
|
||||
true: { text: <Typography.Text type="danger">{$t('拦截')}</Typography.Text> },
|
||||
false: { text: <Typography.Text type="success">{$t('放行')}</Typography.Text> }
|
||||
}
|
||||
},
|
||||
{
|
||||
title: $t('编辑时间'),
|
||||
dataIndex: 'update_time',
|
||||
key: 'update_time',
|
||||
width: 200,
|
||||
render: (time: string) => <Typography.Text>{dayjs(time).format('YYYY-MM-DD HH:mm:ss')}</Typography.Text>
|
||||
},
|
||||
...operation
|
||||
])
|
||||
}
|
||||
const operation: PageProColumns<APIs>[] = [
|
||||
{
|
||||
title: '',
|
||||
@@ -95,7 +186,7 @@ const ApiSettings: React.FC = () => {
|
||||
<TableBtnWithPermission
|
||||
access="team.service.router.view"
|
||||
key="preview"
|
||||
btnType="view"
|
||||
btnType="logs"
|
||||
onClick={() => handlePreview(entity)}
|
||||
btnTitle={$t('预览')}
|
||||
/>
|
||||
@@ -103,65 +194,6 @@ const ApiSettings: React.FC = () => {
|
||||
}
|
||||
]
|
||||
|
||||
const columns: PageProColumns<APIs>[] = [
|
||||
{
|
||||
title: $t('AI 服务'),
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
width: 180
|
||||
},
|
||||
{
|
||||
title: 'API URL',
|
||||
dataIndex: 'request_path',
|
||||
key: 'request_path',
|
||||
width: 200,
|
||||
ellipsis: true,
|
||||
render: (text: string, record: APIs) => (
|
||||
<p>
|
||||
<Typography.Text type="success">{record.method}</Typography.Text>
|
||||
<span className="ml-1">{text}</span>
|
||||
</p>
|
||||
)
|
||||
},
|
||||
{
|
||||
title: $t('模型'),
|
||||
dataIndex: ['model', 'name'],
|
||||
key: 'model',
|
||||
width: 150,
|
||||
filters: true,
|
||||
onFilter: true,
|
||||
valueType: 'select',
|
||||
valueEnum: {}
|
||||
},
|
||||
{
|
||||
title: $t('已用 Token'),
|
||||
dataIndex: 'use_token',
|
||||
key: 'use_token',
|
||||
width: 120,
|
||||
sorter: true
|
||||
},
|
||||
{
|
||||
title: $t('是否放行'),
|
||||
dataIndex: 'disabled',
|
||||
ellipsis: true,
|
||||
filters: true,
|
||||
onFilter: true,
|
||||
valueType: 'select',
|
||||
valueEnum: {
|
||||
true: { text: <Typography.Text type="danger">{$t('拦截')}</Typography.Text> },
|
||||
false: { text: <Typography.Text type="success">{$t('放行')}</Typography.Text> }
|
||||
}
|
||||
},
|
||||
{
|
||||
title: $t('编辑时间'),
|
||||
dataIndex: 'update_time',
|
||||
key: 'update_time',
|
||||
width: 200,
|
||||
render: (time: string) => <Typography.Text>{dayjs(time).format('YYYY-MM-DD HH:mm:ss')}</Typography.Text>
|
||||
},
|
||||
...operation
|
||||
]
|
||||
|
||||
const resetQuery = () => {
|
||||
setTimeButton('day')
|
||||
setTimeRange({ start: null, end: null })
|
||||
@@ -255,7 +287,12 @@ const ApiSettings: React.FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
request={requestApis}
|
||||
request={async (params: any & {
|
||||
pageSize: number;
|
||||
current: number;
|
||||
},
|
||||
sort: Record<string, string>,
|
||||
filter: Record<string, string>) => requestApis(params, sort, filter)}
|
||||
onSearchWordChange={(e) => {
|
||||
setSearchWord(e.target.value)
|
||||
}}
|
||||
|
||||
@@ -20,6 +20,7 @@ import { App, Button, Form, Input, InputNumber, Row, Select, Space, Spin, Switch
|
||||
import { MutableRefObject, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { useNavigate, useParams } from 'react-router-dom'
|
||||
import AiServiceRouterModelConfig, { AiServiceRouterModelConfigHandle } from './AiServiceInsideRouterModelConfig'
|
||||
import WithPermission from '@common/components/aoplatform/WithPermission'
|
||||
|
||||
type AiServiceRouterField = {
|
||||
name: string
|
||||
@@ -51,7 +52,7 @@ type AiServiceRouterConfig = {
|
||||
const AiServiceInsideRouterCreate = () => {
|
||||
const navigator = useNavigate()
|
||||
const { message } = App.useApp()
|
||||
const { serviceId, teamId, routeId } = useParams<RouterParams>()
|
||||
const { serviceId, teamId, routeId, type } = useParams<RouterParams>()
|
||||
const [form] = Form.useForm()
|
||||
const { fetchData } = useFetch()
|
||||
const [loading, setLoading] = useState<boolean>(false)
|
||||
@@ -103,7 +104,8 @@ const AiServiceInsideRouterCreate = () => {
|
||||
})
|
||||
.catch((errInfo) => Promise.reject(errInfo))
|
||||
}
|
||||
|
||||
const isDelete = type === 'apiDetail'
|
||||
const backUrl = isDelete ? `/aiApis/list` : `/service/${teamId}/aiInside/${serviceId}/route`
|
||||
const openDrawer = (type: 'edit') => {
|
||||
setDrawerType(type)
|
||||
}
|
||||
@@ -208,6 +210,7 @@ const AiServiceInsideRouterCreate = () => {
|
||||
}, [])
|
||||
|
||||
const addVariable = () => {
|
||||
if (isDelete) return
|
||||
form.setFieldsValue({
|
||||
variables: [...form.getFieldValue('variables'), { key: '', value: '', require: true }]
|
||||
})
|
||||
@@ -264,12 +267,13 @@ const AiServiceInsideRouterCreate = () => {
|
||||
showBorder={false}
|
||||
scrollPage={false}
|
||||
className="overflow-y-auto"
|
||||
backUrl={`/service/${teamId}/aiInside/${serviceId}/route`}
|
||||
backUrl={backUrl}
|
||||
customBtn={
|
||||
<div className="flex items-center gap-btnbase">
|
||||
<Button
|
||||
icon={<Icon icon="ic:baseline-tune" height={18} width={18} />}
|
||||
iconPosition="end"
|
||||
disabled={isDelete}
|
||||
onClick={() => openDrawer('edit')}
|
||||
>
|
||||
<div className="flex items-center gap-[10px]">
|
||||
@@ -281,10 +285,11 @@ const AiServiceInsideRouterCreate = () => {
|
||||
{defaultLlm?.scopes?.map((x) => <Tag>{x?.toLocaleUpperCase()}</Tag>)}
|
||||
</div>
|
||||
</Button>
|
||||
|
||||
<Button type="primary" onClick={onFinish}>
|
||||
{$t('保存')}
|
||||
</Button>
|
||||
{
|
||||
type !== 'apiDetail' && (<Button type="primary" onClick={onFinish}>
|
||||
{$t('保存')}
|
||||
</Button>)
|
||||
}
|
||||
</div>
|
||||
}
|
||||
>
|
||||
@@ -293,125 +298,130 @@ const AiServiceInsideRouterCreate = () => {
|
||||
spinning={loading}
|
||||
wrapperClassName=" pb-PAGE_INSIDE_B pr-PAGE_INSIDE_X"
|
||||
>
|
||||
<Form
|
||||
layout="vertical"
|
||||
labelAlign="left"
|
||||
scrollToFirstError
|
||||
form={form}
|
||||
className="flex flex-col mx-auto h-full"
|
||||
name="AiServiceInsideRouterCreate"
|
||||
onValuesChange={handleValuesChange}
|
||||
onFinish={onFinish}
|
||||
autoComplete="off"
|
||||
>
|
||||
<div className="">
|
||||
<Row className="flex justify-between items-center w-full gap-btnbase">
|
||||
<Form.Item<AiServiceRouterField>
|
||||
className="flex-1"
|
||||
label={$t('路由名称')}
|
||||
name="name"
|
||||
rules={[{ required: true, whitespace: true }]}
|
||||
>
|
||||
<Input className="w-INPUT_NORMAL" placeholder={$t(PLACEHOLDER.input)} />
|
||||
</Form.Item>
|
||||
<WithPermission disabled={isDelete}>
|
||||
<Form
|
||||
layout="vertical"
|
||||
labelAlign="left"
|
||||
scrollToFirstError
|
||||
form={form}
|
||||
className="flex flex-col mx-auto h-full"
|
||||
name="AiServiceInsideRouterCreate"
|
||||
onValuesChange={handleValuesChange}
|
||||
onFinish={onFinish}
|
||||
autoComplete="off"
|
||||
>
|
||||
<div className="">
|
||||
<Row className="flex justify-between items-center w-full gap-btnbase">
|
||||
<Form.Item<AiServiceRouterField>
|
||||
className="flex-1"
|
||||
label={$t('路由名称')}
|
||||
name="name"
|
||||
rules={[{ required: true, whitespace: true }]}
|
||||
>
|
||||
<Input className="w-INPUT_NORMAL" placeholder={$t(PLACEHOLDER.input)} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item className="flex-1" label={$t('请求路径')}>
|
||||
<Space.Compact block>
|
||||
<Form.Item
|
||||
name="pathMatch"
|
||||
rules={[
|
||||
{ required: true, whitespace: true },
|
||||
{
|
||||
validator: validateUrlSlash
|
||||
}
|
||||
]}
|
||||
noStyle
|
||||
>
|
||||
<Select
|
||||
placeholder={$t(PLACEHOLDER.select)}
|
||||
options={apiPathMatchRulesOptions}
|
||||
className="w-[30%] min-w-[100px]"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item<AiServiceRouterField>
|
||||
name="path"
|
||||
rules={[
|
||||
{ required: true, whitespace: true },
|
||||
{
|
||||
validator: validateUrlSlash
|
||||
}
|
||||
]}
|
||||
noStyle
|
||||
>
|
||||
<Input
|
||||
prefix={prefixForce ? `${apiPrefix}/` : '/'}
|
||||
placeholder={$t(PLACEHOLDER.input)}
|
||||
onChange={(e) => {
|
||||
if ((e.target.value as string).endsWith('/*')) {
|
||||
form.setFieldValue('path', e.target.value.slice(0, -2))
|
||||
form.setFieldValue('pathMatch', 'prefix')
|
||||
<Form.Item className="flex-1" label={$t('请求路径')}>
|
||||
<Space.Compact block>
|
||||
<Form.Item
|
||||
name="pathMatch"
|
||||
rules={[
|
||||
{ required: true, whitespace: true },
|
||||
{
|
||||
validator: validateUrlSlash
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Space.Compact>
|
||||
]}
|
||||
noStyle
|
||||
>
|
||||
<Select
|
||||
placeholder={$t(PLACEHOLDER.select)}
|
||||
options={apiPathMatchRulesOptions}
|
||||
className="w-[30%] min-w-[100px]"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item<AiServiceRouterField>
|
||||
name="path"
|
||||
rules={[
|
||||
{ required: true, whitespace: true },
|
||||
{
|
||||
validator: validateUrlSlash
|
||||
}
|
||||
]}
|
||||
noStyle
|
||||
>
|
||||
<Input
|
||||
prefix={prefixForce ? `${apiPrefix}/` : '/'}
|
||||
placeholder={$t(PLACEHOLDER.input)}
|
||||
onChange={(e) => {
|
||||
if ((e.target.value as string).endsWith('/*')) {
|
||||
form.setFieldValue('path', e.target.value.slice(0, -2))
|
||||
form.setFieldValue('pathMatch', 'prefix')
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Space.Compact>
|
||||
</Form.Item>
|
||||
</Row>
|
||||
|
||||
<Form.Item<AiServiceRouterField> label={$t('提示词')} name="prompt">
|
||||
<PromptEditorResizable disabled={isDelete} variablesChange={handleVariablesChange} promptVariables={variablesTable} />
|
||||
</Form.Item>
|
||||
</Row>
|
||||
|
||||
<Form.Item<AiServiceRouterField> label={$t('提示词')} name="prompt">
|
||||
<PromptEditorResizable variablesChange={handleVariablesChange} promptVariables={variablesTable} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item<AiServiceRouterField>
|
||||
label={
|
||||
<div className="flex justify-between items-center w-full">
|
||||
<span>{$t('变量')}</span>
|
||||
<a className="flex items-center gap-[4px]" onClick={addVariable}>
|
||||
<Icon icon="ic:baseline-add" width={16} height={16} />
|
||||
New
|
||||
</a>
|
||||
</div>
|
||||
}
|
||||
name="variables"
|
||||
className="[&>.ant-row>.ant-col>label]:w-full"
|
||||
>
|
||||
<EditableTableNotAutoGen<VariableItems & { _id: string }>
|
||||
getFromRef={setVariablesTableRef}
|
||||
configFields={AI_SERVICE_VARIABLES_TABLE_COLUMNS}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item<AiServiceRouterField> label={$t('描述')} name="description">
|
||||
<Input.TextArea className="w-INPUT_NORMAL" placeholder={$t('输入这个接口的描述')} />
|
||||
</Form.Item>
|
||||
|
||||
<Row className="flex justify-between items-center w-full gap-btnbase">
|
||||
<Form.Item<AiServiceRouterField>
|
||||
className="flex-1"
|
||||
label={$t('请求超时时间')}
|
||||
name={'timeout'}
|
||||
rules={[{ required: true }]}
|
||||
label={
|
||||
<div className="flex justify-between items-center w-full">
|
||||
<span>{$t('变量')}</span>
|
||||
<a
|
||||
className={`flex items-center gap-[4px] ${isDelete ? 'cursor-not-allowed' : ''}`}
|
||||
onClick={addVariable}
|
||||
>
|
||||
<Icon icon="ic:baseline-add" width={16} height={16} />
|
||||
New
|
||||
</a>
|
||||
</div>
|
||||
}
|
||||
name="variables"
|
||||
className="[&>.ant-row>.ant-col>label]:w-full"
|
||||
>
|
||||
<InputNumber className="w-INPUT_NORMAL" suffix="ms" min={1} placeholder={$t(PLACEHOLDER.input)} />
|
||||
<EditableTableNotAutoGen<VariableItems & { _id: string }>
|
||||
getFromRef={setVariablesTableRef}
|
||||
configFields={AI_SERVICE_VARIABLES_TABLE_COLUMNS}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item<AiServiceRouterField> label={$t('描述')} name="description">
|
||||
<Input.TextArea className="w-INPUT_NORMAL" placeholder={$t('输入这个接口的描述')} />
|
||||
</Form.Item>
|
||||
|
||||
<Row className="flex justify-between items-center w-full gap-btnbase">
|
||||
<Form.Item<AiServiceRouterField>
|
||||
className="flex-1"
|
||||
label={$t('请求超时时间')}
|
||||
name={'timeout'}
|
||||
rules={[{ required: true }]}
|
||||
>
|
||||
<InputNumber className="w-INPUT_NORMAL" suffix="ms" min={1} placeholder={$t(PLACEHOLDER.input)} />
|
||||
</Form.Item>
|
||||
<Form.Item<AiServiceRouterField>
|
||||
className="flex-1"
|
||||
label={$t('重试次数')}
|
||||
name={'retry'}
|
||||
rules={[{ required: true }]}
|
||||
>
|
||||
<InputNumber className="w-INPUT_NORMAL" min={0} placeholder={$t(PLACEHOLDER.input)} />
|
||||
</Form.Item>
|
||||
</Row>
|
||||
<Form.Item<AiServiceRouterField>
|
||||
className="flex-1"
|
||||
label={$t('重试次数')}
|
||||
name={'retry'}
|
||||
rules={[{ required: true }]}
|
||||
label={$t('拦截接口')}
|
||||
name="disabled"
|
||||
extra={$t('开启拦截后,网关会拦截所有该路径的请求。')}
|
||||
>
|
||||
<InputNumber className="w-INPUT_NORMAL" min={0} placeholder={$t(PLACEHOLDER.input)} />
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</Row>
|
||||
<Form.Item<AiServiceRouterField>
|
||||
label={$t('拦截接口')}
|
||||
name="disabled"
|
||||
extra={$t('开启拦截后,网关会拦截所有该路径的请求。')}
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</div>
|
||||
</Form>
|
||||
</div>
|
||||
</Form>
|
||||
</WithPermission>
|
||||
</Spin>
|
||||
<DrawerWithFooter title={$t('模型配置')} open={open} onClose={onClose} onSubmit={() => handlerSubmit()}>
|
||||
<AiServiceRouterModelConfig ref={drawerAddFormRef} llmList={llmList} entity={defaultLlm!} />
|
||||
|
||||
@@ -31,7 +31,7 @@ export default function CustomEdge({
|
||||
{label && (
|
||||
<EdgeLabelRenderer>
|
||||
<a
|
||||
href={`${label?.toString().includes('apis') ? '/aiapis' : '/keysetting'}?modelId=${modelId}`}
|
||||
href={`${label?.toString().includes('apis') ? '/aiApis' : '/keysetting'}?modelId=${modelId}`}
|
||||
target="_blank"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
|
||||
Reference in New Issue
Block a user