feat: add conversation search and usage dashboard
This commit is contained in:
1012
public/app.js
1012
public/app.js
File diff suppressed because it is too large
Load Diff
@@ -24,7 +24,7 @@
|
||||
document.documentElement.dataset.dividerTime = dividerTime;
|
||||
})();
|
||||
</script>
|
||||
<link rel="stylesheet" href="style.css?v=20260730-sidebar-title-refresh-storm">
|
||||
<link rel="stylesheet" href="style.css?v=20260803-usage-statistics">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-dark.min.css">
|
||||
</head>
|
||||
<body>
|
||||
@@ -57,14 +57,24 @@
|
||||
<div id="new-chat-dropdown" class="new-chat-dropdown" hidden>
|
||||
<button id="import-session-btn">导入本地 CLI 会话</button>
|
||||
</div>
|
||||
<div class="session-search">
|
||||
<input id="session-search-input" class="session-search-input" type="search" placeholder="检索会话 / 项目" autocomplete="off" aria-label="检索会话或项目">
|
||||
<button id="session-search-clear" class="session-search-clear" type="button" title="清空检索" aria-label="清空检索" hidden>×</button>
|
||||
<div class="session-search-row">
|
||||
<div class="session-search">
|
||||
<input id="session-search-input" class="session-search-input" type="search" placeholder="检索会话 / 项目" autocomplete="off" aria-label="检索会话或项目">
|
||||
<button id="session-search-clear" class="session-search-clear" type="button" title="清空检索" aria-label="清空检索" hidden>×</button>
|
||||
</div>
|
||||
<button id="advanced-search-open" class="advanced-search-open" type="button" title="高级会话检索" aria-label="打开高级会话检索" aria-controls="advanced-search-panel" aria-expanded="false">⌘</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="session-list" class="session-list"></div>
|
||||
<div class="sidebar-footer">
|
||||
<button id="settings-btn" class="settings-btn" title="设置">⚙</button>
|
||||
<div class="sidebar-footer-actions" role="group" aria-label="CC-Web 工具">
|
||||
<button id="settings-btn" class="settings-btn" type="button" title="设置" aria-label="打开设置">⚙</button>
|
||||
<button id="usage-dashboard-open" class="usage-dashboard-open" type="button" title="使用统计" aria-label="打开使用统计" aria-controls="usage-dashboard-panel" aria-expanded="false" hidden>
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d="M5 21v-6"></path><path d="M12 21V9"></path><path d="M19 21V3"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<span class="brand">CC-Web</span>
|
||||
</div>
|
||||
</aside>
|
||||
@@ -110,6 +120,165 @@
|
||||
<!-- Slash command menu -->
|
||||
<div id="cmd-menu" class="cmd-menu" hidden></div>
|
||||
|
||||
<section id="advanced-search-panel" class="advanced-search-panel" role="dialog" aria-labelledby="advanced-search-title" hidden>
|
||||
<div class="advanced-search-shell">
|
||||
<header class="advanced-search-header">
|
||||
<button id="advanced-search-close" class="advanced-search-close" type="button" aria-label="关闭高级会话检索">‹</button>
|
||||
<div class="advanced-search-field">
|
||||
<label id="advanced-search-title" class="advanced-search-title" for="advanced-search-input">高级会话检索</label>
|
||||
<div class="advanced-search-input-wrap">
|
||||
<input id="advanced-search-input" class="advanced-search-input" type="search" placeholder="搜索会话标题、路径与消息内容" autocomplete="off" aria-label="高级会话检索关键词" aria-describedby="advanced-search-status">
|
||||
<button id="advanced-search-clear" class="advanced-search-clear" type="button" aria-label="清空高级检索关键词" hidden>×</button>
|
||||
</div>
|
||||
</div>
|
||||
<button id="advanced-search-submit" class="advanced-search-submit" type="button" aria-label="执行高级会话检索">↵</button>
|
||||
</header>
|
||||
|
||||
<div class="advanced-search-toolbar" aria-label="高级检索选项">
|
||||
<div class="advanced-search-toggle-group" role="group" aria-label="排序方式">
|
||||
<button id="advanced-search-sort-relevance" class="advanced-search-pill" type="button" aria-pressed="false">最相关</button>
|
||||
<button id="advanced-search-sort-newest" class="advanced-search-pill" type="button" aria-pressed="true">最新优先</button>
|
||||
</div>
|
||||
<div class="advanced-search-toggle-group" role="group" aria-label="匹配方式">
|
||||
<button id="advanced-search-match-contains" class="advanced-search-pill" type="button" aria-pressed="false">包含</button>
|
||||
<button id="advanced-search-match-word" class="advanced-search-pill" type="button" aria-pressed="true">整词</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="advanced-search-status" class="advanced-search-status" role="status" aria-live="polite">输入至少 2 个字符开始检索</div>
|
||||
<div id="advanced-search-results" class="advanced-search-results" role="list" aria-label="高级检索结果"></div>
|
||||
<div id="advanced-search-empty" class="advanced-search-empty" role="status" hidden>没有匹配的会话</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="usage-dashboard-panel" class="usage-dashboard" role="dialog" aria-labelledby="usage-dashboard-title" aria-describedby="usage-dashboard-status" data-state="idle" hidden>
|
||||
<div class="usage-dashboard__shell">
|
||||
<header class="usage-dashboard__header">
|
||||
<button id="usage-dashboard-close" class="usage-dashboard__icon-button usage-dashboard__back" type="button" aria-label="返回聊天" title="返回聊天">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d="m15 18-6-6 6-6"></path>
|
||||
</svg>
|
||||
</button>
|
||||
<div class="usage-dashboard__heading">
|
||||
<h2 id="usage-dashboard-title">使用统计</h2>
|
||||
<p id="usage-dashboard-status" role="status" aria-live="polite">基于当前保留的会话数据</p>
|
||||
</div>
|
||||
<div class="usage-dashboard__header-actions">
|
||||
<time id="usage-dashboard-generated-at" class="usage-dashboard__generated-at"></time>
|
||||
<button id="usage-dashboard-refresh" class="usage-dashboard__icon-button" type="button" aria-label="刷新统计" title="刷新统计">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d="M21 12a9 9 0 0 0-15.12-6.6L3 8"></path><path d="M3 3v5h5"></path><path d="M3 12a9 9 0 0 0 15.12 6.6L21 16"></path><path d="M16 16h5v5"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="usage-dashboard__toolbar" aria-label="统计范围">
|
||||
<div class="usage-dashboard__periods" role="group" aria-label="快捷时间范围">
|
||||
<button id="usage-dashboard-period-week" class="usage-dashboard__period" type="button" aria-pressed="true">本周</button>
|
||||
<button id="usage-dashboard-period-month" class="usage-dashboard__period" type="button" aria-pressed="false">本月</button>
|
||||
</div>
|
||||
<div class="usage-dashboard__dates">
|
||||
<label>从 <input id="usage-dashboard-from" type="date" aria-label="统计开始日期"></label>
|
||||
<span aria-hidden="true">至</span>
|
||||
<label><input id="usage-dashboard-to" type="date" aria-label="统计结束日期"></label>
|
||||
<button id="usage-dashboard-apply" class="usage-dashboard__apply" type="button">应用</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="usage-dashboard__body">
|
||||
<div id="usage-dashboard-loading" class="usage-dashboard__loading" role="status" hidden>正在整理统计数据</div>
|
||||
<div id="usage-dashboard-error" class="usage-dashboard__error" role="alert" hidden></div>
|
||||
|
||||
<section class="usage-dashboard__metric-grid" aria-label="统计概览">
|
||||
<article class="usage-dashboard__metric">
|
||||
<span>新建会话</span><strong data-usage-metric="newSessions">0</strong><small>所选时间内</small>
|
||||
</article>
|
||||
<article class="usage-dashboard__metric">
|
||||
<span>发送消息</span><strong data-usage-metric="messages">0</strong><small data-usage-message-split>直接 0 · 跨会话 0</small>
|
||||
</article>
|
||||
<article class="usage-dashboard__metric">
|
||||
<span>MCP 调用</span><strong data-usage-metric="mcpCalls">0</strong><small>按 assistant 消息时间</small>
|
||||
</article>
|
||||
<article class="usage-dashboard__metric usage-dashboard__metric--danger">
|
||||
<span>MCP 失败</span><strong data-usage-metric="mcpFailures">0</strong><small data-usage-failure-rate>失败率 0%</small>
|
||||
</article>
|
||||
<article class="usage-dashboard__metric">
|
||||
<span>Skill 显式使用</span><strong data-usage-metric="skillMentions">0</strong><small>仅统计 $skill mention</small>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<div class="usage-dashboard__content-grid">
|
||||
<section class="usage-dashboard__panel usage-dashboard__panel--trend" aria-labelledby="usage-dashboard-trend-title">
|
||||
<div class="usage-dashboard__panel-heading">
|
||||
<div><h3 id="usage-dashboard-trend-title">每日趋势</h3><p>会话、消息、MCP 与 Skill</p></div>
|
||||
<div id="usage-dashboard-trend-legend" class="usage-dashboard__legend" aria-label="趋势图例"></div>
|
||||
</div>
|
||||
<div class="usage-dashboard__chart-wrap">
|
||||
<svg id="usage-dashboard-trend" class="usage-dashboard__chart" viewBox="0 0 720 280" role="img" aria-label="每日使用趋势"></svg>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="usage-dashboard__panel usage-dashboard__panel--status" aria-labelledby="usage-dashboard-mcp-status-title">
|
||||
<div class="usage-dashboard__panel-heading">
|
||||
<div><h3 id="usage-dashboard-mcp-status-title">MCP 状态</h3><p>调用结果分布</p></div>
|
||||
</div>
|
||||
<div id="usage-dashboard-mcp-status" class="usage-dashboard__status-list"></div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<section class="usage-dashboard__panel" aria-labelledby="usage-dashboard-mcp-title">
|
||||
<div class="usage-dashboard__panel-heading">
|
||||
<div><h3 id="usage-dashboard-mcp-title">MCP 工具</h3><p>按调用次数排序</p></div>
|
||||
</div>
|
||||
<div class="usage-dashboard__table-wrap">
|
||||
<table class="usage-dashboard__table">
|
||||
<thead><tr><th scope="col">工具</th><th scope="col">调用</th><th scope="col">成功</th><th scope="col">失败</th><th scope="col">成功率</th><th scope="col"><span class="sr-only">操作</span></th></tr></thead>
|
||||
<tbody id="usage-dashboard-mcp-rows"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div id="usage-dashboard-mcp-empty" class="usage-dashboard__empty" hidden>所选时间内没有 MCP 调用</div>
|
||||
</section>
|
||||
|
||||
<section id="usage-dashboard-detail" class="usage-dashboard__panel usage-dashboard__detail" aria-labelledby="usage-dashboard-detail-title" hidden>
|
||||
<div class="usage-dashboard__panel-heading">
|
||||
<div><h3 id="usage-dashboard-detail-title">调用明细</h3><p id="usage-dashboard-detail-meta"></p></div>
|
||||
<button id="usage-dashboard-detail-close" class="usage-dashboard__icon-button" type="button" aria-label="关闭调用明细" title="关闭调用明细">×</button>
|
||||
</div>
|
||||
<div class="usage-dashboard__table-wrap">
|
||||
<table class="usage-dashboard__table">
|
||||
<thead><tr><th scope="col">时间</th><th scope="col">状态</th><th scope="col">会话</th><th scope="col">Agent</th></tr></thead>
|
||||
<tbody id="usage-dashboard-detail-rows"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="usage-dashboard__content-grid usage-dashboard__content-grid--lower">
|
||||
<section class="usage-dashboard__panel" aria-labelledby="usage-dashboard-skills-title">
|
||||
<div class="usage-dashboard__panel-heading">
|
||||
<div><h3 id="usage-dashboard-skills-title">Skill 显式使用</h3><p>按 mention 次数排序</p></div>
|
||||
</div>
|
||||
<ol id="usage-dashboard-skill-rows" class="usage-dashboard__rank-list"></ol>
|
||||
<div id="usage-dashboard-skill-empty" class="usage-dashboard__empty" hidden>所选时间内没有显式 Skill 使用</div>
|
||||
</section>
|
||||
|
||||
<section class="usage-dashboard__panel" aria-labelledby="usage-dashboard-sessions-title">
|
||||
<div class="usage-dashboard__panel-heading">
|
||||
<div><h3 id="usage-dashboard-sessions-title">最近会话</h3><p>点击可返回会话</p></div>
|
||||
</div>
|
||||
<div class="usage-dashboard__table-wrap">
|
||||
<table class="usage-dashboard__table">
|
||||
<thead><tr><th scope="col">会话</th><th scope="col">消息</th><th scope="col">MCP</th><th scope="col">Skill</th><th scope="col">最近时间</th></tr></thead>
|
||||
<tbody id="usage-dashboard-session-rows"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div id="usage-dashboard-session-empty" class="usage-dashboard__empty" hidden>所选时间内没有会话记录</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="input-area">
|
||||
<div class="chat-controls" aria-label="会话控制">
|
||||
<span id="chat-runtime-state" class="chat-runtime-state" hidden>运行中</span>
|
||||
@@ -183,6 +352,6 @@
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/12.0.1/marked.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/mermaid/10.9.1/mermaid.min.js"></script>
|
||||
<script src="app.js?v=20260730-sidebar-title-refresh-storm"></script>
|
||||
<script src="app.js?v=20260803-usage-statistics"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
1583
public/style.css
1583
public/style.css
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user