Merge remote-tracking branch 'origin/main' into feature/volcengine-base-url

This commit is contained in:
huanghejian
2025-09-27 19:53:42 +08:00
14 changed files with 330 additions and 36 deletions

View File

@@ -181,8 +181,8 @@ export function PreCode(props) {
e.preventDefault();
e.stopPropagation();
if (ref.current) {
const code =
ref.current.querySelector('code')?.innerText ?? '';
const codeElement = ref.current.querySelector('code');
const code = codeElement?.textContent ?? '';
copy(code).then((success) => {
if (success) {
Toast.success(t('代码已复制到剪贴板'));

View File

@@ -85,6 +85,26 @@ const REGION_EXAMPLE = {
'claude-3-5-sonnet-20240620': 'europe-west1',
};
// 支持并且已适配通过接口获取模型列表的渠道类型
const MODEL_FETCHABLE_TYPES = new Set([
1,
4,
14,
34,
17,
26,
24,
47,
25,
20,
23,
31,
35,
40,
42,
48,
]);
function type2secretPrompt(type) {
// inputs.type === 15 ? '按照如下格式输入APIKey|SecretKey' : (inputs.type === 18 ? '按照如下格式输入APPID|APISecret|APIKey' : '请输入渠道对应的鉴权密钥')
switch (type) {
@@ -1904,13 +1924,15 @@ const EditChannelModal = (props) => {
>
{t('填入所有模型')}
</Button>
<Button
size='small'
type='tertiary'
onClick={() => fetchUpstreamModelList('models')}
>
{t('获取模型列表')}
</Button>
{MODEL_FETCHABLE_TYPES.has(inputs.type) && (
<Button
size='small'
type='tertiary'
onClick={() => fetchUpstreamModelList('models')}
>
{t('获取模型列表')}
</Button>
)}
<Button
size='small'
type='warning'

View File

@@ -247,6 +247,32 @@ const MultiKeyManageModal = ({ visible, onCancel, channel, onRefresh }) => {
}
};
// Delete a specific key
const handleDeleteKey = async (keyIndex) => {
const operationId = `delete_${keyIndex}`;
setOperationLoading((prev) => ({ ...prev, [operationId]: true }));
try {
const res = await API.post('/api/channel/multi_key/manage', {
channel_id: channel.id,
action: 'delete_key',
key_index: keyIndex,
});
if (res.data.success) {
showSuccess(t('密钥已删除'));
await loadKeyStatus(currentPage, pageSize); // Reload current page
onRefresh && onRefresh(); // Refresh parent component
} else {
showError(res.data.message);
}
} catch (error) {
showError(t('删除密钥失败'));
} finally {
setOperationLoading((prev) => ({ ...prev, [operationId]: false }));
}
};
// Handle page change
const handlePageChange = (page) => {
setCurrentPage(page);
@@ -384,7 +410,7 @@ const MultiKeyManageModal = ({ visible, onCancel, channel, onRefresh }) => {
title: t('操作'),
key: 'action',
fixed: 'right',
width: 100,
width: 150,
render: (_, record) => (
<Space>
{record.status === 1 ? (
@@ -406,6 +432,21 @@ const MultiKeyManageModal = ({ visible, onCancel, channel, onRefresh }) => {
{t('启用')}
</Button>
)}
<Popconfirm
title={t('确定要删除此密钥吗?')}
content={t('此操作不可撤销,将永久删除该密钥')}
onConfirm={() => handleDeleteKey(record.index)}
okType={'danger'}
position={'topRight'}
>
<Button
type='danger'
size='small'
loading={operationLoading[`delete_${record.index}`]}
>
{t('删除')}
</Button>
</Popconfirm>
</Space>
),
},

View File

@@ -118,7 +118,6 @@ export const buildApiPayload = (
model: inputs.model,
group: inputs.group,
messages: processedMessages,
group: inputs.group,
stream: inputs.stream,
};
@@ -132,13 +131,15 @@ export const buildApiPayload = (
seed: 'seed',
};
Object.entries(parameterMappings).forEach(([key, param]) => {
if (
parameterEnabled[key] &&
inputs[param] !== undefined &&
inputs[param] !== null
) {
payload[param] = inputs[param];
const enabled = parameterEnabled[key];
const value = inputs[param];
const hasValue = value !== undefined && value !== null;
if (enabled && hasValue) {
payload[param] = value;
}
});

View File

@@ -75,13 +75,17 @@ export async function copy(text) {
await navigator.clipboard.writeText(text);
} catch (e) {
try {
// 构建input 执行 复制命令
var _input = window.document.createElement('input');
_input.value = text;
window.document.body.appendChild(_input);
_input.select();
window.document.execCommand('Copy');
window.document.body.removeChild(_input);
// 构建 textarea 执行复制命令,保留多行文本格式
const textarea = window.document.createElement('textarea');
textarea.value = text;
textarea.setAttribute('readonly', '');
textarea.style.position = 'fixed';
textarea.style.left = '-9999px';
textarea.style.top = '-9999px';
window.document.body.appendChild(textarea);
textarea.select();
window.document.execCommand('copy');
window.document.body.removeChild(textarea);
} catch (e) {
okay = false;
console.error(e);

View File

@@ -1889,6 +1889,10 @@
"确定要删除所有已自动禁用的密钥吗?": "Are you sure you want to delete all automatically disabled keys?",
"此操作不可撤销,将永久删除已自动禁用的密钥": "This operation cannot be undone, and all automatically disabled keys will be permanently deleted.",
"删除自动禁用密钥": "Delete auto disabled keys",
"确定要删除此密钥吗?": "Are you sure you want to delete this key?",
"此操作不可撤销,将永久删除该密钥": "This operation cannot be undone, and the key will be permanently deleted.",
"密钥已删除": "Key has been deleted",
"删除密钥失败": "Failed to delete key",
"图标": "Icon",
"模型图标": "Model icon",
"请输入图标名称": "Please enter the icon name",