diff --git a/web/src/api/models.ts b/web/src/api/models.ts index eb18ce91..2d590287 100644 --- a/web/src/api/models.ts +++ b/web/src/api/models.ts @@ -66,9 +66,9 @@ export const addModelPlaza = (model_base_id: string) => { } // Create custom model export const addCustomModel = (data: CustomModelForm) => { - return request.post('/models/model_plaza', data) + return request.post('/models', data) } // Update custom model export const updateCustomModel = (model_base_id: string, data: CustomModelForm) => { - return request.put(`/models/model_plaza/${model_base_id}`, data) + return request.put(`/models/${model_base_id}`, data) } \ No newline at end of file diff --git a/web/src/components/Upload/UploadImages.tsx b/web/src/components/Upload/UploadImages.tsx index 47343482..e60a5b81 100644 --- a/web/src/components/Upload/UploadImages.tsx +++ b/web/src/components/Upload/UploadImages.tsx @@ -93,7 +93,7 @@ const UploadImages = forwardRef(({ onChange, disabled = false, fileSize, - fileType = ['png', 'jpg', 'gif'], + fileType = ['png', 'jpg', 'gif', 'svg'], isAutoUpload = true, maxCount = 1, className = 'rb:size-24! rb:leading-1!', diff --git a/web/src/views/ModelManagement/List.tsx b/web/src/views/ModelManagement/List.tsx index bf8b42d7..ffa89fb4 100644 --- a/web/src/views/ModelManagement/List.tsx +++ b/web/src/views/ModelManagement/List.tsx @@ -10,11 +10,11 @@ * Shows model tags and allows viewing model details */ -import { useRef, useState, useEffect, type FC } from 'react'; +import { useRef, useState, useEffect, forwardRef, useImperativeHandle } from 'react'; import { Button, Flex, Row, Col } from 'antd' import { useTranslation } from 'react-i18next'; -import type { ProviderModelItem, KeyConfigModalRef, ModelListDetailRef } from './types' +import type { ProviderModelItem, KeyConfigModalRef, ModelListDetailRef, ModelListItem, BaseRef } from './types' import RbCard from '@/components/RbCard/Card' import { getModelNewList } from '@/api/models' import PageEmpty from '@/components/Empty/PageEmpty'; @@ -26,11 +26,12 @@ import { getLogoUrl } from './utils' /** * Model list component */ -const ModelList: FC<{ query: any }> = ({ query }) => { +const ModelList = forwardRef void; }> (({ query, handleEdit }, ref) => { const { t } = useTranslation(); const keyConfigModalRef = useRef(null) const modelListDetailRef = useRef(null) const [list, setList] = useState([]) + useEffect(() => { getList() }, [query]) @@ -54,6 +55,11 @@ const ModelList: FC<{ query: any }> = ({ query }) => { keyConfigModalRef.current?.handleOpen(vo) } + /** Expose methods to parent component */ + useImperativeHandle(ref, () => ({ + getList, + modelListDetailRefresh: () => modelListDetailRef.current?.handleRefresh() + })); return ( <> {list.length === 0 @@ -96,9 +102,10 @@ const ModelList: FC<{ query: any }> = ({ query }) => { ) -} +}) export default ModelList \ No newline at end of file diff --git a/web/src/views/ModelManagement/Square.tsx b/web/src/views/ModelManagement/Square.tsx index 67ef641d..a9b345a1 100644 --- a/web/src/views/ModelManagement/Square.tsx +++ b/web/src/views/ModelManagement/Square.tsx @@ -26,7 +26,7 @@ import { getLogoUrl } from './utils' /** * Model square component */ -const ModelSquare = forwardRef void; }>(({ query, handleEdit }, ref) => { +const ModelSquare = forwardRef (({ query }, ref) => { const { t } = useTranslation(); const { message } = App.useApp() const modelSquareDetailRef = useRef(null) @@ -96,7 +96,6 @@ const ModelSquare = forwardRef {item.add_count} - {!item.is_official && } {item.is_added ? : @@ -114,7 +113,6 @@ const ModelSquare = forwardRef ) diff --git a/web/src/views/ModelManagement/components/CustomModelModal.tsx b/web/src/views/ModelManagement/components/CustomModelModal.tsx index 5366baa9..fb0db96e 100644 --- a/web/src/views/ModelManagement/components/CustomModelModal.tsx +++ b/web/src/views/ModelManagement/components/CustomModelModal.tsx @@ -11,10 +11,10 @@ */ import { forwardRef, useImperativeHandle, useState } from 'react'; -import { Form, Input, App, Select } from 'antd'; +import { Form, Input, App } from 'antd'; import { useTranslation } from 'react-i18next'; -import type { CustomModelForm, ModelPlazaItem, CustomModelModalRef, CustomModelModalProps } from '../types'; +import type { CustomModelForm, ModelListItem, CustomModelModalRef, CustomModelModalProps } from '../types'; import RbModal from '@/components/RbModal' import CustomSelect from '@/components/CustomSelect' import UploadImages from '@/components/Upload/UploadImages' @@ -30,22 +30,21 @@ const CustomModelModal = forwardRef( const { t } = useTranslation(); const { message } = App.useApp(); const [visible, setVisible] = useState(false); - const [model, setModel] = useState({} as ModelPlazaItem); + const [model, setModel] = useState({} as ModelListItem); const [isEdit, setIsEdit] = useState(false); const [form] = Form.useForm(); const [loading, setLoading] = useState(false) - const formValues = Form.useWatch([], form) /** Close modal and reset state */ const handleClose = () => { - setModel({} as ModelPlazaItem); + setModel({} as ModelListItem); form.resetFields(); setLoading(false) setVisible(false); }; /** Open modal with optional model data for editing */ - const handleOpen = (model?: ModelPlazaItem) => { + const handleOpen = (model?: ModelListItem) => { if (model) { setIsEdit(true); setModel(model); @@ -66,7 +65,7 @@ const CustomModelModal = forwardRef( const res = isEdit ? updateCustomModel(model.id, rest) : addCustomModel(data) res.then(() => { - refresh && refresh() + refresh && refresh(isEdit) handleClose() message.success(isEdit ? t('common.updateSuccess') : t('common.createSuccess')) }) @@ -79,12 +78,10 @@ const CustomModelModal = forwardRef( form .validateFields() .then((values) => { - setLoading(true) const { logo, ...rest } = values; let formData: CustomModelForm = { ...rest } - formData.is_official = false; if (typeof logo === 'object' && logo?.response?.data.file_id) { getFileLink(logo?.response?.data.file_id) @@ -111,8 +108,6 @@ const CustomModelModal = forwardRef( handleOpen, })); - console.log('formValues', formValues) - return ( ( > + + - diff --git a/web/src/views/ModelManagement/components/ModelListDetail.tsx b/web/src/views/ModelManagement/components/ModelListDetail.tsx index 2955660d..aad7b887 100644 --- a/web/src/views/ModelManagement/components/ModelListDetail.tsx +++ b/web/src/views/ModelManagement/components/ModelListDetail.tsx @@ -30,12 +30,13 @@ import CustomSelect from '@/components/CustomSelect' interface ModelListDetailProps { /** Callback to refresh parent list */ refresh?: () => void; + handleEdit: (vo?: ModelListItem) => void; } /** * Model list detail drawer component */ -const ModelListDetail = forwardRef(({ refresh }, ref) => { +const ModelListDetail = forwardRef(({ refresh, handleEdit }, ref) => { const { t } = useTranslation(); const [open, setOpen] = useState(false); const [data, setData] = useState({} as ProviderModelItem) @@ -95,7 +96,8 @@ const ModelListDetail = forwardRef(({ /** Expose methods to parent component */ useImperativeHandle(ref, () => ({ - handleOpen, + handleOpen, + handleRefresh, })); /** Filter models by selected type */ @@ -149,7 +151,10 @@ const ModelListDetail = forwardRef(({
- + + + + diff --git a/web/src/views/ModelManagement/components/ModelSquareDetail.tsx b/web/src/views/ModelManagement/components/ModelSquareDetail.tsx index fd52260a..4fee5a7b 100644 --- a/web/src/views/ModelManagement/components/ModelSquareDetail.tsx +++ b/web/src/views/ModelManagement/components/ModelSquareDetail.tsx @@ -29,14 +29,12 @@ import { getLogoUrl } from '../utils' interface ModelSquareDetailProps { /** Callback to refresh parent list */ refresh: () => void; - /** Callback to edit model */ - handleEdit: (vo: ModelPlazaItem) => void; } /** * Model square detail drawer component */ -const ModelSquareDetail = forwardRef(({ refresh, handleEdit }, ref) => { +const ModelSquareDetail = forwardRef(({ refresh }, ref) => { const { t } = useTranslation(); const { message } = App.useApp() const [model, setModel] = useState({} as ModelPlaza) @@ -112,7 +110,6 @@ const ModelSquareDetail = forwardRef {item.add_count} - {!item.is_official && } {item.is_added ? : diff --git a/web/src/views/ModelManagement/index.tsx b/web/src/views/ModelManagement/index.tsx index c3b5ca83..35d7d864 100644 --- a/web/src/views/ModelManagement/index.tsx +++ b/web/src/views/ModelManagement/index.tsx @@ -15,7 +15,7 @@ import { Button, Flex, Space, type SegmentedProps, Form } from 'antd' import { useTranslation } from 'react-i18next'; import GroupModelModal from './components/GroupModelModal' -import type { ModelListItem, GroupModelModalRef, CustomModelModalRef, ModelPlazaItem, BaseRef, Query } from './types' +import type { ModelListItem, GroupModelModalRef, CustomModelModalRef, BaseRef, Query } from './types' import SearchInput from '@/components/SearchInput' import PageTabs from '@/components/PageTabs' import GroupModel from './Group' @@ -38,7 +38,7 @@ const tabKeys = ['group', 'list', 'square'] const configModalRef = useRef(null) const customModelModalRef = useRef(null) const groupRef = useRef(null) - const squareRef = useRef(null) + const modelListRef = useRef(null) const [form] = Form.useForm() const query = Form.useWatch([], form) @@ -56,24 +56,29 @@ const tabKeys = ['group', 'list', 'square'] } /** Open edit modal based on active tab */ - const handleEdit = (vo?: ModelListItem | ModelPlazaItem) => { + const handleEdit = (vo?: ModelListItem | ModelListItem) => { switch(activeTab) { case 'group': configModalRef?.current?.handleOpen(vo as ModelListItem) break - case 'square': - customModelModalRef?.current?.handleOpen(vo as ModelPlazaItem) + case 'list': + customModelModalRef?.current?.handleOpen(vo as ModelListItem) break } } /** Refresh list based on active tab */ - const handleRefresh = () => { + const handleRefresh = (isEdit?: boolean) => { switch (activeTab) { case 'group': groupRef.current?.getList() break - case 'square': - squareRef.current?.getList() + case 'list': + console.log('isEdit', isEdit) + if (isEdit) { + modelListRef.current?.modelListDetailRefresh?.() + } else { + modelListRef.current?.getList() + } break } } @@ -122,15 +127,15 @@ const tabKeys = ['group', 'list', 'square'] } {activeTab === 'group' && } - {activeTab === 'square' && } + {activeTab === 'list' && }
{activeTab === 'group' && } - {activeTab === 'list' && } - {activeTab === 'square' && } + {activeTab === 'list' && } + {activeTab === 'square' && }
void; + handleRefresh: () => void; } /** @@ -284,10 +285,12 @@ export interface CustomModelForm { logo?: any; /** Model description */ description: string; - /** Whether model is official */ - is_official: boolean; - /** Model tags */ - tags: string[]; + api_keys: Array<{ + /** API key value */ + api_key: string; + /** API base URL */ + api_base: string; + }> } /** @@ -295,7 +298,7 @@ export interface CustomModelForm { */ export interface CustomModelModalRef { /** Open modal with optional model plaza item */ - handleOpen: (vo?: ModelPlazaItem) => void; + handleOpen: (vo?: ModelListItem) => void; } /** @@ -303,7 +306,7 @@ export interface CustomModelModalRef { */ export interface CustomModelModalProps { /** Callback to refresh model list */ - refresh?: () => void; + refresh?: (flag?: boolean) => void; } /** @@ -312,4 +315,5 @@ export interface CustomModelModalProps { export interface BaseRef { /** Refresh list data */ getList: () => void; + modelListDetailRefresh?: () => void; } \ No newline at end of file