增加团队管理页面
This commit is contained in:
parent
e087b6abd8
commit
f60bcf704b
@ -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) && (
|
||||
|
||||
@ -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'
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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(() => {
|
||||
|
||||
@ -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 }) =>
|
||||
|
||||
@ -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>
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user