From e0a5ec08c3bf32268bf4892d2c2d1cfdb8df18b9 Mon Sep 17 00:00:00 2001 From: kang Date: Sat, 9 May 2026 19:21:09 +0800 Subject: [PATCH] auto-save 2026-05-09 19:21 (~6) --- .memory/worklog.json | 40 +++++------ RULES.md | 3 +- src/app.js | 42 +++++++++-- src/index.html | 17 ++++- src/styles.css | 168 ++++++++++++++++++++++++++++++++++--------- src/sw.js | 2 +- 6 files changed, 209 insertions(+), 63 deletions(-) diff --git a/.memory/worklog.json b/.memory/worklog.json index 480bb9a..a777007 100644 --- a/.memory/worklog.json +++ b/.memory/worklog.json @@ -1,26 +1,5 @@ { "entries": [ - { - "files_changed": 1, - "hash": "051750c", - "message": "auto-save 2026-05-07 18:34 (~1)", - "ts": "2026-05-07T18:34:35+08:00", - "type": "commit" - }, - { - "files_changed": 1, - "hash": "410ed58", - "message": "auto-save 2026-05-07 18:40 (~1)", - "ts": "2026-05-07T18:40:09+08:00", - "type": "commit" - }, - { - "files_changed": 1, - "hash": "20dfd2c", - "message": "auto-save 2026-05-07 18:45 (~1)", - "ts": "2026-05-07T18:46:01+08:00", - "type": "commit" - }, { "files_changed": 1, "hash": "8335626", @@ -3457,6 +3436,25 @@ "message": "auto-save 2026-05-09 19:09 (~5)", "hash": "0aba599", "files_changed": 5 + }, + { + "ts": "2026-05-09T19:15:37+08:00", + "type": "commit", + "message": "auto-save 2026-05-09 19:15 (~1)", + "hash": "31965bf", + "files_changed": 1 + }, + { + "ts": "2026-05-09T11:15:54Z", + "type": "session-heartbeat", + "message": "Codex 会话活跃 · 最近命令:codex · 分支 master · 1 项未提交变更 · 最近提交:auto-save 2026-05-09 19:15 (~1)", + "files_changed": 1 + }, + { + "ts": "2026-05-09T11:18:29Z", + "type": "session-heartbeat", + "message": "Codex 会话活跃 · 最近命令:codex · 分支 master · 3 项未提交变更 · 最近提交:auto-save 2026-05-09 19:15 (~1)", + "files_changed": 3 } ] } diff --git a/RULES.md b/RULES.md index 4a36564..89bdb03 100644 --- a/RULES.md +++ b/RULES.md @@ -16,8 +16,9 @@ - 飞书机器人列表:https://hermes.kang-kang.com/feishu/apps(只读展示 App ID / 回调地址,不含 Secret / Token) - 爱马仕前端「集成 → 飞书集成」可自助添加 / 更新飞书机器人;Secret / Token 只写入服务器 `/etc/hermes-feishu-bridge.env` - 爱马仕前端「仪表盘」同步了上游 Hermes 的快捷入口板块,个人版展示主站、API、飞书机器人列表、文档/解析入口 +- 爱马仕前端「仪表盘」活动热力图已重做为带摘要、月份标尺、紧凑格子和细分色阶的活动卡片 - 爱马仕前端「设置 → 连接」可自助维护 API 地址 / API Key 并测试连接;「对话 → 存周报」和「设置 → 周报记录」会在本地保存任务描述、上下文片段和最终周报 -- 当前前端静态壳缓存版本:`hermes-ui-v15` +- 当前前端静态壳缓存版本:`hermes-ui-v16` - 文档 / 解析:https://styles.kang-kang.com - 管理后台:待定 - 代码仓:https://git.kang-kang.com/kangwan/hermes-glass-ui-personal diff --git a/src/app.js b/src/app.js index a207ca2..cb54b23 100644 --- a/src/app.js +++ b/src/app.js @@ -1303,12 +1303,13 @@ function renderHeatmap() { el.innerHTML = ""; const b = bucketUsage(); - // 根据容器宽度动态决定多少列,每格至少 18px - const width = el.parentElement.clientWidth - 80; // 减去 padding 和 label 列 - const cellMin = 22; - const weeksCount = Math.max(12, Math.min(26, Math.floor(width / (cellMin + 8)))); + // 根据容器宽度动态决定多少列,保持格子紧凑不拉伸成大方块 + const width = el.parentElement.clientWidth - 64; // 减去内边距和星期 label 列 + const cellMin = 18; + const weeksCount = Math.max(14, Math.min(30, Math.floor(width / (cellMin + 6)))); el.style.setProperty("--hm-cols", weeksCount); + document.getElementById("heatmapMonths")?.style.setProperty("--hm-cols", weeksCount); // 绝对阈值: 每天消息数落在哪个区间 // 0 = 无活动 | 1-5 = 轻 | 6-15 = 一般 | 16-40 = 活跃 | 41+ = 高强度 @@ -1328,6 +1329,31 @@ function renderHeatmap() { const startMonday = new Date(today); startMonday.setDate(startMonday.getDate() - todayDow - (weeksCount - 1) * 7); + const monthEl = document.getElementById("heatmapMonths"); + if (monthEl) { + const monthNames = ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"]; + const monthCells = ['
']; + for (let w = 0; w < weeksCount; w++) { + const weekStart = new Date(startMonday); + weekStart.setDate(weekStart.getDate() + w * 7); + let label = ""; + for (let d = 0; d < 7; d++) { + const cursor = new Date(weekStart); + cursor.setDate(cursor.getDate() + d); + if (w === 0 || cursor.getDate() === 1) { + label = monthNames[cursor.getMonth()]; + break; + } + } + monthCells.push(`
${label}
`); + } + monthEl.innerHTML = monthCells.join(""); + } + + let activeDays = 0; + let peakMsgs = 0; + let peakKey = ""; + // 按 row(weekday) × col(week) 的顺序铺,每行先放一个 label const labels = ["一", "", "三", "", "五", "", "日"]; for (let dow = 0; dow < 7; dow++) { @@ -1344,15 +1370,23 @@ function renderHeatmap() { const msgs = data?.messages || 0; const lvl = levelOf(msgs); const future = cursor > today; + if (!future && msgs > 0) activeDays += 1; + if (!future && msgs > peakMsgs) { + peakMsgs = msgs; + peakKey = k; + } const cell = document.createElement("div"); cell.className = "hm-cell lvl-" + lvl + (future ? " future" : "") + (k === selectedDay ? " sel" : ""); cell.title = k + (msgs ? ` · ${msgs} 条消息` : " · 无活动"); + cell.setAttribute("aria-label", cell.title); if (!future) { cell.onclick = () => { selectedDay = k; renderHeatmap(); renderDayDetail(k); }; } el.appendChild(cell); } } + setText("hmActiveDays", activeDays + " 个活跃日"); + setText("hmPeakDay", peakMsgs ? ("峰值 " + peakMsgs + " · " + peakKey.slice(5)) : "峰值 0"); } // 窗口尺寸变化时重新渲染热力图 diff --git a/src/index.html b/src/index.html index d226063..77587b1 100644 --- a/src/index.html +++ b/src/index.html @@ -1006,9 +1006,22 @@ git push # Gitea kangwan/hermes-glass-ui-personal -
活动热力图 · 最近 8 周
-
+
+
+
活动热力图
+

最近使用节奏

+

按天聚合消息量,颜色越深代表当天对话越活跃。

+
+
+ 0 个活跃日 + 峰值 0 +
+
+
+
+
+
diff --git a/src/styles.css b/src/styles.css index 966de6c..87d186b 100644 --- a/src/styles.css +++ b/src/styles.css @@ -1955,26 +1955,111 @@ a { color: var(--orange-3); text-decoration: none; } margin-top: 3px; overflow-wrap: anywhere; } -/* 热力图 — 全宽大格 */ +/* 活动热力图 */ .heatmap-wrap { - padding: 24px 28px 22px; - background: var(--card-bg); + padding: 20px 22px 18px; + background: + linear-gradient(135deg, rgba(255,105,0,0.08), rgba(255,255,255,0.035) 42%, rgba(255,178,89,0.035)), + var(--card-bg); border: 1px solid var(--line); - border-radius: 18px; + border-radius: 20px; margin-bottom: 18px; - /* blur 已在外壳统一处理,内部卡片不再单独磨砂以降低合成成本 */ + overflow: hidden; } +[data-theme="light"] .heatmap-wrap { + background: + linear-gradient(135deg, rgba(255,105,0,0.08), rgba(255,255,255,0.68) 48%, rgba(255,178,89,0.08)), + var(--card-bg); +} +.heatmap-head { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 18px; + padding-bottom: 16px; + border-bottom: 1px solid var(--line); + min-width: 0; +} +.heatmap-kicker { + color: var(--orange-3); + font-size: 10px; + font-weight: 800; + letter-spacing: 1.4px; + text-transform: uppercase; + margin-bottom: 5px; +} +.heatmap-head h3 { + margin: 0; + color: var(--text); + font-size: 17px; + font-weight: 850; + letter-spacing: -0.3px; +} +.heatmap-head p { + margin: 5px 0 0; + color: var(--text-dim2); + font-size: 12px; + line-height: 1.55; +} +.heatmap-metrics { + display: flex; + align-items: center; + justify-content: flex-end; + gap: 8px; + flex-wrap: wrap; + flex: 0 0 auto; +} +.heatmap-metrics span { + border: 1px solid rgba(255,105,0,0.24); + background: rgba(255,105,0,0.08); + color: var(--orange-3); + border-radius: 999px; + padding: 6px 9px; + font-size: 11px; + font-weight: 800; + font-variant-numeric: tabular-nums; +} +.heatmap-board { + margin-top: 16px; + padding: 14px; + border: 1px solid var(--line); + border-radius: 16px; + background: rgba(0,0,0,0.12); + overflow-x: auto; + overflow-y: hidden; + overscroll-behavior-inline: contain; +} +[data-theme="light"] .heatmap-board { background: rgba(15,22,40,0.035); } +.heatmap-months { + display: grid; + grid-template-columns: 28px repeat(var(--hm-cols, 16), minmax(12px, 22px)); + gap: 5px; + justify-content: space-between; + min-width: 420px; + margin-bottom: 6px; +} +.hm-month-label { + color: var(--text-dim3); + font-size: 10px; + font-weight: 800; + line-height: 1; + white-space: nowrap; + overflow: visible; +} +.hm-month-spacer { min-width: 28px; } .heatmap { display: grid; - grid-template-columns: auto repeat(var(--hm-cols, 16), 1fr); - grid-auto-rows: 1fr; - gap: 8px; + grid-template-columns: 28px repeat(var(--hm-cols, 16), minmax(12px, 22px)); + grid-auto-rows: clamp(13px, 1.8vw, 20px); + gap: 5px; + justify-content: space-between; width: 100%; + min-width: 420px; } .hm-row-label { font-size: 10px; color: var(--text-dim3); - font-weight: 700; + font-weight: 800; text-align: right; padding-right: 6px; align-self: center; @@ -1982,38 +2067,54 @@ a { color: var(--orange-3); text-decoration: none; } } .hm-cell { width: 100%; - aspect-ratio: 1; - min-height: 0; - border-radius: 6px; - background: rgba(255,255,255,0.04); - border: 1px solid var(--line); + height: 100%; + min-width: 12px; + border-radius: 5px; + background: rgba(255,255,255,0.045); + border: 1px solid rgba(255,255,255,0.07); cursor: pointer; - transition: transform 0.15s, border-color 0.15s, box-shadow 0.15s; + position: relative; + transition: transform 0.16s ease, border-color 0.16s ease, box-shadow 0.16s ease, filter 0.16s ease; +} +[data-theme="light"] .hm-cell { + background: rgba(15,22,40,0.045); + border-color: rgba(15,22,40,0.06); } -[data-theme="light"] .hm-cell { background: rgba(15,22,40,0.04); } .hm-cell:hover { - transform: scale(1.12); - border-color: var(--orange); - box-shadow: 0 0 0 2px rgba(255,105,0,0.25); + transform: translateY(-2px) scale(1.08); + border-color: rgba(255,178,89,0.75); + box-shadow: 0 8px 18px rgba(0,0,0,0.24), 0 0 0 2px rgba(255,105,0,0.2); + filter: saturate(1.08); z-index: 2; } -.hm-cell.lvl-1 { background: rgba(255,105,0,0.22); border-color: rgba(255,105,0,0.35); } -.hm-cell.lvl-2 { background: rgba(255,105,0,0.40); border-color: rgba(255,105,0,0.55); } -.hm-cell.lvl-3 { background: rgba(255,105,0,0.62); border-color: rgba(255,105,0,0.8); } +.hm-cell.lvl-1 { + background: rgba(255,178,89,0.24); + border-color: rgba(255,178,89,0.28); +} +.hm-cell.lvl-2 { + background: rgba(255,136,48,0.42); + border-color: rgba(255,136,48,0.46); +} +.hm-cell.lvl-3 { + background: linear-gradient(135deg, rgba(255,105,0,0.72), rgba(255,178,89,0.52)); + border-color: rgba(255,136,48,0.76); +} .hm-cell.lvl-4 { - background: var(--orange); - border-color: var(--orange); - box-shadow: 0 0 16px rgba(255,105,0,0.4); + background: linear-gradient(135deg, #ff6900, #ffb259); + border-color: rgba(255,178,89,0.9); + box-shadow: 0 0 18px rgba(255,105,0,0.28); } .hm-cell.sel { - outline: 2px solid var(--orange); - outline-offset: 3px; + outline: 2px solid rgba(255,210,150,0.95); + outline-offset: 2px; + box-shadow: 0 0 0 5px rgba(255,105,0,0.12), 0 12px 22px rgba(0,0,0,0.25); z-index: 3; } .hm-cell.future { - opacity: 0.18; + opacity: 0.3; cursor: default; - background: transparent; + background: repeating-linear-gradient(135deg, transparent 0 4px, rgba(255,255,255,0.035) 4px 8px); + border-style: dashed; } .hm-cell.future:hover { transform: none; box-shadow: none; border-color: var(--line); } @@ -2021,19 +2122,18 @@ a { color: var(--orange-3); text-decoration: none; } display: flex; align-items: center; gap: 8px; - margin-top: 18px; - padding-top: 16px; - border-top: 1px solid var(--line); + margin-top: 14px; + justify-content: flex-end; font-size: 11px; color: var(--text-dim2); - font-weight: 600; + font-weight: 700; } .heatmap-legend .hm-cell { width: 16px; height: 16px; - aspect-ratio: auto; cursor: default; flex: 0 0 16px; + min-width: 16px; } .heatmap-legend .hm-cell:hover { transform: none; box-shadow: none; } diff --git a/src/sw.js b/src/sw.js index 1d3a7bd..d0dac7b 100644 --- a/src/sw.js +++ b/src/sw.js @@ -1,6 +1,6 @@ // 爱马仕 Hermes · 轻量 Service Worker // 静态壳走 network-first(拿不到再回退缓存),API 直通 -const CACHE = "hermes-ui-v15"; +const CACHE = "hermes-ui-v16"; const ASSETS = [ "./", "./index.html",