zen-gitsync 2.0.3 → 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/package.json +1 -0
- package/src/ui/client/src/App.vue +368 -219
- package/src/ui/client/src/components/CommitForm.vue +777 -442
- package/src/ui/client/src/components/GitStatus.vue +89 -86
- package/src/ui/client/src/components/LogList.vue +393 -85
- package/src/ui/client/src/main.ts +3 -0
- package/src/ui/client/src/stores/gitLogStore.ts +464 -0
- package/src/ui/client/src/stores/gitStore.ts +301 -0
- 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 +197 -8
- package/src/ui/public/assets/index-BHmYZROy.css +0 -1
- package/src/ui/public/assets/index-kfMX1bxz.js +0 -9
- package/src/ui/public/assets/vendor-DxvF30ca.js +0 -41
|
@@ -1,13 +1,26 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { ref, onMounted,
|
|
2
|
+
import { ref, onMounted, computed } from 'vue'
|
|
3
3
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
|
4
4
|
// import { io } from 'socket.io-client'
|
|
5
5
|
import { Refresh, ArrowLeft, ArrowRight, Folder, Document, ArrowUp, RefreshRight } from '@element-plus/icons-vue'
|
|
6
|
+
import { useGitLogStore } from '../stores/gitLogStore'
|
|
7
|
+
import { useGitStore } from '../stores/gitStore'
|
|
8
|
+
|
|
9
|
+
// 定义props
|
|
10
|
+
const props = defineProps({
|
|
11
|
+
initialDirectory: {
|
|
12
|
+
type: String,
|
|
13
|
+
default: ''
|
|
14
|
+
}
|
|
15
|
+
})
|
|
6
16
|
|
|
7
|
-
const
|
|
17
|
+
const gitLogStore = useGitLogStore()
|
|
18
|
+
const gitStore = useGitStore()
|
|
19
|
+
// 移除本地status定义,直接使用store中的statusText
|
|
20
|
+
// const status = ref('加载中...')
|
|
8
21
|
// const socket = io()
|
|
9
|
-
const isRefreshing =
|
|
10
|
-
|
|
22
|
+
const isRefreshing = computed(() => gitLogStore.isLoadingStatus)
|
|
23
|
+
// 移除本地fileList定义,改用store中的fileList
|
|
11
24
|
const selectedFile = ref('')
|
|
12
25
|
const diffContent = ref('')
|
|
13
26
|
const diffDialogVisible = ref(false)
|
|
@@ -25,66 +38,33 @@ const directoryItems = ref<{name: string, path: string, type: string}[]>([])
|
|
|
25
38
|
const isBrowsing = ref(false)
|
|
26
39
|
const browseErrorMessage = ref('')
|
|
27
40
|
|
|
28
|
-
|
|
29
|
-
function parseStatus(statusText: string) {
|
|
30
|
-
if (statusText === undefined) return
|
|
31
|
-
const lines = statusText.split('\n')
|
|
32
|
-
const files: {path: string, type: string}[] = []
|
|
33
|
-
for (const line of lines) {
|
|
34
|
-
// 匹配常见的 git status --porcelain 格式
|
|
35
|
-
// M: 修改, A: 新增, D: 删除, ??: 未跟踪
|
|
36
|
-
const match = line.match(/^([ MADRCU\?]{2})\s+(.+)$/)
|
|
37
|
-
if (match) {
|
|
38
|
-
let type = ''
|
|
39
|
-
const code = match[1].trim()
|
|
40
|
-
if (code === 'M' || code === 'MM' || code === 'AM' || code === 'RM') type = 'modified'
|
|
41
|
-
else if (code === 'A' || code === 'AA') type = 'added'
|
|
42
|
-
else if (code === 'D' || code === 'AD' || code === 'DA') type = 'deleted'
|
|
43
|
-
else if (code === '??') type = 'untracked'
|
|
44
|
-
else type = 'other'
|
|
45
|
-
files.push({ path: match[2], type })
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
fileList.value = files
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const currentDirectory = ref('')
|
|
41
|
+
const currentDirectory = ref(props.initialDirectory || '');
|
|
52
42
|
async function loadStatus() {
|
|
53
43
|
try {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
44
|
+
// 如果没有初始目录,才需要请求当前目录
|
|
45
|
+
if (!currentDirectory.value) {
|
|
46
|
+
const responseDir = await fetch('/api/current_directory')
|
|
47
|
+
const dirData = await responseDir.json()
|
|
48
|
+
currentDirectory.value = dirData.directory || '未知目录'
|
|
49
|
+
}
|
|
59
50
|
|
|
60
|
-
// 如果不是Git
|
|
61
|
-
if (
|
|
62
|
-
status.value = '当前目录不是一个Git仓库'
|
|
63
|
-
fileList.value = []
|
|
64
|
-
ElMessage.warning('当前目录不是一个Git仓库')
|
|
51
|
+
// 如果不是Git仓库,直接显示提示并返回
|
|
52
|
+
if (!gitStore.isGitRepo) {
|
|
65
53
|
return
|
|
66
54
|
}
|
|
67
55
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const response_porcelain = await fetch('/api/status_porcelain')
|
|
73
|
-
const data_porcelain = await response_porcelain.json()
|
|
74
|
-
parseStatus(data_porcelain.status)
|
|
56
|
+
// 使用gitLogStore获取Git状态
|
|
57
|
+
await gitLogStore.fetchStatus()
|
|
58
|
+
|
|
75
59
|
ElMessage({
|
|
76
60
|
message: 'Git 状态已刷新',
|
|
77
61
|
type: 'success',
|
|
78
62
|
})
|
|
79
63
|
} catch (error) {
|
|
80
|
-
status.value = '加载状态失败: ' + (error as Error).message
|
|
81
|
-
fileList.value = []
|
|
82
64
|
ElMessage({
|
|
83
65
|
message: '刷新失败: ' + (error as Error).message,
|
|
84
66
|
type: 'error',
|
|
85
67
|
})
|
|
86
|
-
} finally {
|
|
87
|
-
isRefreshing.value = false
|
|
88
68
|
}
|
|
89
69
|
}
|
|
90
70
|
|
|
@@ -134,7 +114,7 @@ async function getFileDiff(filePath: string) {
|
|
|
134
114
|
isLoadingDiff.value = true
|
|
135
115
|
selectedFile.value = filePath
|
|
136
116
|
// 设置当前文件索引
|
|
137
|
-
currentFileIndex.value = fileList.
|
|
117
|
+
currentFileIndex.value = gitLogStore.fileList.findIndex(file => file.path === filePath)
|
|
138
118
|
const response = await fetch(`/api/diff?file=${encodeURIComponent(filePath)}`)
|
|
139
119
|
const data = await response.json()
|
|
140
120
|
diffContent.value = data.diff || '没有变更'
|
|
@@ -152,19 +132,19 @@ async function getFileDiff(filePath: string) {
|
|
|
152
132
|
|
|
153
133
|
// 添加切换到上一个文件的方法
|
|
154
134
|
async function goToPreviousFile() {
|
|
155
|
-
if (fileList.
|
|
135
|
+
if (gitLogStore.fileList.length === 0 || currentFileIndex.value <= 0) return
|
|
156
136
|
|
|
157
137
|
const newIndex = currentFileIndex.value - 1
|
|
158
|
-
const prevFile = fileList
|
|
138
|
+
const prevFile = gitLogStore.fileList[newIndex]
|
|
159
139
|
await getFileDiff(prevFile.path)
|
|
160
140
|
}
|
|
161
141
|
|
|
162
142
|
// 添加切换到下一个文件的方法
|
|
163
143
|
async function goToNextFile() {
|
|
164
|
-
if (fileList.
|
|
144
|
+
if (gitLogStore.fileList.length === 0 || currentFileIndex.value >= gitLogStore.fileList.length - 1) return
|
|
165
145
|
|
|
166
146
|
const newIndex = currentFileIndex.value + 1
|
|
167
|
-
const nextFile = fileList
|
|
147
|
+
const nextFile = gitLogStore.fileList[newIndex]
|
|
168
148
|
await getFileDiff(nextFile.path)
|
|
169
149
|
}
|
|
170
150
|
|
|
@@ -289,13 +269,25 @@ async function changeDirectory() {
|
|
|
289
269
|
currentDirectory.value = result.directory
|
|
290
270
|
isDirectoryDialogVisible.value = false
|
|
291
271
|
|
|
292
|
-
//
|
|
293
|
-
|
|
272
|
+
// 直接使用API返回的Git仓库状态
|
|
273
|
+
gitStore.isGitRepo = result.isGitRepo
|
|
274
|
+
|
|
275
|
+
// 如果是Git仓库,加载Git相关数据
|
|
276
|
+
if (result.isGitRepo) {
|
|
277
|
+
// 加载Git分支和用户信息
|
|
278
|
+
await Promise.all([
|
|
279
|
+
gitStore.getCurrentBranch(),
|
|
280
|
+
gitStore.getAllBranches(),
|
|
281
|
+
gitStore.getUserInfo()
|
|
282
|
+
])
|
|
283
|
+
|
|
284
|
+
// 刷新Git状态
|
|
285
|
+
await loadStatus()
|
|
286
|
+
} else {
|
|
294
287
|
ElMessage.warning('当前目录不是一个Git仓库')
|
|
288
|
+
// 清空Git相关状态
|
|
289
|
+
gitStore.$reset() // 使用pinia的reset方法重置状态
|
|
295
290
|
}
|
|
296
|
-
|
|
297
|
-
// 刷新状态
|
|
298
|
-
loadStatus()
|
|
299
291
|
} else {
|
|
300
292
|
ElMessage.error(result.error || '切换目录失败')
|
|
301
293
|
}
|
|
@@ -368,13 +360,9 @@ async function revertFileChanges(filePath: string) {
|
|
|
368
360
|
}
|
|
369
361
|
|
|
370
362
|
onMounted(() => {
|
|
363
|
+
// App.vue已经加载了Git相关数据,此时只需加载状态
|
|
364
|
+
// 如果已有初始目录,则只需加载状态
|
|
371
365
|
loadStatus()
|
|
372
|
-
|
|
373
|
-
// Socket.io 事件
|
|
374
|
-
// socket.on('status_update', (data: { status: string }) => {
|
|
375
|
-
// status.value = data.status
|
|
376
|
-
// parseStatus(data.status)
|
|
377
|
-
// })
|
|
378
366
|
})
|
|
379
367
|
|
|
380
368
|
// onUnmounted(() => {
|
|
@@ -397,7 +385,7 @@ defineExpose({
|
|
|
397
385
|
</el-button>
|
|
398
386
|
</div>
|
|
399
387
|
<div class="status-header">
|
|
400
|
-
<h2>Git
|
|
388
|
+
<h2>Git 状态(git status)</h2>
|
|
401
389
|
<el-button
|
|
402
390
|
type="primary"
|
|
403
391
|
:icon="Refresh"
|
|
@@ -407,11 +395,13 @@ defineExpose({
|
|
|
407
395
|
:loading="isRefreshing"
|
|
408
396
|
/>
|
|
409
397
|
</div>
|
|
410
|
-
<div class="status-box">
|
|
398
|
+
<div class="status-box">
|
|
399
|
+
{{ !gitStore.isGitRepo ? '当前目录不是一个Git仓库' : gitLogStore.statusText || '加载中...' }}
|
|
400
|
+
</div>
|
|
411
401
|
<!-- 颜色区分不同类型文件 -->
|
|
412
|
-
<div v-if="fileList.length" class="file-list">
|
|
402
|
+
<div v-if="gitLogStore.fileList.length" class="file-list">
|
|
413
403
|
<div
|
|
414
|
-
v-for="file in fileList"
|
|
404
|
+
v-for="file in gitLogStore.fileList"
|
|
415
405
|
:key="file.path"
|
|
416
406
|
:class="['file-item', file.type]"
|
|
417
407
|
>
|
|
@@ -492,18 +482,20 @@ defineExpose({
|
|
|
492
482
|
</div>
|
|
493
483
|
|
|
494
484
|
<!-- 目录内容列表 -->
|
|
495
|
-
<
|
|
496
|
-
<
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
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>
|
|
507
499
|
</div>
|
|
508
500
|
</el-dialog>
|
|
509
501
|
|
|
@@ -524,14 +516,14 @@ defineExpose({
|
|
|
524
516
|
<el-button
|
|
525
517
|
:icon="ArrowLeft"
|
|
526
518
|
@click="goToPreviousFile"
|
|
527
|
-
:disabled="currentFileIndex <= 0 || fileList.length === 0"
|
|
519
|
+
:disabled="currentFileIndex <= 0 || gitLogStore.fileList.length === 0"
|
|
528
520
|
circle
|
|
529
521
|
/>
|
|
530
|
-
<span class="file-counter">{{ currentFileIndex + 1 }} / {{ fileList.length }}</span>
|
|
522
|
+
<span class="file-counter">{{ currentFileIndex + 1 }} / {{ gitLogStore.fileList.length }}</span>
|
|
531
523
|
<el-button
|
|
532
524
|
:icon="ArrowRight"
|
|
533
525
|
@click="goToNextFile"
|
|
534
|
-
:disabled="currentFileIndex >= fileList.length - 1 || fileList.length === 0"
|
|
526
|
+
:disabled="currentFileIndex >= gitLogStore.fileList.length - 1 || gitLogStore.fileList.length === 0"
|
|
535
527
|
circle
|
|
536
528
|
/>
|
|
537
529
|
</div>
|
|
@@ -708,14 +700,25 @@ defineExpose({
|
|
|
708
700
|
|
|
709
701
|
.directory-browser {
|
|
710
702
|
padding: 10px;
|
|
711
|
-
|
|
712
|
-
|
|
703
|
+
height: 400px;
|
|
704
|
+
display: flex;
|
|
705
|
+
flex-direction: column;
|
|
713
706
|
}
|
|
714
707
|
|
|
715
708
|
.browser-nav {
|
|
716
709
|
margin-bottom: 10px;
|
|
717
710
|
display: flex;
|
|
718
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;
|
|
719
722
|
}
|
|
720
723
|
|
|
721
724
|
.directory-items {
|