model provider add deselect

This commit is contained in:
zxhlyh 2025-09-12 14:24:55 +08:00
parent 9d75d3d04c
commit 407d66c62d
10 changed files with 55 additions and 17 deletions

View File

@ -107,6 +107,8 @@ export const MODEL_STATUS_TEXT: { [k: string]: TypeWithI18N } = {
export enum CustomConfigurationStatusEnum {
active = 'active',
noConfigure = 'no-configure',
canceled = 'canceled',
removed = 'removed',
}
export type FormShowOnObject = {

View File

@ -46,6 +46,7 @@ const ModelProviderPage = ({ searchText }: Props) => {
providers.forEach((provider) => {
if (
provider.custom_configuration.status === CustomConfigurationStatusEnum.active
|| provider.custom_configuration.status === CustomConfigurationStatusEnum.removed
|| (
provider.system_configuration.enabled === true
&& provider.system_configuration.quota_configurations.find(item => item.quota_type === provider.system_configuration.current_quota_type)

View File

@ -64,6 +64,7 @@ type AuthorizedProps = {
showModelTitle?: boolean
disableDeleteButShowAction?: boolean
disableDeleteTip?: string
showDeselect?: boolean
}
const Authorized = ({
provider,
@ -88,6 +89,7 @@ const Authorized = ({
showModelTitle,
disableDeleteButShowAction,
disableDeleteTip,
showDeselect,
}: AuthorizedProps) => {
const { t } = useTranslation()
const [isLocalOpen, setIsLocalOpen] = useState(false)
@ -112,6 +114,7 @@ const Authorized = ({
handleConfirmDelete,
deleteCredentialId,
handleOpenModal,
handleDeselect,
} = useAuth(
provider,
configurationMethod,
@ -171,8 +174,15 @@ const Authorized = ({
)}>
{
popupTitle && (
<div className='system-xs-medium px-3 pb-0.5 pt-[10px] text-text-tertiary'>
<div className='system-xs-medium flex items-center justify-between px-3 pb-0.5 pt-[10px] text-text-tertiary'>
{popupTitle}
{
showDeselect && (
<div onClick={() => handleDeselect()} className='cursor-pointer'>
{t('common.modelProvider.auth.deselect')}
</div>
)
}
</div>
)
}

View File

@ -29,10 +29,11 @@ const ConfigProvider = ({
const { t } = useTranslation()
const {
hasCredential,
authorized,
current_credential_id,
current_credential_name,
available_credentials,
authorized,
unAuthorized,
} = useCredentialStatus(provider)
const notAllowCustomCredential = provider.allow_custom_token === false
@ -41,11 +42,11 @@ const ConfigProvider = ({
<Button
className='grow'
size='small'
variant={!authorized ? 'secondary-accent' : 'secondary'}
variant={unAuthorized ? 'secondary-accent' : 'secondary'}
>
<RiEqualizer2Line className='mr-1 h-3.5 w-3.5' />
{hasCredential && t('common.operation.config')}
{!hasCredential && t('common.operation.setup')}
{!unAuthorized && t('common.operation.config')}
{unAuthorized && t('common.operation.setup')}
</Button>
)
if (notAllowCustomCredential && !hasCredential) {
@ -59,7 +60,7 @@ const ConfigProvider = ({
)
}
return Item
}, [authorized, hasCredential, notAllowCustomCredential, t])
}, [hasCredential, notAllowCustomCredential, t])
return (
<Authorized
@ -68,7 +69,6 @@ const ConfigProvider = ({
currentCustomConfigurationModelFixedFields={currentCustomConfigurationModelFixedFields}
items={[
{
title: t('common.modelProvider.auth.apiKeys'),
credentials: available_credentials ?? [],
selectedCredential: {
credential_id: current_credential_id ?? '',
@ -77,9 +77,10 @@ const ConfigProvider = ({
},
]}
showItemSelectedIcon
showModelTitle
renderTrigger={renderTrigger}
triggerOnlyOpenModal={!hasCredential && !notAllowCustomCredential}
showDeselect={authorized}
popupTitle={t('common.modelProvider.auth.apiKeys')}
/>
)
}

View File

@ -18,7 +18,10 @@ import {
useModelModalHandler,
useRefreshModel,
} from '@/app/components/header/account-setting/model-provider-page/hooks'
import { useDeleteModel } from '@/service/use-models'
import {
useDeleteModel,
useDeselectModelCredential,
} from '@/service/use-models'
export const useAuth = (
provider: ModelProvider,
@ -46,6 +49,7 @@ export const useAuth = (
getAddCredentialService,
} = useAuthService(provider.provider)
const { mutateAsync: deleteModelService } = useDeleteModel(provider.provider)
const { mutateAsync: deselectModelCredentialService } = useDeselectModelCredential(provider.provider)
const handleOpenModelModal = useModelModalHandler()
const { handleRefreshModel } = useRefreshModel()
const pendingOperationCredentialId = useRef<string | null>(null)
@ -177,6 +181,11 @@ export const useAuth = (
mode,
])
const handleDeselect = useCallback(async () => {
await deselectModelCredentialService()
handleRefreshModel(provider, configurationMethod, undefined)
}, [deselectModelCredentialService, handleRefreshModel, provider, configurationMethod])
return {
pendingOperationCredentialId,
pendingOperationModel,
@ -189,5 +198,6 @@ export const useAuth = (
deleteModel,
handleSaveCredential,
handleOpenModal,
handleDeselect,
}
}

View File

@ -2,16 +2,19 @@ import { useMemo } from 'react'
import type {
ModelProvider,
} from '../../declarations'
import { CustomConfigurationStatusEnum } from '../../declarations'
export const useCredentialStatus = (provider: ModelProvider) => {
const {
current_credential_id,
current_credential_name,
available_credentials,
status: customConfigurationStatus,
} = provider.custom_configuration
const hasCredential = !!available_credentials?.length
const authorized = current_credential_id && current_credential_name
const authRemoved = hasCredential && !current_credential_id && !current_credential_name
const authorized = customConfigurationStatus === CustomConfigurationStatusEnum.active
const authRemoved = customConfigurationStatus === CustomConfigurationStatusEnum.removed
const unAuthorized = customConfigurationStatus === CustomConfigurationStatusEnum.noConfigure || customConfigurationStatus === CustomConfigurationStatusEnum.canceled
const currentCredential = available_credentials?.find(credential => credential.credential_id === current_credential_id)
return useMemo(() => ({
@ -21,6 +24,8 @@ export const useCredentialStatus = (provider: ModelProvider) => {
current_credential_id,
current_credential_name,
available_credentials,
customConfigurationStatus,
notAllowedToUse: currentCredential?.not_allowed_to_use,
unAuthorized,
}), [hasCredential, authorized, authRemoved, current_credential_id, current_credential_name, available_credentials])
}

View File

@ -45,6 +45,7 @@ const CredentialPanel = ({
authRemoved,
current_credential_name,
notAllowedToUse,
unAuthorized,
} = useCredentialStatus(provider)
const handleChangePriority = async (key: PreferredProviderTypeEnum) => {
@ -70,23 +71,23 @@ const CredentialPanel = ({
}
}
const credentialLabel = useMemo(() => {
if (!hasCredential)
if (unAuthorized)
return t('common.modelProvider.auth.unAuthorized')
if (authorized)
return current_credential_name
if (authRemoved)
return t('common.modelProvider.auth.authRemoved')
if (authorized)
return current_credential_name
return ''
}, [authorized, authRemoved, current_credential_name, hasCredential])
}, [authorized, authRemoved, current_credential_name, unAuthorized])
const color = useMemo(() => {
if (authRemoved || !hasCredential)
if (authRemoved || !hasCredential || unAuthorized)
return 'red'
if (notAllowedToUse)
return 'gray'
return 'green'
}, [authRemoved, notAllowedToUse, hasCredential])
}, [authRemoved, notAllowedToUse, hasCredential, unAuthorized])
return (
<>

View File

@ -523,6 +523,7 @@ const translation = {
removeModel: 'Remove Model',
selectModelCredential: 'Select a model credential',
customModelCredentialsDeleteTip: 'Credential is in use and cannot be deleted',
deselect: 'Deselect',
},
},
dataSource: {

View File

@ -517,6 +517,7 @@ const translation = {
removeModel: '移除模型',
selectModelCredential: '选择模型凭据',
customModelCredentialsDeleteTip: '模型凭据正在使用中,无法删除',
deselect: '取消选择',
},
},
dataSource: {

View File

@ -153,3 +153,9 @@ export const useUpdateModelLoadBalancingConfig = (provider: string) => {
}),
})
}
export const useDeselectModelCredential = (provider: string) => {
return useMutation({
mutationFn: () => post<{ result: string }>(`/workspaces/current/model-providers/${provider}/credentials/cancel`),
})
}