- 完全重构前端管理界面,采用模块化架构 - 新增独立的 CSS 和 JS 模块(utils, auth, channels, tokens, pricing, api-test, database) - 实现统一的 loading 遮罩效果,所有 API 请求自动显示加载状态 - 添加现代化多选下拉框组件用于频道选择 - 实现模型部署映射的可视化表格编辑 - 修复页面高度自适应问题,管理页面占满全屏 - 优化侧边栏布局,添加 GitHub 链接和版本号 - 令牌管理页面隐藏敏感 key,添加复制功能 - 管理页面切换时自动重置为列表视图并重新加载数据 - 新增 Claude Proxy 提供商支持 - 统一所有 API 调用的错误处理和 loading 状态管理 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
124 lines
4.0 KiB
JavaScript
124 lines
4.0 KiB
JavaScript
// ===== API Test Module =====
|
|
import { showNotification } from './utils.js';
|
|
|
|
// API Test Template
|
|
export function updateRequestTemplate() {
|
|
const endpoint = document.getElementById('testEndpoint').value;
|
|
const requestBody = document.getElementById('testRequestBody');
|
|
|
|
const templates = {
|
|
'/v1/chat/completions': {
|
|
model: "gpt-3.5-turbo",
|
|
messages: [
|
|
{ role: "user", content: "你好,请介绍一下你自己。" }
|
|
],
|
|
temperature: 0.7,
|
|
max_tokens: 1024
|
|
},
|
|
'/v1/messages': {
|
|
model: "claude-haiku-4-5-20251001",
|
|
max_tokens: 1024,
|
|
messages: [
|
|
{ role: "user", content: "你好,请介绍一下你自己。" }
|
|
]
|
|
},
|
|
'/v1/completions': {
|
|
model: "gpt-3.5-turbo-instruct",
|
|
prompt: "你好,请介绍一下你自己。",
|
|
max_tokens: 1024,
|
|
temperature: 0.7
|
|
}
|
|
};
|
|
|
|
requestBody.value = JSON.stringify(templates[endpoint], null, 2);
|
|
}
|
|
|
|
export async function testAPI(event) {
|
|
event.preventDefault();
|
|
|
|
const endpoint = document.getElementById('testEndpoint').value;
|
|
const token = document.getElementById('testApiToken').value;
|
|
const requestBodyText = document.getElementById('testRequestBody').value;
|
|
|
|
const resultDiv = document.getElementById('testResult');
|
|
const resultContent = document.getElementById('testResultContent');
|
|
const statusBadge = document.getElementById('testStatusBadge');
|
|
const timeBadge = document.getElementById('testTimeBadge');
|
|
const submitBtn = document.getElementById('testSubmitBtn');
|
|
|
|
// Validate JSON
|
|
let requestBody;
|
|
try {
|
|
requestBody = JSON.parse(requestBodyText);
|
|
} catch (error) {
|
|
showNotification('JSON 格式错误:' + error.message, 'error');
|
|
return;
|
|
}
|
|
|
|
resultDiv.classList.remove('hidden');
|
|
resultContent.textContent = '发送请求中...';
|
|
statusBadge.textContent = '请求中';
|
|
statusBadge.className = 'badge badge-warning';
|
|
submitBtn.disabled = true;
|
|
|
|
const startTime = Date.now();
|
|
|
|
try {
|
|
const response = await fetch(endpoint, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Authorization': `Bearer ${token}`
|
|
},
|
|
body: JSON.stringify(requestBody)
|
|
});
|
|
|
|
const endTime = Date.now();
|
|
const duration = endTime - startTime;
|
|
timeBadge.textContent = `${duration}ms`;
|
|
|
|
if (response.ok) {
|
|
statusBadge.textContent = '成功';
|
|
statusBadge.className = 'badge badge-success';
|
|
} else {
|
|
statusBadge.textContent = `失败 ${response.status}`;
|
|
statusBadge.className = 'badge badge-destructive';
|
|
}
|
|
|
|
// Handle streaming vs non-streaming
|
|
const isStreaming = requestBody.stream === true;
|
|
|
|
if (isStreaming) {
|
|
resultContent.textContent = '';
|
|
const reader = response.body.getReader();
|
|
const decoder = new TextDecoder();
|
|
|
|
while (true) {
|
|
const { done, value } = await reader.read();
|
|
if (done) break;
|
|
|
|
const chunk = decoder.decode(value);
|
|
resultContent.textContent += chunk;
|
|
}
|
|
} else {
|
|
const data = await response.json();
|
|
resultContent.textContent = JSON.stringify(data, null, 2);
|
|
}
|
|
|
|
if (!response.ok) {
|
|
showNotification('API 请求失败', 'error');
|
|
}
|
|
} catch (error) {
|
|
const endTime = Date.now();
|
|
const duration = endTime - startTime;
|
|
timeBadge.textContent = `${duration}ms`;
|
|
|
|
statusBadge.textContent = '错误';
|
|
statusBadge.className = 'badge badge-destructive';
|
|
resultContent.textContent = '错误:' + error.message;
|
|
showNotification('请求失败:' + error.message, 'error');
|
|
} finally {
|
|
submitBtn.disabled = false;
|
|
}
|
|
}
|