Compare commits

...

6 Commits

Author SHA1 Message Date
ningyv 07b49030a2 fix: Display only file logs on the log page. 2025-03-19 16:13:03 +08:00
ningyv 0b0cd25d2c fix: Header navigation click range issue 2025-03-19 14:17:13 +08:00
ningyv 2e867da093 feat: feature/1.6-Integrate custom model 2025-03-14 18:47:04 +08:00
ningyv acb0ceb9a9 feat: feature/1.6-Integrate custom model 2025-03-13 13:46:32 +08:00
ningyv a02d505e2e feat: feature/1.6-Integrate custom model 2025-03-13 11:58:28 +08:00
ningyv a58e2c4e67 feat: feature/1.6-Integrate custom model 2025-03-12 15:42:07 +08:00
9 changed files with 86 additions and 31 deletions
@@ -1,5 +1,5 @@
import { App, Col, Form, Input, Row, Table, Tooltip } from 'antd'
import { forwardRef, useEffect, useImperativeHandle, useMemo } from 'react'
import { forwardRef, useEffect, useImperativeHandle, useMemo, useRef } from 'react'
import {
PublishApprovalInfoType,
PublishApprovalModalHandle,
@@ -36,6 +36,7 @@ export const PublishApprovalModalContent = forwardRef<PublishApprovalModalHandle
const [form] = Form.useForm()
const { fetchData } = useFetch()
const { state } = useGlobalContext()
const versionInputRef = useRef<Input>(null)
const save: (operate: 'pass' | 'refuse') => Promise<boolean | string> = (operate) => {
if (type === 'view') {
@@ -140,6 +141,12 @@ export const PublishApprovalModalContent = forwardRef<PublishApprovalModalHandle
useEffect(() => {
form.setFieldsValue({ opinion: '', ...data })
// 如果是添加模式且insidePage为true,自动聚焦版本号输入框
if (type === 'add' && insidePage && versionInputRef.current) {
setTimeout(() => {
versionInputRef.current?.focus()
}, 100)
}
}, [])
const translatedUpstreamColumns = useMemo(
@@ -335,7 +342,12 @@ export const PublishApprovalModalContent = forwardRef<PublishApprovalModalHandle
{insidePage && (
<>
<Form.Item label={$t('版本号')} name="version" rules={[{ required: true, whitespace: true }]}>
<Input className="w-INPUT_NORMAL" disabled={type !== 'add'} placeholder={$t(PLACEHOLDER.input)} />
<Input
className="w-INPUT_NORMAL"
disabled={type !== 'add'}
placeholder={$t(PLACEHOLDER.input)}
ref={versionInputRef}
/>
</Form.Item>
<Form.Item label={$t('版本说明')} name="versionRemark">
@@ -91,8 +91,15 @@ const AIProviderSelect: React.FC<AIProviderSelectProps> = ({ value, onChange, so
label: (
<Space className="flex items-center">
<span
className="flex items-center h-[20px] w-[20px]"
dangerouslySetInnerHTML={{ __html: provider.logo }}
className="flex items-center justify-center h-[20px] w-[20px] overflow-hidden"
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}}
dangerouslySetInnerHTML={{
__html: provider.logo.replace(/<svg/, '<svg style="max-width:100%;max-height:100%;width:auto;height:auto;"')
}}
></span>
<span>{provider.name}</span>
</Space>
+9
View File
@@ -666,6 +666,15 @@ p{
display: none;
}
.apipark-layout-base-menu-horizontal-menu-item {
padding-right: 0px !important;
padding-left: 0px !important;
}
.apipark-layout-base-menu-horizontal-item-title {
padding-left: 16px;
padding-right: 16px;
}
.ant-pro-table-list-toolbar-setting-items{
position:absolute;
top:18px;
@@ -10,7 +10,7 @@ import { DefaultOptionType } from 'antd/es/select'
import { forwardRef, useEffect, useImperativeHandle, useState } from 'react'
export type AiServiceRouterModelConfigHandle = {
save: () => Promise<{ id: string; config: string, type: string, provider: string }>
save: () => Promise<{ id: string; config: string; type: string; provider: string }>
}
export type AiServiceRouterModelConfigProps = {
@@ -49,7 +49,7 @@ const AiServiceRouterModelConfig = forwardRef<AiServiceRouterModelConfigHandle,
/**
* 获取本地模型列表
* @param setDefaultValue
* @param setDefaultValue
*/
const getLocalLlmList = (setDefaultValue?: boolean) => {
fetchData<LocalLlmType[]>('simple/ai/models/local/configured', {
@@ -113,12 +113,11 @@ const AiServiceRouterModelConfig = forwardRef<AiServiceRouterModelConfigHandle,
const { code, data, msg } = response
if (code === STATUS_CODE.SUCCESS) {
setProviderList(
data.providers
?.map((x: SimpleAiProviderItem) => {
return { ...x, label: x.name, value: x.id }
})
data.providers?.map((x: SimpleAiProviderItem) => {
return { ...x, label: x.name, value: x.id }
})
)
if (setDefaultValue && data.providers.length) {
if (setDefaultValue && data.providers.length) {
const id = data.providers[0].id
form.setFieldValue('provider', id)
getLlmList(id)
@@ -179,9 +178,14 @@ const AiServiceRouterModelConfig = forwardRef<AiServiceRouterModelConfigHandle,
rules={[{ required: true }]}
>
<Select
showSearch
className="w-INPUT_NORMAL"
filterOption={(input, option) => (option?.searchText ?? '').includes(input.toLowerCase())}
placeholder={$t(PLACEHOLDER.select)}
options={providerList}
options={providerList.map((x) => ({
...x,
searchText: x.name.toLowerCase()
}))}
onChange={(e) => {
getLlmList(e)
}}
@@ -191,19 +195,20 @@ const AiServiceRouterModelConfig = forwardRef<AiServiceRouterModelConfigHandle,
<Form.Item<AiServiceRouterModelConfigField> label={$t('模型')} name="id" rules={[{ required: true }]}>
<Select
showSearch
className="w-INPUT_NORMAL"
placeholder={$t(PLACEHOLDER.select)}
options={
llmList?.map((x) => ({
value: x.id,
label: (
<div className="flex items-center gap-[10px]" key={x.id}>
<span>{x.name || x.id}</span>
{modelType === 'online' && x?.scopes?.map((s: any) => <Tag>{s?.toLocaleUpperCase()}</Tag>)}
</div>
)
}))
}
filterOption={(input, option) => (option?.searchText ?? '').includes(input.toLowerCase())}
options={llmList?.map((x) => ({
value: x.id,
label: (
<div className="flex items-center gap-[10px]" key={x.id}>
<span>{x.name || x.id}</span>
{modelType === 'online' && x?.scopes?.map((s: any) => <Tag>{s?.toLocaleUpperCase()}</Tag>)}
</div>
),
searchText: x.name.toLowerCase()
}))}
onChange={(e) => {
form.setFieldValue('config', llmList.find((x) => x.id === e)?.config)
}}
@@ -283,8 +283,9 @@ const AiSettingModalContent = forwardRef<AiSettingModalContentHandle, AiSettingM
),
onOk: () => {
return addModelModalRef.current?.save().then((res) => {
if (res === true) {
if (res) {
getLlmList(lastLlmID)
form.setFieldValue('defaultLlm', res)
}
})
},
@@ -102,7 +102,7 @@ const AddModels = forwardRef<addModelsContentHandle, addModelContentProps>((prop
...value,
id: modelID
}
fetchData<BasicResponse<null>>('ai/provider/model', {
fetchData<BasicResponse<{ model: { id: string, name: string } }>>('ai/provider/model', {
method: type === 'edit' ? 'PUT' : 'POST',
eoParams: { provider: providerID },
eoBody: finalValue,
@@ -112,7 +112,8 @@ const AddModels = forwardRef<addModelsContentHandle, addModelContentProps>((prop
const { code, msg } = response
if (code === STATUS_CODE.SUCCESS) {
message.success($t(RESPONSE_TIPS.success) || msg)
resolve(true)
const llmId = response.data?.model?.id
resolve(llmId)
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
reject(msg || $t(RESPONSE_TIPS.error))
@@ -182,7 +182,9 @@ const AddLoadBalancingModel = forwardRef<LoadBalancingHandle>((props, ref: any)
{modelType === 'online' && (
<Form.Item<LoadModelDetailData> label={$t('模型供应商')} name="provider" rules={[{ required: true }]}>
<Select
showSearch
className="w-INPUT_NORMAL"
filterOption={(input, option) => (option?.searchText ?? '').includes(input.toLowerCase())}
placeholder={$t(PLACEHOLDER.select)}
loading={modelProviderLoading}
options={modelProviderData?.map((x) => ({
@@ -191,7 +193,8 @@ const AddLoadBalancingModel = forwardRef<LoadBalancingHandle>((props, ref: any)
<div className="flex items-center gap-[10px]">
<span>{x.name}</span>
</div>
)
),
searchText: x.name.toLowerCase()
}))}
onChange={(e) => {
modelProviderChange(e)
@@ -201,8 +204,10 @@ const AddLoadBalancingModel = forwardRef<LoadBalancingHandle>((props, ref: any)
)}
<Form.Item label={$t('模型')} name="model" className="mt-[16px]" rules={[{ required: true }]}>
<Select
showSearch
className="w-INPUT_NORMAL"
placeholder={$t(PLACEHOLDER.input)}
filterOption={(input, option) => (option?.searchText ?? '').includes(input.toLowerCase())}
loading={llmListLoading}
options={
llmList?.map((x) => ({
@@ -212,7 +217,8 @@ const AddLoadBalancingModel = forwardRef<LoadBalancingHandle>((props, ref: any)
<span>{x.name || x.id}</span>
{ modelType === 'online' &&x?.scopes?.map((s: any) => <Tag key={s}>{s?.toLocaleUpperCase()}</Tag>)}
</div>
)
),
searchText: x.name.toLowerCase()
}))
}
onChange={(value) => {
@@ -40,7 +40,7 @@ const LogSettings = () => {
const menuData = useMemo(() => {
const newMenu = menuItems?.map((x: DynamicMenuItem) => {
return getItem(
<Link to={`template/${x.name}`}>{$t(x.title)}</Link>,
<Link to={`/logsettings/template/${x.name}`}>{$t(x.title)}</Link>,
x.name,
undefined,
undefined,
@@ -450,9 +450,14 @@ const SystemConfig = forwardRef<SystemConfigHandle>((_, ref) => {
>
{providerOptionList && providerOptionList.length > 0 ? (
<Select
showSearch
className="w-INPUT_NORMAL"
filterOption={(input, option) => (option?.searchText ?? '').includes(input.toLowerCase())}
placeholder={$t(PLACEHOLDER.input)}
options={providerOptionList}
options={providerOptionList.map((x) => ({
...x,
searchText: x.name.toLowerCase()
}))}
onChange={(e) => {
modelProviderChange(e)
}}
@@ -467,7 +472,16 @@ const SystemConfig = forwardRef<SystemConfigHandle>((_, ref) => {
)}
</Form.Item>
<Form.Item<AiServiceConfigFieldType> label={$t('默认模型')} name="model" rules={[{ required: true }]}>
<Select className="w-INPUT_NORMAL" placeholder={$t(PLACEHOLDER.input)} options={modelList}></Select>
<Select
showSearch
filterOption={(input, option) => (option?.searchText ?? '').includes(input.toLowerCase())}
className="w-INPUT_NORMAL"
placeholder={$t(PLACEHOLDER.input)}
options={modelList ? modelList.map((x) => ({
...x,
searchText: x.name.toLowerCase()
})) : []}
></Select>
</Form.Item>
</>
)}