124 lines
4.3 KiB
TypeScript
124 lines
4.3 KiB
TypeScript
/*
|
|
* @Author: ZhaoYing
|
|
* @Date: 2026-02-03 15:52:44
|
|
* @Last Modified by: ZhaoYing
|
|
* @Last Modified time: 2026-02-03 15:54:22
|
|
*/
|
|
import { forwardRef, useImperativeHandle, useState } from 'react';
|
|
import { Switch, Button, Tooltip } from 'antd';
|
|
import clsx from 'clsx';
|
|
import { useTranslation } from 'react-i18next';
|
|
|
|
import type { ApiKey, ApiKeyModalRef } from '../types';
|
|
import RbModal from '@/components/RbModal'
|
|
import { getApiKey } from '@/api/apiKey';
|
|
import { formatDateTime } from '@/utils/format'
|
|
import Tag from '@/components/Tag'
|
|
import { maskApiKeys } from '@/utils/apiKeyReplacer';
|
|
|
|
/**
|
|
* Modal component for viewing API key details
|
|
* Displays read-only information about an API key
|
|
*/
|
|
const ApiKeyDetailModal = forwardRef<ApiKeyModalRef, { handleCopy: (content: string) => void }>(({ handleCopy }, ref) => {
|
|
// Hooks
|
|
const { t } = useTranslation();
|
|
|
|
// State
|
|
const [visible, setVisible] = useState(false);
|
|
const [data, setData] = useState<ApiKey>({} as ApiKey)
|
|
|
|
/**
|
|
* Close the modal
|
|
*/
|
|
const handleClose = () => {
|
|
setVisible(false);
|
|
};
|
|
|
|
/**
|
|
* Open modal and fetch API key details
|
|
* @param apiKey - API key item to view
|
|
*/
|
|
const handleOpen = (apiKey?: ApiKey) => {
|
|
if (apiKey?.id) {
|
|
getApiKey(apiKey.id)
|
|
.then((res) => {
|
|
setVisible(true);
|
|
setData(res as ApiKey)
|
|
})
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Expose methods to parent component via ref
|
|
*/
|
|
useImperativeHandle(ref, () => ({
|
|
handleOpen,
|
|
handleClose
|
|
}));
|
|
|
|
return (
|
|
<RbModal
|
|
title={t('apiKey.viewDetail')}
|
|
open={visible}
|
|
onCancel={handleClose}
|
|
>
|
|
<div className="rb:text-[#5B6167] rb:font-medium rb:leading-5 rb:mb-4">{t('apiKey.baseInfo')}</div>
|
|
{['id', 'name', 'is_expired', 'created_at'].map((key, index) => (
|
|
<div key={key} className={clsx("rb:flex rb:justify-between rb:gap-5 rb:font-regular rb:text-[14px]", {
|
|
'rb:mt-3': index !== 0
|
|
})}>
|
|
<span className="rb:text-[#5B6167]">{t(`apiKey.${key}`)}</span>
|
|
<span className="rb:text-right rb:flex-1 rb:text-ellipsis rb:overflow-hidden rb:whitespace-nowrap">
|
|
{ key === 'created_at'
|
|
? formatDateTime(data[key], 'YYYY-MM-DD HH:mm:ss')
|
|
: key === 'is_expired'
|
|
? <Tag color={data[key] ? 'error' : 'processing'}>{data[key] ? t('apiKey.inactive') : t('apiKey.active')}</Tag>
|
|
: <Tooltip title={String(data[key as keyof ApiKey])}>{String(data[key as keyof ApiKey])}</Tooltip>
|
|
}
|
|
</span>
|
|
</div>
|
|
))}
|
|
|
|
<div className="rb:flex rb:items-center rb:justify-between rb:text-[#5B6167] rb:mt-5 rb:p-[8px_16px] rb:bg-[#FFFFFF] rb:border rb:border-[#DFE4ED] rb:rounded-lg rb:leading-5">
|
|
{maskApiKeys(data.api_key)}
|
|
|
|
<Button className="rb:px-2! rb:h-7! rb:group" onClick={() => handleCopy(data.api_key)}>
|
|
<div
|
|
className="rb:w-4 rb:h-4 rb:cursor-pointer rb:bg-cover rb:bg-[url('@/assets/images/copy.svg')] rb:group-hover:bg-[url('@/assets/images/copy_active.svg')]"
|
|
></div>
|
|
{t('common.copy')}
|
|
</Button>
|
|
</div>
|
|
|
|
<div className="rb:text-[#5B6167] rb:font-medium rb:leading-5 rb:my-4">{t('apiKey.permissionInfo')}</div>
|
|
|
|
<div className="rb:flex rb:justify-between rb:gap-5 rb:font-regular rb:text-[14px] rb:mt-3">
|
|
<span className="rb:text-[#5B6167]">{t(`apiKey.memoryEngine`)}</span>
|
|
<span>
|
|
<Switch checked={data.scopes?.includes('memory')} disabled />
|
|
</span>
|
|
</div>
|
|
<div className="rb:flex rb:justify-between rb:gap-5 rb:font-regular rb:text-[14px] rb:mt-3">
|
|
<span className="rb:text-[#5B6167]">{t(`apiKey.knowledgeBase`)}</span>
|
|
<span>
|
|
<Switch checked={data.scopes?.includes('rag')} disabled />
|
|
</span>
|
|
</div>
|
|
|
|
{/* 高级设置 */}
|
|
{data.expires_at && <>
|
|
<div className="rb:text-[#5B6167] rb:font-medium rb:leading-5 rb:my-4">{t('apiKey.advancedSettings')}</div>
|
|
|
|
<div className="rb:flex rb:justify-between rb:gap-5 rb:font-regular rb:text-[14px] rb:mt-3">
|
|
<span className="rb:text-[#5B6167]">{t(`apiKey.expires_at`)}</span>
|
|
<span>
|
|
{data.expires_at ? formatDateTime(data.expires_at as number, 'YYYY-MM-DD HH:mm:ss') : '-'}
|
|
</span>
|
|
</div>
|
|
</>}
|
|
</RbModal>
|
|
);
|
|
});
|
|
|
|
export default ApiKeyDetailModal; |