Skip to content

Commit a3d6c68

Browse files
wangglclaude
andcommitted
feat(ui): refine color palette and improve label clarity
- Apply Financial Dashboard color scheme from UI Pro Max analysis: dark theme uses deep navy (#020617) with slate borders, light theme uses cool white (#f8fafc) with soft borders - Improve all i18n labels for clarity and consistency: zh: 总耗费→总费用, 提示数→Prompt数, 成本占比分布→模型费用占比, 费用消耗趋势→费用趋势, Token消耗明细→Token用量 en: Dashboard→Usage Analytics, Cost Distribution→Cost by Model, Token Usage Breakdown→Token Usage, Cache Create→Cache Write - Separate Session Log title from Sessions stat card i18n key - Add placeholder i18n for project filter input - Switch stat card font to Fira Code for data terminal feel - Update .gitignore for skills/agent tool directories Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 129e136 commit a3d6c68

3 files changed

Lines changed: 72 additions & 35 deletions

File tree

.gitignore

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,37 @@ config.local.yaml
55
agent-usage
66
devobs
77
data/
8+
9+
# Skills / agent tool directories
10+
.agents/
11+
skills/
12+
skills-lock.json
13+
.adal/
14+
.augment/
15+
.bob/
16+
.claude/
17+
.codebuddy/
18+
.commandcode/
19+
.continue/
20+
.cortex/
21+
.crush/
22+
.factory/
23+
.goose/
24+
.iflow/
25+
.junie/
26+
.kilocode/
27+
.kiro/
28+
.kode/
29+
.mcpjam/
30+
.mux/
31+
.neovate/
32+
.openhands/
33+
.pi/
34+
.pochi/
35+
.qoder/
36+
.qwen/
37+
.roo/
38+
.trae/
39+
.vibe/
40+
.windsurf/
41+
.zencoder/

internal/server/static/app.js

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,28 +10,30 @@ const fmtCost = n => n >= 1 ? '$' + n.toFixed(2) : '$' + n.toFixed(4);
1010
// ── i18n ──
1111
const I18N = {
1212
en: {
13-
title: 'Dashboard', to: 'to', totalCost: 'Total Cost', totalTokens: 'Total Tokens',
14-
sessions: 'Sessions', prompts: 'Prompts', apiCalls: 'API Calls', costByModel: 'Cost Distribution', costOverTime: 'Cost Trend',
15-
tokenUsage: 'Token Usage Breakdown', dailySessions: 'Daily Sessions', source: 'Source', project: 'Project',
13+
title: 'Usage Analytics', to: 'to', totalCost: 'Total Cost', totalTokens: 'Total Tokens',
14+
sessions: 'Sessions', prompts: 'Prompts', apiCalls: 'API Calls', costByModel: 'Cost by Model', costOverTime: 'Cost Trend',
15+
tokenUsage: 'Token Usage', dailySessions: 'Daily Sessions', source: 'Source', project: 'Project',
1616
branch: 'Branch', time: 'Time', tokens: 'Tokens', cost: 'Cost', refresh: 'Refresh',
17+
sessionLog: 'Session Log',
1718
today: 'Today', thisWeek: 'This Week', thisMonth: 'This Month', thisYear: 'This Year',
1819
last3d: 'Last 3 Days', last7d: 'Last 7 Days', last30d: 'Last 30 Days', custom: 'Custom',
19-
light: 'Light', dark: 'Dark', system: 'System', autoOn: 'Auto On', autoOff: 'Auto Off',
20-
input: 'Input', output: 'Output', cacheRead: 'Cache Read', cacheCreate: 'Cache Create',
20+
light: 'Light', dark: 'Dark', system: 'System', autoOn: 'Auto ', autoOff: 'Auto',
21+
input: 'Input', output: 'Output', cacheRead: 'Cache Read', cacheCreate: 'Cache Write',
2122
gran_1m: '1 min', gran_30m: '30 min', gran_1h: '1 hour', gran_6h: '6 hours', gran_12h: '12 hours', gran_1d: '1 day', gran_1w: '1 week', gran_1M: '1 month',
2223
model: 'Model', calls: 'Calls', allSources: 'All Sources', claudeCode: 'Claude Code', codex: 'Codex', openClaw: 'OpenClaw',
2324
filterProject: 'Filter by project...', justNow: 'just now', mAgo: 'm ago', hAgo: 'h ago', dAgo: 'd ago',
2425
noSessions: 'No sessions found in this period.'
2526
},
2627
zh: {
27-
title: '分析仪表盘', to: '至', totalCost: '总耗费', totalTokens: '总 Tokens',
28-
sessions: '会话数', prompts: '提示数', apiCalls: 'API 调用', costByModel: '成本占比分布', costOverTime: '费用消耗趋势',
29-
tokenUsage: 'Token 消耗明细', dailySessions: '每日会话数', source: '来源', project: '项目',
30-
branch: '分支', time: '时间', tokens: 'Tokens', cost: '耗费', refresh: '刷新数据',
28+
title: '使用分析', to: '至', totalCost: '总费用', totalTokens: '总 Tokens',
29+
sessions: '会话数', prompts: 'Prompt 数', apiCalls: 'API 调用数', costByModel: '模型费用占比', costOverTime: '费用趋势',
30+
tokenUsage: 'Token 用量', dailySessions: '每日会话数', source: '来源', project: '项目',
31+
branch: '分支', time: '时间', tokens: 'Tokens', cost: '费用', refresh: '刷新',
32+
sessionLog: '会话记录',
3133
today: '今天', thisWeek: '本周', thisMonth: '本月', thisYear: '今年',
3234
last3d: '近3天', last7d: '近7天', last30d: '近30天', custom: '自定义',
33-
light: '浅色', dark: '深色', system: '跟随系统', autoOn: '自动刷新: 开', autoOff: '自动刷新: 关',
34-
input: '输入', output: '输出', cacheRead: '缓存命中', cacheCreate: '写入缓存',
35+
light: '浅色', dark: '深色', system: '跟随系统', autoOn: '自动 ✓', autoOff: '自动',
36+
input: '输入', output: '输出', cacheRead: '缓存读取', cacheCreate: '缓存写入',
3537
gran_1m: '1 分钟', gran_30m: '30 分钟', gran_1h: '1 小时', gran_6h: '6 小时', gran_12h: '12 小时', gran_1d: '1 天', gran_1w: '1 周', gran_1M: '1 个月',
3638
model: '模型', calls: '调用次数', allSources: '全部来源', claudeCode: 'Claude Code', codex: 'Codex', openClaw: 'OpenClaw',
3739
filterProject: '按项目筛选...', justNow: '刚刚', mAgo: '分钟前', hAgo: '小时前', dAgo: '天前',
@@ -40,7 +42,7 @@ const I18N = {
4042
};
4143

4244
// ── State ──
43-
const colors = ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4'];
45+
const colors = ['#3b82f6', '#22c55e', '#f59e0b', '#ef4444', '#8b5cf6', '#06b6d4', '#f97316', '#ec4899'];
4446
const PRESETS = ['today', 'thisWeek', 'thisMonth', 'thisYear', 'last3d', 'last7d', 'last30d', 'custom'];
4547
const GRANULARITIES = ['1m', '30m', '1h', '6h', '12h', '1d', '1w', '1M'];
4648
const REFRESH_INTERVALS = [30, 60, 300, 1800, 3600];
@@ -249,10 +251,10 @@ async function refresh() {
249251
yAxis: { type: 'value', splitLine: { lineStyle: { color: tc.grid } }, axisLabel: { color: tc.muted, formatter: v => fmt(v) } },
250252
series: [
251253
// [重构]: 将折线图全部改为同轴堆叠柱状图,直观展示 Token 总吞吐量与占比,彻底消除量级碾压遮挡
252-
{ name: t('input'), type: 'bar', stack: 'Tokens', data: (tokensTime || []).map(d => d.input_tokens), color: '#5470c6', barMaxWidth: 40 },
253-
{ name: t('output'), type: 'bar', stack: 'Tokens', data: (tokensTime || []).map(d => d.output_tokens), color: '#91cc75' },
254-
{ name: t('cacheRead'), type: 'bar', stack: 'Tokens', data: (tokensTime || []).map(d => d.cache_read), color: '#73c0de' },
255-
{ name: t('cacheCreate'), type: 'bar', stack: 'Tokens', data: (tokensTime || []).map(d => d.cache_create), color: '#fac858' }
254+
{ name: t('input'), type: 'bar', stack: 'Tokens', data: (tokensTime || []).map(d => d.input_tokens), color: '#3b82f6', barMaxWidth: 40 },
255+
{ name: t('output'), type: 'bar', stack: 'Tokens', data: (tokensTime || []).map(d => d.output_tokens), color: '#22c55e' },
256+
{ name: t('cacheRead'), type: 'bar', stack: 'Tokens', data: (tokensTime || []).map(d => d.cache_read), color: '#8b5cf6' },
257+
{ name: t('cacheCreate'), type: 'bar', stack: 'Tokens', data: (tokensTime || []).map(d => d.cache_create), color: '#f59e0b' }
256258
]
257259
}, true);
258260

@@ -456,6 +458,7 @@ function buildControls() {
456458
$('from').value = state.customFrom || new Date().toISOString().slice(0, 10);
457459
$('to').value = state.customTo || new Date().toISOString().slice(0, 10);
458460
}
461+
$('filter-project').placeholder = t('filterProject');
459462
}
460463

461464
// ── Events Binding ──

internal/server/static/index.html

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,25 @@
44
<meta charset="UTF-8">
55
<meta name="viewport" content="width=device-width, initial-scale=1.0">
66
<title>agent-usage — AI Coding Agent Usage</title>
7-
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@600;700&family=Inter:wght@400;500;600;700;800&display=swap">
7+
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600;700&family=Inter:wght@400;500;600;700;800&display=swap">
88
<script src="https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script>
99
<style>
1010
/* ── Modern CSS Variables & Theme ── */
1111
:root, [data-theme="dark"] {
12-
--bg: #0f1117; --bg-rgb: 15, 17, 23; --card: #181a20; --border: #2a2d37; --text: #eceef4; --muted: #8b8fa3;
13-
--accent: #3b82f6; --accent-hover: #2563eb; --accent-bg: rgba(59, 130, 246, 0.1);
14-
--green: #4ade80; --blue: #60a5fa; --orange: #fb923c; --pink: #f472b6;
15-
--select-bg: #1e2028; --hover: #1e2028; --shadow: 0 2px 8px rgba(0,0,0,0.3);
16-
--chart-bg: transparent; --chart-text: #eceef4; --chart-muted: #8b8fa3; --chart-grid: #2a2d37;
17-
--tooltip-bg: rgba(24, 26, 32, 0.95); --tooltip-border: #363944;
12+
--bg: #020617; --bg-rgb: 2, 6, 23; --card: #0e1223; --border: #1e293b; --text: #f1f5f9; --muted: #94a3b8;
13+
--accent: #3b82f6; --accent-hover: #2563eb; --accent-bg: rgba(59, 130, 246, 0.12);
14+
--green: #22c55e; --blue: #3b82f6; --orange: #f59e0b; --pink: #f472b6;
15+
--select-bg: #0f172a; --hover: #1a2332; --shadow: 0 2px 8px rgba(0,0,0,0.4);
16+
--chart-bg: transparent; --chart-text: #f1f5f9; --chart-muted: #94a3b8; --chart-grid: #1e293b;
17+
--tooltip-bg: rgba(14, 18, 35, 0.95); --tooltip-border: #334155;
1818
}
1919
[data-theme="light"] {
20-
--bg: #f4f5f7; --bg-rgb: 244, 245, 247; --card: #ffffff; --border: #e2e4e9; --text: #1a1d26; --muted: #6b7084;
20+
--bg: #f8fafc; --bg-rgb: 248, 250, 252; --card: #ffffff; --border: #e2e8f0; --text: #0f172a; --muted: #64748b;
2121
--accent: #2563eb; --accent-hover: #1d4ed8; --accent-bg: rgba(37, 99, 235, 0.06);
22-
--green: #16a34a; --blue: #2563eb; --orange: #ea580c; --pink: #db2777;
23-
--select-bg: #ffffff; --hover: #f8f9fb; --shadow: 0 2px 8px rgba(0,0,0,0.05);
24-
--chart-bg: transparent; --chart-text: #1a1d26; --chart-muted: #6b7084; --chart-grid: #e2e4e9;
25-
--tooltip-bg: rgba(255, 255, 255, 0.95); --tooltip-border: #e2e4e9;
22+
--green: #16a34a; --blue: #2563eb; --orange: #d97706; --pink: #db2777;
23+
--select-bg: #ffffff; --hover: #f1f5f9; --shadow: 0 1px 3px rgba(0,0,0,0.08);
24+
--chart-bg: transparent; --chart-text: #0f172a; --chart-muted: #64748b; --chart-grid: #e2e8f0;
25+
--tooltip-bg: rgba(255, 255, 255, 0.95); --tooltip-border: #e2e8f0;
2626
}
2727

2828
/* ── Base & Typography ── */
@@ -97,7 +97,7 @@
9797
.stat-card:nth-child(4) { --c: var(--pink); }
9898
.stat-card:nth-child(5) { --c: var(--accent); }
9999
.stat-card .label { font-size: 12px; color: var(--muted); font-weight: 600; letter-spacing: 0.5px; text-transform: uppercase; }
100-
.stat-card .value { font-size: 32px; font-weight: 700; margin-top: 8px; font-feature-settings: "tnum"; font-family: 'IBM Plex Mono', 'SF Mono', monospace; }
100+
.stat-card .value { font-size: 32px; font-weight: 700; margin-top: 8px; font-feature-settings: "tnum"; font-family: 'Fira Code', 'SF Mono', monospace; }
101101
.stat-card { transition: transform 0.2s, box-shadow 0.2s; }
102102
.stat-card:hover { transform: translateY(-2px); box-shadow: 0 8px 30px rgba(0,0,0,0.15); }
103103

@@ -137,11 +137,11 @@
137137
/* Badges */
138138
.badge { display: inline-flex; align-items: center; justify-content: center; padding: 4px 10px; border-radius: 20px; font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; }
139139
.badge.claude { background: rgba(59,130,246,0.1); color: #60a5fa; border: 1px solid rgba(59,130,246,0.2); }
140-
[data-theme="light"] .badge.claude { color: #2563eb; }
141-
.badge.codex { background: rgba(74,222,128,0.1); color: #4ade80; border: 1px solid rgba(74,222,128,0.2); }
142-
[data-theme="light"] .badge.codex { color: #16a34a; }
143-
.badge.openclaw { background: rgba(251,146,60,0.1); color: #fb923c; border: 1px solid rgba(251,146,60,0.2); }
144-
[data-theme="light"] .badge.openclaw { color: #ea580c; }
140+
[data-theme="light"] .badge.claude { color: #2563eb; background: rgba(37,99,235,0.08); border-color: rgba(37,99,235,0.2); }
141+
.badge.codex { background: rgba(34,197,94,0.1); color: #4ade80; border: 1px solid rgba(34,197,94,0.2); }
142+
[data-theme="light"] .badge.codex { color: #16a34a; background: rgba(22,163,74,0.08); border-color: rgba(22,163,74,0.2); }
143+
.badge.openclaw { background: rgba(245,158,11,0.1); color: #fbbf24; border: 1px solid rgba(245,158,11,0.2); }
144+
[data-theme="light"] .badge.openclaw { color: #d97706; background: rgba(217,119,6,0.08); border-color: rgba(217,119,6,0.2); }
145145

146146
/* Sorting */
147147
.sortable { cursor: pointer; user-select: none; transition: color 0.2s; }
@@ -261,7 +261,7 @@ <h1><div class="logo-dot"></div><span>agent-usage</span> <span class="sub" data-
261261

262262
<div class="sessions-card">
263263
<div class="sessions-header">
264-
<h3 data-i18n="sessions">Session Log</h3>
264+
<h3 data-i18n="sessionLog">Session Log</h3>
265265
<div style="display:flex; gap:12px; align-items:center; flex-wrap:wrap;">
266266
<input type="text" id="filter-project" class="filter-input" placeholder="Filter by project...">
267267
</div>

0 commit comments

Comments
 (0)