zen-gitsync 2.0.4 → 2.0.6
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 +31 -2
- package/package.json +3 -1
- package/src/ui/client/components.d.ts +1 -0
- package/src/ui/client/src/App.vue +626 -186
- package/src/ui/client/src/components/CommitForm.vue +508 -401
- package/src/ui/client/src/components/GitStatus.vue +590 -224
- package/src/ui/client/src/components/LogList.vue +809 -83
- package/src/ui/client/src/stores/gitLogStore.ts +440 -125
- package/src/ui/client/src/stores/gitStore.ts +86 -1
- package/src/ui/client/stats.html +1 -1
- package/src/ui/public/assets/index-DaPynzAr.js +10 -0
- package/src/ui/public/assets/index-qfIezZmd.css +1 -0
- package/src/ui/public/assets/vendor-BcSuWc8z.js +45 -0
- package/src/ui/public/index.html +3 -3
- package/src/ui/server/index.js +375 -44
- 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
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { ref, onMounted, computed } from 'vue'
|
|
2
|
+
import { ref, onMounted, computed, watch } from 'vue'
|
|
3
3
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
|
4
4
|
// import { io } from 'socket.io-client'
|
|
5
|
-
import { Refresh, ArrowLeft, ArrowRight, Folder, Document, ArrowUp, RefreshRight } from '@element-plus/icons-vue'
|
|
5
|
+
import { Refresh, ArrowLeft, ArrowRight, Folder, Document, ArrowUp, RefreshRight, Check, Close } from '@element-plus/icons-vue'
|
|
6
6
|
import { useGitLogStore } from '../stores/gitLogStore'
|
|
7
7
|
import { useGitStore } from '../stores/gitStore'
|
|
8
8
|
|
|
@@ -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
|
}
|
|
@@ -337,15 +303,14 @@ function handleFileClick(file: {path: string, type: string}) {
|
|
|
337
303
|
getFileDiff(file.path)
|
|
338
304
|
}
|
|
339
305
|
|
|
340
|
-
//
|
|
341
|
-
function
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
}
|
|
306
|
+
// 暂存单个文件
|
|
307
|
+
async function stageFile(filePath: string) {
|
|
308
|
+
await gitLogStore.addFileToStage(filePath)
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// 取消暂存单个文件
|
|
312
|
+
async function unstageFile(filePath: string) {
|
|
313
|
+
await gitLogStore.unstageFile(filePath)
|
|
349
314
|
}
|
|
350
315
|
|
|
351
316
|
// 刷新Git状态的方法
|
|
@@ -383,26 +348,57 @@ async function revertFileChanges(filePath: string) {
|
|
|
383
348
|
// 刷新Git状态
|
|
384
349
|
await loadStatus()
|
|
385
350
|
} else {
|
|
386
|
-
|
|
351
|
+
// 使用自定义错误信息,避免显示undefined
|
|
352
|
+
ElMessage.error(result.error ? `撤回失败: ${result.error}` : '撤回文件修改失败,请重试')
|
|
387
353
|
}
|
|
388
354
|
} catch (error) {
|
|
389
|
-
//
|
|
390
|
-
if ((error as Error).message
|
|
391
|
-
|
|
355
|
+
// 用户取消操作不显示错误
|
|
356
|
+
if ((error as any) === 'cancel' || (error as Error).message === 'cancel') {
|
|
357
|
+
// 用户取消操作,不做任何处理,也不显示错误
|
|
358
|
+
return
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// 其他错误情况才显示错误消息
|
|
362
|
+
// 避免显示undefined错误信息
|
|
363
|
+
const errorMessage = (error as Error).message || '未知错误';
|
|
364
|
+
if (errorMessage !== 'undefined') {
|
|
365
|
+
ElMessage.error(`撤回文件修改失败: ${errorMessage}`)
|
|
366
|
+
} else {
|
|
367
|
+
ElMessage.error('撤回文件修改失败,请重试')
|
|
392
368
|
}
|
|
393
369
|
}
|
|
394
370
|
}
|
|
395
371
|
|
|
372
|
+
// 提取文件名和目录
|
|
373
|
+
function getFileName(path: string): string {
|
|
374
|
+
const parts = path.split('/')
|
|
375
|
+
return parts[parts.length - 1]
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
function getFileDirectory(path: string): string {
|
|
379
|
+
const parts = path.split('/')
|
|
380
|
+
if (parts.length <= 1) return ''
|
|
381
|
+
|
|
382
|
+
// 保留所有除最后一个部分的路径
|
|
383
|
+
return parts.slice(0, -1).join('/')
|
|
384
|
+
}
|
|
385
|
+
|
|
396
386
|
onMounted(() => {
|
|
397
387
|
// App.vue已经加载了Git相关数据,此时只需加载状态
|
|
398
388
|
// 如果已有初始目录,则只需加载状态
|
|
399
389
|
loadStatus()
|
|
400
390
|
})
|
|
401
391
|
|
|
392
|
+
// 监听autoUpdateEnabled的变化,手动调用toggleAutoUpdate
|
|
393
|
+
watch(() => gitLogStore.autoUpdateEnabled, (newValue, oldValue) => {
|
|
394
|
+
console.log(`自动更新状态变更: ${oldValue} -> ${newValue}`)
|
|
395
|
+
// 调用store中的方法来实现服务器通信功能
|
|
396
|
+
gitLogStore.toggleAutoUpdate()
|
|
397
|
+
}, { immediate: false })
|
|
398
|
+
|
|
402
399
|
// onUnmounted(() => {
|
|
403
400
|
// socket.disconnect()
|
|
404
401
|
// })
|
|
405
|
-
|
|
406
402
|
// 暴露刷新方法给父组件
|
|
407
403
|
defineExpose({
|
|
408
404
|
refreshStatus
|
|
@@ -411,47 +407,165 @@ defineExpose({
|
|
|
411
407
|
|
|
412
408
|
<template>
|
|
413
409
|
<div class="card">
|
|
414
|
-
<div class="current-directory">
|
|
415
|
-
<el-icon><Folder /></el-icon>
|
|
416
|
-
<span>{{ currentDirectory }}</span>
|
|
417
|
-
<el-button type="primary" size="small" @click="openDirectoryDialog" plain>
|
|
418
|
-
切换目录
|
|
419
|
-
</el-button>
|
|
420
|
-
</div>
|
|
421
410
|
<div class="status-header">
|
|
422
|
-
<h2>Git
|
|
423
|
-
<
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
411
|
+
<h2>Git 状态</h2>
|
|
412
|
+
<div class="header-actions">
|
|
413
|
+
<el-tooltip
|
|
414
|
+
:content="gitLogStore.autoUpdateEnabled ? '禁用自动更新文件状态' : '启用自动更新文件状态'"
|
|
415
|
+
placement="top"
|
|
416
|
+
:hide-after="1000"
|
|
417
|
+
>
|
|
418
|
+
<el-switch
|
|
419
|
+
v-model="gitLogStore.autoUpdateEnabled"
|
|
420
|
+
style="--el-switch-on-color: #67C23A; --el-switch-off-color: #909399; margin-right: 10px;"
|
|
421
|
+
inline-prompt
|
|
422
|
+
:active-icon="Check"
|
|
423
|
+
:inactive-icon="Close"
|
|
424
|
+
class="auto-update-switch"
|
|
425
|
+
/>
|
|
426
|
+
</el-tooltip>
|
|
427
|
+
<el-tooltip content="刷新状态" placement="top" :hide-after="1000">
|
|
428
|
+
<el-button
|
|
429
|
+
type="primary"
|
|
430
|
+
:icon="Refresh"
|
|
431
|
+
circle
|
|
432
|
+
size="small"
|
|
433
|
+
@click="refreshStatus"
|
|
434
|
+
:loading="isRefreshing"
|
|
435
|
+
/>
|
|
436
|
+
</el-tooltip>
|
|
437
|
+
</div>
|
|
431
438
|
</div>
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
439
|
+
|
|
440
|
+
<div class="card-content">
|
|
441
|
+
<div class="current-directory">
|
|
442
|
+
<el-icon><Folder /></el-icon>
|
|
443
|
+
<span>{{ currentDirectory }}</span>
|
|
444
|
+
<el-button type="primary" size="small" @click="openDirectoryDialog" plain>
|
|
445
|
+
切换目录
|
|
446
|
+
</el-button>
|
|
447
|
+
</div>
|
|
448
|
+
|
|
449
|
+
<div v-if="!gitStore.isGitRepo" class="status-box">
|
|
450
|
+
当前目录不是一个Git仓库
|
|
451
|
+
</div>
|
|
452
|
+
|
|
453
|
+
<!-- 现代化、简洁的文件列表 -->
|
|
454
|
+
<div v-if="gitLogStore.fileList.length" class="file-list-container">
|
|
455
|
+
<!-- 分组显示文件 -->
|
|
456
|
+
<div v-if="gitLogStore.fileList.some(f => f.type === 'added')" class="file-group">
|
|
457
|
+
<div class="file-group-header">已暂存的更改</div>
|
|
458
|
+
<div class="file-list">
|
|
459
|
+
<div
|
|
460
|
+
v-for="file in gitLogStore.fileList.filter(f => f.type === 'added')"
|
|
461
|
+
:key="file.path"
|
|
462
|
+
class="file-item"
|
|
463
|
+
@click="handleFileClick(file)"
|
|
464
|
+
>
|
|
465
|
+
<div class="file-info">
|
|
466
|
+
<div class="file-path-container">
|
|
467
|
+
<span class="file-name">{{ getFileName(file.path) }}</span>
|
|
468
|
+
<span class="file-directory">{{ getFileDirectory(file.path) }}</span>
|
|
469
|
+
</div>
|
|
470
|
+
</div>
|
|
471
|
+
<div class="file-actions">
|
|
472
|
+
<el-tooltip content="取消暂存" placement="top" :hide-after="1000">
|
|
473
|
+
<el-button
|
|
474
|
+
type="warning"
|
|
475
|
+
size="small"
|
|
476
|
+
circle
|
|
477
|
+
@click.stop="unstageFile(file.path)"
|
|
478
|
+
>-</el-button>
|
|
479
|
+
</el-tooltip>
|
|
480
|
+
</div>
|
|
481
|
+
</div>
|
|
482
|
+
</div>
|
|
443
483
|
</div>
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
484
|
+
|
|
485
|
+
<div v-if="gitLogStore.fileList.some(f => f.type === 'modified' || f.type === 'deleted')" class="file-group">
|
|
486
|
+
<div class="file-group-header">未暂存的更改</div>
|
|
487
|
+
<div class="file-list">
|
|
488
|
+
<div
|
|
489
|
+
v-for="file in gitLogStore.fileList.filter(f => f.type === 'modified' || f.type === 'deleted')"
|
|
490
|
+
:key="file.path"
|
|
491
|
+
class="file-item"
|
|
492
|
+
@click="handleFileClick(file)"
|
|
493
|
+
>
|
|
494
|
+
<div class="file-info">
|
|
495
|
+
<div class="file-status-indicator" :class="file.type"></div>
|
|
496
|
+
<div class="file-path-container">
|
|
497
|
+
<span class="file-name">{{ getFileName(file.path) }}</span>
|
|
498
|
+
<span class="file-directory">{{ getFileDirectory(file.path) }}</span>
|
|
499
|
+
</div>
|
|
500
|
+
</div>
|
|
501
|
+
<div class="file-actions">
|
|
502
|
+
<el-tooltip content="添加到暂存区" placement="top" :hide-after="1000">
|
|
503
|
+
<el-button
|
|
504
|
+
type="success"
|
|
505
|
+
size="small"
|
|
506
|
+
circle
|
|
507
|
+
@click.stop="stageFile(file.path)"
|
|
508
|
+
>+</el-button>
|
|
509
|
+
</el-tooltip>
|
|
510
|
+
<el-tooltip content="撤回修改" placement="top" :hide-after="1000">
|
|
511
|
+
<el-button
|
|
512
|
+
type="danger"
|
|
513
|
+
size="small"
|
|
514
|
+
:icon="RefreshRight"
|
|
515
|
+
circle
|
|
516
|
+
@click.stop="revertFileChanges(file.path)"
|
|
517
|
+
/>
|
|
518
|
+
</el-tooltip>
|
|
519
|
+
</div>
|
|
520
|
+
</div>
|
|
521
|
+
</div>
|
|
522
|
+
</div>
|
|
523
|
+
|
|
524
|
+
<div v-if="gitLogStore.fileList.some(f => f.type === 'untracked')" class="file-group">
|
|
525
|
+
<div class="file-group-header">未跟踪的文件</div>
|
|
526
|
+
<div class="file-list">
|
|
527
|
+
<div
|
|
528
|
+
v-for="file in gitLogStore.fileList.filter(f => f.type === 'untracked')"
|
|
529
|
+
:key="file.path"
|
|
530
|
+
class="file-item"
|
|
531
|
+
@click="handleFileClick(file)"
|
|
532
|
+
>
|
|
533
|
+
<div class="file-info">
|
|
534
|
+
<div class="file-status-indicator untracked"></div>
|
|
535
|
+
<div class="file-path-container">
|
|
536
|
+
<span class="file-name">{{ getFileName(file.path) }}</span>
|
|
537
|
+
<span class="file-directory">{{ getFileDirectory(file.path) }}</span>
|
|
538
|
+
</div>
|
|
539
|
+
</div>
|
|
540
|
+
<div class="file-actions">
|
|
541
|
+
<el-tooltip content="添加到暂存区" placement="top" :hide-after="1000">
|
|
542
|
+
<el-button
|
|
543
|
+
type="success"
|
|
544
|
+
size="small"
|
|
545
|
+
circle
|
|
546
|
+
@click.stop="stageFile(file.path)"
|
|
547
|
+
>+</el-button>
|
|
548
|
+
</el-tooltip>
|
|
549
|
+
<el-tooltip content="删除文件" placement="top" :hide-after="1000">
|
|
550
|
+
<el-button
|
|
551
|
+
type="danger"
|
|
552
|
+
size="small"
|
|
553
|
+
:icon="Close"
|
|
554
|
+
circle
|
|
555
|
+
@click.stop="revertFileChanges(file.path)"
|
|
556
|
+
/>
|
|
557
|
+
</el-tooltip>
|
|
558
|
+
</div>
|
|
559
|
+
</div>
|
|
560
|
+
</div>
|
|
561
|
+
</div>
|
|
562
|
+
</div>
|
|
563
|
+
|
|
564
|
+
<div v-else-if="gitStore.isGitRepo" class="empty-status">
|
|
565
|
+
<div class="empty-icon">
|
|
566
|
+
<el-icon><Document /></el-icon>
|
|
454
567
|
</div>
|
|
568
|
+
<div class="empty-text">没有检测到任何更改</div>
|
|
455
569
|
</div>
|
|
456
570
|
</div>
|
|
457
571
|
|
|
@@ -514,18 +628,20 @@ defineExpose({
|
|
|
514
628
|
</div>
|
|
515
629
|
|
|
516
630
|
<!-- 目录内容列表 -->
|
|
517
|
-
<
|
|
518
|
-
<
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
631
|
+
<div class="directory-items-container">
|
|
632
|
+
<ul class="directory-items">
|
|
633
|
+
<li
|
|
634
|
+
v-for="item in directoryItems"
|
|
635
|
+
:key="item.path"
|
|
636
|
+
:class="['directory-item', item.type]"
|
|
637
|
+
@click="selectDirectoryItem(item)"
|
|
638
|
+
>
|
|
639
|
+
<el-icon v-if="item.type === 'directory'"><Folder /></el-icon>
|
|
640
|
+
<el-icon v-else><Document /></el-icon>
|
|
641
|
+
<span>{{ item.name }}</span>
|
|
642
|
+
</li>
|
|
643
|
+
</ul>
|
|
644
|
+
</div>
|
|
529
645
|
</div>
|
|
530
646
|
</el-dialog>
|
|
531
647
|
|
|
@@ -535,6 +651,7 @@ defineExpose({
|
|
|
535
651
|
:title="`文件差异: ${selectedFile}`"
|
|
536
652
|
width="80%"
|
|
537
653
|
destroy-on-close
|
|
654
|
+
class="diff-dialog"
|
|
538
655
|
>
|
|
539
656
|
<div v-loading="isLoadingDiff" class="diff-content">
|
|
540
657
|
<div v-if="diffContent" v-html="formatDiff(diffContent)" class="diff-formatted"></div>
|
|
@@ -546,14 +663,14 @@ defineExpose({
|
|
|
546
663
|
<el-button
|
|
547
664
|
:icon="ArrowLeft"
|
|
548
665
|
@click="goToPreviousFile"
|
|
549
|
-
:disabled="currentFileIndex <= 0 || fileList.length === 0"
|
|
666
|
+
:disabled="currentFileIndex <= 0 || gitLogStore.fileList.length === 0"
|
|
550
667
|
circle
|
|
551
668
|
/>
|
|
552
|
-
<span class="file-counter">{{ currentFileIndex + 1 }} / {{ fileList.length }}</span>
|
|
669
|
+
<span class="file-counter">{{ currentFileIndex + 1 }} / {{ gitLogStore.fileList.length }}</span>
|
|
553
670
|
<el-button
|
|
554
671
|
:icon="ArrowRight"
|
|
555
672
|
@click="goToNextFile"
|
|
556
|
-
:disabled="currentFileIndex >= fileList.length - 1 || fileList.length === 0"
|
|
673
|
+
:disabled="currentFileIndex >= gitLogStore.fileList.length - 1 || gitLogStore.fileList.length === 0"
|
|
557
674
|
circle
|
|
558
675
|
/>
|
|
559
676
|
</div>
|
|
@@ -565,215 +682,418 @@ defineExpose({
|
|
|
565
682
|
.card {
|
|
566
683
|
background-color: #fff;
|
|
567
684
|
border-radius: 8px;
|
|
568
|
-
box-shadow: 0 2px
|
|
569
|
-
|
|
570
|
-
|
|
685
|
+
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.03);
|
|
686
|
+
border: 1px solid rgba(0, 0, 0, 0.03);
|
|
687
|
+
height: 100%;
|
|
688
|
+
width: 100%;
|
|
689
|
+
display: flex;
|
|
690
|
+
flex-direction: column;
|
|
691
|
+
overflow: hidden;
|
|
571
692
|
}
|
|
572
693
|
|
|
573
694
|
.status-header {
|
|
574
695
|
display: flex;
|
|
575
696
|
justify-content: space-between;
|
|
576
697
|
align-items: center;
|
|
577
|
-
|
|
698
|
+
padding: 8px 16px;
|
|
699
|
+
border-bottom: 1px solid #f0f0f0;
|
|
700
|
+
height: 36px;
|
|
578
701
|
}
|
|
579
702
|
|
|
580
703
|
.status-header h2 {
|
|
581
704
|
margin: 0;
|
|
705
|
+
font-size: 16px;
|
|
706
|
+
font-weight: 500;
|
|
707
|
+
color: #303133;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
.header-actions {
|
|
711
|
+
display: flex;
|
|
712
|
+
align-items: center;
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
.card-content {
|
|
716
|
+
padding: 15px;
|
|
717
|
+
overflow-y: auto;
|
|
718
|
+
flex: 1;
|
|
719
|
+
display: flex;
|
|
720
|
+
flex-direction: column;
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
.current-directory {
|
|
724
|
+
display: flex;
|
|
725
|
+
align-items: center;
|
|
726
|
+
margin-bottom: 16px;
|
|
727
|
+
padding: 10px;
|
|
728
|
+
background-color: #f8f9fa;
|
|
729
|
+
border-radius: 6px;
|
|
730
|
+
font-family: monospace;
|
|
731
|
+
border: 1px solid #f0f0f0;
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
.current-directory .el-icon {
|
|
735
|
+
margin-right: 8px;
|
|
736
|
+
color: #409eff;
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
.current-directory span {
|
|
740
|
+
flex-grow: 1;
|
|
741
|
+
word-break: break-all;
|
|
742
|
+
margin-right: 10px;
|
|
582
743
|
}
|
|
583
744
|
|
|
584
745
|
.status-box {
|
|
585
746
|
white-space: pre-wrap;
|
|
586
747
|
font-family: monospace;
|
|
587
|
-
background-color: #
|
|
588
|
-
padding:
|
|
589
|
-
border-radius:
|
|
590
|
-
margin-bottom:
|
|
591
|
-
max-height:
|
|
748
|
+
background-color: #f8f9fa;
|
|
749
|
+
padding: 16px;
|
|
750
|
+
border-radius: 6px;
|
|
751
|
+
margin-bottom: 20px;
|
|
752
|
+
max-height: 200px;
|
|
592
753
|
overflow-y: auto;
|
|
754
|
+
border: 1px solid #f0f0f0;
|
|
755
|
+
font-size: 14px;
|
|
756
|
+
line-height: 1.5;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
/* 现代化的文件列表容器 */
|
|
760
|
+
.file-list-container {
|
|
761
|
+
flex: 1;
|
|
762
|
+
overflow: hidden;
|
|
763
|
+
display: flex;
|
|
764
|
+
flex-direction: column;
|
|
765
|
+
margin-bottom: 0;
|
|
766
|
+
gap: 12px;
|
|
767
|
+
height: calc(100% - 70px); /* 给底部留出些空间 */
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
.file-group {
|
|
771
|
+
background-color: #f8f9fa;
|
|
772
|
+
border-radius: 6px;
|
|
773
|
+
overflow: hidden;
|
|
774
|
+
border: 1px solid #ebeef5;
|
|
775
|
+
margin-bottom: 12px;
|
|
776
|
+
display: flex;
|
|
777
|
+
flex-direction: column;
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
/* 让每个文件组根据内容自动增长 */
|
|
781
|
+
.file-group {
|
|
782
|
+
flex: 0 1 auto; /* 不主动增长,但允许缩小,基于内容大小 */
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
/* 最后一个分组可以吸收剩余空间 */
|
|
786
|
+
.file-group:last-child {
|
|
787
|
+
margin-bottom: 0;
|
|
788
|
+
flex: 1 1 auto; /* 可以增长占用剩余空间 */
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
.file-group-header {
|
|
792
|
+
font-size: 14px;
|
|
793
|
+
font-weight: bold;
|
|
794
|
+
padding: 8px 12px;
|
|
795
|
+
background-color: #f0f2f5;
|
|
796
|
+
color: #606266;
|
|
797
|
+
border-bottom: 1px solid #ebeef5;
|
|
798
|
+
flex-shrink: 0; /* 防止header被压缩 */
|
|
593
799
|
}
|
|
594
800
|
|
|
595
801
|
.file-list {
|
|
596
|
-
max-height: 300px;
|
|
597
802
|
overflow-y: auto;
|
|
803
|
+
min-height: 40px; /* 最小高度 */
|
|
804
|
+
flex-grow: 1; /* 允许文件列表在文件组内扩展 */
|
|
805
|
+
padding: 0;
|
|
806
|
+
margin: 0;
|
|
807
|
+
scrollbar-width: thin; /* Firefox */
|
|
808
|
+
scrollbar-color: rgba(144, 147, 153, 0.3) transparent; /* Firefox */
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
/* Webkit浏览器的滚动条样式 */
|
|
812
|
+
.file-list::-webkit-scrollbar {
|
|
813
|
+
width: 6px;
|
|
814
|
+
height: 6px;
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
.file-list::-webkit-scrollbar-thumb {
|
|
818
|
+
background-color: rgba(144, 147, 153, 0.3);
|
|
819
|
+
border-radius: 4px;
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
.file-list::-webkit-scrollbar-thumb:hover {
|
|
823
|
+
background-color: rgba(144, 147, 153, 0.5);
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
.file-list::-webkit-scrollbar-track {
|
|
827
|
+
background-color: transparent;
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
/* 让每个文件列表自适应高度,使其在容器中更好地分配空间 */
|
|
831
|
+
.file-list:empty {
|
|
832
|
+
display: none; /* 如果列表为空,不显示 */
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
/* 当没有足够的项目填充列表时,禁用滚动 */
|
|
836
|
+
.file-list:has(.empty-file-group) {
|
|
837
|
+
overflow-y: hidden;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
/* 替换为更兼容的选择器 */
|
|
841
|
+
/* 改用直接为empty-file-group父容器添加样式 */
|
|
842
|
+
.empty-file-container {
|
|
843
|
+
overflow-y: hidden !important; /* 强制禁用滚动 */
|
|
844
|
+
display: flex;
|
|
845
|
+
flex-direction: column;
|
|
846
|
+
align-items: stretch;
|
|
847
|
+
flex: 1;
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
.empty-file-group {
|
|
851
|
+
padding: 16px;
|
|
852
|
+
text-align: center;
|
|
853
|
+
color: #909399;
|
|
854
|
+
font-size: 13px;
|
|
855
|
+
font-style: italic;
|
|
856
|
+
display: flex;
|
|
857
|
+
align-items: center;
|
|
858
|
+
justify-content: center;
|
|
859
|
+
min-height: 50px; /* 增加最小高度 */
|
|
860
|
+
background-color: #f8f9fa;
|
|
861
|
+
border-radius: 4px;
|
|
862
|
+
margin: 8px;
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
/* 自定义每个分组的展开逻辑 */
|
|
866
|
+
/* 已暂存文件分组 - 保持小巧 */
|
|
867
|
+
.file-group:nth-child(1) {
|
|
868
|
+
flex: 0 1 auto;
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
/* 未暂存更改分组 - 稍微大一些 */
|
|
872
|
+
.file-group:nth-child(2) {
|
|
873
|
+
flex: 0 1 auto;
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
/* 未跟踪文件分组 - 可以占据剩余空间 */
|
|
877
|
+
.file-group:nth-child(3) {
|
|
878
|
+
flex: 1 1 auto;
|
|
598
879
|
}
|
|
599
880
|
|
|
600
881
|
.file-item {
|
|
601
882
|
padding: 8px 12px;
|
|
602
|
-
margin-bottom: 5px;
|
|
603
|
-
border-radius: 4px;
|
|
604
|
-
cursor: pointer;
|
|
605
883
|
display: flex;
|
|
606
884
|
align-items: center;
|
|
607
885
|
justify-content: space-between;
|
|
886
|
+
border-bottom: 1px solid #ebeef5;
|
|
887
|
+
cursor: pointer;
|
|
888
|
+
transition: background-color 0.2s;
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
.file-item:last-child {
|
|
892
|
+
border-bottom: none;
|
|
608
893
|
}
|
|
609
894
|
|
|
610
895
|
.file-item:hover {
|
|
611
|
-
background-color: #
|
|
896
|
+
background-color: #ecf5ff;
|
|
612
897
|
}
|
|
613
898
|
|
|
614
899
|
.file-info {
|
|
615
900
|
display: flex;
|
|
616
901
|
align-items: center;
|
|
617
902
|
flex-grow: 1;
|
|
903
|
+
overflow: hidden;
|
|
904
|
+
white-space: nowrap;
|
|
905
|
+
gap: 8px;
|
|
618
906
|
}
|
|
619
907
|
|
|
620
|
-
.file-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
908
|
+
.file-status-indicator {
|
|
909
|
+
width: 6px;
|
|
910
|
+
height: 6px;
|
|
911
|
+
border-radius: 50%;
|
|
912
|
+
background-color: #409eff;
|
|
913
|
+
flex-shrink: 0;
|
|
624
914
|
}
|
|
625
915
|
|
|
626
|
-
.file-
|
|
627
|
-
|
|
916
|
+
.file-status-indicator.added {
|
|
917
|
+
background-color: #67c23a;
|
|
628
918
|
}
|
|
629
919
|
|
|
630
|
-
.file-
|
|
631
|
-
|
|
632
|
-
padding: 2px 6px;
|
|
633
|
-
border-radius: 10px;
|
|
634
|
-
margin-right: 10px;
|
|
635
|
-
flex-shrink: 0;
|
|
920
|
+
.file-status-indicator.modified {
|
|
921
|
+
background-color: #409eff;
|
|
636
922
|
}
|
|
637
923
|
|
|
638
|
-
.
|
|
639
|
-
background-color: #
|
|
640
|
-
color: #67c23a;
|
|
924
|
+
.file-status-indicator.deleted {
|
|
925
|
+
background-color: #f56c6c;
|
|
641
926
|
}
|
|
642
927
|
|
|
643
|
-
.
|
|
644
|
-
background-color: #
|
|
645
|
-
color: #409eff;
|
|
928
|
+
.file-status-indicator.untracked {
|
|
929
|
+
background-color: #e6a23c;
|
|
646
930
|
}
|
|
647
931
|
|
|
648
|
-
.
|
|
649
|
-
|
|
650
|
-
|
|
932
|
+
.file-path-container {
|
|
933
|
+
display: flex;
|
|
934
|
+
flex-direction: column;
|
|
935
|
+
overflow: hidden;
|
|
651
936
|
}
|
|
652
937
|
|
|
653
|
-
.
|
|
654
|
-
|
|
655
|
-
color: #
|
|
938
|
+
.file-name {
|
|
939
|
+
font-weight: 500;
|
|
940
|
+
color: #303133;
|
|
941
|
+
overflow: hidden;
|
|
942
|
+
text-overflow: ellipsis;
|
|
943
|
+
line-height: 1.2;
|
|
656
944
|
}
|
|
657
945
|
|
|
658
|
-
.file-
|
|
659
|
-
font-
|
|
660
|
-
|
|
946
|
+
.file-directory {
|
|
947
|
+
font-size: 12px;
|
|
948
|
+
color: #909399;
|
|
949
|
+
overflow: hidden;
|
|
950
|
+
text-overflow: ellipsis;
|
|
951
|
+
line-height: 1.2;
|
|
661
952
|
}
|
|
662
953
|
|
|
663
|
-
.
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
padding: 10px;
|
|
669
|
-
background-color: #f5f7fa;
|
|
670
|
-
border-radius: 4px;
|
|
954
|
+
.file-actions {
|
|
955
|
+
display: flex;
|
|
956
|
+
gap: 5px;
|
|
957
|
+
opacity: 0;
|
|
958
|
+
transition: opacity 0.2s;
|
|
671
959
|
}
|
|
672
960
|
|
|
673
|
-
.
|
|
674
|
-
|
|
675
|
-
line-height: 1.5;
|
|
961
|
+
.file-item:hover .file-actions {
|
|
962
|
+
opacity: 1;
|
|
676
963
|
}
|
|
677
964
|
|
|
678
|
-
.
|
|
965
|
+
.empty-status {
|
|
679
966
|
display: flex;
|
|
680
|
-
|
|
967
|
+
flex-direction: column;
|
|
681
968
|
align-items: center;
|
|
969
|
+
justify-content: center;
|
|
970
|
+
height: calc(100% - 70px);
|
|
971
|
+
background-color: #f8f9fa;
|
|
972
|
+
border-radius: 6px;
|
|
973
|
+
border: 1px solid #ebeef5;
|
|
682
974
|
margin-top: 15px;
|
|
683
975
|
}
|
|
684
976
|
|
|
685
|
-
.
|
|
686
|
-
|
|
977
|
+
.empty-icon {
|
|
978
|
+
font-size: 32px;
|
|
979
|
+
color: #c0c4cc;
|
|
980
|
+
margin-bottom: 10px;
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
.empty-text {
|
|
984
|
+
color: #909399;
|
|
687
985
|
font-size: 14px;
|
|
688
|
-
color: #606266;
|
|
689
986
|
}
|
|
690
987
|
|
|
691
|
-
|
|
988
|
+
/* 添加针对空内容区域的样式 */
|
|
989
|
+
.card-content:empty {
|
|
692
990
|
display: flex;
|
|
693
991
|
align-items: center;
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
border
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
.current-directory .el-icon {
|
|
702
|
-
margin-right: 8px;
|
|
703
|
-
color: #409eff;
|
|
992
|
+
justify-content: center;
|
|
993
|
+
background-color: #f8f9fa;
|
|
994
|
+
border-radius: 6px;
|
|
995
|
+
border: 1px dashed #dcdfe6;
|
|
996
|
+
color: #909399;
|
|
997
|
+
height: 100%;
|
|
704
998
|
}
|
|
705
999
|
|
|
706
|
-
.
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
margin-right: 10px;
|
|
1000
|
+
.card-content:empty::after {
|
|
1001
|
+
content: '没有Git状态信息可显示';
|
|
1002
|
+
font-size: 14px;
|
|
710
1003
|
}
|
|
711
1004
|
|
|
1005
|
+
/* 添加目录浏览相关样式 */
|
|
712
1006
|
.browser-current-path {
|
|
713
|
-
margin-bottom: 10px;
|
|
714
|
-
font-size: 14px;
|
|
715
|
-
color: #606266;
|
|
716
|
-
background-color: #f5f7fa;
|
|
717
|
-
padding: 8px 12px;
|
|
718
|
-
border-radius: 4px;
|
|
719
1007
|
font-family: monospace;
|
|
720
|
-
|
|
1008
|
+
margin-bottom: 15px;
|
|
1009
|
+
padding: 10px;
|
|
1010
|
+
background-color: #f5f7fa;
|
|
1011
|
+
border-radius: 6px;
|
|
1012
|
+
overflow-x: auto;
|
|
1013
|
+
white-space: nowrap;
|
|
1014
|
+
border: 1px solid #ebeef5;
|
|
721
1015
|
}
|
|
722
1016
|
|
|
723
1017
|
.browser-error {
|
|
724
|
-
margin-bottom: 10px;
|
|
725
1018
|
color: #f56c6c;
|
|
726
|
-
|
|
1019
|
+
margin: 10px 0;
|
|
1020
|
+
padding: 10px;
|
|
727
1021
|
background-color: #fef0f0;
|
|
728
1022
|
border-radius: 4px;
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
.directory-browser {
|
|
732
|
-
padding: 10px;
|
|
733
|
-
max-height: 400px;
|
|
734
|
-
overflow-y: auto;
|
|
1023
|
+
border-left: 3px solid #f56c6c;
|
|
735
1024
|
}
|
|
736
1025
|
|
|
737
1026
|
.browser-nav {
|
|
1027
|
+
display: flex;
|
|
1028
|
+
gap: 10px;
|
|
738
1029
|
margin-bottom: 10px;
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
.no-padding-left {
|
|
1033
|
+
padding-left: 12px;
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
.directory-browser {
|
|
1037
|
+
height: 400px;
|
|
1038
|
+
border: 1px solid #ebeef5;
|
|
1039
|
+
border-radius: 6px;
|
|
1040
|
+
overflow: hidden;
|
|
739
1041
|
display: flex;
|
|
740
|
-
|
|
1042
|
+
flex-direction: column;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
.directory-items-container {
|
|
1046
|
+
flex: 1;
|
|
1047
|
+
overflow-y: auto;
|
|
1048
|
+
background-color: #f8f9fa;
|
|
1049
|
+
padding: 10px;
|
|
741
1050
|
}
|
|
742
1051
|
|
|
743
1052
|
.directory-items {
|
|
744
1053
|
list-style: none;
|
|
745
1054
|
padding: 0;
|
|
746
1055
|
margin: 0;
|
|
1056
|
+
display: grid;
|
|
1057
|
+
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
|
|
1058
|
+
gap: 10px;
|
|
747
1059
|
}
|
|
748
1060
|
|
|
749
1061
|
.directory-item {
|
|
750
|
-
padding: 8px 12px;
|
|
751
|
-
margin-bottom: 5px;
|
|
752
|
-
border-radius: 4px;
|
|
753
|
-
cursor: pointer;
|
|
754
1062
|
display: flex;
|
|
755
1063
|
align-items: center;
|
|
1064
|
+
padding: 8px;
|
|
1065
|
+
cursor: pointer;
|
|
1066
|
+
border-radius: 4px;
|
|
1067
|
+
background-color: white;
|
|
1068
|
+
border: 1px solid #ebeef5;
|
|
1069
|
+
transition: all 0.2s;
|
|
1070
|
+
overflow: hidden;
|
|
1071
|
+
white-space: nowrap;
|
|
1072
|
+
text-overflow: ellipsis;
|
|
1073
|
+
gap: 5px;
|
|
756
1074
|
}
|
|
757
1075
|
|
|
758
1076
|
.directory-item:hover {
|
|
759
|
-
background-color: #
|
|
1077
|
+
background-color: #ecf5ff;
|
|
1078
|
+
border-color: #c6e2ff;
|
|
760
1079
|
}
|
|
761
1080
|
|
|
762
1081
|
.directory-item.directory {
|
|
1082
|
+
background-color: #f0f7ff;
|
|
763
1083
|
color: #409eff;
|
|
764
1084
|
}
|
|
765
1085
|
|
|
766
|
-
.directory-item.
|
|
767
|
-
|
|
1086
|
+
.directory-item .el-icon {
|
|
1087
|
+
margin-right: 5px;
|
|
1088
|
+
flex-shrink: 0;
|
|
768
1089
|
}
|
|
769
1090
|
|
|
770
|
-
.directory-item .el-icon {
|
|
771
|
-
|
|
1091
|
+
.directory-item.directory .el-icon {
|
|
1092
|
+
color: #409eff;
|
|
772
1093
|
}
|
|
773
1094
|
|
|
774
|
-
.directory-item
|
|
775
|
-
|
|
776
|
-
word-break: break-all;
|
|
1095
|
+
.directory-item.file .el-icon {
|
|
1096
|
+
color: #909399;
|
|
777
1097
|
}
|
|
778
1098
|
|
|
779
1099
|
.directory-buttons {
|
|
@@ -781,41 +1101,87 @@ defineExpose({
|
|
|
781
1101
|
gap: 10px;
|
|
782
1102
|
margin-top: 10px;
|
|
783
1103
|
}
|
|
784
|
-
|
|
785
|
-
/* 移除按钮左侧的内边距 */
|
|
786
|
-
.no-padding-left {
|
|
787
|
-
padding-left: 8px !important;
|
|
788
|
-
}
|
|
789
1104
|
</style>
|
|
790
1105
|
|
|
791
|
-
<!--
|
|
1106
|
+
<!-- 非scoped样式,使diff格式化样式对动态内容生效 -->
|
|
792
1107
|
<style>
|
|
793
1108
|
.diff-header {
|
|
794
1109
|
font-weight: bold;
|
|
795
1110
|
background-color: #e6f1fc;
|
|
796
|
-
padding:
|
|
797
|
-
margin:
|
|
1111
|
+
padding: 5px;
|
|
1112
|
+
margin: 8px 0;
|
|
1113
|
+
border-radius: 4px;
|
|
1114
|
+
color: #0366d6;
|
|
1115
|
+
border-bottom: 1px solid #c8e1ff;
|
|
798
1116
|
}
|
|
799
1117
|
|
|
800
1118
|
.diff-old-file, .diff-new-file {
|
|
801
|
-
color: #
|
|
1119
|
+
color: #586069;
|
|
1120
|
+
padding: 2px 5px;
|
|
1121
|
+
font-family: monospace;
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
.diff-old-file {
|
|
1125
|
+
color: #cb2431;
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
.diff-new-file {
|
|
1129
|
+
color: #22863a;
|
|
802
1130
|
}
|
|
803
1131
|
|
|
804
1132
|
.diff-hunk-header {
|
|
805
1133
|
color: #6f42c1;
|
|
1134
|
+
background-color: #f1f8ff;
|
|
1135
|
+
padding: 2px 5px;
|
|
1136
|
+
margin: 5px 0;
|
|
1137
|
+
border-radius: 3px;
|
|
1138
|
+
font-family: monospace;
|
|
806
1139
|
}
|
|
807
1140
|
|
|
808
1141
|
.diff-added {
|
|
809
1142
|
background-color: #e6ffed;
|
|
810
|
-
color: #
|
|
1143
|
+
color: #22863a;
|
|
1144
|
+
padding: 0 5px;
|
|
1145
|
+
border-left: 4px solid #22863a;
|
|
1146
|
+
font-family: monospace;
|
|
1147
|
+
display: block;
|
|
1148
|
+
margin: 2px 0;
|
|
811
1149
|
}
|
|
812
1150
|
|
|
813
1151
|
.diff-removed {
|
|
814
1152
|
background-color: #ffeef0;
|
|
815
|
-
color: #
|
|
1153
|
+
color: #cb2431;
|
|
1154
|
+
padding: 0 5px;
|
|
1155
|
+
border-left: 4px solid #cb2431;
|
|
1156
|
+
font-family: monospace;
|
|
1157
|
+
display: block;
|
|
1158
|
+
margin: 2px 0;
|
|
816
1159
|
}
|
|
817
1160
|
|
|
818
1161
|
.diff-context {
|
|
819
1162
|
color: #444;
|
|
1163
|
+
padding: 0 5px;
|
|
1164
|
+
font-family: monospace;
|
|
1165
|
+
display: block;
|
|
1166
|
+
margin: 2px 0;
|
|
1167
|
+
background-color: #fafbfc;
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
/* 增加自动更新开关的样式 */
|
|
1171
|
+
.auto-update-switch .el-switch__core {
|
|
1172
|
+
transition: all 0.3s ease-in-out;
|
|
1173
|
+
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
.auto-update-switch .el-switch__core:hover {
|
|
1177
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
.auto-update-switch.is-checked .el-switch__core {
|
|
1181
|
+
box-shadow: 0 2px 5px rgba(103, 194, 58, 0.3);
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
.auto-update-switch.is-checked .el-switch__core:hover {
|
|
1185
|
+
box-shadow: 0 2px 8px rgba(103, 194, 58, 0.5);
|
|
820
1186
|
}
|
|
821
1187
|
</style>
|