diff --git a/frontend/packages/common/src/components/aoplatform/BasicLayout.tsx b/frontend/packages/common/src/components/aoplatform/BasicLayout.tsx index 19767e95..738a6866 100644 --- a/frontend/packages/common/src/components/aoplatform/BasicLayout.tsx +++ b/frontend/packages/common/src/components/aoplatform/BasicLayout.tsx @@ -280,9 +280,9 @@ function BasicLayout({ project = 'core' }: { project: string }) { collapsedButtonRender={false} >
diff --git a/frontend/packages/common/src/components/aoplatform/InsidePage.tsx b/frontend/packages/common/src/components/aoplatform/InsidePage.tsx index 3260e886..40d55930 100644 --- a/frontend/packages/common/src/components/aoplatform/InsidePage.tsx +++ b/frontend/packages/common/src/components/aoplatform/InsidePage.tsx @@ -22,6 +22,7 @@ class InsidePageProps { headerClassName?: string = '' /** 整个页面滚动 */ scrollPage?: boolean = true + customPadding?: boolean customBtn?: ReactNode } @@ -41,6 +42,7 @@ const InsidePage: FC = ({ contentClassName = '', headerClassName = '', scrollPage = true, + customPadding = false, customBtn }) => { const navigate = useNavigate() @@ -57,7 +59,7 @@ const InsidePage: FC = ({ {!pageTitle && !description && !backUrl && !customBtn ? ( <> ) : ( -
+
{backUrl && (
+
+ + ) + } + + const getOllamaData = async () => { + const response = await fetchData>('model/local/source/ollama', { + method: 'GET' + }) + + if (response.code === STATUS_CODE.SUCCESS) { + setOllamaAddress(response.data?.config?.address || '') + } else { + message.error(response.msg || $t(RESPONSE_TIPS.error)) + } + } + const handleEdit = (record: ModelListData) => { modal.confirm({ title: $t('模型设置'), - content: , + content: ( + + ), onOk: () => { return EditLocalModelModalRef.current?.save().then((res) => { if (res === true) { @@ -243,7 +323,7 @@ const LocalModelList: React.FC = () => { { title: '', key: 'option', - btnNums: 4, + btnNums: 2, fixed: 'right', valueType: 'option', render: (_: React.ReactNode, entity: ModelListData) => [ @@ -283,7 +363,9 @@ const LocalModelList: React.FC = () => { } const modalInstance = modal.confirm({ title: $t('部署过程'), - content: , + content: ( + + ), footer: () => { return }, @@ -319,13 +401,14 @@ const LocalModelList: React.FC = () => { } }} > - {stateColumnMap[entity?.state as string]?.text || '-'} + {$t(stateColumnMap[entity?.state as string]?.text || '-')} ) }, { title: $t('Apis'), dataIndex: 'apiCount', + width: 100, render: (dom: React.ReactNode, record: ModelListData) => ( { { setSearchWord(e.target.value) pageListRef.current?.reload() }} + beforeNewBtn={ + [] + } showPagination={true} searchPlaceholder={$t('请输入名称搜索')} columns={columns} diff --git a/frontend/packages/core/src/pages/guide/AIModelGuide.tsx b/frontend/packages/core/src/pages/guide/AIModelGuide.tsx index 0ca41ad1..89fef2da 100644 --- a/frontend/packages/core/src/pages/guide/AIModelGuide.tsx +++ b/frontend/packages/core/src/pages/guide/AIModelGuide.tsx @@ -6,16 +6,18 @@ import { $t } from '@common/locales' import { Icon } from '@iconify/react/dist/iconify.js' import { App } from 'antd' import { Card } from 'antd' -import { useRef } from 'react' +import { useEffect, useRef, useState } from 'react' import { useNavigate } from 'react-router-dom' import AiSettingModalContent, { AiSettingModalContentHandle } from '../aiSetting/AiSettingModal' import { checkAccess } from '@common/utils/permission' import LocalAiDeploy, { LocalAiDeployHandle } from './LocalAiDeploy' import useDeployLocalModel from './deployModelUtil' import RestAIDeploy, { RestAIDeployHandle } from './RestAIDeploy' +import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const' +import { useFetch } from '@common/hooks/http' export const AIModelGuide = () => { - const { modal } = App.useApp() + const { message, modal } = App.useApp() const entityData = useRef(null) const navigateTo = useNavigate() const { accessData } = useGlobalContext() @@ -23,6 +25,8 @@ export const AIModelGuide = () => { const localAiDeployRef = useRef() const restAiDeployRef = useRef() const { deployLocalModel } = useDeployLocalModel() + const { fetchData } = useFetch() + const [ollamaAddress, setOllamaAddress] = useState('') const dumpServerPage = () => { navigateTo('/service/list') @@ -105,10 +109,31 @@ export const AIModelGuide = () => { }) } + + const getOllamaData = async () => { + const response = await fetchData>('model/local/source/ollama', { + method: 'GET' + }) + + if (response.code === STATUS_CODE.SUCCESS) { + setOllamaAddress(response.data?.config?.address || '') + } else { + message.error(response.msg || $t(RESPONSE_TIPS.error)) + } + } + + useEffect(() => { + getOllamaData() + }, []) + /** * 本地部署 AI 并生成 API */ const localModelCardClick = async () => { + if (!ollamaAddress) { + navigateTo('/aisetting?status=unconfigure') + return + } const modalInstance = modal.confirm({ title: $t('部署本地模型'), content: { @@ -131,6 +156,10 @@ export const AIModelGuide = () => { } const deployDeepSeek = async (e: any) => { e.stopPropagation() + if (!ollamaAddress) { + navigateTo('/aisetting?status=unconfigure') + return + } await deployLocalModel({ modelID: 'deepseek-r1' }) @@ -141,13 +170,13 @@ export const AIModelGuide = () => { { imgSrc: restAPIPic, title: $t('添加 Rest 服务'), - description: $t('支持批量添加现有 API 文档以实现统一的外部访问。'), + description: $t('导入OpenAPI文档,将现有系统的API发布到APIPark。'), click: restCardClick }, { imgSrc: onlineAIPic, title: $t('添加在线 AI API'), - description: $t('快速调用 AI 模型的云服务 API,方便管理提示词和统一计费。'), + description: $t('添加公有云AI模型的 API Key,通过APIPark 统一调用公有云的AI模型。'), click: aiCardClick }, { @@ -164,7 +193,9 @@ export const AIModelGuide = () => { } ] return ( -
+ <> +

{$t('⚡您可快速通过以下方式开放API供大家使用:')}

+
{cardList.map((item, itemIndex) => ( { ))}
+ ) } diff --git a/frontend/packages/core/src/pages/guide/Guide.tsx b/frontend/packages/core/src/pages/guide/Guide.tsx index deeff7fe..72801b99 100644 --- a/frontend/packages/core/src/pages/guide/Guide.tsx +++ b/frontend/packages/core/src/pages/guide/Guide.tsx @@ -151,12 +151,13 @@ export default function Guide() { description={

+ 🦄 APIPark {$t( - '你能通过 APIPark 快速在企业内部构建 API 开放门户/市场,享受极致的转发性能、API 可观测、服务治理、多租户管理、订阅审核流程等诸多好处。' + '是开源的一站式 AI 网关与 API 门户,可快速接入 OpenAI/DeepSeek 等各类 AI 模型,通过统一请求格式避免模型切换对业务造成影响,提供企业级 API 安全防护(鉴权/限流/敏感词过滤)与实时用量监控,支持团队内 API 共享协作,管理接口订阅授权并保证您的API安全。' )}

- {$t('如果你喜欢我们的产品,欢迎给我们 Star 或提供产品反馈意见。')} + {$t('✨ 欢迎在 Github 为我们 Star 或提供产品反馈意见。')} {$t('点击这里')} @@ -184,7 +185,9 @@ export default function Guide() { } showBorder={false} scrollPage={false} - contentClassName=" w-full pr-PAGE_INSIDE_X pb-PAGE_INSIDE_B" + customPadding={true} + headerClassName="pt-[30px] pl-[40px]" + contentClassName=" w-full pr-PAGE_INSIDE_X pb-PAGE_INSIDE_B pl-[40px]" >

diff --git a/frontend/packages/core/src/pages/guide/LocalAiDeploy.tsx b/frontend/packages/core/src/pages/guide/LocalAiDeploy.tsx index 1e5839ef..e131687b 100644 --- a/frontend/packages/core/src/pages/guide/LocalAiDeploy.tsx +++ b/frontend/packages/core/src/pages/guide/LocalAiDeploy.tsx @@ -114,7 +114,7 @@ const LocalAiDeploy = forwardRef((props: any, ref: any name="partitionInsideCert" autoComplete="off" > - + - - -
{$t('热点模型')} @@ -179,6 +158,27 @@ const LocalAiDeploy = forwardRef((props: any, ref: any : null}
+ + + + - OR + {$t('或')}