mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-25 19:30:17 +08:00
refactor: improve model type checking logic in models.ts and ModelEditContent.tsx * Refactor isFunctionCallingModel, isEmbeddingModel, isVisionModel, isReasoningModel, and isWebSearchModel functions for better readability and maintainability. * Simplify type selection logic in ModelEditContent by directly using model.type or defaultTypes. * Remove unnecessary conditional checks to streamline the code. Co-authored-by: kanweiwei <kanweiwei@nutstore.net>
226 lines
7.3 KiB
TypeScript
226 lines
7.3 KiB
TypeScript
import { DownOutlined, UpOutlined } from '@ant-design/icons'
|
|
import CopyIcon from '@renderer/components/Icons/CopyIcon'
|
|
import {
|
|
isEmbeddingModel,
|
|
isFunctionCallingModel,
|
|
isReasoningModel,
|
|
isVisionModel,
|
|
isWebSearchModel
|
|
} from '@renderer/config/models'
|
|
import { Model, ModelType } from '@renderer/types'
|
|
import { getDefaultGroupName } from '@renderer/utils'
|
|
import { Button, Checkbox, Divider, Flex, Form, Input, message, Modal } from 'antd'
|
|
import { FC, useState } from 'react'
|
|
import { useTranslation } from 'react-i18next'
|
|
import styled from 'styled-components'
|
|
interface ModelEditContentProps {
|
|
model: Model
|
|
onUpdateModel: (model: Model) => void
|
|
open: boolean
|
|
onClose: () => void
|
|
}
|
|
|
|
const ModelEditContent: FC<ModelEditContentProps> = ({ model, onUpdateModel, open, onClose }) => {
|
|
const [form] = Form.useForm()
|
|
const { t } = useTranslation()
|
|
const [showModelTypes, setShowModelTypes] = useState(false)
|
|
const onFinish = (values: any) => {
|
|
const updatedModel = {
|
|
...model,
|
|
id: values.id || model.id,
|
|
name: values.name || model.name,
|
|
group: values.group || model.group
|
|
}
|
|
onUpdateModel(updatedModel)
|
|
setShowModelTypes(false)
|
|
onClose()
|
|
}
|
|
const handleClose = () => {
|
|
setShowModelTypes(false)
|
|
onClose()
|
|
}
|
|
return (
|
|
<Modal
|
|
title={t('models.edit')}
|
|
open={open}
|
|
onCancel={handleClose}
|
|
footer={null}
|
|
maskClosable={false}
|
|
centered
|
|
afterOpenChange={(visible) => {
|
|
if (visible) {
|
|
form.getFieldInstance('id')?.focus()
|
|
} else {
|
|
setShowModelTypes(false)
|
|
}
|
|
}}>
|
|
<Form
|
|
form={form}
|
|
labelCol={{ flex: '110px' }}
|
|
labelAlign="left"
|
|
colon={false}
|
|
style={{ marginTop: 15 }}
|
|
initialValues={{
|
|
id: model.id,
|
|
name: model.name,
|
|
group: model.group
|
|
}}
|
|
onFinish={onFinish}>
|
|
<Form.Item
|
|
name="id"
|
|
label={t('settings.models.add.model_id')}
|
|
tooltip={t('settings.models.add.model_id.tooltip')}
|
|
rules={[{ required: true }]}>
|
|
<Flex justify="space-between" gap={5}>
|
|
<Input
|
|
placeholder={t('settings.models.add.model_id.placeholder')}
|
|
spellCheck={false}
|
|
maxLength={200}
|
|
disabled={true}
|
|
value={model.id}
|
|
onChange={(e) => {
|
|
const value = e.target.value
|
|
form.setFieldValue('name', value)
|
|
form.setFieldValue('group', getDefaultGroupName(value))
|
|
}}
|
|
/>
|
|
<Button
|
|
onClick={() => {
|
|
//copy model id
|
|
const val = form.getFieldValue('name')
|
|
navigator.clipboard.writeText((val.id || model.id) as string)
|
|
message.success(t('message.copied'))
|
|
}}>
|
|
<CopyIcon /> {t('chat.topics.copy.title')}
|
|
</Button>
|
|
</Flex>
|
|
</Form.Item>
|
|
<Form.Item
|
|
name="name"
|
|
label={t('settings.models.add.model_name')}
|
|
tooltip={t('settings.models.add.model_name.tooltip')}>
|
|
<Input placeholder={t('settings.models.add.model_name.placeholder')} spellCheck={false} />
|
|
</Form.Item>
|
|
<Form.Item
|
|
name="group"
|
|
label={t('settings.models.add.group_name')}
|
|
tooltip={t('settings.models.add.group_name.tooltip')}>
|
|
<Input placeholder={t('settings.models.add.group_name.placeholder')} spellCheck={false} />
|
|
</Form.Item>
|
|
<Form.Item style={{ marginBottom: 15, textAlign: 'center' }}>
|
|
<Flex justify="space-between" align="center" style={{ position: 'relative' }}>
|
|
<MoreSettingsRow onClick={() => setShowModelTypes(!showModelTypes)}>
|
|
{t('settings.moresetting')}
|
|
<ExpandIcon>{showModelTypes ? <UpOutlined /> : <DownOutlined />}</ExpandIcon>
|
|
</MoreSettingsRow>
|
|
<Button type="primary" htmlType="submit" size="middle">
|
|
{t('common.save')}
|
|
</Button>
|
|
</Flex>
|
|
</Form.Item>
|
|
{showModelTypes && (
|
|
<div>
|
|
<Divider style={{ margin: '0 0 15px 0' }} />
|
|
<TypeTitle>{t('models.type.select')}:</TypeTitle>
|
|
{(() => {
|
|
const defaultTypes = [
|
|
...(isVisionModel(model) ? ['vision'] : []),
|
|
...(isEmbeddingModel(model) ? ['embedding'] : []),
|
|
...(isReasoningModel(model) ? ['reasoning'] : []),
|
|
...(isFunctionCallingModel(model) ? ['function_calling'] : []),
|
|
...(isWebSearchModel(model) ? ['web_search'] : [])
|
|
] as ModelType[]
|
|
|
|
// 合并现有选择和默认类型
|
|
const selectedTypes = model.type ? model.type : defaultTypes
|
|
|
|
const showTypeConfirmModal = (type: string) => {
|
|
window.modal.confirm({
|
|
title: t('settings.moresetting.warn'),
|
|
content: t('settings.moresetting.check.warn'),
|
|
okText: t('settings.moresetting.check.confirm'),
|
|
cancelText: t('common.cancel'),
|
|
okButtonProps: { danger: true },
|
|
cancelButtonProps: { type: 'primary' },
|
|
onOk: () => onUpdateModel({ ...model, type: [...selectedTypes, type] as ModelType[] }),
|
|
onCancel: () => {},
|
|
centered: true
|
|
})
|
|
}
|
|
|
|
const handleTypeChange = (types: string[]) => {
|
|
const newType = types.find((type) => !selectedTypes.includes(type as ModelType))
|
|
|
|
if (newType) {
|
|
showTypeConfirmModal(newType)
|
|
} else {
|
|
onUpdateModel({ ...model, type: types as ModelType[] })
|
|
}
|
|
}
|
|
|
|
return (
|
|
<Checkbox.Group
|
|
value={selectedTypes}
|
|
onChange={handleTypeChange}
|
|
options={[
|
|
{
|
|
label: t('models.type.vision'),
|
|
value: 'vision'
|
|
},
|
|
{
|
|
label: t('models.type.websearch'),
|
|
value: 'web_search'
|
|
},
|
|
{
|
|
label: t('models.type.embedding'),
|
|
value: 'embedding'
|
|
},
|
|
{
|
|
label: t('models.type.reasoning'),
|
|
value: 'reasoning'
|
|
},
|
|
{
|
|
label: t('models.type.function_calling'),
|
|
value: 'function_calling'
|
|
}
|
|
]}
|
|
/>
|
|
)
|
|
})()}
|
|
</div>
|
|
)}
|
|
</Form>
|
|
</Modal>
|
|
)
|
|
}
|
|
|
|
const TypeTitle = styled.div`
|
|
margin-bottom: 12px;
|
|
font-size: 14px;
|
|
font-weight: 600;
|
|
`
|
|
|
|
const ExpandIcon = styled.div`
|
|
font-size: 12px;
|
|
color: var(--color-text-3);
|
|
`
|
|
|
|
const MoreSettingsRow = styled.div`
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
color: var(--color-text-3);
|
|
cursor: pointer;
|
|
padding: 4px 8px;
|
|
border-radius: 4px;
|
|
max-width: 150px;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
|
|
&:hover {
|
|
background-color: var(--color-background-soft);
|
|
}
|
|
`
|
|
|
|
export default ModelEditContent
|