feat: add project usage analytics with ECharts
This commit is contained in:
@@ -24,7 +24,7 @@
|
||||
document.documentElement.dataset.dividerTime = dividerTime;
|
||||
})();
|
||||
</script>
|
||||
<link rel="stylesheet" href="style.css?v=20260803-usage-statistics">
|
||||
<link rel="stylesheet" href="style.css?v=20260803-usage-statistics-echarts">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-dark.min.css">
|
||||
</head>
|
||||
<body>
|
||||
@@ -154,35 +154,44 @@
|
||||
<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="刷新统计">
|
||||
<button id="usage-dashboard-refresh" class="usage-dashboard__refresh" 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>
|
||||
<span>刷新</span>
|
||||
</button>
|
||||
<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>
|
||||
</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 class="usage-dashboard__filters">
|
||||
<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>
|
||||
<button id="usage-dashboard-period-custom" class="usage-dashboard__period" type="button" aria-pressed="false">自定义</button>
|
||||
</div>
|
||||
<div class="usage-dashboard__dates">
|
||||
<span class="usage-dashboard__date-icon" aria-hidden="true">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<rect x="3" y="5" width="18" height="16" rx="2"></rect><path d="M16 3v4M8 3v4M3 10h18"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<label><span class="sr-only">统计开始日期</span><input id="usage-dashboard-from" type="date" aria-label="统计开始日期"></label>
|
||||
<span class="usage-dashboard__date-separator" aria-hidden="true">~</span>
|
||||
<label><span class="sr-only">统计结束日期</span><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>
|
||||
|
||||
@@ -191,56 +200,71 @@
|
||||
<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 class="usage-dashboard__metric usage-dashboard__metric--sessions">
|
||||
<span class="usage-dashboard__metric-icon" aria-hidden="true">
|
||||
<svg viewBox="0 0 24 24"><path d="M6 3.5h9l3 3V20.5H6z"></path><path d="M14 3.5v4h4M12 11v6M9 14h6"></path></svg>
|
||||
</span>
|
||||
<span class="usage-dashboard__metric-copy"><span class="usage-dashboard__metric-label">新建会话</span><strong data-usage-metric="newSessions">0</strong><small>所选范围内</small></span>
|
||||
<div class="usage-dashboard__sparkline" data-usage-spark="newSessions" role="img" aria-label="新建会话每日微趋势"></div>
|
||||
</article>
|
||||
<article class="usage-dashboard__metric">
|
||||
<span>发送消息</span><strong data-usage-metric="messages">0</strong><small data-usage-message-split>直接 0 · 跨会话 0</small>
|
||||
<article class="usage-dashboard__metric usage-dashboard__metric--messages">
|
||||
<span class="usage-dashboard__metric-icon" aria-hidden="true">
|
||||
<svg viewBox="0 0 24 24"><path d="M4 6.5h10.5a3 3 0 0 1 3 3v4a3 3 0 0 1-3 3H9l-4 3v-3.1a3 3 0 0 1-1-2.2v-4.7a3 3 0 0 1 3-3Z"></path><path d="m15 9 4 4-4 4M12 13h7"></path></svg>
|
||||
</span>
|
||||
<span class="usage-dashboard__metric-copy"><span class="usage-dashboard__metric-label">发送消息</span><strong data-usage-metric="messages">0</strong><small data-usage-message-split>直接 0 · 跨会话 0</small></span>
|
||||
<div class="usage-dashboard__sparkline" data-usage-spark="messages" role="img" aria-label="发送消息每日微趋势"></div>
|
||||
</article>
|
||||
<article class="usage-dashboard__metric">
|
||||
<span>MCP 调用</span><strong data-usage-metric="mcpCalls">0</strong><small>按 assistant 消息时间</small>
|
||||
<article class="usage-dashboard__metric usage-dashboard__metric--mcp">
|
||||
<span class="usage-dashboard__metric-icon" aria-hidden="true">
|
||||
<svg viewBox="0 0 24 24"><path d="M7 6.5 12 4l5 2.5v5L12 14l-5-2.5zM7 16.5 12 14l5 2.5v3L12 22l-5-2.5z"></path><path d="M7 9.5 4 11v5l3 1.5M17 9.5l3 1.5v5L17 18"></path></svg>
|
||||
</span>
|
||||
<span class="usage-dashboard__metric-copy"><span class="usage-dashboard__metric-label">MCP 调用</span><strong data-usage-metric="mcpCalls">0</strong><small>按消息时间归属</small></span>
|
||||
<div class="usage-dashboard__sparkline" data-usage-spark="mcpCalls" role="img" aria-label="MCP 调用每日微趋势"></div>
|
||||
</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>
|
||||
<span class="usage-dashboard__metric-icon" aria-hidden="true">
|
||||
<svg viewBox="0 0 24 24"><path d="m12 3 9 16H3z"></path><path d="M12 9v4M12 17.2v.1"></path><path d="m5 5 14 14"></path></svg>
|
||||
</span>
|
||||
<span class="usage-dashboard__metric-copy"><span class="usage-dashboard__metric-label">MCP 失败</span><strong data-usage-metric="mcpFailures">0</strong><small data-usage-failure-rate>失败率 0%</small></span>
|
||||
<div class="usage-dashboard__sparkline" data-usage-spark="mcpFailures" role="img" aria-label="MCP 失败每日微趋势"></div>
|
||||
</article>
|
||||
<article class="usage-dashboard__metric">
|
||||
<span>Skill 显式使用</span><strong data-usage-metric="skillMentions">0</strong><small>仅统计 $skill mention</small>
|
||||
<article class="usage-dashboard__metric usage-dashboard__metric--projects">
|
||||
<span class="usage-dashboard__metric-icon" aria-hidden="true">
|
||||
<svg viewBox="0 0 24 24"><path d="M3.5 6.5h6l2 2h9v10.5h-17z"></path><path d="M3.5 9h17"></path></svg>
|
||||
</span>
|
||||
<span class="usage-dashboard__metric-copy"><span class="usage-dashboard__metric-label">涉及项目</span><strong data-usage-metric="projects">0</strong><small>有活动的项目</small></span>
|
||||
<div class="usage-dashboard__sparkline" data-usage-spark="projects" role="img" aria-label="每日涉及项目微趋势"></div>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<div class="usage-dashboard__content-grid">
|
||||
<div class="usage-dashboard__content-grid usage-dashboard__content-grid--primary">
|
||||
<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><h3 id="usage-dashboard-trend-title">使用趋势</h3><p>每日变化 · 柱:消息 / MCP,线:会话 / 项目</p></div>
|
||||
<div class="usage-dashboard__trend-tools"><span class="usage-dashboard__grain">按日</span></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 id="usage-dashboard-trend" class="usage-dashboard__chart" role="img" aria-label="每日消息、MCP、会话和项目使用趋势"></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="usage-dashboard__panel usage-dashboard__panel--status" aria-labelledby="usage-dashboard-mcp-status-title">
|
||||
<section class="usage-dashboard__panel usage-dashboard__panel--mcp" aria-labelledby="usage-dashboard-mcp-title">
|
||||
<div class="usage-dashboard__panel-heading">
|
||||
<div><h3 id="usage-dashboard-mcp-status-title">MCP 状态</h3><p>调用结果分布</p></div>
|
||||
<div><h3 id="usage-dashboard-mcp-title">MCP 使用明细</h3><p>按调用次数排序 · 点击成功率查看明细</p></div>
|
||||
</div>
|
||||
<div id="usage-dashboard-mcp-status" class="usage-dashboard__status-list"></div>
|
||||
<div class="usage-dashboard__table-wrap">
|
||||
<table class="usage-dashboard__table usage-dashboard__table--mcp">
|
||||
<thead><tr><th scope="col">排名</th><th scope="col">MCP Server / Tool</th><th scope="col">调用次数</th><th scope="col">成功次数</th><th scope="col">失败次数</th><th scope="col">成功率</th></tr></thead>
|
||||
<tbody id="usage-dashboard-mcp-rows"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<button id="usage-dashboard-mcp-more" class="usage-dashboard__list-more" type="button" aria-expanded="false" hidden></button>
|
||||
<div id="usage-dashboard-mcp-empty" class="usage-dashboard__empty" hidden>所选时间内没有 MCP 调用</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>
|
||||
<button id="usage-dashboard-detail-scrim" class="usage-dashboard__detail-scrim" type="button" aria-label="关闭调用明细" hidden></button>
|
||||
<section id="usage-dashboard-detail" class="usage-dashboard__panel usage-dashboard__detail" role="dialog" aria-modal="true" aria-labelledby="usage-dashboard-detail-title" aria-describedby="usage-dashboard-detail-meta" 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>
|
||||
@@ -254,27 +278,37 @@
|
||||
</section>
|
||||
|
||||
<div class="usage-dashboard__content-grid usage-dashboard__content-grid--lower">
|
||||
<section class="usage-dashboard__panel" aria-labelledby="usage-dashboard-skills-title">
|
||||
<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-skills-title">Skill 显式使用</h3><p>按 mention 次数排序</p></div>
|
||||
<div><h3 id="usage-dashboard-mcp-status-title">状态统计</h3><p>真实拆分 · 调用结果、消息来源与项目归属</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>
|
||||
<div id="usage-dashboard-mcp-status" class="usage-dashboard__status-list"></div>
|
||||
</section>
|
||||
|
||||
<section class="usage-dashboard__panel" aria-labelledby="usage-dashboard-sessions-title">
|
||||
<section class="usage-dashboard__panel usage-dashboard__panel--projects" aria-labelledby="usage-dashboard-projects-title">
|
||||
<div class="usage-dashboard__panel-heading">
|
||||
<div><h3 id="usage-dashboard-sessions-title">最近会话</h3><p>点击可返回会话</p></div>
|
||||
<div><h3 id="usage-dashboard-projects-title">项目使用排行</h3><p>按消息活跃量排序 · 汇总会话与 MCP</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 class="usage-dashboard__rank-head" aria-hidden="true">
|
||||
<span>排名</span><span>项目</span><span>会话</span><span>消息</span><span>MCP</span>
|
||||
</div>
|
||||
<div id="usage-dashboard-session-empty" class="usage-dashboard__empty" hidden>所选时间内没有会话记录</div>
|
||||
<ol id="usage-dashboard-project-rows" class="usage-dashboard__rank-list usage-dashboard__project-list"></ol>
|
||||
<div id="usage-dashboard-project-empty" class="usage-dashboard__empty" hidden>所选时间内没有可归属的项目活动</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<section class="usage-dashboard__panel usage-dashboard__panel--sessions" 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 usage-dashboard__table--sessions">
|
||||
<thead><tr><th scope="col">会话名称</th><th scope="col">消息数</th><th scope="col">MCP 调用次数</th><th scope="col">项目</th><th scope="col">最近时间</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>
|
||||
</section>
|
||||
@@ -352,6 +386,7 @@
|
||||
<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=20260803-usage-statistics"></script>
|
||||
<script src="vendor/echarts.min.js?v=5.6.0"></script>
|
||||
<script src="app.js?v=20260803-usage-statistics-echarts"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user