/* * @Author: ZhaoYing * @Date: 2026-02-03 15:52:50 * @Last Modified by: ZhaoYing * @Last Modified time: 2026-02-03 15:52:50 */ import React, { useRef } from 'react'; import { useTranslation } from 'react-i18next'; import { Button, App, Space } from 'antd'; import clsx from 'clsx'; import { DeleteOutlined, EditOutlined, EyeOutlined } from '@ant-design/icons'; import copy from 'copy-to-clipboard' import type { ApiKey, ApiKeyModalRef } from './types'; import ApiKeyModal from './components/ApiKeyModal'; import ApiKeyDetailModal from './components/ApiKeyDetailModal'; import RbCard from '@/components/RbCard/Card' import { getApiKeyListUrl, deleteApiKey } from '@/api/apiKey'; import PageScrollList, { type PageScrollListRef } from '@/components/PageScrollList' import { formatDateTime } from '@/utils/format'; import Tag from '@/components/Tag' import { maskApiKeys } from '@/utils/apiKeyReplacer'; /** * API Key Management page component * Manages service API keys with CRUD operations */ const ApiKeyManagement: React.FC = () => { // Hooks const { t } = useTranslation(); const { modal, message } = App.useApp(); // Refs const apiKeyModalRef = useRef(null); const apiKeyDetailModalRef = useRef(null) const scrollListRef = useRef(null) /** * Refresh the API key list */ const refresh = () => { scrollListRef.current?.refresh(); } /** * Open modal to create or edit API key * @param item - Optional API key item for edit mode */ const handleEdit = (item?: ApiKey) => { apiKeyModalRef.current?.handleOpen(item); } /** * Open modal to view API key details * @param item - API key item to view */ const handleView = (item: ApiKey) => { apiKeyDetailModalRef.current?.handleOpen(item); } /** * Delete API key with confirmation * @param item - API key item to delete */ const handleDelete = (item: ApiKey) => { modal.confirm({ title: t('common.confirmDeleteDesc', { name: item.name }), okText: t('common.delete'), cancelText: t('common.cancel'), okType: 'danger', onOk: () => { deleteApiKey(item.id) .then(() => { refresh(); message.success(t('common.deleteSuccess')) }) } }) } /** * Copy content to clipboard * @param content - Content to copy */ const handleCopy = (content: string) => { copy(content) message.success(t('common.copySuccess')) } return ( <>
ref={scrollListRef} url={getApiKeyListUrl} query={{ is_active: true, type: 'service' }} column={2} renderItem={(apiKeyItem) => { return ( {['id', 'is_expired', 'created_at'].map((key, index) => (
{t(`apiKey.${key}`)} { key === 'created_at' ? formatDateTime(apiKeyItem[key], 'YYYY-MM-DD HH:mm:ss') : key === 'is_expired' ? {apiKeyItem[key] ? t('apiKey.inactive') : t('apiKey.active')} : String(apiKeyItem[key as keyof ApiKey]) }
))}
{maskApiKeys(apiKeyItem.api_key)}
{apiKeyItem.scopes?.includes('memory') && {t('apiKey.memoryEngine')}} {apiKeyItem.scopes?.includes('rag') && {t('apiKey.knowledgeBase')}}
); }} /> ); }; export default ApiKeyManagement;