From b19b0f3679831f2e4fcad0a677940ab14300aded Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=9D=E5=B0=98?= <237809796@qq.com> Date: Tue, 30 Jun 2026 20:59:15 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E:=20Git=20=E6=8F=90=E4=BA=A4?= =?UTF-8?q?=E5=8E=86=E5=8F=B2=E6=98=BE=E7=A4=BA=E4=BD=9C=E8=80=85=20+=20?= =?UTF-8?q?=E6=8F=90=E4=BA=A4=E8=AF=A6=E6=83=85=E5=90=AB=E4=BD=9C=E8=80=85?= =?UTF-8?q?/=E6=97=B6=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 后端 git log format 加 %an 作者名(状态查询+分页查询) - 提交列表每行显示 hash/作者/主题/时间 - 提交详情头部补充作者显示 - 分支切换按钮占位(后续接入分支列表 IPC) --- src-tauri/src/commands/module.rs | 18 ++++++++---- src/api/module.ts | 4 ++- src/components/project/GitChanges.vue | 41 +++++++++++++++++++++++++-- src/i18n/en/gitChanges.ts | 1 + src/i18n/zh-CN/gitChanges.ts | 1 + 5 files changed, 55 insertions(+), 10 deletions(-) diff --git a/src-tauri/src/commands/module.rs b/src-tauri/src/commands/module.rs index 3286c3a..55cef92 100644 --- a/src-tauri/src/commands/module.rs +++ b/src-tauri/src/commands/module.rs @@ -266,6 +266,8 @@ struct GitRecentCommit { subject: String, /// Unix 时间戳(秒),供前端格式化显示。 timestamp: i64, + /// 作者名(git an) + author: String, } /// Git 状态返回结构(无 .git 时各字段空,前端据此显示"非 Git 仓库")。 @@ -367,23 +369,25 @@ fn run_git_status(dir: &str) -> GitStatus { } } - // 3) 最近提交:`git log -50 --format="%h %ct %s"`(hash + unix 时间戳 + subject) + // 3) 最近提交:`git log -50 --format="%h %ct %an %s"`(hash + 时间戳 + 作者 + subject) let mut recent_commits = Vec::new(); - if let Some(out) = run_git_cmd(path, &["log", "-50", "--format=%h %ct %s"], timeout) { + if let Some(out) = run_git_cmd(path, &["log", "-50", "--format=%h %ct %an %s"], timeout) { for line in out.lines() { - // format:" " + // format:" "(作者不含空格) let line = line.trim(); if line.is_empty() { continue; } - let mut parts = line.splitn(3, ' '); + let mut parts = line.splitn(4, ' '); let hash = parts.next().unwrap_or("").to_string(); let ts_str = parts.next().unwrap_or("0"); let timestamp: i64 = ts_str.parse().unwrap_or(0); + let author = parts.next().unwrap_or("").to_string(); let subject = parts.next().unwrap_or("").to_string(); if !hash.is_empty() { recent_commits.push(GitRecentCommit { hash, subject, timestamp, + author, }); } } @@ -922,7 +926,7 @@ pub async fn get_module_commits( "log", &format!("--skip={}", skip), &format!("-{}", fetch_plus), - "--format=%h %ct %s", + "--format=%h %ct %an %s", ]) .current_dir(&dir_for_git) .env("LANG", "en_US.UTF-8") @@ -937,16 +941,18 @@ pub async fn get_module_commits( let line = line.trim(); if line.is_empty() { continue; } if commits.len() >= fetch as usize { break; } - let mut parts = line.splitn(3, ' '); + let mut parts = line.splitn(4, ' '); let hash = parts.next().unwrap_or("").to_string(); let ts_str = parts.next().unwrap_or("0"); let timestamp: i64 = ts_str.parse().unwrap_or(0); + let author = parts.next().unwrap_or("").to_string(); let subject = parts.next().unwrap_or("").to_string(); if !hash.is_empty() { commits.push(serde_json::json!({ "hash": hash, "subject": subject, "timestamp": timestamp, + "author": author, })); } } diff --git a/src/api/module.ts b/src/api/module.ts index 2de1c56..b4cf997 100644 --- a/src/api/module.ts +++ b/src/api/module.ts @@ -65,6 +65,8 @@ export interface GitRecentCommit { subject: string /** Unix 时间戳(秒) */ timestamp: number + /** 作者名 */ + author: string } /** getModuleGitStatus 返回结构。 */ @@ -151,7 +153,7 @@ export const moduleApi = { /** 分页查询工程 Git 提交历史。返回 { commits, has_more }。 */ getModuleCommits(moduleId: string, skip?: number, limit?: number): Promise<{ - commits: { hash: string; subject: string; timestamp: number }[] + commits: { hash: string; subject: string; timestamp: number; author: string }[] has_more: boolean }> { return invoke('get_module_commits', { moduleId, skip: skip ?? 0, limit: limit ?? 50 }) diff --git a/src/components/project/GitChanges.vue b/src/components/project/GitChanges.vue index 31a012d..b545a5f 100644 --- a/src/components/project/GitChanges.vue +++ b/src/components/project/GitChanges.vue @@ -5,6 +5,9 @@ {{ branchName }} {{ gitStatus?.changed_files.length ?? 0 }} {{ $t('gitChanges.changedFiles') }} +
@@ -54,6 +57,7 @@
{{ selectedCommit.hash }} + {{ selectedCommit.author }} {{ selectedCommit.subject }} {{ formatTime(selectedCommit.timestamp) }} @@ -96,6 +100,7 @@ @click="selectCommit(c)" > {{ c.hash.slice(0, 8) }} + {{ c.author }} {{ c.subject }} {{ formatTime(c.timestamp) }}
@@ -137,7 +142,7 @@ const diffContent = ref('') const diffLoading = ref(false) // 提交历史(分页) -const commits = ref<{ hash: string; subject: string; timestamp: number }[]>([]) +const commits = ref<{ hash: string; subject: string; timestamp: number; author: string }[]>([]) const totalCommits = ref(0) const hasMoreCommits = ref(false) const loadingMore = ref(false) @@ -145,7 +150,7 @@ const commitSkip = ref(0) const COMMIT_PAGE_SIZE = 50 // 已选提交详情 -const selectedCommit = ref<{ hash: string; subject: string; timestamp: number } | null>(null) +const selectedCommit = ref<{ hash: string; subject: string; timestamp: number; author: string } | null>(null) const commitDetail = ref<{ files: { status: string; path: string }[]; diff: string } | null>(null) const commitDetailLoading = ref(false) const commitSelectedFile = ref('') @@ -271,6 +276,11 @@ async function loadStatus() { } } +/** 占位:分支切换后续接入(需拉取分支列表 + checkout IPC)。 */ +function onSwitchBranch() { + // TODO: 弹出分支列表选择 + 调用 git checkout +} + async function loadMoreCommits() { if (loadingMore.value || !hasMoreCommits.value) return loadingMore.value = true @@ -311,7 +321,7 @@ async function selectFile(path: string) { } /** 点击提交行 → 加载该提交的变更文件列表 */ -async function selectCommit(c: { hash: string; subject: string; timestamp: number }) { +async function selectCommit(c: { hash: string; subject: string; timestamp: number; author: string }) { selectedCommit.value = c commitDetail.value = null commitSelectedFile.value = '' @@ -370,6 +380,21 @@ watch(() => props.moduleId, loadStatus, { immediate: true }) .branch-icon { font-size: 16px; } .branch-name { font-weight: 600; color: var(--df-accent); } .branch-count { margin-left: auto; font-size: 12px; color: var(--df-text-dim); } +.branch-switch-btn { + background: none; + border: none; + color: var(--df-text-dim); + cursor: pointer; + padding: 2px 6px; + border-radius: 3px; + display: flex; + align-items: center; + transition: all 0.15s; +} +.branch-switch-btn:hover { + color: var(--df-text); + background: rgba(255,255,255,0.05); +} /* Tabs */ .gc-tabs { display: flex; border-bottom: 0.5px solid var(--df-border); flex-shrink: 0; } @@ -424,6 +449,12 @@ watch(() => props.moduleId, loadStatus, { immediate: true }) font-size: 11px; color: var(--df-accent); flex-shrink: 0; } .gc-commit-msg { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; } +.gc-commit-author { + font-size: 11px; color: var(--df-text-dim); + flex-shrink: 0; + max-width: 100px; + overflow: hidden; text-overflow: ellipsis; white-space: nowrap; +} .gc-commit-time { font-size: 11px; color: var(--df-text-dim); flex-shrink: 0; } /* 提交详情 */ @@ -438,6 +469,10 @@ watch(() => props.moduleId, loadStatus, { immediate: true }) font-size: 11px; color: var(--df-accent); } .gc-commit-detail-msg { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; } +.gc-commit-detail-author { + font-size: 11px; color: var(--df-text-dim); + flex-shrink: 0; +} .gc-commit-detail-time { font-size: 11px; color: var(--df-text-dim); flex-shrink: 0; } .gc-detail-close { background: none; border: none; color: var(--df-text-dim); diff --git a/src/i18n/en/gitChanges.ts b/src/i18n/en/gitChanges.ts index 66bc18d..83ad0ab 100644 --- a/src/i18n/en/gitChanges.ts +++ b/src/i18n/en/gitChanges.ts @@ -13,5 +13,6 @@ export default { notGitRepo: 'Not a git repository', detached: 'HEAD detached', loadMore: 'Load more', + switchBranch: 'Switch branch', }, } diff --git a/src/i18n/zh-CN/gitChanges.ts b/src/i18n/zh-CN/gitChanges.ts index da0e733..7222ac1 100644 --- a/src/i18n/zh-CN/gitChanges.ts +++ b/src/i18n/zh-CN/gitChanges.ts @@ -13,5 +13,6 @@ export default { notGitRepo: '非 Git 仓库', detached: 'HEAD 分离', loadMore: '加载更多', + switchBranch: '切换分支', }, }