forked from admin/hair-keeper
feat: 开发者面板页面git工具支持推送远程仓库
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { GitBranch, GitCommit as GitCommitIcon, CornerRightUp, RotateCcw, AlertTriangle, RefreshCw, GitCommit } from 'lucide-react'
|
import { GitBranch, GitCommit as GitCommitIcon, CornerRightUp, RotateCcw, AlertTriangle, RefreshCw, GitCommit, Upload } from 'lucide-react'
|
||||||
import { Button } from '@/components/ui/button'
|
import { Button } from '@/components/ui/button'
|
||||||
import { Separator } from '@/components/ui/separator'
|
import { Separator } from '@/components/ui/separator'
|
||||||
import { trpc } from '@/lib/trpc'
|
import { trpc } from '@/lib/trpc'
|
||||||
@@ -73,7 +73,7 @@ export function VersionControl({ isOpen }: { isOpen: boolean }) {
|
|||||||
const [isLoadingMore, setIsLoadingMore] = React.useState(false)
|
const [isLoadingMore, setIsLoadingMore] = React.useState(false)
|
||||||
const [commitType, setCommitType] = React.useState<'normal' | 'amend' | null>(null)
|
const [commitType, setCommitType] = React.useState<'normal' | 'amend' | null>(null)
|
||||||
const [confirmAction, setConfirmAction] = React.useState<{
|
const [confirmAction, setConfirmAction] = React.useState<{
|
||||||
type: 'checkout' | 'checkout-branch' | 'revert' | 'reset'
|
type: 'checkout' | 'checkout-branch' | 'revert' | 'reset' | 'push'
|
||||||
commitId?: string
|
commitId?: string
|
||||||
message?: string
|
message?: string
|
||||||
title?: string
|
title?: string
|
||||||
@@ -191,6 +191,17 @@ export function VersionControl({ isOpen }: { isOpen: boolean }) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 推送远程仓库mutation
|
||||||
|
const pushToRemoteMutation = trpc.devPanel!.pushToRemote.useMutation({
|
||||||
|
onSuccess: (data) => {
|
||||||
|
toast.success(data.message)
|
||||||
|
setConfirmAction(null)
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
toast.error(error.message)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
// 处理分支选择(仅用于查看历史,不切换实际分支)
|
// 处理分支选择(仅用于查看历史,不切换实际分支)
|
||||||
const handleBranchChange = (branchName: string | null) => {
|
const handleBranchChange = (branchName: string | null) => {
|
||||||
if (!branchName) return
|
if (!branchName) return
|
||||||
@@ -306,9 +317,21 @@ export function VersionControl({ isOpen }: { isOpen: boolean }) {
|
|||||||
resetToCommitMutation.mutate({ commitId: confirmAction.commitId })
|
resetToCommitMutation.mutate({ commitId: confirmAction.commitId })
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
|
case 'push':
|
||||||
|
pushToRemoteMutation.mutate({ branchName: selectedBranch })
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理推送远程仓库
|
||||||
|
const handlePushToRemote = () => {
|
||||||
|
setConfirmAction({
|
||||||
|
type: 'push',
|
||||||
|
title: '推送到远程仓库',
|
||||||
|
description: `确定要将分支 "${selectedBranch}" 的最新提交推送到远程仓库吗?`,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// 手动刷新所有数据
|
// 手动刷新所有数据
|
||||||
const handleRefresh = () => {
|
const handleRefresh = () => {
|
||||||
refetchBranches()
|
refetchBranches()
|
||||||
@@ -357,7 +380,7 @@ export function VersionControl({ isOpen }: { isOpen: boolean }) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 右半部分:Commit按钮和刷新按钮 */}
|
{/* 右半部分:Commit按钮、推送按钮和刷新按钮 */}
|
||||||
<div className="flex items-center gap-2 flex-1 justify-end">
|
<div className="flex items-center gap-2 flex-1 justify-end">
|
||||||
<Button
|
<Button
|
||||||
onClick={() => setShowCommitDialog(true)}
|
onClick={() => setShowCommitDialog(true)}
|
||||||
@@ -367,6 +390,16 @@ export function VersionControl({ isOpen }: { isOpen: boolean }) {
|
|||||||
<GitCommit className="mr-2 h-4 w-4" />
|
<GitCommit className="mr-2 h-4 w-4" />
|
||||||
提交更改
|
提交更改
|
||||||
</Button>
|
</Button>
|
||||||
|
{selectedBranch && !selectedBranch.startsWith('origin/') && (
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
onClick={handlePushToRemote}
|
||||||
|
disabled={pushToRemoteMutation.isPending}
|
||||||
|
title="推送到远程仓库"
|
||||||
|
>
|
||||||
|
<Upload className={cn("h-4 w-4", pushToRemoteMutation.isPending && "animate-pulse")} />
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
onClick={handleRefresh}
|
onClick={handleRefresh}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import {
|
|||||||
resetToCommit,
|
resetToCommit,
|
||||||
getCurrentBranch,
|
getCurrentBranch,
|
||||||
hasUncommittedChanges,
|
hasUncommittedChanges,
|
||||||
|
pushToRemote,
|
||||||
} from '@/server/utils/git-helper'
|
} from '@/server/utils/git-helper'
|
||||||
|
|
||||||
|
|
||||||
@@ -224,6 +225,25 @@ export const devPanelRouter = createTRPCRouter({
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 推送分支到远程仓库
|
||||||
|
*/
|
||||||
|
pushToRemote: permissionRequiredProcedure('SUPER_ADMIN_ONLY')
|
||||||
|
.input(z.object({
|
||||||
|
branchName: z.string().min(1, '分支名称不能为空'),
|
||||||
|
}))
|
||||||
|
.mutation(async ({ input }) => {
|
||||||
|
try {
|
||||||
|
await pushToRemote(input.branchName)
|
||||||
|
return { success: true, message: `已推送分支 ${input.branchName} 到远程仓库` }
|
||||||
|
} catch (error: any) {
|
||||||
|
throw new TRPCError({
|
||||||
|
code: 'INTERNAL_SERVER_ERROR',
|
||||||
|
message: `推送失败: ${error.message}`,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
export type DevPanelRouter = typeof devPanelRouter
|
export type DevPanelRouter = typeof devPanelRouter
|
||||||
@@ -632,3 +632,19 @@ export async function hasUncommittedChanges(): Promise<boolean> {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 推送当前分支到远程仓库
|
||||||
|
* @param branchName 分支名称
|
||||||
|
*/
|
||||||
|
export async function pushToRemote(branchName: string): Promise<void> {
|
||||||
|
try {
|
||||||
|
await execAsync(`git push origin "${branchName}"`, {
|
||||||
|
cwd: process.cwd(),
|
||||||
|
encoding: 'utf-8',
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
console.error('推送到远程仓库失败:', error)
|
||||||
|
throw new Error(`无法推送到远程仓库: ${error instanceof Error ? error.message : String(error)}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user