feat(git): 在面板中显示当前Git分支并改进布局
- 新增获取当前分支的API接口和前端状态管理 - 在Git面板顶部显示当前分支名称和图标 - 重新组织操作按钮布局,将远程仓库和刷新按钮移至顶部工具栏 - 为状态列表添加文件数量统计 - 优化响应式布局,使拉取/推送按钮等宽显示
This commit is contained in:
parent
44a2c54da3
commit
18db27a22c
|
|
@ -176,6 +176,10 @@ window.services = {
|
||||||
return this.execGit("-c core.quotePath=false status --short", dirPath);
|
return this.execGit("-c core.quotePath=false status --short", dirPath);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async gitBranch(dirPath) {
|
||||||
|
return this.execGit("branch --show-current", dirPath);
|
||||||
|
},
|
||||||
|
|
||||||
async gitAdd(dirPath, files = ".") {
|
async gitAdd(dirPath, files = ".") {
|
||||||
return this.execGit(`add ${files}`, dirPath);
|
return this.execGit(`add ${files}`, dirPath);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -5,28 +5,39 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else class="git-content">
|
<div v-else class="git-content">
|
||||||
|
<div class="git-header">
|
||||||
|
<div class="git-branch" v-if="state.branch">
|
||||||
|
<BranchesOutlined />
|
||||||
|
<span class="branch-name">{{ state.branch }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="git-toolbar">
|
||||||
|
<a-button @click="openRemoteUrl" :disabled="!state.remoteUrl" title="打开 Git 仓库" size="small">
|
||||||
|
<template #icon><GithubOutlined /></template>
|
||||||
|
</a-button>
|
||||||
|
<a-button @click="handleRefresh" :loading="state.loading" size="small">
|
||||||
|
<template #icon><ReloadOutlined /></template>
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="git-actions">
|
<div class="git-actions">
|
||||||
<a-button-group>
|
<a-button-group class="action-group">
|
||||||
<a-button @click="handlePull" :loading="state.loading">
|
<a-button @click="handlePull" :loading="state.loading" block>
|
||||||
<template #icon><ArrowDownOutlined /></template>
|
<template #icon><ArrowDownOutlined /></template>
|
||||||
拉取
|
拉取
|
||||||
</a-button>
|
</a-button>
|
||||||
<a-button @click="handlePush" :loading="state.loading">
|
<a-button @click="handlePush" :loading="state.loading" block>
|
||||||
<template #icon><ArrowUpOutlined /></template>
|
<template #icon><ArrowUpOutlined /></template>
|
||||||
推送
|
推送
|
||||||
</a-button>
|
</a-button>
|
||||||
<a-button @click="openRemoteUrl" :disabled="!state.remoteUrl" title="打开 Git 仓库">
|
|
||||||
<template #icon><GithubOutlined /></template>
|
|
||||||
</a-button>
|
|
||||||
</a-button-group>
|
</a-button-group>
|
||||||
|
|
||||||
<a-button @click="handleRefresh" :loading="state.loading">
|
|
||||||
<template #icon><ReloadOutlined /></template>
|
|
||||||
</a-button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="git-status">
|
<div class="git-status">
|
||||||
<h3>状态</h3>
|
<div class="status-header">
|
||||||
|
<h3>状态</h3>
|
||||||
|
<span class="status-count" v-if="state.statusFiles.length">{{ state.statusFiles.length }}</span>
|
||||||
|
</div>
|
||||||
<div class="status-list" v-if="state.statusFiles.length > 0">
|
<div class="status-list" v-if="state.statusFiles.length > 0">
|
||||||
<div v-for="(file, index) in state.statusFiles" :key="index" class="status-item">
|
<div v-for="(file, index) in state.statusFiles" :key="index" class="status-item">
|
||||||
<span class="status-badge" :class="getStatusClass(file.status)">{{ file.status }}</span>
|
<span class="status-badge" :class="getStatusClass(file.status)">{{ file.status }}</span>
|
||||||
|
|
@ -60,7 +71,7 @@
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, watch } from 'vue';
|
import { ref, onMounted, watch } from 'vue';
|
||||||
import { ArrowDownOutlined, ArrowUpOutlined, ReloadOutlined, GithubOutlined } from '@ant-design/icons-vue';
|
import { ArrowDownOutlined, ArrowUpOutlined, ReloadOutlined, GithubOutlined, BranchesOutlined } from '@ant-design/icons-vue';
|
||||||
import { useGit } from '../composables/useGit';
|
import { useGit } from '../composables/useGit';
|
||||||
import { useFileTree } from '../composables/useFileTree';
|
import { useFileTree } from '../composables/useFileTree';
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
|
|
@ -143,16 +154,66 @@ const getStatusClass = (status) => {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.git-actions {
|
.git-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
border-bottom: 1px solid var(--border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.git-branch {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-weight: bold;
|
||||||
|
color: var(--primary-color, #1890ff);
|
||||||
|
}
|
||||||
|
|
||||||
|
.branch-name {
|
||||||
|
margin-left: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.git-toolbar {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.git-actions {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.action-group {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-group .ant-btn {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
.git-status {
|
.git-status {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.status-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-header h3 {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-count {
|
||||||
|
background-color: var(--border-color);
|
||||||
|
padding: 2px 6px;
|
||||||
|
border-radius: 10px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
.status-list {
|
.status-list {
|
||||||
border: 1px solid var(--border-color);
|
border: 1px solid var(--border-color);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ const state = reactive({
|
||||||
statusOutput: '',
|
statusOutput: '',
|
||||||
statusFiles: [],
|
statusFiles: [],
|
||||||
remoteUrl: '',
|
remoteUrl: '',
|
||||||
|
branch: '',
|
||||||
loading: false
|
loading: false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -17,6 +18,18 @@ export function useGit() {
|
||||||
// 自动获取一次状态
|
// 自动获取一次状态
|
||||||
await getStatus(rootDir);
|
await getStatus(rootDir);
|
||||||
await getRemoteUrl(rootDir);
|
await getRemoteUrl(rootDir);
|
||||||
|
await getBranch(rootDir);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getBranch = async (rootDir) => {
|
||||||
|
try {
|
||||||
|
const res = await window.services.gitBranch(rootDir);
|
||||||
|
if (res.success) {
|
||||||
|
state.branch = res.stdout.trim();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Failed to get branch", e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -97,6 +110,7 @@ export function useGit() {
|
||||||
checkGitRepo,
|
checkGitRepo,
|
||||||
getStatus,
|
getStatus,
|
||||||
getRemoteUrl,
|
getRemoteUrl,
|
||||||
|
getBranch,
|
||||||
openRemoteUrl,
|
openRemoteUrl,
|
||||||
commit,
|
commit,
|
||||||
push,
|
push,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue