feat(web): model logo update

This commit is contained in:
zhaoying
2026-01-28 10:50:48 +08:00
parent ce01e588c9
commit 2c21712d58
8 changed files with 47 additions and 29 deletions

View File

@@ -7,14 +7,15 @@ import { useTranslation } from 'react-i18next';
import PlusIcon from '@/assets/images/plus.svg' import PlusIcon from '@/assets/images/plus.svg'
import { cookieUtils } from '@/utils/request' import { cookieUtils } from '@/utils/request'
import { fileUploadUrl } from '@/api/fileStorage' import { fileUploadUrl } from '@/api/fileStorage'
import styles from './index.module.less'
interface UploadImagesProps extends Omit<UploadProps, 'onChange'> { interface UploadImagesProps extends Omit<UploadProps, 'onChange' | 'fileList'> {
/** 上传接口地址 */ /** 上传接口地址 */
action?: string; action?: string;
/** 是否支持多选 */ /** 是否支持多选 */
multiple?: boolean; multiple?: boolean;
/** 已上传的文件列表 */ /** 已上传的文件列表 */
fileList?: UploadFile[]; fileList?: UploadFile[] | UploadFile;
/** 文件列表变化回调 */ /** 文件列表变化回调 */
onChange?: (fileList?: UploadFile[] | UploadFile) => void; onChange?: (fileList?: UploadFile[] | UploadFile) => void;
/** 禁用上传 */ /** 禁用上传 */
@@ -73,12 +74,18 @@ const UploadImages = forwardRef<UploadImagesRef, UploadImagesProps>(({
}, ref) => { }, ref) => {
const { t } = useTranslation(); const { t } = useTranslation();
const { message, modal } = App.useApp() const { message, modal } = App.useApp()
const [fileList, setFileList] = useState<UploadFile[]>(propFileList); const [fileList, setFileList] = useState<UploadFile[]>([]);
const [accept, setAccept] = useState<string | undefined>(); const [accept, setAccept] = useState<string | undefined>();
// const [loading, setLoading] = useState(false); // const [loading, setLoading] = useState(false);
const [previewOpen, setPreviewOpen] = useState(false); const [previewOpen, setPreviewOpen] = useState(false);
const [previewImage, setPreviewImage] = useState(''); const [previewImage, setPreviewImage] = useState('');
useEffect(() => {
if (!Array.isArray(propFileList) && typeof propFileList === 'object') {
setFileList([propFileList]);
}
}, [propFileList])
const updateValue = (list: UploadFile[]) => { const updateValue = (list: UploadFile[]) => {
if (maxCount === 1) { if (maxCount === 1) {
onChange?.(list[0]) onChange?.(list[0])
@@ -185,6 +192,7 @@ const UploadImages = forwardRef<UploadImagesRef, UploadImagesProps>(({
showRemoveIcon: true, showRemoveIcon: true,
showDownloadIcon: false, showDownloadIcon: false,
}, },
className: `${styles.imageUpload} ${className}`,
...props, ...props,
}; };

View File

@@ -0,0 +1,7 @@
.image-upload:global(.ant-upload-wrapper.ant-upload-picture-card-wrapper .ant-upload-list.ant-upload-list-picture-card .ant-upload-list-item-container),
.image-upload:global(.ant-upload-wrapper.ant-upload-picture-circle-wrapper .ant-upload-list.ant-upload-list-picture-card .ant-upload-list-item-container),
.image-upload:global(.ant-upload-wrapper.ant-upload-picture-card-wrapper .ant-upload-list.ant-upload-list-picture-circle .ant-upload-list-item-container),
.image-upload:global(.ant-upload-wrapper.ant-upload-picture-circle-wrapper .ant-upload-list.ant-upload-list-picture-circle .ant-upload-list-item-container) {
width: 96px;
height: 96px;
}

View File

@@ -20,7 +20,7 @@ import type {
} from './types' } from './types'
import type { Variable } from './components/VariableList/types' import type { Variable } from './components/VariableList/types'
import type { KnowledgeConfig } from './components/Knowledge/types' import type { KnowledgeConfig } from './components/Knowledge/types'
import type { Model } from '@/views/ModelManagement/types' import type { ModelListItem } from '@/views/ModelManagement/types'
import { getModelList } from '@/api/models'; import { getModelList } from '@/api/models';
import { saveAgentConfig } from '@/api/application' import { saveAgentConfig } from '@/api/application'
import Knowledge from './components/Knowledge/Knowledge' import Knowledge from './components/Knowledge/Knowledge'
@@ -96,8 +96,8 @@ const Agent = forwardRef<AgentRef>((_props, ref) => {
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false)
const [data, setData] = useState<Config | null>(null); const [data, setData] = useState<Config | null>(null);
const modelConfigModalRef = useRef<ModelConfigModalRef>(null) const modelConfigModalRef = useRef<ModelConfigModalRef>(null)
const [modelList, setModelList] = useState<Model[]>([]) const [modelList, setModelList] = useState<ModelListItem[]>([])
const [defaultModel, setDefaultModel] = useState<Model | null>(null) const [defaultModel, setDefaultModel] = useState<ModelListItem | null>(null)
const [chatList, setChatList] = useState<ChatData[]>([]) const [chatList, setChatList] = useState<ChatData[]>([])
const values = Form.useWatch<Config>([], form) const values = Form.useWatch<Config>([], form)
const [isSave, setIsSave] = useState(false) const [isSave, setIsSave] = useState(false)
@@ -239,7 +239,7 @@ const Agent = forwardRef<AgentRef>((_props, ref) => {
const getModels = () => { const getModels = () => {
getModelList({ type: 'llm,chat', pagesize: 100, page: 1, is_active: true }) getModelList({ type: 'llm,chat', pagesize: 100, page: 1, is_active: true })
.then(res => { .then(res => {
const response = res as { items: Model[] } const response = res as { items: ModelListItem[] }
setModelList(response.items) setModelList(response.items)
}) })
} }
@@ -249,7 +249,7 @@ const Agent = forwardRef<AgentRef>((_props, ref) => {
useEffect(() => { useEffect(() => {
if (values?.default_model_config_id && modelList.length > 0) { if (values?.default_model_config_id && modelList.length > 0) {
const filterValue = modelList.find(item => item.id === values.default_model_config_id) const filterValue = modelList.find(item => item.id === values.default_model_config_id)
setDefaultModel(filterValue as Model | null) setDefaultModel(filterValue as ModelListItem | null)
setChatList([{ setChatList([{
label: filterValue?.name || '', label: filterValue?.name || '',
model_config_id: filterValue?.id || '', model_config_id: filterValue?.id || '',

View File

@@ -86,6 +86,7 @@ const ModelSquare = forwardRef <BaseRef, { query: any; handleEdit: (vo?: ModelPl
<ModelSquareDetail <ModelSquareDetail
ref={modelSquareDetailRef} ref={modelSquareDetailRef}
refresh={getList} refresh={getList}
handleEdit={handleEdit}
/> />
</> </>
) )

View File

@@ -34,6 +34,7 @@ const CustomModelModal = forwardRef<CustomModelModalRef, CustomModelModalProps>(
setModel(model); setModel(model);
form.setFieldsValue({ form.setFieldsValue({
...model, ...model,
logo: model.logo ? { url: model.logo, uid: model.logo, status: 'done', name: 'logo' } : undefined
}); });
} else { } else {
setIsEdit(false); setIsEdit(false);
@@ -48,7 +49,7 @@ const CustomModelModal = forwardRef<CustomModelModalRef, CustomModelModalProps>(
setLoading(true) setLoading(true)
values.is_official = false; values.is_official = false;
const logo = values.logo as any; const logo = values.logo as any;
if (typeof logo === 'object') { if (typeof logo === 'object' && logo?.response?.data.file_id) {
getFileLink(logo?.response?.data.file_id).then(res => { getFileLink(logo?.response?.data.file_id).then(res => {
const logoRes = res as { url: string } const logoRes = res as { url: string }
values.logo = logoRes.url values.logo = logoRes.url
@@ -64,6 +65,7 @@ const CustomModelModal = forwardRef<CustomModelModalRef, CustomModelModalProps>(
}); });
}) })
} else { } else {
values.logo = typeof logo === 'string' ? logo : logo.url
updateCustomModel(model.id, values).then(() => { updateCustomModel(model.id, values).then(() => {
if (refresh) { if (refresh) {
refresh(); refresh();
@@ -111,7 +113,7 @@ const CustomModelModal = forwardRef<CustomModelModalRef, CustomModelModalProps>(
<Form.Item <Form.Item
name="name" name="name"
label={t('modelNew.model_name')} label={t('modelNew.model_name')}
rules={[{ required: true, message: t('common.inputPlaceholder', { title: t('modelNew.displayName') }) }]} rules={[{ required: true, message: t('common.inputPlaceholder', { title: t('modelNew.model_name') }) }]}
> >
<Input placeholder={t('common.pleaseEnter')} /> <Input placeholder={t('common.pleaseEnter')} />
</Form.Item> </Form.Item>

View File

@@ -36,7 +36,7 @@ const GroupModelModal = forwardRef<GroupModelModalRef, GroupModelModalProps>(({
form.setFieldsValue({ form.setFieldsValue({
...model, ...model,
api_key_ids: model.api_keys, api_key_ids: model.api_keys,
logo: model.logo ? [{url: model.logo, uid: model.logo, status: 'done', name: 'logo'}] : undefined logo: model.logo ? { url: model.logo, uid: model.logo, status: 'done', name: 'logo' } : undefined
}) })
} else { } else {
setIsEdit(false); setIsEdit(false);
@@ -48,7 +48,7 @@ const GroupModelModal = forwardRef<GroupModelModalRef, GroupModelModalProps>(({
form form
.validateFields() .validateFields()
.then((values) => { .then((values) => {
const { api_key_ids, logo, ...rest } = values const { api_key_ids = [], logo, ...rest } = values
const formData: CompositeModelForm = { const formData: CompositeModelForm = {
...rest, ...rest,
@@ -62,6 +62,7 @@ const GroupModelModal = forwardRef<GroupModelModalRef, GroupModelModalProps>(({
handleUpdate(formData) handleUpdate(formData)
}) })
} else { } else {
formData.logo = typeof logo === 'string' ? logo : logo.url
handleUpdate(formData) handleUpdate(formData)
} }
}) })

View File

@@ -1,6 +1,7 @@
import { useState, useImperativeHandle, forwardRef } from 'react'; import { useState, useImperativeHandle, forwardRef } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Button, Space, App } from 'antd' import { Button, Space, App, Flex } from 'antd'
import { UsergroupAddOutlined } from '@ant-design/icons';
import type { ModelPlaza, ModelPlazaItem, ModelSquareDetailRef } from '../types'; import type { ModelPlaza, ModelPlazaItem, ModelSquareDetailRef } from '../types';
import RbDrawer from '@/components/RbDrawer'; import RbDrawer from '@/components/RbDrawer';
@@ -11,8 +12,9 @@ import PageEmpty from '@/components/Empty/PageEmpty';
interface ModelSquareDetailProps { interface ModelSquareDetailProps {
refresh: () => void; refresh: () => void;
handleEdit: (vo: ModelPlazaItem) => void;
} }
const ModelSquareDetail = forwardRef<ModelSquareDetailRef, ModelSquareDetailProps>(({ refresh }, ref) => { const ModelSquareDetail = forwardRef<ModelSquareDetailRef, ModelSquareDetailProps>(({ refresh, handleEdit }, ref) => {
const { t } = useTranslation(); const { t } = useTranslation();
const { message } = App.useApp() const { message } = App.useApp()
const [model, setModel] = useState<ModelPlaza>({} as ModelPlaza) const [model, setModel] = useState<ModelPlaza>({} as ModelPlaza)
@@ -71,10 +73,17 @@ const ModelSquareDetail = forwardRef<ModelSquareDetailRef, ModelSquareDetailProp
<Tag>{t(`modelNew.${item.type}`)}</Tag> <Tag>{t(`modelNew.${item.type}`)}</Tag>
<div className="rb:text-[#5B6167] rb:text-[12px] rb:leading-4.5 rb:mt-3 rb:h-9">{item.description}</div> <div className="rb:text-[#5B6167] rb:text-[12px] rb:leading-4.5 rb:mt-3 rb:h-9">{item.description}</div>
<Space size={8} className="rb:mt-3">{item.tags.map((tag, tagIndex) => <Tag key={tagIndex}>{tag}</Tag>)}</Space> <Space size={8} className="rb:mt-3">{item.tags.map((tag, tagIndex) => <Tag key={tagIndex}>{tag}</Tag>)}</Space>
{item.is_added
? <Button className="rb:mt-3" type="primary" disabled block>{t('modelNew.added')}</Button> <Flex justify="space-between">
: <Button className="rb:mt-3" type="primary" ghost block onClick={() => handleAdd(item)}>+ {t('common.add')}</Button> <Space size={8}><UsergroupAddOutlined /> {item.add_count}</Space>
} <Space>
{!item.is_official && <Button type="primary" disabled={item.is_deprecated} onClick={() => handleEdit(item)}>{t('modelNew.edit')}</Button>}
{item.is_added
? <Button type="primary" disabled>{t('modelNew.added')}</Button>
: <Button type="primary" ghost disabled={item.is_deprecated} onClick={() => handleAdd(item)}>+ {t('common.add')}</Button>
}
</Space>
</Flex>
</RbCard> </RbCard>
))} ))}
</div> </div>

View File

@@ -27,16 +27,6 @@ export interface GroupModelModalRef {
export interface GroupModelModalProps { export interface GroupModelModalProps {
refresh?: () => void; refresh?: () => void;
} }
export interface SubModelModalForm {
provider: string;
model_ids: string[]
}
export interface SubModelModalRef {
handleOpen: (model?: SubModelModalForm) => void;
}
export interface SubModelModalProps {
refresh?: () => void;
}
export interface ModelListDetailRef { export interface ModelListDetailRef {
handleOpen: (vo: ProviderModelItem) => void; handleOpen: (vo: ProviderModelItem) => void;
} }
@@ -131,7 +121,7 @@ export interface CustomModelForm {
name: string; name: string;
type: string; type: string;
provider: string; provider: string;
logo: string; logo?: any;
description: string; description: string;
is_official: boolean; is_official: boolean;
tags: string[]; tags: string[];