增加团队管理页面

This commit is contained in:
dengqichen 2025-10-30 10:53:39 +08:00
parent e087b6abd8
commit f60bcf704b
6 changed files with 76 additions and 61 deletions

View File

@ -38,7 +38,6 @@ import {
ChevronDown,
ExternalLink,
Shield,
Code2,
Calendar,
User,
@ -379,26 +378,14 @@ const GitManager: React.FC = () => {
// 选中仓库组(支持反选取消)
const handleSelectGroup = useCallback((group: RepositoryGroupResponse) => {
// 如果点击的是已选中的组,则取消选择
setSelectedGroup((prev) => {
const newGroup = prev?.id === group.id ? undefined : group;
setSelectedProject(undefined);
setBranches([]);
// 加载项目列表,如果取消选择则不传 repoGroupId加载所有项目
loadProjects(newGroup?.repoGroupId || newGroup?.id);
return newGroup;
});
}, [loadProjects]);
setSelectedGroup((prev) => prev?.id === group.id ? undefined : group);
}, []);
// 选中项目(支持反选取消)
const handleSelectProject = useCallback((project: RepositoryProjectResponse) => {
// 如果点击的是已选中的项目,则取消选择
setSelectedProject((prev) => {
const newProject = prev?.id === project.id ? undefined : project;
// 加载分支列表,如果取消选择则不传 repoProjectId加载所有分支
loadBranches(newProject?.repoProjectId || newProject?.id);
return newProject;
});
}, [loadBranches]);
setSelectedProject((prev) => prev?.id === project.id ? undefined : project);
}, []);
// 格式化时间
const formatTime = useCallback((time?: string) => {
@ -571,6 +558,7 @@ const GitManager: React.FC = () => {
loadInstancesEffect();
}, [selectedInstanceId, toast]);
// 监听实例变化
useEffect(() => {
if (selectedInstanceId) {
loadGroupTree();
@ -581,6 +569,26 @@ const GitManager: React.FC = () => {
}
}, [selectedInstanceId, loadGroupTree]);
// 监听仓库组加载完成 或 仓库组选择变化,自动加载项目列表
useEffect(() => {
// 只有当仓库组不在加载中时才加载项目
if (selectedInstanceId && !loading.groups) {
setSelectedProject(undefined);
setBranches([]);
// 如果选择了组传递repoGroupId否则不传加载所有项目
loadProjects(selectedGroup?.repoGroupId || selectedGroup?.id);
}
}, [loading.groups, selectedInstanceId, selectedGroup, loadProjects]);
// 监听项目加载完成 或 项目选择变化,自动加载分支列表
useEffect(() => {
// 只有当项目不在加载中时才加载分支
if (selectedInstanceId && !loading.projects) {
// 如果选择了项目传递repoProjectId否则不传加载所有分支
loadBranches(selectedProject?.repoProjectId || selectedProject?.id);
}
}, [loading.projects, selectedInstanceId, selectedProject, loadBranches]);
const filteredGroupTree = useMemo(() => filterGroupTree(groupTree), [groupTree, filterGroupTree]);
return (
@ -910,24 +918,11 @@ const GitManager: React.FC = () => {
</TooltipContent>
</Tooltip>
)}
{branch.isProtected && (
<Tooltip>
<TooltipTrigger asChild>
<Badge variant="secondary" className="text-xs flex items-center gap-1 cursor-help">
<Shield className="h-3 w-3" />
</Badge>
</TooltipTrigger>
<TooltipContent>
<p></p>
</TooltipContent>
</Tooltip>
)}
</div>
{branch.lastCommitMessage && (
{branch.commitMessage && (
<p className="text-xs text-muted-foreground mt-1 line-clamp-2">
<GitCommit className="h-3 w-3 inline mr-1" />
{branch.lastCommitMessage}
{branch.commitMessage}
</p>
)}
{(branch.commitAuthor || branch.commitDate) && (

View File

@ -71,17 +71,27 @@ export const syncRepositoryProjects = (externalSystemId: number, repoGroupId?: n
// ==================== 仓库分支 ====================
/**
*
*
*/
export const getRepositoryBranches = (params?: RepositoryBranchQuery) =>
request.get<RepositoryBranchResponse[]>(`${BRANCH_URL}/list`, { params });
request.get<RepositoryBranchResponse[]>(`${BRANCH_URL}/list`, {
params: {
...params,
sortField: 'lastUpdateTime',
sortOrder: 'desc'
}
});
/**
* ID获取分支列表
* ID获取分支列表
*/
export const getBranchesByProjectId = (repoProjectId: number) =>
request.get<RepositoryBranchResponse[]>(`${BRANCH_URL}/list`, {
params: { repoProjectId },
params: {
repoProjectId,
sortField: 'lastUpdateTime',
sortOrder: 'desc'
},
});
/**

View File

@ -74,8 +74,6 @@ export interface RepositoryBranchResponse extends BaseResponse {
name: string;
/** 是否为默认分支 */
isDefaultBranch?: boolean;
/** 是否受保护 */
isProtected?: boolean;
/** 是否可推送 */
canPush?: boolean;
/** 开发者是否可推送 */
@ -84,15 +82,19 @@ export interface RepositoryBranchResponse extends BaseResponse {
developersCanMerge?: boolean;
/** 最后提交ID */
lastCommitId?: string;
/** 最后提交信息 */
lastCommitMessage?: string;
/** 提交信息 */
commitMessage?: string;
/** 提交作者 */
commitAuthor?: string;
/** 提交日期 */
commitDate?: string;
/** 最后更新时间 */
lastUpdateTime?: string;
/** 网页URL */
webUrl?: string;
/** 所属项目ID */
/** 项目ID */
projectId?: number;
/** 所属项目ID外部系统中的项目ID */
repoProjectId: number;
/** 外部系统ID */
externalSystemId: number;

View File

@ -309,23 +309,25 @@ const JenkinsManager: React.FC = () => {
}
}, [selectedInstanceId, loadViews]);
// 监听视图选择变化
useEffect(() => {
if (selectedInstanceId) {
// 监听视图加载完成 或 视图选择变化,自动加载任务列表
useEffect(() => {
// 只有当视图不在加载中时才加载任务
if (selectedInstanceId && !loading.views) {
setSelectedJob(undefined);
setBuilds([]);
// 如果选择了视图传递viewId否则不传加载所有任务
loadJobs(selectedView?.id);
}
}, [selectedView, selectedInstanceId, loadJobs]);
}, [loading.views, selectedInstanceId, selectedView, loadJobs]);
// 监听任务选择变化
// 监听任务加载完成 或 任务选择变化,自动加载构建列表
useEffect(() => {
if (selectedInstanceId) {
// 只有当任务不在加载中时才加载构建
if (selectedInstanceId && !loading.jobs) {
// 如果选择了任务传递jobId否则不传加载所有构建
loadBuilds(selectedJob?.id);
}
}, [selectedJob, selectedInstanceId, loadBuilds]);
}, [loading.jobs, selectedInstanceId, selectedJob, loadBuilds]);
// 过滤视图(使用防抖搜索值)
const filteredViews = useMemo(() => {

View File

@ -36,9 +36,15 @@ export const syncJenkinsJobs = (params: { externalSystemId: number; viewId?: num
// ==================== Jenkins 构建 ====================
// 获取构建列表
// 获取构建列表(按开始时间倒序排序)
export const getJenkinsBuilds = (params: { externalSystemId: number; jobId?: number }) =>
request.get<JenkinsBuildDTO[]>(`/api/v1/jenkins-build/list`, { params });
request.get<JenkinsBuildDTO[]>(`/api/v1/jenkins-build/list`, {
params: {
...params,
sortField: 'starttime',
sortOrder: 'desc'
}
});
// 同步构建根据jobId
export const syncJenkinsBuilds = (params: { externalSystemId: number; jobId?: number }) =>

View File

@ -282,8 +282,8 @@ const MemberManageDialog: React.FC<MemberManageDialogProps> = ({
</DialogTitle>
</DialogHeader>
<div className="flex-1 overflow-hidden flex flex-col px-6 pb-6">
<div className="space-y-4 flex-1 overflow-y-auto">
<div className="flex-1 overflow-hidden flex flex-col px-6 pb-6">
<div className="space-y-4 flex-1 overflow-y-auto">
{/* 操作栏 */}
<div className="flex items-center gap-2">
<div className="relative flex-1">
@ -358,8 +358,8 @@ const MemberManageDialog: React.FC<MemberManageDialogProps> = ({
</>
) : (
<>
<Plus className="h-4 w-4 mr-2" />
<Plus className="h-4 w-4 mr-2" />
</>
)}
</Button>
@ -451,8 +451,8 @@ const MemberManageDialog: React.FC<MemberManageDialogProps> = ({
</div>
)}
</div>
</div>
</div>
</div>
</DialogContent>
</Dialog>
@ -469,8 +469,8 @@ const MemberManageDialog: React.FC<MemberManageDialogProps> = ({
</div>
<div className="space-y-2">
<label className="text-sm font-medium"></label>
<Input
placeholder="请输入团队角色,如:开发、测试、产品经理等"
<Input
placeholder="请输入团队角色,如:开发、测试、产品经理等"
value={editRole}
onChange={(e) => setEditRole(e.target.value)}
/>
@ -478,12 +478,12 @@ const MemberManageDialog: React.FC<MemberManageDialogProps> = ({
</div>
<div className="flex justify-end gap-2">
<Button variant="outline" onClick={() => setEditDialogOpen(false)}>
</Button>
</Button>
<Button onClick={handleEditSave}>
</Button>
</div>
</Button>
</div>
</DialogContent>
</Dialog>