新增功能区分推送与未推送的版本
This commit is contained in:
@@ -1 +1 @@
|
||||
c6a7af2915380768678ecf3032701af1
|
||||
b3473eff2f1694108cc3ae68b4ae04f0
|
||||
|
||||
BIN
bin/gitpilot.exe
BIN
bin/gitpilot.exe
Binary file not shown.
@@ -19,6 +19,7 @@ import {
|
||||
UserOutlined,
|
||||
RollbackOutlined,
|
||||
ExclamationCircleOutlined,
|
||||
CloseCircleOutlined,
|
||||
} from '@ant-design/icons-vue'
|
||||
import { Modal } from 'ant-design-vue'
|
||||
import { AppService } from '../../bindings/github.com/zhuy1228/GitPilot/internal/app'
|
||||
@@ -614,6 +615,33 @@ async function resetToCommit(commit, mode = 'hard') {
|
||||
})
|
||||
}
|
||||
|
||||
async function revertCommit(commit) {
|
||||
if (!props.project?.path || !commit) return
|
||||
Modal.confirm({
|
||||
title: '确认撤回提交',
|
||||
icon: h(ExclamationCircleOutlined),
|
||||
content: h('div', [
|
||||
h('p', '将创建一个新提交来撤回以下提交的更改:'),
|
||||
h('p', { style: 'font-family: monospace; color: #89b4fa;' }, `${commit.shortHash} - ${commit.message}`),
|
||||
h('p', { style: 'color: var(--text-muted); font-size: 12px; margin-top: 8px;' }, '此操作会生成一个新的反向提交,不会丢失历史记录。'),
|
||||
]),
|
||||
okText: '确认撤回',
|
||||
cancelText: '取消',
|
||||
okButtonProps: { danger: true },
|
||||
async onOk() {
|
||||
try {
|
||||
await AppService.RevertCommit(props.project.path, commit.hash)
|
||||
await loadStatus()
|
||||
selectedCommit.value = null
|
||||
commitDiff.value = ''
|
||||
} catch (e) {
|
||||
console.error('撤回提交失败:', e)
|
||||
Modal.error({ title: '撤回失败', content: String(e) })
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
function formatTime(ts) {
|
||||
if (!ts) return ''
|
||||
const d = new Date(ts * 1000)
|
||||
@@ -842,16 +870,29 @@ function formatTime(ts) {
|
||||
v-for="log in commitLogs"
|
||||
:key="log.hash"
|
||||
class="commit-item"
|
||||
:class="{ active: selectedCommit?.hash === log.hash }"
|
||||
:class="{ active: selectedCommit?.hash === log.hash, unpushed: !log.pushed }"
|
||||
@click="selectCommit(log)"
|
||||
>
|
||||
<div class="commit-msg-row">
|
||||
<span v-if="!log.pushed" class="commit-unpushed-dot" title="未推送"></span>
|
||||
<div class="commit-msg">{{ log.message }}</div>
|
||||
<a-dropdown :trigger="['click']" @click.stop>
|
||||
<div class="commit-action-btns" @click.stop>
|
||||
<!-- 撤回按钮 -->
|
||||
<a-button
|
||||
type="text"
|
||||
size="small"
|
||||
class="commit-reset-btn"
|
||||
class="commit-action-btn"
|
||||
title="撤回此提交"
|
||||
@click.stop="revertCommit(log)"
|
||||
>
|
||||
<template #icon><CloseCircleOutlined /></template>
|
||||
</a-button>
|
||||
<!-- 回滚下拉 -->
|
||||
<a-dropdown :trigger="['click']">
|
||||
<a-button
|
||||
type="text"
|
||||
size="small"
|
||||
class="commit-action-btn"
|
||||
:loading="resetLoading"
|
||||
@click.stop
|
||||
>
|
||||
@@ -875,8 +916,10 @@ function formatTime(ts) {
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
<div class="commit-meta">
|
||||
<span class="commit-hash">{{ log.shortHash }}</span>
|
||||
<span v-if="!log.pushed" class="commit-push-tag">未推送</span>
|
||||
<span class="commit-author"><UserOutlined /> {{ log.author }}</span>
|
||||
<span class="commit-time">{{ formatTime(log.timestamp) }}</span>
|
||||
</div>
|
||||
@@ -1379,22 +1422,52 @@ function formatTime(ts) {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.commit-reset-btn {
|
||||
visibility: hidden;
|
||||
color: var(--text-muted) !important;
|
||||
.commit-action-btns {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0;
|
||||
flex-shrink: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.commit-action-btn {
|
||||
color: var(--text-muted) !important;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.commit-reset-btn:hover {
|
||||
.commit-action-btn:hover {
|
||||
color: #f38ba8 !important;
|
||||
}
|
||||
|
||||
.commit-item:hover .commit-reset-btn {
|
||||
.commit-item:hover .commit-action-btns {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
/* 未推送标识 */
|
||||
.commit-unpushed-dot {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
border-radius: 50%;
|
||||
background: #a6e3a1;
|
||||
flex-shrink: 0;
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.commit-push-tag {
|
||||
font-size: 10px;
|
||||
padding: 0 5px;
|
||||
border-radius: 3px;
|
||||
background: rgba(166, 227, 161, 0.15);
|
||||
color: #a6e3a1;
|
||||
line-height: 16px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.commit-item.unpushed {
|
||||
border-left: 2px solid #a6e3a1;
|
||||
}
|
||||
|
||||
.commit-msg {
|
||||
font-size: 13px;
|
||||
color: var(--text-primary);
|
||||
|
||||
@@ -282,6 +282,16 @@ export function ResetProject(path, hash, mode) {
|
||||
return $Call.ByID(2061148684, path, hash, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* RevertCommit 撤回指定提交(生成一个反向提交)
|
||||
* @param {string} path
|
||||
* @param {string} hash
|
||||
* @returns {$CancellablePromise<void>}
|
||||
*/
|
||||
export function RevertCommit(path, hash) {
|
||||
return $Call.ByID(1334788539, path, hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* SelectDirectory 打开系统文件夹选择器,返回选中的路径
|
||||
* @returns {$CancellablePromise<string>}
|
||||
|
||||
@@ -133,6 +133,13 @@ export class CommitLog {
|
||||
*/
|
||||
this["message"] = "";
|
||||
}
|
||||
if (!("pushed" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {boolean}
|
||||
*/
|
||||
this["pushed"] = false;
|
||||
}
|
||||
|
||||
Object.assign(this, $$source);
|
||||
}
|
||||
|
||||
@@ -569,6 +569,7 @@ type CommitLog struct {
|
||||
Email string `json:"email"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
Message string `json:"message"`
|
||||
Pushed bool `json:"pushed"`
|
||||
}
|
||||
|
||||
// BranchInfo 分支信息
|
||||
@@ -589,7 +590,39 @@ func (s *AppService) GetCommitLog(path string, count int) ([]CommitLog, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取提交历史失败: %w", err)
|
||||
}
|
||||
return parseCommitLog(out), nil
|
||||
logs := parseCommitLog(out)
|
||||
|
||||
// 获取当前分支名,查询未推送的提交
|
||||
branch, brErr := s.gitClient.Branch(path)
|
||||
if brErr == nil {
|
||||
branch = strings.TrimSpace(branch)
|
||||
unpushedOut, upErr := s.gitClient.UnpushedCommits(path, branch)
|
||||
unpushedSet := make(map[string]bool)
|
||||
if upErr == nil {
|
||||
for _, h := range strings.Split(strings.TrimSpace(unpushedOut), "\n") {
|
||||
if h != "" {
|
||||
unpushedSet[h] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
for i := range logs {
|
||||
logs[i].Pushed = !unpushedSet[logs[i].Hash]
|
||||
}
|
||||
}
|
||||
|
||||
return logs, nil
|
||||
}
|
||||
|
||||
// RevertCommit 撤回指定提交(生成一个反向提交)
|
||||
func (s *AppService) RevertCommit(path, hash string) error {
|
||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||
return fmt.Errorf("项目路径不存在: %s", path)
|
||||
}
|
||||
if strings.TrimSpace(hash) == "" {
|
||||
return fmt.Errorf("提交哈希不能为空")
|
||||
}
|
||||
_, err := s.gitClient.RevertCommit(path, strings.TrimSpace(hash))
|
||||
return err
|
||||
}
|
||||
|
||||
func parseCommitLog(output string) []CommitLog {
|
||||
|
||||
@@ -119,6 +119,16 @@ func (g *GitClient) Log(path string, count int) (string, error) {
|
||||
)
|
||||
}
|
||||
|
||||
// UnpushedCommits 获取当前分支上未推送到远程的提交哈希列表
|
||||
func (g *GitClient) UnpushedCommits(path, branch string) (string, error) {
|
||||
return g.Run(path, "rev-list", "origin/"+branch+"..HEAD")
|
||||
}
|
||||
|
||||
// RevertCommit 撤回指定提交(创建一个反向提交)
|
||||
func (g *GitClient) RevertCommit(path, hash string) (string, error) {
|
||||
return g.Run(path, "revert", "--no-edit", hash)
|
||||
}
|
||||
|
||||
// BranchList 获取所有本地分支
|
||||
func (g *GitClient) BranchList(path string) (string, error) {
|
||||
return g.Run(path, "branch", "--format=%(refname:short)\t%(HEAD)")
|
||||
|
||||
Reference in New Issue
Block a user