Files
tianxuan/templates/analysis/dashboard.html
T
PM-pinou 8fa36b774e v7: 19 issues fixed — SQLite storage, new clustering pipeline, display_id, globe rewrite, Chinese tools
Key changes:
- New: data_loader.py SQLite persistence with drop_sqlite_table
- New: db_utils.py retry_on_lock decorator (3 retries, exponential backoff)
- New: tool_registry.py with 27 MCP tools (filter_and_cluster, compute_scores, etc.)
- New: tls_ref.py for TLS cipher/reference data
- New: import_tlsdb.py management command
- New: scripts/start_server.py for portable runtime
- New: migrations 0003-0007 for SQLite table, display_id, llm fields
- Changed: views.py unified pipeline worker, retry_run, display_id everywhere
- Changed: models.py with display_id auto-assignment, run_type, sqlite_table, llm_thinking, tool_calls_json
- Changed: urls.py added retry_run route
- Changed: session_store.py robust JSON persistence
- Changed: AGENTS.md v7 fix summary added
- Changed: templates — globe rewrite (inertia/polar flip), auto.html (thinking/tool accordions), base.html (toast/config), all pages use display_id
- Changed: run.bat PYTHONUTF8=1
- Deleted: entity_detector.py, entity_aggregator.py (replaced by filter_and_cluster clustering pipeline)
- Test: 92/92 unit tests passing
2026-07-20 13:33:13 +08:00

82 lines
3.2 KiB
HTML

{% extends 'base.html' %}
{% block title %}首页 - 天璇{% endblock %}
{% block content %}
<div class="card">
<h2>TLS Flow Analysis Dashboard</h2>
<p style="color:#666;margin-bottom:1rem;">Upload CSV flow data, detect entities, cluster behavior profiles, and visualize results.</p>
</div>
{% if runs %}
<div class="card">
<h2>Recent Analysis Runs</h2>
<table>
<thead>
<tr>
<th>ID</th>
<th>Started</th>
<th>Status</th>
<th>Flows</th>
<th>Entities</th>
<th>Clusters</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for run in runs %}
<tr>
<td>#{{ run.display_id }}</td>
<td>{{ run.created_at|date:"Y-m-d H:i" }}</td>
<td>
{% if run.status == 'completed' %}
<span class="badge badge-success">Completed</span>
{% elif run.status == 'failed' %}
<span class="badge badge-danger">Failed</span>
{% else %}
<span class="badge badge-info">{{ run.get_status_display }}</span>
{% endif %}
</td>
<td>{{ run.total_flows|default:"-" }}</td>
<td>{{ run.entity_count|default:"-" }}</td>
<td>{{ run.cluster_count|default:"-" }}</td>
<td><a href="{% url 'analysis:run_detail' run.display_id %}" class="btn btn-primary">View</a></td>
<td><button class="btn btn-danger" style="background:#dc3545;color:#fff;padding:0.25rem 0.5rem;font-size:0.8rem;" onclick="deleteRun({{ run.display_id }})">删除</button></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="card empty-state">
<div style="font-size:3rem;">📊</div>
<p>No analysis runs yet. Use MCP tools to load data and start analysis.</p>
<p style="font-size:0.9rem;color:#bbb;margin-top:0.5rem;">Call <code>load_data()</code> via MCP to begin.</p>
</div>
{% endif %}
<div style="display:none;">{% csrf_token %}</div>
<script>
async function deleteRun(runId) {
if (!confirm('确定要删除此运行记录吗?此操作不可撤销。')) return;
try {
const csrf = document.querySelector('[name=csrfmiddlewaretoken]');
if (!csrf) { showError('页面已过期,请刷新后重试'); return; }
const resp = await fetch('/runs/' + runId + '/delete/', {
method: 'POST',
headers: { 'X-CSRFToken': csrf.value },
});
if (!resp.ok) {
const text = await resp.text().catch(() => '');
showError('删除失败 (HTTP ' + resp.status + '): ' + (text.length > 200 ? text.substring(0, 200) + '…' : text || '服务器内部错误'));
return;
}
const data = await resp.json();
if (data.deleted) { showSuccess('已删除'); location.reload(); }
else { showError('删除失败: 服务器返回了意外的响应'); }
} catch (err) {
showError('删除失败: ' + err.message + ' — 请刷新页面后重试');
}
}
</script>
{% endblock %}