zen-gitsync 2.0.5 → 2.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.
@@ -1,7 +1,8 @@
1
1
  import { defineStore } from 'pinia'
2
- import { ref } from 'vue'
2
+ import { ref, onMounted, onUnmounted } from 'vue'
3
3
  import { ElMessage } from 'element-plus'
4
4
  import { useGitStore } from './gitStore'
5
+ import { io, Socket } from 'socket.io-client'
5
6
 
6
7
  // 定义Git操作间隔时间(毫秒)
7
8
  const GIT_OPERATION_DELAY = 300
@@ -10,6 +11,11 @@ export const useGitLogStore = defineStore('gitLog', () => {
10
11
  // 引用gitStore获取仓库状态
11
12
  const gitStore = useGitStore()
12
13
 
14
+ // 定义socket连接
15
+ let socket: Socket | null = null
16
+ // 自动更新状态开关
17
+ const autoUpdateEnabled = ref(true)
18
+
13
19
  // 状态
14
20
  const log = ref<any[]>([])
15
21
  const status = ref<{ staged: string[], unstaged: string[], untracked: string[] }>({
@@ -28,6 +34,163 @@ export const useGitLogStore = defineStore('gitLog', () => {
28
34
  const isPushing = ref(false)
29
35
  const isResetting = ref(false)
30
36
 
37
+ // Socket.io连接处理
38
+ function initSocketConnection() {
39
+ // 如果已经有socket连接,先断开
40
+ if (socket) {
41
+ socket.disconnect()
42
+ }
43
+
44
+ // 创建新连接
45
+ try {
46
+ // 修正Socket.IO连接URL,使用固定的后端服务器端口3000
47
+ const backendUrl = 'http://localhost:3000'
48
+
49
+ console.log('尝试连接Socket.IO服务器:', backendUrl)
50
+
51
+ socket = io(backendUrl, {
52
+ reconnectionDelayMax: 10000,
53
+ reconnection: true,
54
+ reconnectionAttempts: 10,
55
+ reconnectionDelay: 1000, // 初始重连延迟1秒
56
+ timeout: 20000, // 连接超时时间
57
+ autoConnect: true, // 自动连接
58
+ forceNew: true, // 强制创建新连接
59
+ transports: ['websocket', 'polling'] // 优先使用WebSocket
60
+ })
61
+
62
+ // 检查socket是否成功创建
63
+ if (!socket) {
64
+ console.error('Socket.IO初始化失败: socket为null')
65
+ return
66
+ }
67
+ console.log('Socket.IO初始化成功,socket ID:', socket.id || '未连接')
68
+
69
+ // 监听连接事件
70
+ socket.on('connect', () => {
71
+ console.log('成功连接到Socket.IO服务器')
72
+
73
+ // 如果自动更新开启,向服务器请求开始监控
74
+ if (autoUpdateEnabled.value && socket) {
75
+ socket.emit('start_monitoring')
76
+ }
77
+ })
78
+
79
+ // 监听断开连接事件
80
+ socket.on('disconnect', (reason) => {
81
+ console.log('与Socket.IO服务器断开连接:', reason)
82
+ })
83
+
84
+ // 监听Git状态更新事件
85
+ socket.on('git_status_update', (data) => {
86
+ if (!autoUpdateEnabled.value) return
87
+
88
+ console.log('收到Git状态更新通知:', new Date().toLocaleTimeString())
89
+
90
+ // 更新状态文本
91
+ if (data.status) {
92
+ statusText.value = data.status
93
+ }
94
+
95
+ // 更新文件列表
96
+ if (data.porcelain !== undefined) {
97
+ parseStatusPorcelain(data.porcelain)
98
+ }
99
+
100
+ // 根据文件列表判断是否需要更新日志
101
+ const hasChanges = fileList.value.length > 0
102
+
103
+ // 如果有变化,更新状态
104
+ if (hasChanges) {
105
+ // 自动刷新日志,但不要显示消息通知
106
+ fetchLog(false)
107
+ }
108
+ })
109
+
110
+ // 监听监控状态
111
+ socket.on('monitoring_status', (data) => {
112
+ console.log('文件监控状态:', data.active ? '已启动' : '已停止')
113
+ })
114
+
115
+ // 添加额外的连接问题诊断
116
+ socket.on('connect_error', (error) => {
117
+ console.error('Socket连接错误:', error.message)
118
+ })
119
+
120
+ socket.on('connect_timeout', () => {
121
+ console.error('Socket连接超时')
122
+ })
123
+
124
+ socket.on('reconnect', (attemptNumber) => {
125
+ console.log(`Socket重连成功,尝试次数: ${attemptNumber}`)
126
+
127
+ // 重连后检查自动更新状态
128
+ if (autoUpdateEnabled.value) {
129
+ console.log('重连后重新发送start_monitoring请求')
130
+ socket?.emit('start_monitoring')
131
+ }
132
+ })
133
+
134
+ socket.on('reconnect_attempt', (attemptNumber) => {
135
+ console.log(`Socket尝试重连,第 ${attemptNumber} 次尝试`)
136
+ })
137
+
138
+ socket.on('reconnect_error', (error) => {
139
+ console.error('Socket重连错误:', error.message)
140
+ })
141
+
142
+ socket.on('reconnect_failed', () => {
143
+ console.error('Socket重连失败,已达到最大重试次数')
144
+ })
145
+
146
+ // 手动尝试连接
147
+ if (socket && !socket.connected) {
148
+ console.log('Socket未连接,尝试手动连接...')
149
+ socket.connect()
150
+ }
151
+ } catch (error) {
152
+ console.error('Socket.IO连接初始化失败:', error)
153
+ }
154
+ }
155
+
156
+ // 切换自动更新状态
157
+ function toggleAutoUpdate() {
158
+ // autoUpdateEnabled.value = !autoUpdateEnabled.value
159
+ console.log('toggleAutoUpdate调用,当前值:', autoUpdateEnabled.value)
160
+
161
+ if (!socket) {
162
+ console.error('无法切换自动更新状态: socket连接不存在')
163
+ ElMessage.error('无法连接到服务器,自动更新可能不会生效')
164
+
165
+ // 尝试重新初始化socket连接
166
+ console.log('尝试重新建立socket连接...')
167
+ initSocketConnection()
168
+
169
+ // 即使socket可能不存在,也保存设置
170
+ localStorage.setItem('zen-gitsync-auto-update', autoUpdateEnabled.value.toString())
171
+ return
172
+ }
173
+
174
+ try {
175
+ if (autoUpdateEnabled.value) {
176
+ console.log('发送start_monitoring命令...')
177
+ socket.emit('start_monitoring')
178
+ ElMessage.success('自动更新已启用')
179
+ } else {
180
+ console.log('发送stop_monitoring命令...')
181
+ socket.emit('stop_monitoring')
182
+ ElMessage.info('自动更新已禁用')
183
+ }
184
+
185
+ // 保存设置到localStorage
186
+ localStorage.setItem('zen-gitsync-auto-update', autoUpdateEnabled.value.toString())
187
+ console.log('已保存自动更新设置到本地存储:', autoUpdateEnabled.value)
188
+ } catch (error) {
189
+ console.error('切换自动更新状态时出错:', error)
190
+ ElMessage.error(`切换自动更新失败: ${(error as Error).message}`)
191
+ }
192
+ }
193
+
31
194
  // 解析 git status --porcelain 输出,提取文件及类型
32
195
  function parseStatusPorcelain(statusText: string) {
33
196
  if (statusText === undefined || statusText === '') {
@@ -44,12 +207,37 @@ export const useGitLogStore = defineStore('gitLog', () => {
44
207
  const match = line.match(/^([ MADRCU\?]{2})\s+(.+)$/)
45
208
  if (match) {
46
209
  let type = ''
47
- const code = match[1].trim()
48
- if (code === 'M' || code === 'MM' || code === 'AM' || code === 'RM') type = 'modified'
49
- else if (code === 'A' || code === 'AA') type = 'added'
50
- else if (code === 'D' || code === 'AD' || code === 'DA') type = 'deleted'
51
- else if (code === '??') type = 'untracked'
52
- else type = 'other'
210
+ const code = match[1]
211
+ const indexStatus = code.charAt(0)
212
+ const workTreeStatus = code.charAt(1)
213
+
214
+ // 根据暂存区状态和工作区状态确定文件类型
215
+ if (indexStatus === 'A') {
216
+ // 已暂存的新文件
217
+ type = 'added'
218
+ } else if (indexStatus === 'M') {
219
+ // 已暂存的修改文件
220
+ type = 'added'
221
+ } else if (indexStatus === 'D') {
222
+ // 已暂存的删除文件
223
+ type = 'added'
224
+ } else if (indexStatus === 'R') {
225
+ // 已暂存的重命名文件
226
+ type = 'added'
227
+ } else if (indexStatus === ' ' && workTreeStatus === 'M') {
228
+ // 已修改未暂存的文件
229
+ type = 'modified'
230
+ } else if (indexStatus === ' ' && workTreeStatus === 'D') {
231
+ // 已删除未暂存的文件
232
+ type = 'deleted'
233
+ } else if (code === '??') {
234
+ // 未跟踪的文件
235
+ type = 'untracked'
236
+ } else {
237
+ // 其他情况
238
+ type = 'other'
239
+ }
240
+
53
241
  files.push({ path: match[2], type })
54
242
  }
55
243
  }
@@ -57,7 +245,7 @@ export const useGitLogStore = defineStore('gitLog', () => {
57
245
  }
58
246
 
59
247
  // 获取提交日志
60
- async function fetchLog() {
248
+ async function fetchLog(showMessage = true) {
61
249
  // 检查是否是Git仓库
62
250
  if (!gitStore.isGitRepo) {
63
251
  console.log('当前目录不是Git仓库,跳过加载提交历史')
@@ -67,18 +255,35 @@ export const useGitLogStore = defineStore('gitLog', () => {
67
255
  try {
68
256
  isLoadingLog.value = true
69
257
  console.log('开始加载提交历史...')
70
- const response = await fetch('/api/log')
258
+
259
+ // 增加时间戳参数避免缓存,确保获取最新数据
260
+ const timestamp = new Date().getTime()
261
+ const response = await fetch(`/api/log?page=1&_t=${timestamp}`)
71
262
  const data = await response.json()
72
- if (data && Array.isArray(data)) {
73
- log.value = data
263
+
264
+ if (data && data.data && Array.isArray(data.data)) {
265
+ // 清空并更新日志数组
266
+ log.value = [...data.data]
267
+ console.log(`提交历史加载完成,共 ${log.value.length} 条记录`)
268
+ } else {
269
+ console.warn('API返回的提交历史格式不正确:', data)
270
+ log.value = [] // 如果数据格式不对,清空日志
271
+ }
272
+
273
+ if (showMessage) {
274
+ ElMessage({
275
+ message: '提交历史已更新',
276
+ type: 'success'
277
+ })
74
278
  }
75
- console.log(`提交历史加载完成,共 ${log.value.length} 条记录`)
76
279
  } catch (error) {
77
280
  console.error('获取提交历史失败:', error)
78
- ElMessage({
79
- message: `获取提交历史失败: ${(error as Error).message}`,
80
- type: 'error'
81
- })
281
+ if (showMessage) {
282
+ ElMessage({
283
+ message: `获取提交历史失败: ${(error as Error).message}`,
284
+ type: 'error'
285
+ })
286
+ }
82
287
  } finally {
83
288
  isLoadingLog.value = false
84
289
  }
@@ -121,6 +326,7 @@ export const useGitLogStore = defineStore('gitLog', () => {
121
326
 
122
327
  // 获取Git状态 (porcelain格式)
123
328
  async function fetchStatusPorcelain() {
329
+ console.log('开始获取Git状态(porcelain格式)...')
124
330
  // 检查是否是Git仓库
125
331
  if (!gitStore.isGitRepo) {
126
332
  console.log('当前目录不是Git仓库,跳过加载Git状态')
@@ -190,6 +396,100 @@ export const useGitLogStore = defineStore('gitLog', () => {
190
396
  }
191
397
  }
192
398
 
399
+ // 添加单个文件到暂存区
400
+ async function addFileToStage(filePath: string) {
401
+ // 检查是否是Git仓库
402
+ if (!gitStore.isGitRepo) {
403
+ ElMessage.warning('当前目录不是Git仓库')
404
+ return false
405
+ }
406
+
407
+ try {
408
+ isAddingFiles.value = true
409
+ const response = await fetch('/api/add-file', {
410
+ method: 'POST',
411
+ headers: {
412
+ 'Content-Type': 'application/json'
413
+ },
414
+ body: JSON.stringify({ filePath })
415
+ })
416
+
417
+ const result = await response.json()
418
+ if (result.success) {
419
+ ElMessage({
420
+ message: '文件已暂存',
421
+ type: 'success'
422
+ })
423
+
424
+ // 刷新状态
425
+ fetchStatus()
426
+
427
+ return true
428
+ } else {
429
+ ElMessage({
430
+ message: `暂存文件失败: ${result.error}`,
431
+ type: 'error'
432
+ })
433
+ return false
434
+ }
435
+ } catch (error) {
436
+ ElMessage({
437
+ message: `暂存文件失败: ${(error as Error).message}`,
438
+ type: 'error'
439
+ })
440
+ return false
441
+ } finally {
442
+ isAddingFiles.value = false
443
+ }
444
+ }
445
+
446
+ // 取消暂存单个文件
447
+ async function unstageFile(filePath: string) {
448
+ // 检查是否是Git仓库
449
+ if (!gitStore.isGitRepo) {
450
+ ElMessage.warning('当前目录不是Git仓库')
451
+ return false
452
+ }
453
+
454
+ try {
455
+ isResetting.value = true
456
+ const response = await fetch('/api/unstage-file', {
457
+ method: 'POST',
458
+ headers: {
459
+ 'Content-Type': 'application/json'
460
+ },
461
+ body: JSON.stringify({ filePath })
462
+ })
463
+
464
+ const result = await response.json()
465
+ if (result.success) {
466
+ ElMessage({
467
+ message: '已取消暂存文件',
468
+ type: 'success'
469
+ })
470
+
471
+ // 刷新状态
472
+ fetchStatus()
473
+
474
+ return true
475
+ } else {
476
+ ElMessage({
477
+ message: `取消暂存失败: ${result.error}`,
478
+ type: 'error'
479
+ })
480
+ return false
481
+ }
482
+ } catch (error) {
483
+ ElMessage({
484
+ message: `取消暂存失败: ${(error as Error).message}`,
485
+ type: 'error'
486
+ })
487
+ return false
488
+ } finally {
489
+ isResetting.value = false
490
+ }
491
+ }
492
+
193
493
  // 添加延时函数
194
494
  function delay(ms: number) {
195
495
  return new Promise(resolve => setTimeout(resolve, ms))
@@ -435,6 +735,25 @@ export const useGitLogStore = defineStore('gitLog', () => {
435
735
  }
436
736
  }
437
737
 
738
+ // 在组件挂载时初始化socket连接
739
+ onMounted(() => {
740
+ // 从localStorage加载自动更新设置
741
+ const savedAutoUpdate = localStorage.getItem('zen-gitsync-auto-update')
742
+ if (savedAutoUpdate !== null) {
743
+ autoUpdateEnabled.value = savedAutoUpdate === 'true'
744
+ }
745
+
746
+ initSocketConnection()
747
+ })
748
+
749
+ // 在组件卸载时断开socket连接
750
+ onUnmounted(() => {
751
+ if (socket) {
752
+ socket.disconnect()
753
+ socket = null
754
+ }
755
+ })
756
+
438
757
  return {
439
758
  // 状态
440
759
  log,
@@ -447,6 +766,7 @@ export const useGitLogStore = defineStore('gitLog', () => {
447
766
  isResetting,
448
767
  isCommiting,
449
768
  isPushing,
769
+ autoUpdateEnabled,
450
770
 
451
771
  // 方法
452
772
  fetchLog,
@@ -454,11 +774,14 @@ export const useGitLogStore = defineStore('gitLog', () => {
454
774
  fetchStatusPorcelain,
455
775
  parseStatusPorcelain,
456
776
  addToStage,
777
+ addFileToStage,
778
+ unstageFile,
457
779
  commitChanges,
458
780
  pushToRemote,
459
781
  addAndCommit,
460
782
  addCommitAndPush,
461
783
  resetHead,
462
- resetToRemote
784
+ resetToRemote,
785
+ toggleAutoUpdate
463
786
  }
464
787
  })
@@ -13,6 +13,12 @@ export const useGitStore = defineStore('git', () => {
13
13
  const isGitRepo = ref(false) // 当前目录是否是Git仓库
14
14
  const lastCheckedTime = ref(0) // 上次检查Git仓库状态的时间戳
15
15
 
16
+ // 添加分支状态相关变量
17
+ const branchAhead = ref(0) // 当前分支领先远程分支的提交数
18
+ const branchBehind = ref(0) // 当前分支落后远程分支的提交数
19
+ const hasUpstream = ref(false) // 当前分支是否有上游分支
20
+ const upstreamBranch = ref('') // 上游分支名称
21
+
16
22
  // 添加重置方法
17
23
  function $reset() {
18
24
  currentBranch.value = ''
@@ -23,6 +29,34 @@ export const useGitStore = defineStore('git', () => {
23
29
  isCreatingBranch.value = false
24
30
  isGitRepo.value = false
25
31
  lastCheckedTime.value = 0
32
+ branchAhead.value = 0
33
+ branchBehind.value = 0
34
+ hasUpstream.value = false
35
+ upstreamBranch.value = ''
36
+ }
37
+
38
+ // 获取分支状态(领先/落后远程)
39
+ async function getBranchStatus() {
40
+ if (!isGitRepo.value) return;
41
+
42
+ try {
43
+ const response = await fetch('/api/branch-status');
44
+ const data = await response.json();
45
+
46
+ if (data) {
47
+ branchAhead.value = data.ahead || 0;
48
+ branchBehind.value = data.behind || 0;
49
+ hasUpstream.value = data.hasUpstream || false;
50
+ upstreamBranch.value = data.upstreamBranch || '';
51
+ }
52
+ } catch (error) {
53
+ console.error('获取分支状态失败:', error);
54
+ // 出错时重置状态
55
+ branchAhead.value = 0;
56
+ branchBehind.value = 0;
57
+ hasUpstream.value = false;
58
+ upstreamBranch.value = '';
59
+ }
26
60
  }
27
61
 
28
62
  // 检查当前目录是否是Git仓库
@@ -56,6 +90,8 @@ export const useGitStore = defineStore('git', () => {
56
90
  const data = await response.json()
57
91
  if (data.branch) {
58
92
  currentBranch.value = data.branch
93
+ // 获取分支状态信息
94
+ await getBranchStatus();
59
95
  }
60
96
  } catch (error) {
61
97
  console.error('获取分支信息失败:', error)
@@ -285,6 +321,10 @@ export const useGitStore = defineStore('git', () => {
285
321
  isCreatingBranch,
286
322
  isGitRepo,
287
323
  lastCheckedTime,
324
+ branchAhead,
325
+ branchBehind,
326
+ hasUpstream,
327
+ upstreamBranch,
288
328
 
289
329
  // 方法
290
330
  $reset,
@@ -296,6 +336,7 @@ export const useGitStore = defineStore('git', () => {
296
336
  createBranch,
297
337
  loadInitialData,
298
338
  clearUserConfig,
299
- restoreUserConfig
339
+ restoreUserConfig,
340
+ getBranchStatus
300
341
  }
301
342
  })