zen-gitsync 1.5.6 → 2.0.3
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/README.md +9 -0
- package/package.json +10 -3
- package/src/config.js +2 -1
- package/src/gitCommit.js +7 -0
- package/src/ui/client/README.md +5 -0
- package/src/ui/client/auto-imports.d.ts +10 -0
- package/src/ui/client/components.d.ts +31 -0
- package/src/ui/client/index.html +13 -0
- package/src/ui/client/package.json +27 -0
- package/src/ui/client/public/favicon.svg +27 -0
- package/src/ui/client/public/logo.svg +27 -0
- package/src/ui/client/public/vite.svg +1 -0
- package/src/ui/client/src/App.vue +539 -0
- package/src/ui/client/src/assets/logo.svg +27 -0
- package/src/ui/client/src/components/CommitForm.vue +904 -0
- package/src/ui/client/src/components/GitStatus.vue +799 -0
- package/src/ui/client/src/components/LogList.vue +270 -0
- package/src/ui/client/src/main.ts +4 -0
- package/src/ui/client/src/vite-env.d.ts +1 -0
- package/src/ui/client/stats.html +4949 -0
- package/src/ui/client/tsconfig.app.json +14 -0
- package/src/ui/client/tsconfig.json +7 -0
- package/src/ui/client/tsconfig.node.json +24 -0
- package/src/ui/client/vite.config.ts +48 -0
- package/src/ui/public/assets/index-BHmYZROy.css +1 -0
- package/src/ui/public/assets/index-kfMX1bxz.js +9 -0
- package/src/ui/public/assets/vendor-Dp0FkvMe.css +1 -0
- package/src/ui/public/assets/vendor-DxvF30ca.js +41 -0
- package/src/ui/public/favicon.svg +27 -0
- package/src/ui/public/index.html +16 -0
- package/src/ui/public/logo.svg +27 -0
- package/src/ui/public/vite.svg +1 -0
- package/src/ui/server/index.js +598 -0
- package/src/utils/index.js +4 -0
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref, onMounted, defineExpose } from 'vue'
|
|
3
|
+
import { ElTable, ElTableColumn, ElTag, ElButton } from 'element-plus'
|
|
4
|
+
import { RefreshRight } from '@element-plus/icons-vue'
|
|
5
|
+
import 'element-plus/dist/index.css'
|
|
6
|
+
import { createGitgraph } from '@gitgraph/js'
|
|
7
|
+
|
|
8
|
+
interface LogItem {
|
|
9
|
+
hash: string
|
|
10
|
+
date: string
|
|
11
|
+
author: string
|
|
12
|
+
email: string // 添加邮箱字段
|
|
13
|
+
message: string
|
|
14
|
+
branch?: string // 添加分支信息字段
|
|
15
|
+
parents?: string[] // 添加父提交信息
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const logs = ref<LogItem[]>([])
|
|
19
|
+
const errorMessage = ref('')
|
|
20
|
+
const isLoading = ref(false)
|
|
21
|
+
const showAllCommits = ref(false)
|
|
22
|
+
const totalCommits = ref(0)
|
|
23
|
+
const showGraphView = ref(true) // 控制是否显示图表视图
|
|
24
|
+
const graphContainer = ref<HTMLElement | null>(null)
|
|
25
|
+
|
|
26
|
+
// 加载提交历史
|
|
27
|
+
async function loadLog(all = false) {
|
|
28
|
+
try {
|
|
29
|
+
isLoading.value = true
|
|
30
|
+
showAllCommits.value = all
|
|
31
|
+
// 修改API调用,获取更详细的提交信息,包括父提交
|
|
32
|
+
const url = all ? '/api/log?all=true&graph=true' : '/api/log?graph=true'
|
|
33
|
+
const response = await fetch(url)
|
|
34
|
+
logs.value = await response.json()
|
|
35
|
+
totalCommits.value = logs.value.length
|
|
36
|
+
errorMessage.value = ''
|
|
37
|
+
|
|
38
|
+
// 加载完数据后渲染图表
|
|
39
|
+
if (showGraphView.value) {
|
|
40
|
+
setTimeout(renderGraph, 0)
|
|
41
|
+
}
|
|
42
|
+
} catch (error) {
|
|
43
|
+
errorMessage.value = '加载提交历史失败: ' + (error as Error).message
|
|
44
|
+
} finally {
|
|
45
|
+
isLoading.value = false
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// 渲染Git图表
|
|
50
|
+
async function renderGraph() {
|
|
51
|
+
if (!graphContainer.value || logs.value.length === 0) return
|
|
52
|
+
|
|
53
|
+
// 清空容器
|
|
54
|
+
graphContainer.value.innerHTML = ''
|
|
55
|
+
|
|
56
|
+
// 获取当前分支
|
|
57
|
+
const branchResponse = await fetch('/api/branch')
|
|
58
|
+
const { branch: currentBranch } = await branchResponse.json()
|
|
59
|
+
|
|
60
|
+
// 创建gitgraph实例
|
|
61
|
+
const gitgraph = createGitgraph(graphContainer.value, {
|
|
62
|
+
// 自定义选项
|
|
63
|
+
// @ts-ignore: true
|
|
64
|
+
orientation: 'vertical-reverse', // 从上到下的方向
|
|
65
|
+
// @ts-ignore: true
|
|
66
|
+
template: 'metro', // 使用metro模板
|
|
67
|
+
author: '提交者 <committer@example.com>'
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
// 处理分支和提交数据
|
|
71
|
+
// 注意:这里的实现是简化的,实际需要根据API返回的数据结构调整
|
|
72
|
+
const branches: Record<string, any> = {}
|
|
73
|
+
const mainBranch = gitgraph.branch(currentBranch || 'main') // 使用API获取的分支或默认main
|
|
74
|
+
branches[currentBranch || 'main'] = mainBranch
|
|
75
|
+
|
|
76
|
+
// 简化示例 - 实际实现需要根据API返回的数据结构调整
|
|
77
|
+
logs.value.forEach(commit => {
|
|
78
|
+
// 这里需要根据实际数据结构构建分支图
|
|
79
|
+
let currentBranch = mainBranch
|
|
80
|
+
|
|
81
|
+
// 如果有分支信息,使用对应的分支
|
|
82
|
+
if (commit.branch) {
|
|
83
|
+
const branchName = formatBranchName(commit.branch.split(',')[0])
|
|
84
|
+
if (!branches[branchName]) {
|
|
85
|
+
branches[branchName] = gitgraph.branch(branchName)
|
|
86
|
+
}
|
|
87
|
+
currentBranch = branches[branchName]
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// 创建提交,添加邮箱信息
|
|
91
|
+
currentBranch.commit({
|
|
92
|
+
hash: commit.hash,
|
|
93
|
+
subject: commit.message,
|
|
94
|
+
author: `${commit.author} <${commit.email}>`
|
|
95
|
+
})
|
|
96
|
+
})
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// 切换视图模式
|
|
100
|
+
function toggleViewMode() {
|
|
101
|
+
showGraphView.value = !showGraphView.value
|
|
102
|
+
if (showGraphView.value && logs.value.length > 0) {
|
|
103
|
+
// 延迟执行以确保DOM已更新
|
|
104
|
+
setTimeout(renderGraph, 0)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// 切换显示所有提交
|
|
109
|
+
function toggleAllCommits() {
|
|
110
|
+
loadLog(!showAllCommits.value)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
onMounted(() => {
|
|
114
|
+
loadLog()
|
|
115
|
+
})
|
|
116
|
+
const refreshLog = () => loadLog(showAllCommits.value)
|
|
117
|
+
// 暴露方法给父组件
|
|
118
|
+
defineExpose({
|
|
119
|
+
refreshLog
|
|
120
|
+
})
|
|
121
|
+
</script>
|
|
122
|
+
|
|
123
|
+
<template>
|
|
124
|
+
<div class="card">
|
|
125
|
+
<div class="log-header">
|
|
126
|
+
<h2>提交历史</h2>
|
|
127
|
+
<div class="log-actions">
|
|
128
|
+
<el-button
|
|
129
|
+
type="primary"
|
|
130
|
+
size="small"
|
|
131
|
+
@click="toggleViewMode"
|
|
132
|
+
>
|
|
133
|
+
{{ showGraphView ? '表格视图' : '图表视图' }}
|
|
134
|
+
</el-button>
|
|
135
|
+
<el-button
|
|
136
|
+
type="primary"
|
|
137
|
+
size="small"
|
|
138
|
+
@click="toggleAllCommits"
|
|
139
|
+
:loading="isLoading"
|
|
140
|
+
>
|
|
141
|
+
{{ showAllCommits ? '显示最近100条' : '显示所有提交' }}
|
|
142
|
+
</el-button>
|
|
143
|
+
<el-button
|
|
144
|
+
:icon="RefreshRight"
|
|
145
|
+
circle
|
|
146
|
+
size="small"
|
|
147
|
+
@click="refreshLog()"
|
|
148
|
+
:loading="isLoading"
|
|
149
|
+
/>
|
|
150
|
+
</div>
|
|
151
|
+
</div>
|
|
152
|
+
<div v-if="errorMessage">{{ errorMessage }}</div>
|
|
153
|
+
<div v-else>
|
|
154
|
+
<!-- 图表视图 -->
|
|
155
|
+
<div v-if="showGraphView" class="graph-view">
|
|
156
|
+
<div class="commit-count" v-if="logs.length > 0">
|
|
157
|
+
显示 {{ logs.length }} 条提交记录 {{ showAllCommits ? '(全部)' : '(最近100条)' }}
|
|
158
|
+
</div>
|
|
159
|
+
<div ref="graphContainer" class="graph-container"></div>
|
|
160
|
+
</div>
|
|
161
|
+
|
|
162
|
+
<!-- 表格视图 -->
|
|
163
|
+
<div v-else>
|
|
164
|
+
<div class="commit-count" v-if="logs.length > 0">
|
|
165
|
+
显示 {{ logs.length }} 条提交记录 {{ showAllCommits ? '(全部)' : '(最近100条)' }}
|
|
166
|
+
</div>
|
|
167
|
+
<el-table :data="logs" style="width: 100%" stripe border v-loading="isLoading">
|
|
168
|
+
<el-table-column prop="hash" label="提交哈希" width="100" resizable />
|
|
169
|
+
<el-table-column prop="date" label="日期" width="180" resizable />
|
|
170
|
+
<el-table-column label="作者" width="200" resizable>
|
|
171
|
+
<template #default="scope">
|
|
172
|
+
{{ scope.row.author }} <{{ scope.row.email }}>
|
|
173
|
+
</template>
|
|
174
|
+
</el-table-column>
|
|
175
|
+
<el-table-column label="分支" width="180" resizable>
|
|
176
|
+
<template #default="scope">
|
|
177
|
+
<div v-if="scope.row.branch" class="branch-container">
|
|
178
|
+
<el-tag
|
|
179
|
+
v-for="(ref, index) in scope.row.branch.split(',')"
|
|
180
|
+
:key="index"
|
|
181
|
+
size="small"
|
|
182
|
+
:type="getBranchTagType(ref)"
|
|
183
|
+
class="branch-tag"
|
|
184
|
+
>
|
|
185
|
+
{{ formatBranchName(ref) }}
|
|
186
|
+
</el-tag>
|
|
187
|
+
</div>
|
|
188
|
+
</template>
|
|
189
|
+
</el-table-column>
|
|
190
|
+
<el-table-column prop="message" label="提交信息" min-width="250" />
|
|
191
|
+
</el-table>
|
|
192
|
+
</div>
|
|
193
|
+
</div>
|
|
194
|
+
</div>
|
|
195
|
+
</template>
|
|
196
|
+
|
|
197
|
+
<style scoped>
|
|
198
|
+
.log-header {
|
|
199
|
+
display: flex;
|
|
200
|
+
justify-content: space-between;
|
|
201
|
+
align-items: center;
|
|
202
|
+
margin-bottom: 10px;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.log-actions {
|
|
206
|
+
display: flex;
|
|
207
|
+
gap: 8px;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.branch-container {
|
|
211
|
+
display: flex;
|
|
212
|
+
flex-wrap: wrap;
|
|
213
|
+
gap: 4px;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.branch-tag {
|
|
217
|
+
margin-right: 4px;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.commit-count {
|
|
221
|
+
margin-bottom: 10px;
|
|
222
|
+
font-size: 14px;
|
|
223
|
+
color: #606266;
|
|
224
|
+
text-align: right;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.graph-container {
|
|
228
|
+
width: 100%;
|
|
229
|
+
height: 600px;
|
|
230
|
+
overflow: auto;
|
|
231
|
+
border: 1px solid #ebeef5;
|
|
232
|
+
border-radius: 4px;
|
|
233
|
+
padding: 10px;
|
|
234
|
+
background-color: #fff;
|
|
235
|
+
/* transform: scale(0.8); */
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.graph-view {
|
|
239
|
+
width: 100%;
|
|
240
|
+
}
|
|
241
|
+
</style>
|
|
242
|
+
|
|
243
|
+
<script lang="ts">
|
|
244
|
+
// 辅助函数:格式化分支名称
|
|
245
|
+
function formatBranchName(ref: string) {
|
|
246
|
+
// 移除 "HEAD -> " 前缀
|
|
247
|
+
ref = ref.trim().replace(/^HEAD\s*->\s*/, '')
|
|
248
|
+
|
|
249
|
+
// 移除 "origin/" 前缀
|
|
250
|
+
ref = ref.replace(/^origin\//, '')
|
|
251
|
+
|
|
252
|
+
// 移除 "tag: " 前缀,但保留标签名
|
|
253
|
+
ref = ref.replace(/^tag:\s*/, '')
|
|
254
|
+
|
|
255
|
+
return ref.trim()
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// 辅助函数:根据分支类型返回不同的标签类型
|
|
259
|
+
function getBranchTagType(ref: string) {
|
|
260
|
+
if (ref.includes('HEAD')) return 'success'
|
|
261
|
+
if (ref.includes('tag:')) return 'warning'
|
|
262
|
+
if (ref.includes('origin/')) return 'info'
|
|
263
|
+
return 'primary' // 修改空字符串为有效的type值
|
|
264
|
+
}
|
|
265
|
+
</script>
|
|
266
|
+
|
|
267
|
+
/* 添加表格列调整样式 */
|
|
268
|
+
.el-table .el-table__cell .cell {
|
|
269
|
+
word-break: break-all;
|
|
270
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/// <reference types="vite/client" />
|