File size: 5,050 Bytes
e636070 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
// api-panel.js
class APIPanel {
constructor() {
// 初始化时从服务器获取配置
this.init();
}
async init() {
this.providerSelect = document.getElementById('api-provider');
this.modelSelect = document.getElementById('api-model');
this.keysContainer = document.querySelector('.api-keys-container');
// 从服务器获取配置
await this.fetchAPIConfigs();
this.providerSelect.addEventListener('change', () => this.updateProviderUI());
this.initAPIForm();
this.updateProviderUI(); // 初始化UI
}
async fetchAPIConfigs() {
try {
// 发送WebSocket消息请求配置
if (window.ws && window.ws.readyState === WebSocket.OPEN) {
window.ws.send(JSON.stringify({
type: 'request_api_configs'
}));
}
// 添加一次性事件监听器来接收配置
await new Promise((resolve) => {
const configHandler = (event) => {
const message = JSON.parse(event.data);
if (message.type === 'api_configs') {
this.modelConfigs = message.data;
window.removeEventListener('message', configHandler);
resolve();
}
};
window.ws.addEventListener('message', configHandler);
});
// 初始化提供商选择器
this.initProviderSelect();
} catch (error) {
console.error('获取API配置失败:', error);
// 使用默认配置作为后备
this.modelConfigs = this.getDefaultConfigs();
this.initProviderSelect();
}
}
getDefaultConfigs() {
// 默认配置作为后备
return {
openai: {
label: 'OpenAI API Key',
models: ['gpt-3.5-turbo', 'gpt-4'],
envKey: 'OPENAI_API_KEY'
},
anthropic: {
label: 'Claude API Key',
models: ['claude-3-opus', 'claude-3-sonnet'],
envKey: 'ANTHROPIC_API_KEY'
}
};
}
initProviderSelect() {
this.providerSelect.innerHTML = Object.entries(this.modelConfigs)
.map(([key, config]) => `
<option value="${key}">${config.label.split(' API Key')[0]}</option>
`)
.join('');
}
updateProviderUI() {
const provider = this.providerSelect.value;
// 更新API密钥输入区域
this.keysContainer.innerHTML = this.createKeyInput(
this.modelConfigs[provider].label,
this.modelConfigs[provider].envKey
);
// 更新模型选择器
this.modelSelect.innerHTML = this.modelConfigs[provider].models
.map(model => `<option value="${model}">${model}</option>`)
.join('');
// 为密码可见性切换添加事件监听
const toggles = document.querySelectorAll('.toggle-visibility');
toggles.forEach(toggle => {
toggle.addEventListener('click', (e) => {
const input = e.target.previousElementSibling;
const type = input.type === 'password' ? 'text' : 'password';
input.type = type;
e.target.innerHTML = type === 'password' ? '👁️' : '👁️🗨️';
});
});
}
createKeyInput(label, envKey) {
return `
<div class="api-key-input">
<label>${label}</label>
<div style="position: relative;">
<input type="password"
data-env-key="${envKey}"
placeholder="Enter API Key">
<span class="toggle-visibility">👁️</span>
</div>
</div>
`;
}
initAPIForm() {
const submitBtn = document.querySelector('.api-submit-btn');
if (submitBtn) {
submitBtn.addEventListener('click', () => {
const provider = this.providerSelect.value;
const model = this.modelSelect.value;
const apiKey = document.querySelector(`[data-env-key="${this.modelConfigs[provider].envKey}"]`).value;
if (window.ws && window.ws.readyState === WebSocket.OPEN) {
window.ws.send(JSON.stringify({
type: 'api_settings',
data: {
provider: provider,
model: model,
apiKey: apiKey,
envKey: this.modelConfigs[provider].envKey
}
}));
}
});
}
}
}
// 初始化API面板
document.addEventListener('DOMContentLoaded', () => {
new APIPanel();
});
|