zen-gitsync 2.0.4 → 2.0.5
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/package.json +1 -1
- package/src/ui/client/components.d.ts +1 -0
- package/src/ui/client/src/App.vue +214 -68
- package/src/ui/client/src/components/CommitForm.vue +399 -365
- package/src/ui/client/src/components/GitStatus.vue +46 -65
- package/src/ui/client/src/components/LogList.vue +42 -0
- package/src/ui/client/src/stores/gitLogStore.ts +126 -126
- package/src/ui/client/src/stores/gitStore.ts +86 -1
- package/src/ui/client/stats.html +1 -1
- package/src/ui/public/assets/index-CALk9kKc.js +9 -0
- package/src/ui/public/assets/index-D3zIiSNw.css +1 -0
- package/src/ui/public/assets/vendor-BfXVsoKv.js +45 -0
- package/src/ui/public/index.html +3 -3
- package/src/ui/server/index.js +88 -4
- package/src/ui/public/assets/index-D5irnfho.css +0 -1
- package/src/ui/public/assets/index-DBck3u67.js +0 -8
- package/src/ui/public/assets/vendor-CdJ34PvS.js +0 -45
|
@@ -16,10 +16,11 @@ const props = defineProps({
|
|
|
16
16
|
|
|
17
17
|
const gitLogStore = useGitLogStore()
|
|
18
18
|
const gitStore = useGitStore()
|
|
19
|
-
|
|
19
|
+
// 移除本地status定义,直接使用store中的statusText
|
|
20
|
+
// const status = ref('加载中...')
|
|
20
21
|
// const socket = io()
|
|
21
22
|
const isRefreshing = computed(() => gitLogStore.isLoadingStatus)
|
|
22
|
-
|
|
23
|
+
// 移除本地fileList定义,改用store中的fileList
|
|
23
24
|
const selectedFile = ref('')
|
|
24
25
|
const diffContent = ref('')
|
|
25
26
|
const diffDialogVisible = ref(false)
|
|
@@ -37,29 +38,6 @@ const directoryItems = ref<{name: string, path: string, type: string}[]>([])
|
|
|
37
38
|
const isBrowsing = ref(false)
|
|
38
39
|
const browseErrorMessage = ref('')
|
|
39
40
|
|
|
40
|
-
// 解析 git status 输出,提取文件及类型
|
|
41
|
-
function parseStatus(statusText: string) {
|
|
42
|
-
if (statusText === undefined) return
|
|
43
|
-
const lines = statusText.split('\n')
|
|
44
|
-
const files: {path: string, type: string}[] = []
|
|
45
|
-
for (const line of lines) {
|
|
46
|
-
// 匹配常见的 git status --porcelain 格式
|
|
47
|
-
// M: 修改, A: 新增, D: 删除, ??: 未跟踪
|
|
48
|
-
const match = line.match(/^([ MADRCU\?]{2})\s+(.+)$/)
|
|
49
|
-
if (match) {
|
|
50
|
-
let type = ''
|
|
51
|
-
const code = match[1].trim()
|
|
52
|
-
if (code === 'M' || code === 'MM' || code === 'AM' || code === 'RM') type = 'modified'
|
|
53
|
-
else if (code === 'A' || code === 'AA') type = 'added'
|
|
54
|
-
else if (code === 'D' || code === 'AD' || code === 'DA') type = 'deleted'
|
|
55
|
-
else if (code === '??') type = 'untracked'
|
|
56
|
-
else type = 'other'
|
|
57
|
-
files.push({ path: match[2], type })
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
fileList.value = files
|
|
61
|
-
}
|
|
62
|
-
|
|
63
41
|
const currentDirectory = ref(props.initialDirectory || '');
|
|
64
42
|
async function loadStatus() {
|
|
65
43
|
try {
|
|
@@ -72,26 +50,17 @@ async function loadStatus() {
|
|
|
72
50
|
|
|
73
51
|
// 如果不是Git仓库,直接显示提示并返回
|
|
74
52
|
if (!gitStore.isGitRepo) {
|
|
75
|
-
status.value = '当前目录不是一个Git仓库'
|
|
76
|
-
fileList.value = []
|
|
77
53
|
return
|
|
78
54
|
}
|
|
79
55
|
|
|
80
|
-
//
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
status.value = data.status
|
|
84
|
-
|
|
85
|
-
const response_porcelain = await fetch('/api/status_porcelain')
|
|
86
|
-
const data_porcelain = await response_porcelain.json()
|
|
87
|
-
parseStatus(data_porcelain.status)
|
|
56
|
+
// 使用gitLogStore获取Git状态
|
|
57
|
+
await gitLogStore.fetchStatus()
|
|
58
|
+
|
|
88
59
|
ElMessage({
|
|
89
60
|
message: 'Git 状态已刷新',
|
|
90
61
|
type: 'success',
|
|
91
62
|
})
|
|
92
63
|
} catch (error) {
|
|
93
|
-
status.value = '加载状态失败: ' + (error as Error).message
|
|
94
|
-
fileList.value = []
|
|
95
64
|
ElMessage({
|
|
96
65
|
message: '刷新失败: ' + (error as Error).message,
|
|
97
66
|
type: 'error',
|
|
@@ -145,7 +114,7 @@ async function getFileDiff(filePath: string) {
|
|
|
145
114
|
isLoadingDiff.value = true
|
|
146
115
|
selectedFile.value = filePath
|
|
147
116
|
// 设置当前文件索引
|
|
148
|
-
currentFileIndex.value = fileList.
|
|
117
|
+
currentFileIndex.value = gitLogStore.fileList.findIndex(file => file.path === filePath)
|
|
149
118
|
const response = await fetch(`/api/diff?file=${encodeURIComponent(filePath)}`)
|
|
150
119
|
const data = await response.json()
|
|
151
120
|
diffContent.value = data.diff || '没有变更'
|
|
@@ -163,19 +132,19 @@ async function getFileDiff(filePath: string) {
|
|
|
163
132
|
|
|
164
133
|
// 添加切换到上一个文件的方法
|
|
165
134
|
async function goToPreviousFile() {
|
|
166
|
-
if (fileList.
|
|
135
|
+
if (gitLogStore.fileList.length === 0 || currentFileIndex.value <= 0) return
|
|
167
136
|
|
|
168
137
|
const newIndex = currentFileIndex.value - 1
|
|
169
|
-
const prevFile = fileList
|
|
138
|
+
const prevFile = gitLogStore.fileList[newIndex]
|
|
170
139
|
await getFileDiff(prevFile.path)
|
|
171
140
|
}
|
|
172
141
|
|
|
173
142
|
// 添加切换到下一个文件的方法
|
|
174
143
|
async function goToNextFile() {
|
|
175
|
-
if (fileList.
|
|
144
|
+
if (gitLogStore.fileList.length === 0 || currentFileIndex.value >= gitLogStore.fileList.length - 1) return
|
|
176
145
|
|
|
177
146
|
const newIndex = currentFileIndex.value + 1
|
|
178
|
-
const nextFile = fileList
|
|
147
|
+
const nextFile = gitLogStore.fileList[newIndex]
|
|
179
148
|
await getFileDiff(nextFile.path)
|
|
180
149
|
}
|
|
181
150
|
|
|
@@ -316,9 +285,6 @@ async function changeDirectory() {
|
|
|
316
285
|
await loadStatus()
|
|
317
286
|
} else {
|
|
318
287
|
ElMessage.warning('当前目录不是一个Git仓库')
|
|
319
|
-
status.value = '当前目录不是一个Git仓库'
|
|
320
|
-
fileList.value = []
|
|
321
|
-
|
|
322
288
|
// 清空Git相关状态
|
|
323
289
|
gitStore.$reset() // 使用pinia的reset方法重置状态
|
|
324
290
|
}
|
|
@@ -429,11 +395,13 @@ defineExpose({
|
|
|
429
395
|
:loading="isRefreshing"
|
|
430
396
|
/>
|
|
431
397
|
</div>
|
|
432
|
-
<div class="status-box">
|
|
398
|
+
<div class="status-box">
|
|
399
|
+
{{ !gitStore.isGitRepo ? '当前目录不是一个Git仓库' : gitLogStore.statusText || '加载中...' }}
|
|
400
|
+
</div>
|
|
433
401
|
<!-- 颜色区分不同类型文件 -->
|
|
434
|
-
<div v-if="fileList.length" class="file-list">
|
|
402
|
+
<div v-if="gitLogStore.fileList.length" class="file-list">
|
|
435
403
|
<div
|
|
436
|
-
v-for="file in fileList"
|
|
404
|
+
v-for="file in gitLogStore.fileList"
|
|
437
405
|
:key="file.path"
|
|
438
406
|
:class="['file-item', file.type]"
|
|
439
407
|
>
|
|
@@ -514,18 +482,20 @@ defineExpose({
|
|
|
514
482
|
</div>
|
|
515
483
|
|
|
516
484
|
<!-- 目录内容列表 -->
|
|
517
|
-
<
|
|
518
|
-
<
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
485
|
+
<div class="directory-items-container">
|
|
486
|
+
<ul class="directory-items">
|
|
487
|
+
<li
|
|
488
|
+
v-for="item in directoryItems"
|
|
489
|
+
:key="item.path"
|
|
490
|
+
:class="['directory-item', item.type]"
|
|
491
|
+
@click="selectDirectoryItem(item)"
|
|
492
|
+
>
|
|
493
|
+
<el-icon v-if="item.type === 'directory'"><Folder /></el-icon>
|
|
494
|
+
<el-icon v-else><Document /></el-icon>
|
|
495
|
+
<span>{{ item.name }}</span>
|
|
496
|
+
</li>
|
|
497
|
+
</ul>
|
|
498
|
+
</div>
|
|
529
499
|
</div>
|
|
530
500
|
</el-dialog>
|
|
531
501
|
|
|
@@ -546,14 +516,14 @@ defineExpose({
|
|
|
546
516
|
<el-button
|
|
547
517
|
:icon="ArrowLeft"
|
|
548
518
|
@click="goToPreviousFile"
|
|
549
|
-
:disabled="currentFileIndex <= 0 || fileList.length === 0"
|
|
519
|
+
:disabled="currentFileIndex <= 0 || gitLogStore.fileList.length === 0"
|
|
550
520
|
circle
|
|
551
521
|
/>
|
|
552
|
-
<span class="file-counter">{{ currentFileIndex + 1 }} / {{ fileList.length }}</span>
|
|
522
|
+
<span class="file-counter">{{ currentFileIndex + 1 }} / {{ gitLogStore.fileList.length }}</span>
|
|
553
523
|
<el-button
|
|
554
524
|
:icon="ArrowRight"
|
|
555
525
|
@click="goToNextFile"
|
|
556
|
-
:disabled="currentFileIndex >= fileList.length - 1 || fileList.length === 0"
|
|
526
|
+
:disabled="currentFileIndex >= gitLogStore.fileList.length - 1 || gitLogStore.fileList.length === 0"
|
|
557
527
|
circle
|
|
558
528
|
/>
|
|
559
529
|
</div>
|
|
@@ -730,14 +700,25 @@ defineExpose({
|
|
|
730
700
|
|
|
731
701
|
.directory-browser {
|
|
732
702
|
padding: 10px;
|
|
733
|
-
|
|
734
|
-
|
|
703
|
+
height: 400px;
|
|
704
|
+
display: flex;
|
|
705
|
+
flex-direction: column;
|
|
735
706
|
}
|
|
736
707
|
|
|
737
708
|
.browser-nav {
|
|
738
709
|
margin-bottom: 10px;
|
|
739
710
|
display: flex;
|
|
740
711
|
justify-content: space-between;
|
|
712
|
+
position: sticky;
|
|
713
|
+
top: 0;
|
|
714
|
+
background-color: #fff;
|
|
715
|
+
z-index: 1;
|
|
716
|
+
padding: 10px 0;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
.directory-items-container {
|
|
720
|
+
flex: 1;
|
|
721
|
+
overflow-y: auto;
|
|
741
722
|
}
|
|
742
723
|
|
|
743
724
|
.directory-items {
|
|
@@ -39,6 +39,9 @@ const minScale = 0.5
|
|
|
39
39
|
const maxScale = 1.5
|
|
40
40
|
const scaleStep = 0.1
|
|
41
41
|
|
|
42
|
+
// 添加日志被刷新的提示状态
|
|
43
|
+
const logRefreshed = ref(false)
|
|
44
|
+
|
|
42
45
|
// 加载提交历史
|
|
43
46
|
async function loadLog(all = false) {
|
|
44
47
|
// 从gitStore获取仓库状态
|
|
@@ -95,6 +98,11 @@ async function loadLog(all = false) {
|
|
|
95
98
|
|
|
96
99
|
console.log(`logsData长度: ${logsData.length}`) // 添加调试日志
|
|
97
100
|
|
|
101
|
+
// 设置刷新提示状态
|
|
102
|
+
logRefreshed.value = true
|
|
103
|
+
// 2秒后隐藏提示
|
|
104
|
+
setTimeout(() => { logRefreshed.value = false }, 2000)
|
|
105
|
+
|
|
98
106
|
// 加载完数据后渲染图表
|
|
99
107
|
if (showGraphView.value) {
|
|
100
108
|
setTimeout(renderGraph, 0)
|
|
@@ -365,11 +373,17 @@ function fitGraphToContainer() {
|
|
|
365
373
|
size="small"
|
|
366
374
|
@click="refreshLog()"
|
|
367
375
|
:loading="isLoading"
|
|
376
|
+
:class="{ 'refresh-button-animated': logRefreshed }"
|
|
368
377
|
/>
|
|
369
378
|
</div>
|
|
370
379
|
</div>
|
|
371
380
|
<div v-if="errorMessage">{{ errorMessage }}</div>
|
|
372
381
|
<div v-else>
|
|
382
|
+
<!-- 添加刷新提示 -->
|
|
383
|
+
<div v-if="logRefreshed" class="refresh-notification">
|
|
384
|
+
提交历史已刷新
|
|
385
|
+
</div>
|
|
386
|
+
|
|
373
387
|
<!-- 图表视图 -->
|
|
374
388
|
<div v-if="showGraphView" class="graph-view">
|
|
375
389
|
<div class="commit-count" v-if="logsData.length > 0">
|
|
@@ -528,6 +542,34 @@ function fitGraphToContainer() {
|
|
|
528
542
|
font-size: 14px;
|
|
529
543
|
color: #606266;
|
|
530
544
|
}
|
|
545
|
+
|
|
546
|
+
.refresh-button-animated {
|
|
547
|
+
animation: pulse 1s;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
.refresh-notification {
|
|
551
|
+
background-color: #f0f9eb;
|
|
552
|
+
color: #67c23a;
|
|
553
|
+
padding: 8px;
|
|
554
|
+
border-radius: 4px;
|
|
555
|
+
margin-bottom: 10px;
|
|
556
|
+
text-align: center;
|
|
557
|
+
font-size: 14px;
|
|
558
|
+
border-left: 4px solid #67c23a;
|
|
559
|
+
animation: fadeOut 2s forwards;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
@keyframes pulse {
|
|
563
|
+
0% { transform: scale(1); }
|
|
564
|
+
50% { transform: scale(1.2); }
|
|
565
|
+
100% { transform: scale(1); }
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
@keyframes fadeOut {
|
|
569
|
+
0% { opacity: 1; }
|
|
570
|
+
70% { opacity: 1; }
|
|
571
|
+
100% { opacity: 0; }
|
|
572
|
+
}
|
|
531
573
|
</style>
|
|
532
574
|
|
|
533
575
|
/* 添加表格列调整样式 */
|
|
@@ -3,6 +3,9 @@ import { ref } from 'vue'
|
|
|
3
3
|
import { ElMessage } from 'element-plus'
|
|
4
4
|
import { useGitStore } from './gitStore'
|
|
5
5
|
|
|
6
|
+
// 定义Git操作间隔时间(毫秒)
|
|
7
|
+
const GIT_OPERATION_DELAY = 300
|
|
8
|
+
|
|
6
9
|
export const useGitLogStore = defineStore('gitLog', () => {
|
|
7
10
|
// 引用gitStore获取仓库状态
|
|
8
11
|
const gitStore = useGitStore()
|
|
@@ -14,11 +17,45 @@ export const useGitLogStore = defineStore('gitLog', () => {
|
|
|
14
17
|
unstaged: [],
|
|
15
18
|
untracked: []
|
|
16
19
|
})
|
|
20
|
+
// 添加Git状态文本
|
|
21
|
+
const statusText = ref('')
|
|
22
|
+
// 添加fileList状态用于保存porcelain格式的状态
|
|
23
|
+
const fileList = ref<{path: string, type: string}[]>([])
|
|
17
24
|
const isLoadingLog = ref(false)
|
|
18
25
|
const isLoadingStatus = ref(false)
|
|
19
26
|
const isAddingFiles = ref(false)
|
|
27
|
+
const isCommiting = ref(false)
|
|
28
|
+
const isPushing = ref(false)
|
|
20
29
|
const isResetting = ref(false)
|
|
21
30
|
|
|
31
|
+
// 解析 git status --porcelain 输出,提取文件及类型
|
|
32
|
+
function parseStatusPorcelain(statusText: string) {
|
|
33
|
+
if (statusText === undefined || statusText === '') {
|
|
34
|
+
// 如果状态为空字符串,清空文件列表
|
|
35
|
+
fileList.value = []
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const lines = statusText.split('\n')
|
|
40
|
+
const files: {path: string, type: string}[] = []
|
|
41
|
+
for (const line of lines) {
|
|
42
|
+
// 匹配常见的 git status --porcelain 格式
|
|
43
|
+
// M: 修改, A: 新增, D: 删除, ??: 未跟踪
|
|
44
|
+
const match = line.match(/^([ MADRCU\?]{2})\s+(.+)$/)
|
|
45
|
+
if (match) {
|
|
46
|
+
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'
|
|
53
|
+
files.push({ path: match[2], type })
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
fileList.value = files
|
|
57
|
+
}
|
|
58
|
+
|
|
22
59
|
// 获取提交日志
|
|
23
60
|
async function fetchLog() {
|
|
24
61
|
// 检查是否是Git仓库
|
|
@@ -32,8 +69,8 @@ export const useGitLogStore = defineStore('gitLog', () => {
|
|
|
32
69
|
console.log('开始加载提交历史...')
|
|
33
70
|
const response = await fetch('/api/log')
|
|
34
71
|
const data = await response.json()
|
|
35
|
-
if (data
|
|
36
|
-
log.value = data
|
|
72
|
+
if (data && Array.isArray(data)) {
|
|
73
|
+
log.value = data
|
|
37
74
|
}
|
|
38
75
|
console.log(`提交历史加载完成,共 ${log.value.length} 条记录`)
|
|
39
76
|
} catch (error) {
|
|
@@ -60,12 +97,17 @@ export const useGitLogStore = defineStore('gitLog', () => {
|
|
|
60
97
|
const response = await fetch('/api/status')
|
|
61
98
|
const data = await response.json()
|
|
62
99
|
if (data.status) {
|
|
100
|
+
// 更新状态文本
|
|
101
|
+
statusText.value = data.status
|
|
63
102
|
status.value = {
|
|
64
103
|
staged: data.status.staged || [],
|
|
65
104
|
unstaged: data.status.unstaged || [],
|
|
66
105
|
untracked: data.status.untracked || []
|
|
67
106
|
}
|
|
68
107
|
}
|
|
108
|
+
|
|
109
|
+
// 同时获取porcelain格式的状态
|
|
110
|
+
await fetchStatusPorcelain()
|
|
69
111
|
} catch (error) {
|
|
70
112
|
console.error('获取Git状态失败:', error)
|
|
71
113
|
ElMessage({
|
|
@@ -77,6 +119,34 @@ export const useGitLogStore = defineStore('gitLog', () => {
|
|
|
77
119
|
}
|
|
78
120
|
}
|
|
79
121
|
|
|
122
|
+
// 获取Git状态 (porcelain格式)
|
|
123
|
+
async function fetchStatusPorcelain() {
|
|
124
|
+
// 检查是否是Git仓库
|
|
125
|
+
if (!gitStore.isGitRepo) {
|
|
126
|
+
console.log('当前目录不是Git仓库,跳过加载Git状态')
|
|
127
|
+
return
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
const response = await fetch('/api/status_porcelain')
|
|
132
|
+
const data = await response.json()
|
|
133
|
+
if (data.status !== undefined) {
|
|
134
|
+
parseStatusPorcelain(data.status)
|
|
135
|
+
} else {
|
|
136
|
+
// 如果没有收到有效的 status 字段,清空文件列表
|
|
137
|
+
fileList.value = []
|
|
138
|
+
}
|
|
139
|
+
} catch (error) {
|
|
140
|
+
console.error('获取Git状态(porcelain)失败:', error)
|
|
141
|
+
ElMessage({
|
|
142
|
+
message: `获取Git状态(porcelain)失败: ${(error as Error).message}`,
|
|
143
|
+
type: 'error'
|
|
144
|
+
})
|
|
145
|
+
// 清空文件列表
|
|
146
|
+
fileList.value = []
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
80
150
|
// 添加文件到暂存区 (git add .)
|
|
81
151
|
async function addToStage() {
|
|
82
152
|
// 检查是否是Git仓库
|
|
@@ -120,6 +190,11 @@ export const useGitLogStore = defineStore('gitLog', () => {
|
|
|
120
190
|
}
|
|
121
191
|
}
|
|
122
192
|
|
|
193
|
+
// 添加延时函数
|
|
194
|
+
function delay(ms: number) {
|
|
195
|
+
return new Promise(resolve => setTimeout(resolve, ms))
|
|
196
|
+
}
|
|
197
|
+
|
|
123
198
|
// 提交更改
|
|
124
199
|
async function commitChanges(message: string, noVerify = false) {
|
|
125
200
|
// 检查是否是Git仓库
|
|
@@ -129,6 +204,7 @@ export const useGitLogStore = defineStore('gitLog', () => {
|
|
|
129
204
|
}
|
|
130
205
|
|
|
131
206
|
try {
|
|
207
|
+
isCommiting.value = true
|
|
132
208
|
const response = await fetch('/api/commit', {
|
|
133
209
|
method: 'POST',
|
|
134
210
|
headers: {
|
|
@@ -166,6 +242,8 @@ export const useGitLogStore = defineStore('gitLog', () => {
|
|
|
166
242
|
type: 'error'
|
|
167
243
|
})
|
|
168
244
|
return false
|
|
245
|
+
} finally {
|
|
246
|
+
isCommiting.value = false
|
|
169
247
|
}
|
|
170
248
|
}
|
|
171
249
|
|
|
@@ -178,6 +256,7 @@ export const useGitLogStore = defineStore('gitLog', () => {
|
|
|
178
256
|
}
|
|
179
257
|
|
|
180
258
|
try {
|
|
259
|
+
isPushing.value = true
|
|
181
260
|
const response = await fetch('/api/push', {
|
|
182
261
|
method: 'POST'
|
|
183
262
|
})
|
|
@@ -188,6 +267,8 @@ export const useGitLogStore = defineStore('gitLog', () => {
|
|
|
188
267
|
message: '推送成功',
|
|
189
268
|
type: 'success'
|
|
190
269
|
})
|
|
270
|
+
// 刷新状态
|
|
271
|
+
fetchStatus()
|
|
191
272
|
|
|
192
273
|
// 刷新日志
|
|
193
274
|
fetchLog()
|
|
@@ -206,54 +287,57 @@ export const useGitLogStore = defineStore('gitLog', () => {
|
|
|
206
287
|
type: 'error'
|
|
207
288
|
})
|
|
208
289
|
return false
|
|
290
|
+
} finally {
|
|
291
|
+
isPushing.value = false
|
|
209
292
|
}
|
|
210
293
|
}
|
|
211
294
|
|
|
212
295
|
// 暂存并提交
|
|
213
296
|
async function addAndCommit(message: string, noVerify = false) {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
// 再提交
|
|
222
|
-
return await commitChanges(message, noVerify)
|
|
223
|
-
} catch (error) {
|
|
224
|
-
ElMessage({
|
|
225
|
-
message: `暂存并提交失败: ${(error as Error).message}`,
|
|
226
|
-
type: 'error'
|
|
227
|
-
})
|
|
228
|
-
return false
|
|
229
|
-
}
|
|
297
|
+
const addResult = await addToStage()
|
|
298
|
+
if (!addResult) return false
|
|
299
|
+
|
|
300
|
+
// 使用新的延时常量
|
|
301
|
+
await delay(GIT_OPERATION_DELAY)
|
|
302
|
+
|
|
303
|
+
return await commitChanges(message, noVerify)
|
|
230
304
|
}
|
|
231
305
|
|
|
232
306
|
// 暂存、提交并推送
|
|
233
307
|
async function addCommitAndPush(message: string, noVerify = false) {
|
|
234
308
|
try {
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
if (!commitResult) {
|
|
238
|
-
return false
|
|
239
|
-
}
|
|
309
|
+
const addResult = await addToStage()
|
|
310
|
+
if (!addResult) return false
|
|
240
311
|
|
|
241
|
-
//
|
|
242
|
-
|
|
312
|
+
// 使用新的延时常量
|
|
313
|
+
await delay(GIT_OPERATION_DELAY)
|
|
243
314
|
|
|
244
|
-
|
|
245
|
-
if (
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
fetchLog()
|
|
250
|
-
}, 300)
|
|
251
|
-
}
|
|
315
|
+
const commitResult = await commitChanges(message, noVerify)
|
|
316
|
+
if (!commitResult) return false
|
|
317
|
+
|
|
318
|
+
// 使用新的延时常量
|
|
319
|
+
await delay(GIT_OPERATION_DELAY)
|
|
252
320
|
|
|
253
|
-
return
|
|
321
|
+
return await pushToRemote()
|
|
254
322
|
} catch (error) {
|
|
323
|
+
// 如果发生错误,尝试删除 index.lock 文件
|
|
324
|
+
try {
|
|
325
|
+
const response = await fetch('/api/remove-lock', {
|
|
326
|
+
method: 'POST'
|
|
327
|
+
})
|
|
328
|
+
const result = await response.json()
|
|
329
|
+
if (result.success) {
|
|
330
|
+
ElMessage({
|
|
331
|
+
message: '已清理锁定文件,请重试操作',
|
|
332
|
+
type: 'warning'
|
|
333
|
+
})
|
|
334
|
+
}
|
|
335
|
+
} catch (e) {
|
|
336
|
+
console.error('清理锁定文件失败:', e)
|
|
337
|
+
}
|
|
338
|
+
|
|
255
339
|
ElMessage({
|
|
256
|
-
message:
|
|
340
|
+
message: `操作失败: ${(error as Error).message}`,
|
|
257
341
|
type: 'error'
|
|
258
342
|
})
|
|
259
343
|
return false
|
|
@@ -351,114 +435,30 @@ export const useGitLogStore = defineStore('gitLog', () => {
|
|
|
351
435
|
}
|
|
352
436
|
}
|
|
353
437
|
|
|
354
|
-
// 暂存文件
|
|
355
|
-
async function stageFiles(files: string[]) {
|
|
356
|
-
// 检查是否是Git仓库
|
|
357
|
-
if (!gitStore.isGitRepo) {
|
|
358
|
-
ElMessage.warning('当前目录不是Git仓库')
|
|
359
|
-
return false
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
try {
|
|
363
|
-
const response = await fetch('/api/stage', {
|
|
364
|
-
method: 'POST',
|
|
365
|
-
headers: {
|
|
366
|
-
'Content-Type': 'application/json'
|
|
367
|
-
},
|
|
368
|
-
body: JSON.stringify({ files })
|
|
369
|
-
})
|
|
370
|
-
|
|
371
|
-
const result = await response.json()
|
|
372
|
-
if (result.success) {
|
|
373
|
-
ElMessage({
|
|
374
|
-
message: '暂存文件成功',
|
|
375
|
-
type: 'success'
|
|
376
|
-
})
|
|
377
|
-
|
|
378
|
-
// 刷新状态
|
|
379
|
-
fetchStatus()
|
|
380
|
-
|
|
381
|
-
return true
|
|
382
|
-
} else {
|
|
383
|
-
ElMessage({
|
|
384
|
-
message: `暂存文件失败: ${result.error}`,
|
|
385
|
-
type: 'error'
|
|
386
|
-
})
|
|
387
|
-
return false
|
|
388
|
-
}
|
|
389
|
-
} catch (error) {
|
|
390
|
-
ElMessage({
|
|
391
|
-
message: `暂存文件失败: ${(error as Error).message}`,
|
|
392
|
-
type: 'error'
|
|
393
|
-
})
|
|
394
|
-
return false
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
// 取消暂存文件
|
|
399
|
-
async function unstageFiles(files: string[]) {
|
|
400
|
-
// 检查是否是Git仓库
|
|
401
|
-
if (!gitStore.isGitRepo) {
|
|
402
|
-
ElMessage.warning('当前目录不是Git仓库')
|
|
403
|
-
return false
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
try {
|
|
407
|
-
const response = await fetch('/api/unstage', {
|
|
408
|
-
method: 'POST',
|
|
409
|
-
headers: {
|
|
410
|
-
'Content-Type': 'application/json'
|
|
411
|
-
},
|
|
412
|
-
body: JSON.stringify({ files })
|
|
413
|
-
})
|
|
414
|
-
|
|
415
|
-
const result = await response.json()
|
|
416
|
-
if (result.success) {
|
|
417
|
-
ElMessage({
|
|
418
|
-
message: '取消暂存成功',
|
|
419
|
-
type: 'success'
|
|
420
|
-
})
|
|
421
|
-
|
|
422
|
-
// 刷新状态
|
|
423
|
-
fetchStatus()
|
|
424
|
-
|
|
425
|
-
return true
|
|
426
|
-
} else {
|
|
427
|
-
ElMessage({
|
|
428
|
-
message: `取消暂存失败: ${result.error}`,
|
|
429
|
-
type: 'error'
|
|
430
|
-
})
|
|
431
|
-
return false
|
|
432
|
-
}
|
|
433
|
-
} catch (error) {
|
|
434
|
-
ElMessage({
|
|
435
|
-
message: `取消暂存失败: ${(error as Error).message}`,
|
|
436
|
-
type: 'error'
|
|
437
|
-
})
|
|
438
|
-
return false
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
|
|
442
438
|
return {
|
|
443
439
|
// 状态
|
|
444
440
|
log,
|
|
445
441
|
status,
|
|
442
|
+
statusText,
|
|
443
|
+
fileList,
|
|
446
444
|
isLoadingLog,
|
|
447
445
|
isLoadingStatus,
|
|
448
446
|
isAddingFiles,
|
|
449
447
|
isResetting,
|
|
448
|
+
isCommiting,
|
|
449
|
+
isPushing,
|
|
450
450
|
|
|
451
451
|
// 方法
|
|
452
452
|
fetchLog,
|
|
453
453
|
fetchStatus,
|
|
454
|
+
fetchStatusPorcelain,
|
|
455
|
+
parseStatusPorcelain,
|
|
454
456
|
addToStage,
|
|
455
457
|
commitChanges,
|
|
456
458
|
pushToRemote,
|
|
457
459
|
addAndCommit,
|
|
458
460
|
addCommitAndPush,
|
|
459
461
|
resetHead,
|
|
460
|
-
resetToRemote
|
|
461
|
-
stageFiles,
|
|
462
|
-
unstageFiles
|
|
462
|
+
resetToRemote
|
|
463
463
|
}
|
|
464
464
|
})
|