diff --git a/src/renderer/src/pages/home/Tabs/AssistantItem.tsx b/src/renderer/src/pages/home/Tabs/AssistantItem.tsx index a0a664a0..de0fd8e1 100644 --- a/src/renderer/src/pages/home/Tabs/AssistantItem.tsx +++ b/src/renderer/src/pages/home/Tabs/AssistantItem.tsx @@ -133,10 +133,9 @@ const Container = styled.div` display: flex; flex-direction: row; justify-content: space-between; - padding: 7px 12px; + padding: 7px 10px; position: relative; margin: 0 10px; - padding-right: 35px; font-family: Ubuntu; border-radius: var(--list-item-border-radius); border: 0.5px solid transparent; @@ -152,7 +151,6 @@ const Container = styled.div` background-color: var(--color-background-soft); border: 0.5px solid var(--color-border); .name { - font-weight: 500; } } ` diff --git a/src/renderer/src/pages/home/Tabs/TopicsTab.tsx b/src/renderer/src/pages/home/Tabs/TopicsTab.tsx index d85902bc..2223b99e 100644 --- a/src/renderer/src/pages/home/Tabs/TopicsTab.tsx +++ b/src/renderer/src/pages/home/Tabs/TopicsTab.tsx @@ -388,7 +388,6 @@ const TopicListItem = styled.div` background-color: var(--color-background-soft); border: 0.5px solid var(--color-border); .name { - font-weight: 500; } .menu { opacity: 1; diff --git a/src/renderer/src/pages/home/Tabs/index.tsx b/src/renderer/src/pages/home/Tabs/index.tsx index 6cd163c1..e969f90b 100644 --- a/src/renderer/src/pages/home/Tabs/index.tsx +++ b/src/renderer/src/pages/home/Tabs/index.tsx @@ -159,6 +159,12 @@ const TabContent = styled.div` ` const Segmented = styled(AntSegmented)` + &.ant-segmented { + background-color: transparent; + border-radius: 0 !important; + border-bottom: 0.5px solid var(--color-border); + padding-bottom: 10px; + } .ant-segmented-item { overflow: hidden; transition: none !important; @@ -202,14 +208,8 @@ const Segmented = styled(AntSegmented)` border-radius: var(--list-item-border-radius); box-shadow: none; } - - /* Added styles from AntdProvider */ - &.ant-segmented { - background-color: transparent; - } - /* These styles ensure the same appearance as before */ - border-radius: 16px; + border-radius: 0; box-shadow: none; ` diff --git a/src/renderer/src/pages/settings/ProviderSettings/ModelEditContent.tsx b/src/renderer/src/pages/settings/ProviderSettings/ModelEditContent.tsx new file mode 100644 index 00000000..5aa7ea42 --- /dev/null +++ b/src/renderer/src/pages/settings/ProviderSettings/ModelEditContent.tsx @@ -0,0 +1,204 @@ +import { DownOutlined, UpOutlined } from '@ant-design/icons' +import { isEmbeddingModel, isReasoningModel, isVisionModel } from '@renderer/config/models' +import { Model, ModelType } from '@renderer/types' +import { getDefaultGroupName } from '@renderer/utils' +import { Button, Checkbox, Divider, Flex, Form, Input, 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 = ({ 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 ( + { + if (visible) { + form.getFieldInstance('id')?.focus() + } else { + setShowModelTypes(false) + } + }}> +
+ + { + const value = e.target.value + form.setFieldValue('name', value) + form.setFieldValue('group', getDefaultGroupName(value)) + }} + /> + + + + + + + + + +
+ +
+ setShowModelTypes(!showModelTypes)} + style={{ position: 'absolute', right: 0 }}> + {t('settings.moresetting')} + {showModelTypes ? : } + +
+
+ {showModelTypes && ( +
+ + {t('models.type.select')}: + {(() => { + const defaultTypes = [ + ...(isVisionModel(model) ? ['vision'] : []), + ...(isEmbeddingModel(model) ? ['embedding'] : []), + ...(isReasoningModel(model) ? ['reasoning'] : []) + ] as ModelType[] + + // 合并现有选择和默认类型 + const selectedTypes = [...new Set([...(model.type || []), ...defaultTypes])] + + const showTypeConfirmModal = (type: string) => { + 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 ( + + ) + })()} +
+ )} +
+
+ ) +} + +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 diff --git a/src/renderer/src/pages/settings/ProviderSettings/ProviderSetting.tsx b/src/renderer/src/pages/settings/ProviderSettings/ProviderSetting.tsx index 36a6c944..df0f1acd 100644 --- a/src/renderer/src/pages/settings/ProviderSettings/ProviderSetting.tsx +++ b/src/renderer/src/pages/settings/ProviderSettings/ProviderSetting.tsx @@ -1,18 +1,16 @@ import { CheckOutlined, - DownOutlined, EditOutlined, ExportOutlined, LoadingOutlined, MinusCircleOutlined, PlusOutlined, - SettingOutlined, - UpOutlined + SettingOutlined } from '@ant-design/icons' import { HStack } from '@renderer/components/Layout' import ModelTags from '@renderer/components/ModelTags' import OAuthButton from '@renderer/components/OAuth/OAuthButton' -import { getModelLogo, isEmbeddingModel, isReasoningModel, isVisionModel } from '@renderer/config/models' +import { getModelLogo } from '@renderer/config/models' import { PROVIDER_CONFIG } from '@renderer/config/providers' import { useTheme } from '@renderer/context/ThemeProvider' import { useAssistants, useDefaultModel } from '@renderer/hooks/useAssistant' @@ -23,11 +21,10 @@ import { checkApi } from '@renderer/services/ApiService' import { isProviderSupportAuth, isProviderSupportCharge } from '@renderer/services/ProviderService' import { useAppDispatch } from '@renderer/store' import { setModel } from '@renderer/store/assistants' -import { Model, ModelType, Provider } from '@renderer/types' -import { getDefaultGroupName } from '@renderer/utils' +import { Model, Provider } from '@renderer/types' import { formatApiHost } from '@renderer/utils/api' import { providerCharge } from '@renderer/utils/oauth' -import { Avatar, Button, Card, Checkbox, Divider, Flex, Form, Input, Modal, Space, Switch } from 'antd' +import { Avatar, Button, Card, Divider, Flex, Input, Space, Switch } from 'antd' import Link from 'antd/es/typography/Link' import { groupBy, isEmpty } from 'lodash' import { FC, useEffect, useState } from 'react' @@ -47,6 +44,7 @@ import ApiCheckPopup from './ApiCheckPopup' import EditModelsPopup from './EditModelsPopup' import GraphRAGSettings from './GraphRAGSettings' import LMStudioSettings from './LMStudioSettings' +import ModelEditContent from './ModelEditContent' import OllamSettings from './OllamaSettings' import SelectProviderModelPopup from './SelectProviderModelPopup' @@ -54,170 +52,6 @@ interface Props { provider: Provider } -interface ModelEditContentProps { - model: Model - onUpdateModel: (model: Model) => void - open: boolean - onClose: () => void -} - -const ModelEditContent: FC = ({ 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 ( - { - if (visible) { - form.getFieldInstance('id')?.focus() - } else { - setShowModelTypes(false) - } - }}> -
- - { - const value = e.target.value - form.setFieldValue('name', value) - form.setFieldValue('group', getDefaultGroupName(value)) - }} - /> - - - - - - - - - -
- -
- setShowModelTypes(!showModelTypes)} - style={{ position: 'absolute', right: 0 }}> - {t('settings.moresetting')} - {showModelTypes ? : } - -
-
- - {showModelTypes && ( -
- {t('models.type.select')}: - {(() => { - const defaultTypes = [ - ...(isVisionModel(model) ? ['vision'] : []), - ...(isEmbeddingModel(model) ? ['embedding'] : []), - ...(isReasoningModel(model) ? ['reasoning'] : []) - ] as ModelType[] - - // 合并现有选择和默认类型 - const selectedTypes = [...new Set([...(model.type || []), ...defaultTypes])] - - const showTypeConfirmModal = (type: string) => { - 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 ( - - ) - })()} -
- )} - -
- ) -} - const ProviderSetting: FC = ({ provider: _provider }) => { const { provider } = useProvider(_provider.id) const [apiKey, setApiKey] = useState(provider.apiKey) @@ -361,17 +195,6 @@ const ProviderSetting: FC = ({ provider: _provider }) => { } } - const modelTypeContent = (model: Model) => { - return ( - setEditingModel(null)} - /> - ) - } - const formatApiKeys = (value: string) => { return value.replaceAll(',', ',').replaceAll(' ', ',').replaceAll(' ', '').replaceAll('\n', ',') } @@ -528,7 +351,15 @@ const ProviderSetting: FC = ({ provider: _provider }) => { {t('button.add')} - {models.map((model) => modelTypeContent(model))} + {models.map((model) => ( + setEditingModel(null)} + key={model.id} + /> + ))} ) } @@ -577,32 +408,4 @@ const ProviderName = styled.span` font-weight: 500; ` -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 ProviderSetting