wukong-gitlog-cli 1.0.6 → 1.0.7
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 +7 -0
- package/package.json +1 -1
- package/web/app.js +105 -38
- package/web/index.html +20 -5
- package/web/static/echarts.min.js +45 -0
- package/web/style.css +6 -0
- package/web/static/chart.js +0 -14
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
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.7](https://github.com/tomatobybike/wukong-gitlog-cli/compare/v1.0.6...v1.0.7) (2025-11-29)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* 🎸 charts 2 echarts ([6d6d780](https://github.com/tomatobybike/wukong-gitlog-cli/commit/6d6d780c053cd094a3a59ee58249d55bec504655))
|
|
11
|
+
|
|
5
12
|
### [1.0.6](https://github.com/tomatobybike/wukong-gitlog-cli/compare/v1.0.5...v1.0.6) (2025-11-29)
|
|
6
13
|
|
|
7
14
|
|
package/package.json
CHANGED
package/web/app.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* global Chart */
|
|
2
1
|
/* eslint-disable import/no-absolute-path */
|
|
3
2
|
const formatDate = (d) => new Date(d).toLocaleString();
|
|
4
3
|
|
|
@@ -19,38 +18,103 @@ async function loadData() {
|
|
|
19
18
|
}
|
|
20
19
|
}
|
|
21
20
|
|
|
22
|
-
|
|
21
|
+
let commitsAll = [];
|
|
22
|
+
let filtered = [];
|
|
23
|
+
let page = 1;
|
|
24
|
+
let pageSize = 10;
|
|
25
|
+
|
|
26
|
+
function renderCommitsTablePage() {
|
|
23
27
|
const tbody = document.querySelector('#commitsTable tbody');
|
|
24
28
|
tbody.innerHTML = '';
|
|
25
|
-
|
|
29
|
+
const start = (page - 1) * pageSize;
|
|
30
|
+
const end = start + pageSize;
|
|
31
|
+
filtered.slice(start, end).forEach((c) => {
|
|
26
32
|
const tr = document.createElement('tr');
|
|
27
33
|
tr.innerHTML = `<td>${c.hash.slice(0, 8)}</td><td>${c.author}</td><td>${formatDate(c.date)}</td><td>${c.message}</td>`;
|
|
28
34
|
tbody.appendChild(tr);
|
|
29
35
|
});
|
|
30
36
|
}
|
|
31
37
|
|
|
38
|
+
function updatePager() {
|
|
39
|
+
const totalPages = Math.max(1, Math.ceil(filtered.length / pageSize));
|
|
40
|
+
if (page > totalPages) page = totalPages;
|
|
41
|
+
const pageInfo = document.getElementById('pageInfo');
|
|
42
|
+
pageInfo.textContent = `${page} / ${totalPages}`;
|
|
43
|
+
document.getElementById('prevPage').disabled = page <= 1;
|
|
44
|
+
document.getElementById('nextPage').disabled = page >= totalPages;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function applySearch() {
|
|
48
|
+
const q = document.getElementById('searchInput').value.trim().toLowerCase();
|
|
49
|
+
if (!q) {
|
|
50
|
+
filtered = commitsAll.slice();
|
|
51
|
+
} else {
|
|
52
|
+
filtered = commitsAll.filter((c) => {
|
|
53
|
+
const h = c.hash.toLowerCase();
|
|
54
|
+
const a = String(c.author || '').toLowerCase();
|
|
55
|
+
const m = String(c.message || '').toLowerCase();
|
|
56
|
+
const d = formatDate(c.date).toLowerCase();
|
|
57
|
+
return h.includes(q) || a.includes(q) || m.includes(q) || d.includes(q);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
page = 1;
|
|
61
|
+
updatePager();
|
|
62
|
+
renderCommitsTablePage();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function initTableControls() {
|
|
66
|
+
document.getElementById('searchInput').addEventListener('input', applySearch);
|
|
67
|
+
document.getElementById('pageSize').addEventListener('change', (e) => {
|
|
68
|
+
pageSize = parseInt(e.target.value, 10) || 10;
|
|
69
|
+
page = 1;
|
|
70
|
+
updatePager();
|
|
71
|
+
renderCommitsTablePage();
|
|
72
|
+
});
|
|
73
|
+
document.getElementById('prevPage').addEventListener('click', () => {
|
|
74
|
+
if (page > 1) {
|
|
75
|
+
page -= 1;
|
|
76
|
+
updatePager();
|
|
77
|
+
renderCommitsTablePage();
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
document.getElementById('nextPage').addEventListener('click', () => {
|
|
81
|
+
const totalPages = Math.max(1, Math.ceil(filtered.length / pageSize));
|
|
82
|
+
if (page < totalPages) {
|
|
83
|
+
page += 1;
|
|
84
|
+
updatePager();
|
|
85
|
+
renderCommitsTablePage();
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
32
90
|
function drawHourlyOvertime(stats) {
|
|
33
|
-
const
|
|
91
|
+
const el = document.getElementById('hourlyOvertimeChart');
|
|
92
|
+
const chart = echarts.init(el);
|
|
34
93
|
const data = stats.hourlyOvertimeCommits || [];
|
|
35
94
|
const labels = Array.from({ length: 24 }, (_, i) => String(i).padStart(2, '0'));
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
95
|
+
chart.setOption({
|
|
96
|
+
tooltip: {},
|
|
97
|
+
xAxis: { type: 'category', data: labels },
|
|
98
|
+
yAxis: { type: 'value' },
|
|
99
|
+
series: [{ type: 'bar', name: 'Overtime commits', data }]
|
|
40
100
|
});
|
|
41
|
-
return
|
|
101
|
+
return chart;
|
|
42
102
|
}
|
|
43
103
|
|
|
44
104
|
function drawOutsideVsInside(stats) {
|
|
45
|
-
const
|
|
105
|
+
const el = document.getElementById('outsideVsInsideChart');
|
|
106
|
+
const chart = echarts.init(el);
|
|
46
107
|
const outside = stats.outsideWorkCount || 0;
|
|
47
108
|
const total = stats.total || 0;
|
|
48
109
|
const inside = Math.max(0, total - outside);
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
110
|
+
chart.setOption({
|
|
111
|
+
tooltip: {},
|
|
112
|
+
series: [{ type: 'pie', radius: '55%', data: [
|
|
113
|
+
{ value: inside, name: '工作时间内' },
|
|
114
|
+
{ value: outside, name: '下班时间' }
|
|
115
|
+
] }]
|
|
52
116
|
});
|
|
53
|
-
return
|
|
117
|
+
return chart;
|
|
54
118
|
}
|
|
55
119
|
|
|
56
120
|
function drawDailyTrend(commits) {
|
|
@@ -61,42 +125,45 @@ function drawDailyTrend(commits) {
|
|
|
61
125
|
});
|
|
62
126
|
const labels = Array.from(map.keys()).sort();
|
|
63
127
|
const data = labels.map(l => map.get(l));
|
|
64
|
-
const
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
128
|
+
const el = document.getElementById('dailyTrendChart');
|
|
129
|
+
const chart = echarts.init(el);
|
|
130
|
+
chart.setOption({
|
|
131
|
+
tooltip: {},
|
|
132
|
+
xAxis: { type: 'category', data: labels },
|
|
133
|
+
yAxis: { type: 'value' },
|
|
134
|
+
series: [{ type: 'line', name: '每日提交', data, areaStyle: {} }]
|
|
68
135
|
});
|
|
69
|
-
return
|
|
136
|
+
return chart;
|
|
70
137
|
}
|
|
71
138
|
|
|
72
139
|
function drawWeeklyTrend(weekly) {
|
|
73
140
|
const labels = weekly.map(w => w.period);
|
|
74
141
|
const dataRate = weekly.map(w => +(w.outsideWorkRate * 100).toFixed(1));
|
|
75
142
|
const dataCount = weekly.map(w => w.outsideWorkCount);
|
|
76
|
-
const
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
y1: { type: 'linear', position: 'left', min: 0, max: 100 },
|
|
90
|
-
y2: { type: 'linear', position: 'right' }
|
|
91
|
-
}
|
|
92
|
-
}
|
|
143
|
+
const el = document.getElementById('weeklyTrendChart');
|
|
144
|
+
const chart = echarts.init(el);
|
|
145
|
+
chart.setOption({
|
|
146
|
+
tooltip: {},
|
|
147
|
+
xAxis: { type: 'category', data: labels },
|
|
148
|
+
yAxis: [
|
|
149
|
+
{ type: 'value', min: 0, max: 100 },
|
|
150
|
+
{ type: 'value' }
|
|
151
|
+
],
|
|
152
|
+
series: [
|
|
153
|
+
{ type: 'line', name: '加班占比(%)', data: dataRate, yAxisIndex: 0 },
|
|
154
|
+
{ type: 'line', name: '加班次数', data: dataCount, yAxisIndex: 1 }
|
|
155
|
+
]
|
|
93
156
|
});
|
|
94
|
-
return
|
|
157
|
+
return chart;
|
|
95
158
|
}
|
|
96
159
|
|
|
97
160
|
(async function main() {
|
|
98
161
|
const { commits, stats, weekly } = await loadData();
|
|
99
|
-
|
|
162
|
+
commitsAll = commits;
|
|
163
|
+
filtered = commitsAll.slice();
|
|
164
|
+
initTableControls();
|
|
165
|
+
updatePager();
|
|
166
|
+
renderCommitsTablePage();
|
|
100
167
|
drawHourlyOvertime(stats);
|
|
101
168
|
drawOutsideVsInside(stats);
|
|
102
169
|
drawDailyTrend(commits);
|
package/web/index.html
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
|
6
6
|
<title>wukong-gitlog-cli — Overtime Dashboard</title>
|
|
7
7
|
<link rel="stylesheet" href="/style.css" />
|
|
8
|
-
<script src="./static/
|
|
8
|
+
<script src="./static/echarts.min.js"></script>
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
11
11
|
<header>
|
|
@@ -15,28 +15,43 @@
|
|
|
15
15
|
<section id="chartsHalf">
|
|
16
16
|
<div class="chart-card">
|
|
17
17
|
<h2>下班时间 vs 工作时间提交占比</h2>
|
|
18
|
-
<
|
|
18
|
+
<div id="outsideVsInsideChart" class="echart"></div>
|
|
19
19
|
</div>
|
|
20
20
|
<div class="chart-card"></div>
|
|
21
21
|
</section>
|
|
22
22
|
<section id="charts">
|
|
23
23
|
<div class="chart-card">
|
|
24
24
|
<h2>每小时加班分布 (小时 -> 提交数)</h2>
|
|
25
|
-
<
|
|
25
|
+
<div id="hourlyOvertimeChart" class="echart"></div>
|
|
26
26
|
</div>
|
|
27
27
|
|
|
28
28
|
<div class="chart-card">
|
|
29
29
|
<h2>按日提交趋势</h2>
|
|
30
|
-
<
|
|
30
|
+
<div id="dailyTrendChart" class="echart"></div>
|
|
31
31
|
</div>
|
|
32
32
|
<div class="chart-card">
|
|
33
33
|
<h2>每周趋势(加班占比)</h2>
|
|
34
|
-
<
|
|
34
|
+
<div id="weeklyTrendChart" class="echart"></div>
|
|
35
35
|
</div>
|
|
36
36
|
</section>
|
|
37
37
|
|
|
38
38
|
<section class="table-card">
|
|
39
39
|
<h2>提交清单</h2>
|
|
40
|
+
<div id="tableControls">
|
|
41
|
+
<input id="searchInput" type="search" placeholder="搜索作者/信息/Hash" />
|
|
42
|
+
<label for="pageSize">每页显示</label>
|
|
43
|
+
<select id="pageSize">
|
|
44
|
+
<option value="10">10</option>
|
|
45
|
+
<option value="20">20</option>
|
|
46
|
+
<option value="50">50</option>
|
|
47
|
+
<option value="100">100</option>
|
|
48
|
+
</select>
|
|
49
|
+
<div class="pager">
|
|
50
|
+
<button id="prevPage">上一页</button>
|
|
51
|
+
<span id="pageInfo"></span>
|
|
52
|
+
<button id="nextPage">下一页</button>
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
40
55
|
<table id="commitsTable">
|
|
41
56
|
<thead>
|
|
42
57
|
<tr>
|