1
This commit is contained in:
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -28,7 +28,7 @@
|
|||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
<script type="module" crossorigin src="/assets/index-nOnojq6k.js"></script>
|
<script type="module" crossorigin src="/assets/index-7k1wmlIX.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-D3fwIbOp.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-D3fwIbOp.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
@@ -231,18 +231,39 @@ const AdminApiKeys: React.FC = () => {
|
|||||||
const handleCopyKey = async (key: ApiKey) => {
|
const handleCopyKey = async (key: ApiKey) => {
|
||||||
try {
|
try {
|
||||||
const result = await revealApiKey(key.id);
|
const result = await revealApiKey(key.id);
|
||||||
if (result?.apiKey) {
|
const plainKey: string | undefined = result?.apiKey || result?.data?.apiKey;
|
||||||
await navigator.clipboard.writeText(result.apiKey);
|
if (!plainKey) {
|
||||||
message.success('API Key 已复制到剪贴板');
|
|
||||||
} else {
|
|
||||||
message.error('获取 API Key 失败');
|
message.error('获取 API Key 失败');
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
// 优先用 Clipboard API,不支持时回退到 execCommand
|
||||||
|
if (navigator.clipboard && typeof navigator.clipboard.writeText === 'function') {
|
||||||
|
try {
|
||||||
|
await navigator.clipboard.writeText(plainKey);
|
||||||
|
} catch {
|
||||||
|
fallbackCopy(plainKey);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fallbackCopy(plainKey);
|
||||||
|
}
|
||||||
|
message.success('API Key 已复制到剪贴板');
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
const msg = e?.response?.data?.detail || '复制失败';
|
const msg = e?.response?.data?.detail || '复制失败';
|
||||||
message.error(msg);
|
message.error(msg);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const fallbackCopy = (text: string) => {
|
||||||
|
const textarea = document.createElement('textarea');
|
||||||
|
textarea.value = text;
|
||||||
|
textarea.style.position = 'fixed';
|
||||||
|
textarea.style.opacity = '0';
|
||||||
|
document.body.appendChild(textarea);
|
||||||
|
textarea.select();
|
||||||
|
document.execCommand('copy');
|
||||||
|
document.body.removeChild(textarea);
|
||||||
|
};
|
||||||
|
|
||||||
const viewUsage = async (key: ApiKey) => {
|
const viewUsage = async (key: ApiKey) => {
|
||||||
try {
|
try {
|
||||||
const usage = await getApiKeyUsage(key.id, 30);
|
const usage = await getApiKeyUsage(key.id, 30);
|
||||||
@@ -305,8 +326,13 @@ const AdminApiKeys: React.FC = () => {
|
|||||||
{
|
{
|
||||||
title: 'Key 前缀',
|
title: 'Key 前缀',
|
||||||
dataIndex: 'apiKeyPrefix',
|
dataIndex: 'apiKeyPrefix',
|
||||||
width: 110,
|
width: 180,
|
||||||
render: (v: string) => <code style={{ background: '#f5f5f5', padding: '2px 6px', borderRadius: 4 }}>{v}****</code>,
|
render: (v: string, r: ApiKey) => (
|
||||||
|
<Space size={4}>
|
||||||
|
<code style={{ background: '#f5f5f5', padding: '2px 6px', borderRadius: 4 }}>{v}****</code>
|
||||||
|
<Button type="link" size="small" icon={<CopyOutlined />} onClick={() => handleCopyKey(r)}>api-key</Button>
|
||||||
|
</Space>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '配额(元)',
|
title: '配额(元)',
|
||||||
@@ -355,7 +381,6 @@ const AdminApiKeys: React.FC = () => {
|
|||||||
width: 260,
|
width: 260,
|
||||||
render: (_: any, r: ApiKey) => (
|
render: (_: any, r: ApiKey) => (
|
||||||
<Space size={0}>
|
<Space size={0}>
|
||||||
<Button type="link" size="small" icon={<CopyOutlined />} onClick={() => handleCopyKey(r)}>复制</Button>
|
|
||||||
<Button type="link" size="small" icon={<EyeOutlined />} onClick={() => viewUsage(r)}>统计</Button>
|
<Button type="link" size="small" icon={<EyeOutlined />} onClick={() => viewUsage(r)}>统计</Button>
|
||||||
<Button type="link" size="small" icon={<EditOutlined />} onClick={() => openEdit(r)}>编辑</Button>
|
<Button type="link" size="small" icon={<EditOutlined />} onClick={() => openEdit(r)}>编辑</Button>
|
||||||
<Popconfirm title="确定删除?" onConfirm={() => handleDelete(r.id)}>
|
<Popconfirm title="确定删除?" onConfirm={() => handleDelete(r.id)}>
|
||||||
|
|||||||
Reference in New Issue
Block a user