feat: structure view in dashboard and settings persistence
- Add GET /api/claude/sessions/{session_id}/builder API for structure view
- Load builder session tags and snippets by Claude session ID
- Implement structure view in dashboard: shows tag selections and snippet details
- Add LoadSettings to persist LLM config changes across restarts
- Settings are now loaded from database on startup
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
+54
-3
@@ -162,7 +162,6 @@
|
||||
}
|
||||
|
||||
function renderPromptCard(prompt, index) {
|
||||
const preview = truncateText(prompt.prompt, 150);
|
||||
return `
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
@@ -176,7 +175,7 @@
|
||||
${renderPromptContent(prompt.prompt)}
|
||||
</div>
|
||||
<div id="prompt-struct-${index}" class="prompt-struct-view hidden">
|
||||
<div class="text-sm text-muted">结构视图暂不可用(需要关联构建会话数据)</div>
|
||||
<div class="text-sm text-muted" id="struct-content-${index}">加载中...</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -227,7 +226,7 @@
|
||||
return parts.length > 0 ? parts.join('') : `<div style="white-space:pre-wrap">${escapeHtml(text)}</div>`;
|
||||
}
|
||||
|
||||
function togglePromptView(index) {
|
||||
async function togglePromptView(index) {
|
||||
const textView = document.getElementById(`prompt-text-${index}`);
|
||||
const structView = document.getElementById(`prompt-struct-${index}`);
|
||||
const btn = document.getElementById(`view-btn-${index}`);
|
||||
@@ -240,6 +239,58 @@
|
||||
textView.classList.add('hidden');
|
||||
structView.classList.remove('hidden');
|
||||
btn.textContent = '切换到文本视图';
|
||||
// Load structure view data
|
||||
await loadStructureView(index);
|
||||
}
|
||||
}
|
||||
|
||||
async function loadStructureView(index) {
|
||||
const container = document.getElementById(`struct-content-${index}`);
|
||||
if (container.dataset.loaded) return;
|
||||
|
||||
try {
|
||||
const data = await API.get(`/api/claude/sessions/${currentSession}/builder`);
|
||||
if (!data || !data.session) {
|
||||
container.innerHTML = '<div class="text-sm text-muted">未找到关联的构建会话</div>';
|
||||
container.dataset.loaded = 'true';
|
||||
return;
|
||||
}
|
||||
|
||||
let html = '';
|
||||
|
||||
// Tags
|
||||
if (data.tags && data.tags.length > 0) {
|
||||
html += '<div class="mb-3"><div class="text-sm font-medium mb-2">🏷️ 标签选择</div>';
|
||||
html += data.tags.map(t => `
|
||||
<div class="mb-2 p-2" style="background:var(--bg-tertiary);border-radius:6px">
|
||||
<div class="text-sm font-medium">${escapeHtml(t.tag_name)}</div>
|
||||
<div class="text-xs text-muted mt-1">选项: ${escapeHtml(t.option_label)}</div>
|
||||
<div class="text-xs mt-1" style="color:var(--text-secondary)">${escapeHtml(t.constraint_text)}</div>
|
||||
</div>
|
||||
`).join('');
|
||||
html += '</div>';
|
||||
}
|
||||
|
||||
// Snippets
|
||||
if (data.snippets && data.snippets.length > 0) {
|
||||
html += '<div class="mb-3"><div class="text-sm font-medium mb-2">📄 片段</div>';
|
||||
html += data.snippets.map(s => `
|
||||
<div class="mb-2 p-2" style="background:var(--bg-tertiary);border-radius:6px">
|
||||
<div class="text-sm font-medium">${escapeHtml(s.name)} <span class="text-xs text-muted">(${escapeHtml(s.category)})</span></div>
|
||||
<div class="text-xs mt-1" style="color:var(--text-secondary);white-space:pre-wrap">${escapeHtml(s.content.substring(0, 200))}${s.content.length > 200 ? '...' : ''}</div>
|
||||
</div>
|
||||
`).join('');
|
||||
html += '</div>';
|
||||
}
|
||||
|
||||
if (!html) {
|
||||
html = '<div class="text-sm text-muted">无标签和片段数据</div>';
|
||||
}
|
||||
|
||||
container.innerHTML = html;
|
||||
container.dataset.loaded = 'true';
|
||||
} catch (e) {
|
||||
container.innerHTML = '<div class="text-sm text-muted">加载结构视图失败</div>';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user