mirror of
https://github.com/wisdgod/cursor-api.git
synced 2025-12-24 13:38:01 +08:00
386 lines
13 KiB
HTML
386 lines
13 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh">
|
||
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<link rel="icon" type="image/x-icon" href="data:image/x-icon;,">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>配置管理</title>
|
||
<!-- 引入共享样式 -->
|
||
<link rel="stylesheet" href="/static/shared-styles.css">
|
||
<script src="/static/shared.js"></script>
|
||
</head>
|
||
|
||
<body>
|
||
<h1>配置管理</h1>
|
||
|
||
<div class="container">
|
||
<div class="form-group">
|
||
<label>路径:</label>
|
||
<select id="path">
|
||
<option value="/">根路径 (/)</option>
|
||
<option value="/logs">日志页面 (/logs)</option>
|
||
<option value="/config">配置页面 (/config)</option>
|
||
<option value="/tokens">Token 管理页面 (/tokens)</option>
|
||
<option value="/proxies">代理管理页面 (/proxies)</option>
|
||
<option value="/static/shared-styles.css">共享样式 (/static/shared-styles.css)</option>
|
||
<option value="/static/shared.js">共享脚本 (/static/shared.js)</option>
|
||
<option value="/about">关于页面 (/about)</option>
|
||
<option value="/readme">ReadMe文档 (/readme)</option>
|
||
<option value="/api">api调用 (/api)</option>
|
||
<option value="/build-key">构建动态 Key (/build-key)</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label>内容类型:</label>
|
||
<select id="content_type">
|
||
<option value="default">默认</option>
|
||
<option value="text">纯文本</option>
|
||
<option value="html">HTML</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label>内容:</label>
|
||
<textarea id="content"></textarea>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label>图片处理能力:</label>
|
||
<select id="vision_ability">
|
||
<option value="">保持不变</option>
|
||
<option value="disabled">禁用</option>
|
||
<option value="base64-only">仅 Base64</option>
|
||
<option value="base64-http">Base64 + HTTP</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label>慢速池:</label>
|
||
<select id="enable_slow_pool">
|
||
<option value="">保持不变</option>
|
||
<option value="true">启用</option>
|
||
<option value="false">禁用</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label>长上下文:</label>
|
||
<select id="enable_long_context">
|
||
<option value="">保持不变</option>
|
||
<option value="true">启用</option>
|
||
<option value="false">禁用</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label>使用量检查模型规则:</label>
|
||
<select id="usage_check_models_type">
|
||
<option value="">保持不变</option>
|
||
<option value="none">禁用</option>
|
||
<option value="default">默认</option>
|
||
<option value="all">所有</option>
|
||
<option value="list">自定义列表</option>
|
||
</select>
|
||
<input type="text" id="usage_check_models_list" placeholder="模型列表,以逗号分隔" style="display: none;">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label>是否允许动态配置Key:</label>
|
||
<select id="enable_dynamic_key">
|
||
<option value="">保持不变</option>
|
||
<option value="true">启用</option>
|
||
<option value="false">禁用</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label>包含网络引用:</label>
|
||
<select id="include_web_references">
|
||
<option value="">保持不变</option>
|
||
<option value="true">启用</option>
|
||
<option value="false">禁用</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label>共享令牌(空表示禁用):</label>
|
||
<input type="text" id="shareToken">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label>认证令牌:</label>
|
||
<input type="password" id="authToken">
|
||
</div>
|
||
|
||
<div class="button-group">
|
||
<button onclick="updateConfig('get')">获取配置</button>
|
||
<button onclick="updateConfig('update')">更新配置</button>
|
||
<button onclick="updateConfig('reset')" class="secondary">重置配置</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="message"></div>
|
||
|
||
<script>
|
||
// 添加缓存对象
|
||
let configCache = {};
|
||
|
||
// 比较函数,返回变更的配置项
|
||
function getChangedConfig() {
|
||
const currentConfig = {
|
||
path: document.getElementById('path').value,
|
||
content: {
|
||
type: document.getElementById('content_type').value,
|
||
content: document.getElementById('content').value
|
||
},
|
||
vision_ability: document.getElementById('vision_ability').value,
|
||
enable_slow_pool: parseBooleanFromString(document.getElementById('enable_slow_pool').value),
|
||
enable_long_context: parseBooleanFromString(document.getElementById('enable_long_context').value),
|
||
usage_check_models: {
|
||
type: document.getElementById('usage_check_models_type').value,
|
||
content: document.getElementById('usage_check_models_list').value
|
||
},
|
||
enable_dynamic_key: parseBooleanFromString(document.getElementById('enable_dynamic_key').value),
|
||
include_web_references: parseBooleanFromString(document.getElementById('include_web_references').value),
|
||
share_token: document.getElementById('shareToken').value.trim()
|
||
};
|
||
|
||
const changes = {};
|
||
|
||
// 始终包含路径
|
||
changes.path = currentConfig.path;
|
||
|
||
// 比较并只收集变更的配置
|
||
for (const [key, value] of Object.entries(currentConfig)) {
|
||
if (key === 'path') continue;
|
||
|
||
if (key === 'content') {
|
||
if (configCache.content?.type !== currentConfig.content.type ||
|
||
(currentConfig.content.type !== 'default' && configCache.content?.content !== currentConfig.content.content)) {
|
||
// 当类型为default时,只发送类型信息
|
||
if (currentConfig.content.type === 'default') {
|
||
changes.content = { type: 'default' };
|
||
} else {
|
||
changes.content = value;
|
||
}
|
||
}
|
||
continue;
|
||
}
|
||
|
||
if (key === 'usage_check_models') {
|
||
if (value.type && (
|
||
configCache.usage_check_models?.type !== value.type ||
|
||
(value.type === 'list' && configCache.usage_check_models?.content !== value.content)
|
||
)) {
|
||
changes.usage_check_models = value;
|
||
}
|
||
continue;
|
||
}
|
||
|
||
// 对于布尔值,需要特殊处理
|
||
if (key === 'enable_slow_pool' || key === 'enable_long_context' ||
|
||
key === 'enable_dynamic_key' || key === 'include_web_references') {
|
||
// 只有当值不为null且与缓存不同时才添加
|
||
if (value !== null && value !== configCache[key]) {
|
||
changes[key] = value;
|
||
}
|
||
continue;
|
||
}
|
||
|
||
// 对于其他值,只有当值不为空且与缓存不同时才添加
|
||
if (value && value !== configCache[key]) {
|
||
changes[key] = value;
|
||
}
|
||
}
|
||
|
||
return changes;
|
||
}
|
||
|
||
async function fetchConfig() {
|
||
try {
|
||
const path = document.getElementById('path').value;
|
||
const data = await makeAuthenticatedRequest('/config', {
|
||
body: JSON.stringify({ action: 'get', path })
|
||
});
|
||
|
||
if (data) {
|
||
let content = '';
|
||
|
||
// 获取当前路径的页面内容
|
||
const pageContent = data.data.page_content;
|
||
|
||
// 更新内容类型下拉框
|
||
const contentTypeSelect = document.getElementById('content_type');
|
||
contentTypeSelect.value = pageContent?.type || 'default';
|
||
|
||
// 更新内容文本区域
|
||
const contentTextarea = document.getElementById('content');
|
||
|
||
// 如果是 default 类型,需要从路径获取内容
|
||
if (pageContent?.type === 'default') {
|
||
try {
|
||
// 直接从路径获取内容
|
||
const response = await fetch(path);
|
||
content = await response.text();
|
||
contentTextarea.disabled = true;
|
||
} catch (err) {
|
||
console.error('获取默认内容失败:', err);
|
||
content = '';
|
||
contentTextarea.disabled = true;
|
||
}
|
||
} else if (pageContent?.type === 'text' || pageContent?.type === 'html') {
|
||
content = pageContent.content || '';
|
||
contentTextarea.disabled = false;
|
||
} else {
|
||
contentTextarea.disabled = true;
|
||
}
|
||
|
||
contentTextarea.value = content;
|
||
|
||
// 标准化 vision_ability 的值
|
||
let visionValue = data.data.vision_ability || '';
|
||
switch (visionValue) {
|
||
case 'none':
|
||
visionValue = 'disabled';
|
||
break;
|
||
case 'base64':
|
||
visionValue = 'base64-only';
|
||
break;
|
||
case 'all':
|
||
visionValue = 'base64-http';
|
||
break;
|
||
}
|
||
document.getElementById('vision_ability').value = visionValue;
|
||
document.getElementById('enable_slow_pool').value =
|
||
parseStringFromBoolean(data.data.enable_slow_pool, '');
|
||
document.getElementById('enable_long_context').value =
|
||
parseStringFromBoolean(data.data.enable_long_context, '');
|
||
|
||
// 处理使用量检查模型
|
||
const usageCheckModelsType = data.data.usage_check_models?.type || '';
|
||
document.getElementById('usage_check_models_type').value = usageCheckModelsType;
|
||
|
||
const usageCheckModelsList = document.getElementById('usage_check_models_list');
|
||
usageCheckModelsList.value = data.data.usage_check_models?.type === 'list' ?
|
||
data.data.usage_check_models?.content || '' : '';
|
||
usageCheckModelsList.style.display = usageCheckModelsType === 'list' ? 'inline-block' : 'none';
|
||
|
||
document.getElementById('enable_dynamic_key').value =
|
||
parseStringFromBoolean(data.data.enable_dynamic_key, '');
|
||
document.getElementById('include_web_references').value =
|
||
parseStringFromBoolean(data.data.include_web_references, '');
|
||
document.getElementById('shareToken').value = data.data.share_token || '';
|
||
|
||
// 更新缓存
|
||
configCache = {
|
||
path: document.getElementById('path').value,
|
||
content: pageContent || { type: 'default' },
|
||
vision_ability: visionValue,
|
||
enable_slow_pool: data.data.enable_slow_pool,
|
||
enable_long_context: data.data.enable_long_context,
|
||
usage_check_models: {
|
||
type: usageCheckModelsType,
|
||
content: usageCheckModelsList.value
|
||
},
|
||
enable_dynamic_key: data.data.enable_dynamic_key,
|
||
include_web_references: data.data.include_web_references,
|
||
share_token: document.getElementById('shareToken').value.trim()
|
||
};
|
||
|
||
// 添加获取配置成功提示
|
||
showGlobalMessage(`成功获取 ${path} 的配置`, false);
|
||
}
|
||
} catch (error) {
|
||
showGlobalMessage(error.message || '获取配置失败', true);
|
||
}
|
||
}
|
||
|
||
async function updateConfig(action) {
|
||
try {
|
||
if (action === 'get') {
|
||
await fetchConfig();
|
||
return;
|
||
}
|
||
|
||
if (action === 'reset') {
|
||
// 重置操作发送完整的重置请求
|
||
const data = {
|
||
action,
|
||
path: document.getElementById('path').value
|
||
};
|
||
|
||
const result = await makeAuthenticatedRequest('/config', {
|
||
body: JSON.stringify(data)
|
||
});
|
||
|
||
if (result) {
|
||
showGlobalMessage(result.message, false);
|
||
await fetchConfig();
|
||
}
|
||
return;
|
||
}
|
||
|
||
// 获取变更的配置
|
||
const changes = getChangedConfig();
|
||
|
||
// 如果没有变更,提示用户
|
||
if (Object.keys(changes).length <= 1 && changes.path) {
|
||
showGlobalMessage('没有配置发生变更', false);
|
||
return;
|
||
}
|
||
|
||
// 发送变更的配置
|
||
const data = {
|
||
action,
|
||
...changes
|
||
};
|
||
|
||
// 调试信息
|
||
console.log('发送的配置数据:', data);
|
||
|
||
const result = await makeAuthenticatedRequest('/config', {
|
||
body: JSON.stringify(data)
|
||
});
|
||
|
||
if (result) {
|
||
showGlobalMessage(result.message, false);
|
||
await fetchConfig();
|
||
}
|
||
} catch (error) {
|
||
showGlobalMessage(error.message || '操作失败', true);
|
||
}
|
||
}
|
||
|
||
// 添加按钮事件监听
|
||
document.getElementById('path').addEventListener('change', fetchConfig);
|
||
|
||
// 更新内容类型变更处理
|
||
document.getElementById('content_type').addEventListener('change', function () {
|
||
const textarea = document.getElementById('content');
|
||
textarea.disabled = this.value === 'default';
|
||
});
|
||
|
||
// 初始化 token 处理
|
||
initializeTokenHandling('authToken');
|
||
|
||
// 添加使用量检查模型类型变更处理
|
||
document.getElementById('usage_check_models_type').addEventListener('change', function () {
|
||
const input = document.getElementById('usage_check_models_list');
|
||
input.style.display = this.value === 'list' ? 'inline-block' : 'none';
|
||
});
|
||
|
||
// 页面加载完成后自动获取配置
|
||
document.addEventListener('DOMContentLoaded', async () => {
|
||
try {
|
||
await fetchConfig();
|
||
showGlobalMessage('页面加载完成', false);
|
||
} catch (error) {
|
||
showGlobalMessage('初始化配置加载失败', true);
|
||
}
|
||
});
|
||
</script>
|
||
</body>
|
||
|
||
</html> |