auto-save 2026-05-09 19:21 (~6)

This commit is contained in:
2026-05-09 19:21:09 +08:00
parent 31965bf9ed
commit e0a5ec08c3
6 changed files with 209 additions and 63 deletions

View File

@@ -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
}
]
}

View File

@@ -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

View File

@@ -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 = ['<div class="hm-month-spacer"></div>'];
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(`<div class="hm-month-label">${label}</div>`);
}
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");
}
// 窗口尺寸变化时重新渲染热力图

View File

@@ -1006,9 +1006,22 @@ git push # Gitea kangwan/hermes-glass-ui-personal
</div>
<!-- 热力图 -->
<div class="dash-section-label">活动热力图 · 最近 8 周</div>
<div class="heatmap-wrap">
<div class="heatmap-head">
<div>
<div class="heatmap-kicker">活动热力图</div>
<h3>最近使用节奏</h3>
<p>按天聚合消息量,颜色越深代表当天对话越活跃。</p>
</div>
<div class="heatmap-metrics">
<span id="hmActiveDays">0 个活跃日</span>
<span id="hmPeakDay">峰值 0</span>
</div>
</div>
<div class="heatmap-board">
<div class="heatmap-months" id="heatmapMonths"></div>
<div class="heatmap" id="heatmap"></div>
</div>
<div class="heatmap-legend">
<span></span>
<div class="hm-cell lvl-0"></div>

View File

@@ -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; }

View File

@@ -1,6 +1,6 @@
// 爱马仕 Hermes · 轻量 Service Worker
// 静态壳走 network-first拿不到再回退缓存API 直通
const CACHE = "hermes-ui-v15";
const CACHE = "hermes-ui-v16";
const ASSETS = [
"./",
"./index.html",