wukong-gitlog-cli 1.0.15 → 1.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,19 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [1.0.16](https://github.com/tomatobybike/wukong-gitlog-cli/compare/v1.0.15...v1.0.16) (2025-12-03)
6
+
7
+
8
+ ### Features
9
+
10
+ * 🎸 sider bar UI ([e3a48ab](https://github.com/tomatobybike/wukong-gitlog-cli/commit/e3a48abe5b0148fe0d9dcd42b7b028cad53d4c94))
11
+ * 🎸 ui show ([e9eba58](https://github.com/tomatobybike/wukong-gitlog-cli/commit/e9eba5823333545d598be363b58eca1f6ecfa6ed))
12
+
13
+
14
+ ### Bug Fixes
15
+
16
+ * 🐛 makeline clickEvent ([4ad6378](https://github.com/tomatobybike/wukong-gitlog-cli/commit/4ad6378d88aca2dde6083efde844730443228e48))
17
+
5
18
  ### [1.0.15](https://github.com/tomatobybike/wukong-gitlog-cli/compare/v1.0.14...v1.0.15) (2025-12-03)
6
19
 
7
20
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wukong-gitlog-cli",
3
- "version": "1.0.15",
3
+ "version": "1.0.16",
4
4
  "description": "Advanced Git commit log exporter with Excel/JSON/TXT output, grouping, stats and CLI.",
5
5
  "keywords": [
6
6
  "git",
package/web/app.js CHANGED
@@ -184,14 +184,24 @@ function drawHourlyOvertime(stats, onHourClick) {
184
184
  data: [
185
185
  {
186
186
  name: '上班开始',
187
+ nameValue: String(stats.startHour).padStart(2, '0'),
187
188
  xAxis: String(stats.startHour).padStart(2, '0')
188
189
  },
189
- { name: '下班时间', xAxis: String(stats.endHour).padStart(2, '0') },
190
+ {
191
+ name: '下班时间',
192
+ nameValue: String(stats.endHour).padStart(2, '0'),
193
+ xAxis: String(stats.endHour).padStart(2, '0')
194
+ },
190
195
  {
191
196
  name: '午休开始',
197
+ nameValue: String(stats.lunchStart).padStart(2, '0'),
192
198
  xAxis: String(stats.lunchStart).padStart(2, '0')
193
199
  },
194
- { name: '午休结束', xAxis: String(stats.lunchEnd).padStart(2, '0') }
200
+ {
201
+ name: '午休结束',
202
+ nameValue: String(stats.lunchEnd).padStart(2, '0'),
203
+ xAxis: String(stats.lunchEnd).padStart(2, '0')
204
+ }
195
205
  ]
196
206
  }
197
207
  }
@@ -201,7 +211,14 @@ function drawHourlyOvertime(stats, onHourClick) {
201
211
  // 点击事件(点击某小时 → 打开侧栏)
202
212
  if (typeof onHourClick === 'function') {
203
213
  chart.on('click', (p) => {
204
- const hour = Number(p.name)
214
+ let hour = Number(p.name)
215
+ if(p.componentType === 'markLine') {
216
+ hour = Number(p.data.xAxis)
217
+ }
218
+ // FIXME: remove debug log before production
219
+ console.log('❌', 'hour', hour, p)
220
+ document.getElementById('dayDetailSidebar').classList.remove('show')
221
+ if (Object.is(hour, NaN)) return
205
222
  onHourClick(hour, commits[hour])
206
223
  })
207
224
  }
@@ -214,6 +231,7 @@ function showSideBarForHour(hour, commitsOrCount) {
214
231
  // 支持传入 number(仅次数)或 array(详细 commit 列表)
215
232
  // 统一复用通用详情侧栏 DOM
216
233
  const sidebar = document.getElementById('dayDetailSidebar')
234
+ const backdrop = document.getElementById('sidebarBackdrop')
217
235
  const titleEl = document.getElementById('sidebarTitle')
218
236
  const contentEl = document.getElementById('sidebarContent')
219
237
 
@@ -235,19 +253,22 @@ function showSideBarForHour(hour, commitsOrCount) {
235
253
  } else if (Array.isArray(commitsOrCount)) {
236
254
  // commits 列表:展示作者/时间/消息(最多前 50 条,避免性能问题)
237
255
  const commits = commitsOrCount.slice(0, 50)
238
- contentEl.innerHTML = commits
256
+ contentEl.innerHTML = `<div class="sidebar-list">${commits
239
257
  .map((c) => {
240
258
  const author = c.author ?? c.name ?? 'unknown'
241
259
  const time = c.date ?? c.time ?? ''
242
260
  const msg = (c.message ?? c.msg ?? c.body ?? '').replace(/\n/g, ' ')
243
261
  return `
244
- <div class="hour-commit">
245
- <div class="meta">👤 <b>${escapeHtml(author)}</b> · 🕒 ${escapeHtml(time)}</div>
246
- <div class="msg">${escapeHtml(msg)}</div>
247
- </div>
248
- `
262
+ <div class="sidebar-item">
263
+ <div class="sidebar-item-header">
264
+ <span class="author">👤 ${escapeHtml(author)}</span>
265
+ <span class="time">🕒 ${escapeHtml(time)}</span>
266
+ </div>
267
+ <div class="sidebar-item-message">${escapeHtml(msg)}</div>
268
+ </div>
269
+ `
249
270
  })
250
- .join('')
271
+ .join('')}</div>`
251
272
 
252
273
  if (commitsOrCount.length > 50) {
253
274
  const more = commitsOrCount.length - 50
@@ -257,8 +278,9 @@ function showSideBarForHour(hour, commitsOrCount) {
257
278
  contentEl.innerHTML = `<div style="font-size:14px;">无可展示数据</div>`
258
279
  }
259
280
 
260
- // 打开侧栏
281
+ // 打开侧栏 + 遮罩
261
282
  sidebar.classList.add('show')
283
+ if (backdrop) backdrop.classList.add('show')
262
284
  }
263
285
 
264
286
  // 简单的 HTML 转义,防止 XSS 与布局断裂
@@ -410,6 +432,7 @@ function drawDailyTrend(commits, onDayClick) {
410
432
  function showSideBarForWeek(period, weeklyItem, commits = []) {
411
433
  // 统一复用通用详情侧栏 DOM
412
434
  const sidebar = document.getElementById('dayDetailSidebar')
435
+ const backdrop = document.getElementById('sidebarBackdrop')
413
436
  const titleEl = document.getElementById('sidebarTitle')
414
437
  const contentEl = document.getElementById('sidebarContent')
415
438
 
@@ -426,22 +449,27 @@ function showSideBarForWeek(period, weeklyItem, commits = []) {
426
449
  if (!commits.length) {
427
450
  html += `<div style="padding:10px;color:#777;">该周无提交记录</div>`
428
451
  } else {
429
- html += commits
452
+ html += `<div class="sidebar-list">${commits
430
453
  .map((c) => {
454
+ const author = escapeHtml(c.author || 'unknown')
455
+ const time = escapeHtml(c.date || '')
456
+ const msg = escapeHtml((c.message || '').replace(/\n/g, ' '))
431
457
  return `
432
- <div class="week-commit">
433
- <div class="meta">👤 <b>${escapeHtml(c.author || 'unknown')}</b> · 🕒 ${
434
- c.date
435
- }</div>
436
- <div class="msg">${escapeHtml((c.message || '').replace(/\n/g, ' '))}</div>
458
+ <div class="sidebar-item">
459
+ <div class="sidebar-item-header">
460
+ <span class="author">👤 ${author}</span>
461
+ <span class="time">🕒 ${time}</span>
462
+ </div>
463
+ <div class="sidebar-item-message">${msg}</div>
437
464
  </div>
438
465
  `
439
466
  })
440
- .join('')
467
+ .join('')}</div>`
441
468
  }
442
469
 
443
470
  contentEl.innerHTML = html
444
471
  sidebar.classList.add('show')
472
+ if (backdrop) backdrop.classList.add('show')
445
473
  }
446
474
 
447
475
  function drawWeeklyTrend(weekly, commits, onWeekClick) {
@@ -543,7 +571,6 @@ function drawWeeklyTrend(weekly, commits, onWeekClick) {
543
571
  const idx = p.dataIndex
544
572
  const w = weekly[idx]
545
573
 
546
-
547
574
  const start = new Date(w.range.start)
548
575
  const end = new Date(w.range.end)
549
576
  end.setHours(23, 59, 59, 999) // 包含当天
@@ -828,9 +855,7 @@ function drawDailySeverity(latestByDay, commits, onDayClick) {
828
855
 
829
856
  // 若某天 latestHourNormalized 为空,表示「没有下班后到次日上班前的提交」,
830
857
  // 这里按 0 小时加班处理,保证折线连续。
831
- const sev = raw.map((v) =>
832
- v == null ? 0 : Math.max(0, Number(v) - endH)
833
- )
858
+ const sev = raw.map((v) => (v == null ? 0 : Math.max(0, Number(v) - endH)))
834
859
 
835
860
  const el = document.getElementById('dailySeverityChart')
836
861
  // eslint-disable-next-line no-undef
@@ -1101,6 +1126,7 @@ function drawDailyTrendSeverity(commits, weekly, onDayClick) {
1101
1126
 
1102
1127
  function showDayDetailSidebar(date, count, commits) {
1103
1128
  const sidebar = document.getElementById('dayDetailSidebar')
1129
+ const backdrop = document.getElementById('sidebarBackdrop')
1104
1130
  const title = document.getElementById('sidebarTitle')
1105
1131
  const content = document.getElementById('sidebarContent')
1106
1132
 
@@ -1110,17 +1136,19 @@ function showDayDetailSidebar(date, count, commits) {
1110
1136
  content.innerHTML = commits
1111
1137
  .map(
1112
1138
  (c) => `
1113
- <div style="margin-bottom:12px;">
1114
- <div>👤 <b>${c.author}</b></div>
1115
- <div>🕒 ${c.time || c.date}</div>
1116
- <div>💬 ${c.msg ||c.message}</div>
1139
+ <div class="sidebar-item">
1140
+ <div class="sidebar-item-header">
1141
+ <span class="author">👤 ${escapeHtml(c.author || 'unknown')}</span>
1142
+ <span class="time">🕒 ${escapeHtml(c.time || c.date || '')}</span>
1143
+ </div>
1144
+ <div class="sidebar-item-message">${escapeHtml(c.msg || c.message || '')}</div>
1117
1145
  </div>
1118
- <hr/>
1119
1146
  `
1120
1147
  )
1121
1148
  .join('')
1122
1149
 
1123
1150
  sidebar.classList.add('show')
1151
+ if (backdrop) backdrop.classList.add('show')
1124
1152
  }
1125
1153
 
1126
1154
  function renderKpi(stats) {
@@ -1132,13 +1160,13 @@ function renderKpi(stats) {
1132
1160
  // 使用 cutoff + 上下班时间,重新在全部 commits 中计算「加班最晚一次提交」
1133
1161
  const cutoff = window.__overnightCutoff ?? 6
1134
1162
  const startHour =
1135
- (typeof stats.startHour === 'number' && stats.startHour >= 0
1163
+ typeof stats.startHour === 'number' && stats.startHour >= 0
1136
1164
  ? stats.startHour
1137
- : 9)
1165
+ : 9
1138
1166
  const endHour =
1139
- (typeof stats.endHour === 'number' && stats.endHour >= 0
1167
+ typeof stats.endHour === 'number' && stats.endHour >= 0
1140
1168
  ? stats.endHour
1141
- : window.__overtimeEndHour ?? 18)
1169
+ : (window.__overtimeEndHour ?? 18)
1142
1170
 
1143
1171
  let latestOut = null
1144
1172
  let latestOutHour = null
@@ -1349,8 +1377,18 @@ function computeAndRenderLatestOvertime(latestByDay) {
1349
1377
  }
1350
1378
  }
1351
1379
 
1352
- // 关闭按钮
1380
+ // 抽屉关闭交互(按钮 + 点击遮罩)
1353
1381
  document.getElementById('sidebarClose').onclick = () => {
1354
1382
  document.getElementById('dayDetailSidebar').classList.remove('show')
1383
+ const backdrop = document.getElementById('sidebarBackdrop')
1384
+ if (backdrop) backdrop.classList.remove('show')
1385
+ }
1386
+
1387
+ const sidebarBackdropEl = document.getElementById('sidebarBackdrop')
1388
+ if (sidebarBackdropEl) {
1389
+ sidebarBackdropEl.addEventListener('click', () => {
1390
+ document.getElementById('dayDetailSidebar').classList.remove('show')
1391
+ sidebarBackdropEl.classList.remove('show')
1392
+ })
1355
1393
  }
1356
1394
  main()
package/web/index.html CHANGED
@@ -102,6 +102,8 @@
102
102
  >
103
103
  </footer>
104
104
  <!-- 通用:右侧滑出的详情侧栏(小时 / 天 / 周 复用同一个 DOM) -->
105
+ <!-- 背景遮罩,点击可关闭侧栏 -->
106
+ <div id="sidebarBackdrop" class="sidebar-backdrop"></div>
105
107
  <div id="dayDetailSidebar" class="sidebar">
106
108
  <div class="sidebar-header">
107
109
  <span id="sidebarTitle"></span>
@@ -189,20 +189,40 @@ td {
189
189
  margin-bottom: 8px;
190
190
  color: #00a76f;
191
191
  }
192
+ /* 抽屉 & 遮罩(参考 Material UI Drawer) -------------------- */
193
+ .sidebar-backdrop {
194
+ position: fixed;
195
+ inset: 0;
196
+ background: rgba(15, 23, 42, 0.38); /* 深色半透明遮罩 */
197
+ opacity: 0;
198
+ pointer-events: none;
199
+ transition: opacity 0.25s ease;
200
+ z-index: 1200;
201
+ }
202
+
203
+ .sidebar-backdrop.show {
204
+ opacity: 1;
205
+ pointer-events: auto;
206
+ }
207
+
192
208
  .sidebar {
193
209
  position: fixed;
194
210
  top: 0;
195
- right: -400px;
196
- width: 400px;
211
+ right: -460px;
212
+ width: min(460px, 100%);
197
213
  height: 100%;
198
214
  background: #fff;
199
- box-shadow: -2px 0 6px rgba(0, 0, 0, 0.15);
200
- transition: right 0.35s ease;
201
- z-index: 9999;
202
- padding: 16px;
215
+ box-shadow:
216
+ 0 10px 15px rgba(0, 0, 0, 0.1),
217
+ 0 4px 6px rgba(0, 0, 0, 0.08);
218
+ transition: right 0.3s ease;
219
+ z-index: 1300;
220
+ padding: 20px 20px 16px;
203
221
  display: flex;
204
222
  flex-direction: column;
205
223
  box-sizing: border-box;
224
+ border-radius: 12px 0 0 12px;
225
+ border-left: 1px solid rgba(145, 158, 171, 0.24);
206
226
  }
207
227
 
208
228
  .sidebar.show {
@@ -213,35 +233,115 @@ td {
213
233
  display: flex;
214
234
  justify-content: space-between;
215
235
  align-items: center;
216
- font-size: 18px;
217
- margin-bottom: 16px;
236
+ font-size: 16px;
237
+ font-weight: 500;
238
+ margin-bottom: 12px;
239
+ color: #111827;
240
+ }
241
+
242
+ .sidebar-header span {
243
+ display: inline-flex;
244
+ align-items: center;
245
+ gap: 6px;
218
246
  }
219
247
 
220
248
  .sidebar-header button {
221
- background: none;
249
+ width: 32px;
250
+ height: 32px;
251
+ display: inline-flex;
252
+ align-items: center;
253
+ justify-content: center;
254
+ background: rgba(148, 163, 184, 0.12);
222
255
  border: none;
223
- font-size: 24px;
256
+ border-radius: 999px;
257
+ font-size: 18px;
224
258
  cursor: pointer;
259
+ color: #4b5563;
260
+ transition:
261
+ background 0.2s ease,
262
+ color 0.2s ease,
263
+ box-shadow 0.2s ease;
264
+ }
265
+
266
+ .sidebar-header button:hover {
267
+ background: rgba(148, 163, 184, 0.22);
268
+ color: #111827;
269
+ box-shadow: 0 2px 6px rgba(15, 23, 42, 0.18);
225
270
  }
226
271
 
227
272
  .sidebar-content {
228
273
  overflow-y: auto;
229
- font-size: 14px;
274
+ font-size: 13px;
275
+ line-height: 1.6;
276
+ padding-right: 4px;
230
277
  }
231
- /* 小块提交记录样式 */
232
- .hour-commit {
233
- padding: 10px 8px;
234
- border-radius: 6px;
235
- background: #fafafa;
236
- margin-bottom: 10px;
237
- box-shadow: 0 1px 0 rgba(0, 0, 0, 0.02);
278
+
279
+ .sidebar-content::-webkit-scrollbar {
280
+ width: 6px;
281
+ }
282
+
283
+ .sidebar-content::-webkit-scrollbar-thumb {
284
+ background: rgba(148, 163, 184, 0.6);
285
+ border-radius: 999px;
238
286
  }
239
- .hour-commit .meta {
240
- color: #666;
287
+
288
+ .sidebar-content::-webkit-scrollbar-track {
289
+ background: transparent;
290
+ }
291
+
292
+ /* 抽屉中的提交列表(参考 MUI List / ListItem) ------------- */
293
+ .sidebar-list {
294
+ display: flex;
295
+ flex-direction: column;
296
+ gap: 8px;
297
+ padding: 4px 0;
298
+ }
299
+
300
+ .sidebar-item,
301
+ .hour-commit,
302
+ .week-commit {
303
+ padding: 10px 12px;
304
+ border-radius: 8px;
305
+ background: #f9fafb;
306
+ border: 1px solid rgba(148, 163, 184, 0.25);
307
+ box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
308
+ transition:
309
+ background 0.18s ease,
310
+ box-shadow 0.18s ease,
311
+ transform 0.1s ease;
312
+ margin: 8px 0;
313
+ }
314
+
315
+ .sidebar-item:hover,
316
+ .hour-commit:hover,
317
+ .week-commit:hover {
318
+ background: #f3f4ff;
319
+ box-shadow: 0 3px 8px rgba(15, 23, 42, 0.12);
320
+ transform: translateY(-1px);
321
+ }
322
+
323
+ .sidebar-item-header {
324
+ display: flex;
325
+ justify-content: space-between;
326
+ align-items: center;
241
327
  font-size: 12px;
242
- margin-bottom: 6px;
328
+ color: #64748b;
329
+ margin-bottom: 4px;
243
330
  }
244
- .hour-commit .msg {
331
+
332
+ .sidebar-item-header .author {
333
+ font-weight: 600;
334
+ color: #111827;
335
+ }
336
+
337
+ .sidebar-item-header .time {
338
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
339
+ 'Liberation Mono', 'Courier New', monospace;
340
+ }
341
+
342
+ .sidebar-item-message {
343
+ font-size: 13px;
344
+ color: #111827;
245
345
  font-weight: 500;
246
346
  word-break: break-word;
247
347
  }