Add files via upload

This commit is contained in:
公明
2025-11-13 01:26:40 +08:00
committed by GitHub
parent b50dd2b5d7
commit 989766a73b
10 changed files with 971 additions and 17 deletions
+244
View File
@@ -84,6 +84,12 @@ header {
margin: 0;
}
.header-right {
display: flex;
align-items: center;
gap: 16px;
}
.header-subtitle {
font-size: 0.875rem;
color: rgba(255, 255, 255, 0.7);
@@ -91,6 +97,28 @@ header {
font-weight: 400;
}
.settings-btn {
background: transparent;
border: 1px solid rgba(255, 255, 255, 0.2);
color: white;
padding: 8px;
border-radius: 6px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s;
}
.settings-btn:hover {
background: rgba(255, 255, 255, 0.1);
border-color: rgba(255, 255, 255, 0.3);
}
.settings-btn svg {
stroke: currentColor;
}
/* 侧边栏样式 */
.sidebar {
width: 280px;
@@ -755,6 +783,7 @@ header {
box-shadow: var(--shadow-lg);
border: 1px solid var(--border-color);
animation: slideDown 0.3s ease-out;
overflow: hidden;
}
@keyframes slideDown {
@@ -775,6 +804,8 @@ header {
padding: 20px 24px;
border-bottom: 1px solid var(--border-color);
background: var(--bg-primary);
border-top-left-radius: 12px;
border-top-right-radius: 12px;
}
.modal-header h2 {
@@ -1302,3 +1333,216 @@ header {
font-size: 0.875rem;
color: var(--error-color);
}
/* 设置模态框样式 */
.settings-modal-content {
max-width: 800px;
max-height: 90vh;
display: flex;
flex-direction: column;
}
.settings-body {
overflow-y: auto;
flex: 1;
padding: 24px;
}
.settings-section {
margin-bottom: 32px;
}
.settings-section:last-child {
margin-bottom: 0;
}
.settings-section h3 {
font-size: 1.125rem;
font-weight: 600;
color: var(--text-primary);
margin-bottom: 16px;
padding-bottom: 8px;
border-bottom: 2px solid var(--border-color);
}
.settings-form {
display: flex;
flex-direction: column;
gap: 16px;
}
.form-group {
display: flex;
flex-direction: column;
gap: 6px;
}
.form-group label {
font-size: 0.875rem;
font-weight: 500;
color: var(--text-primary);
}
.form-group input {
padding: 10px 12px;
border: 1px solid var(--border-color);
border-radius: 6px;
font-size: 0.9375rem;
background: var(--bg-primary);
color: var(--text-primary);
transition: border-color 0.2s;
}
.form-group input:focus {
outline: none;
border-color: var(--accent-color);
box-shadow: 0 0 0 3px rgba(0, 102, 255, 0.1);
}
.form-group input.error {
border-color: var(--error-color);
box-shadow: 0 0 0 3px rgba(220, 53, 69, 0.1);
}
.form-group input.error:focus {
border-color: var(--error-color);
box-shadow: 0 0 0 3px rgba(220, 53, 69, 0.2);
}
.tools-controls {
display: flex;
flex-direction: column;
gap: 12px;
}
.tools-actions {
display: flex;
gap: 8px;
align-items: center;
}
.tools-actions button {
padding: 8px 16px;
border: 1px solid var(--border-color);
border-radius: 6px;
background: var(--bg-primary);
color: var(--text-primary);
font-size: 0.875rem;
cursor: pointer;
transition: all 0.2s;
}
.tools-actions button:hover {
background: var(--bg-tertiary);
border-color: var(--accent-color);
}
.tools-actions input {
flex: 1;
padding: 8px 12px;
border: 1px solid var(--border-color);
border-radius: 6px;
font-size: 0.875rem;
background: var(--bg-primary);
color: var(--text-primary);
}
.tools-list {
max-height: 400px;
overflow-y: auto;
border: 1px solid var(--border-color);
border-radius: 6px;
background: var(--bg-primary);
padding: 8px;
}
.tool-item {
display: flex;
align-items: center;
gap: 12px;
padding: 10px 12px;
border-radius: 6px;
transition: background 0.2s;
cursor: pointer;
}
.tool-item:hover {
background: var(--bg-tertiary);
}
.tool-item input[type="checkbox"] {
width: 18px;
height: 18px;
cursor: pointer;
accent-color: var(--accent-color);
}
.tool-item-info {
flex: 1;
min-width: 0;
}
.tool-item-name {
font-weight: 500;
color: var(--text-primary);
font-size: 0.9375rem;
margin-bottom: 4px;
}
.tool-item-desc {
font-size: 0.8125rem;
color: var(--text-secondary);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.tool-item.hidden {
display: none;
}
.modal-footer {
display: flex;
justify-content: flex-end;
gap: 12px;
padding: 16px 24px;
border-top: 1px solid var(--border-color);
flex-shrink: 0;
border-bottom-left-radius: 12px;
border-bottom-right-radius: 12px;
}
.btn-primary {
padding: 10px 20px;
background: var(--accent-color);
color: white;
border: none;
border-radius: 6px;
font-size: 0.9375rem;
font-weight: 500;
cursor: pointer;
transition: all 0.2s;
}
.btn-primary:hover {
background: var(--accent-hover);
transform: translateY(-1px);
box-shadow: var(--shadow-sm);
}
.btn-secondary {
padding: 10px 20px;
background: var(--bg-secondary);
color: var(--text-primary);
border: 1px solid var(--border-color);
border-radius: 6px;
font-size: 0.9375rem;
font-weight: 500;
cursor: pointer;
transition: all 0.2s;
}
.btn-secondary:hover {
background: var(--bg-tertiary);
border-color: var(--accent-color);
}
+205 -7
View File
@@ -1002,13 +1002,6 @@ function closeMCPDetail() {
document.getElementById('mcp-detail-modal').style.display = 'none';
}
// 点击模态框外部关闭
window.onclick = function(event) {
const modal = document.getElementById('mcp-detail-modal');
if (event.target == modal) {
closeMCPDetail();
}
}
// 工具函数
function getStatusText(status) {
@@ -1353,6 +1346,211 @@ async function cancelActiveTask(conversationId, button) {
}
}
// 设置相关功能
let currentConfig = null;
let allTools = [];
// 打开设置
async function openSettings() {
const modal = document.getElementById('settings-modal');
modal.style.display = 'block';
// 每次打开时重新加载最新配置
await loadConfig();
// 清除之前的验证错误状态
document.querySelectorAll('.form-group input').forEach(input => {
input.classList.remove('error');
});
}
// 关闭设置
function closeSettings() {
const modal = document.getElementById('settings-modal');
modal.style.display = 'none';
}
// 点击模态框外部关闭
window.onclick = function(event) {
const settingsModal = document.getElementById('settings-modal');
const mcpModal = document.getElementById('mcp-detail-modal');
if (event.target == settingsModal) {
closeSettings();
}
if (event.target == mcpModal) {
closeMCPDetail();
}
}
// 加载配置
async function loadConfig() {
try {
const response = await fetch('/api/config');
if (!response.ok) {
throw new Error('获取配置失败');
}
currentConfig = await response.json();
// 填充OpenAI配置
document.getElementById('openai-api-key').value = currentConfig.openai.api_key || '';
document.getElementById('openai-base-url').value = currentConfig.openai.base_url || '';
document.getElementById('openai-model').value = currentConfig.openai.model || '';
// 填充Agent配置
document.getElementById('agent-max-iterations').value = currentConfig.agent.max_iterations || 30;
// 填充工具列表
allTools = currentConfig.tools || [];
renderToolsList();
} catch (error) {
console.error('加载配置失败:', error);
alert('加载配置失败: ' + error.message);
}
}
// 渲染工具列表
function renderToolsList() {
const toolsList = document.getElementById('tools-list');
toolsList.innerHTML = '';
allTools.forEach(tool => {
const toolItem = document.createElement('div');
toolItem.className = 'tool-item';
toolItem.dataset.toolName = tool.name; // 保存原始工具名称
toolItem.innerHTML = `
<input type="checkbox" id="tool-${tool.name}" ${tool.enabled ? 'checked' : ''} />
<div class="tool-item-info">
<div class="tool-item-name">${escapeHtml(tool.name)}</div>
<div class="tool-item-desc">${escapeHtml(tool.description || '无描述')}</div>
</div>
`;
toolsList.appendChild(toolItem);
});
}
// 全选工具
function selectAllTools() {
document.querySelectorAll('#tools-list input[type="checkbox"]').forEach(checkbox => {
checkbox.checked = true;
});
}
// 全不选工具
function deselectAllTools() {
document.querySelectorAll('#tools-list input[type="checkbox"]').forEach(checkbox => {
checkbox.checked = false;
});
}
// 过滤工具
function filterTools() {
const searchTerm = document.getElementById('tools-search').value.toLowerCase();
document.querySelectorAll('.tool-item').forEach(item => {
const toolName = (item.dataset.toolName || '').toLowerCase();
const toolDesc = item.querySelector('.tool-item-desc').textContent.toLowerCase();
if (toolName.includes(searchTerm) || toolDesc.includes(searchTerm)) {
item.classList.remove('hidden');
} else {
item.classList.add('hidden');
}
});
}
// 应用设置
async function applySettings() {
try {
// 清除之前的验证错误状态
document.querySelectorAll('.form-group input').forEach(input => {
input.classList.remove('error');
});
// 验证必填字段
const apiKey = document.getElementById('openai-api-key').value.trim();
const baseUrl = document.getElementById('openai-base-url').value.trim();
const model = document.getElementById('openai-model').value.trim();
let hasError = false;
if (!apiKey) {
document.getElementById('openai-api-key').classList.add('error');
hasError = true;
}
if (!baseUrl) {
document.getElementById('openai-base-url').classList.add('error');
hasError = true;
}
if (!model) {
document.getElementById('openai-model').classList.add('error');
hasError = true;
}
if (hasError) {
alert('请填写所有必填字段(标记为 * 的字段)');
return;
}
// 收集配置
const config = {
openai: {
api_key: apiKey,
base_url: baseUrl,
model: model
},
agent: {
max_iterations: parseInt(document.getElementById('agent-max-iterations').value) || 30
},
tools: []
};
// 收集工具启用状态
document.querySelectorAll('#tools-list .tool-item').forEach(item => {
const checkbox = item.querySelector('input[type="checkbox"]');
const toolName = item.dataset.toolName;
if (toolName) {
// 直接使用工具名称
config.tools.push({
name: toolName,
enabled: checkbox.checked
});
}
});
// 更新配置
const updateResponse = await fetch('/api/config', {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(config)
});
if (!updateResponse.ok) {
const error = await updateResponse.json();
throw new Error(error.error || '更新配置失败');
}
// 应用配置
const applyResponse = await fetch('/api/config/apply', {
method: 'POST'
});
if (!applyResponse.ok) {
const error = await applyResponse.json();
throw new Error(error.error || '应用配置失败');
}
alert('配置已成功应用!');
closeSettings();
} catch (error) {
console.error('应用配置失败:', error);
alert('应用配置失败: ' + error.message);
}
}
// 页面加载时初始化
document.addEventListener('DOMContentLoaded', function() {
// 加载对话列表