增加图标展示,区分清楚项目类型
This commit is contained in:
parent
456a4bede2
commit
d65e82b0e8
@ -171,6 +171,37 @@ const SelectItem = React.forwardRef<
|
|||||||
))
|
))
|
||||||
SelectItem.displayName = SelectPrimitive.Item.displayName
|
SelectItem.displayName = SelectPrimitive.Item.displayName
|
||||||
|
|
||||||
|
// 支持副标题的选项组件
|
||||||
|
interface SelectItemWithDescriptionProps extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item> {
|
||||||
|
label: string;
|
||||||
|
description?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SelectItemWithDescription = React.forwardRef<
|
||||||
|
React.ElementRef<typeof SelectPrimitive.Item>,
|
||||||
|
SelectItemWithDescriptionProps
|
||||||
|
>(({ className, label, description, ...props }, ref) => (
|
||||||
|
<SelectPrimitive.Item
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"relative flex w-full cursor-default select-none flex-col items-start rounded-sm py-2 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<span className="absolute right-2 top-2 flex h-3.5 w-3.5 items-center justify-center">
|
||||||
|
<SelectPrimitive.ItemIndicator>
|
||||||
|
<Check className="h-4 w-4" />
|
||||||
|
</SelectPrimitive.ItemIndicator>
|
||||||
|
</span>
|
||||||
|
<SelectPrimitive.ItemText className="font-medium">{label}</SelectPrimitive.ItemText>
|
||||||
|
{description && (
|
||||||
|
<span className="text-xs text-muted-foreground mt-0.5">{description}</span>
|
||||||
|
)}
|
||||||
|
</SelectPrimitive.Item>
|
||||||
|
))
|
||||||
|
SelectItemWithDescription.displayName = "SelectItemWithDescription"
|
||||||
|
|
||||||
const SelectSeparator = React.forwardRef<
|
const SelectSeparator = React.forwardRef<
|
||||||
React.ElementRef<typeof SelectPrimitive.Separator>,
|
React.ElementRef<typeof SelectPrimitive.Separator>,
|
||||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
|
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
|
||||||
@ -225,6 +256,7 @@ export {
|
|||||||
SelectContent,
|
SelectContent,
|
||||||
SelectLabel,
|
SelectLabel,
|
||||||
SelectItem,
|
SelectItem,
|
||||||
|
SelectItemWithDescription,
|
||||||
SelectSeparator,
|
SelectSeparator,
|
||||||
SelectScrollUpButton,
|
SelectScrollUpButton,
|
||||||
SelectScrollDownButton,
|
SelectScrollDownButton,
|
||||||
|
|||||||
57
frontend/src/pages/Dashboard/utils/languageIcons.tsx
Normal file
57
frontend/src/pages/Dashboard/utils/languageIcons.tsx
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import {
|
||||||
|
CodeOutlined,
|
||||||
|
JavaOutlined,
|
||||||
|
NodeIndexOutlined,
|
||||||
|
PythonOutlined,
|
||||||
|
} from '@ant-design/icons';
|
||||||
|
import { DevelopmentLanguageTypeEnum } from '@/pages/Deploy/Application/List/types';
|
||||||
|
|
||||||
|
interface LanguageIconConfig {
|
||||||
|
icon: React.ReactNode;
|
||||||
|
color: string;
|
||||||
|
label: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 语言图标配置映射(与 /deploy/applications 保持一致)
|
||||||
|
*/
|
||||||
|
export const LANGUAGE_ICONS: Record<DevelopmentLanguageTypeEnum, LanguageIconConfig> = {
|
||||||
|
JAVA: {
|
||||||
|
icon: <JavaOutlined />,
|
||||||
|
color: '#E76F00',
|
||||||
|
label: 'Java'
|
||||||
|
},
|
||||||
|
NODE_JS: {
|
||||||
|
icon: <NodeIndexOutlined />,
|
||||||
|
color: '#339933',
|
||||||
|
label: 'NodeJS'
|
||||||
|
},
|
||||||
|
PYTHON: {
|
||||||
|
icon: <PythonOutlined />,
|
||||||
|
color: '#3776AB',
|
||||||
|
label: 'Python'
|
||||||
|
},
|
||||||
|
GO: {
|
||||||
|
icon: <CodeOutlined />,
|
||||||
|
color: '#00ADD8',
|
||||||
|
label: 'Go'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取语言图标配置
|
||||||
|
*/
|
||||||
|
export const getLanguageIcon = (language?: DevelopmentLanguageTypeEnum): LanguageIconConfig => {
|
||||||
|
if (!language) {
|
||||||
|
return {
|
||||||
|
icon: <CodeOutlined />,
|
||||||
|
color: '#666666',
|
||||||
|
label: '未知'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return LANGUAGE_ICONS[language] || {
|
||||||
|
icon: <CodeOutlined />,
|
||||||
|
color: '#666666',
|
||||||
|
label: language
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -0,0 +1,254 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import { Label } from '@/components/ui/label';
|
||||||
|
import { Input } from '@/components/ui/input';
|
||||||
|
import { Button } from '@/components/ui/button';
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from '@/components/ui/select';
|
||||||
|
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
|
||||||
|
import { ScrollArea } from '@/components/ui/scroll-area';
|
||||||
|
import { Search, Check, ChevronDown } from 'lucide-react';
|
||||||
|
import { cn } from '@/lib/utils';
|
||||||
|
import type { RepositoryBranchResponse } from '@/pages/Resource/Git/List/types';
|
||||||
|
|
||||||
|
interface GitConfigSelectorProps {
|
||||||
|
label: string; // "源" 或 "目标"
|
||||||
|
// Git系统
|
||||||
|
gitSystems: any[];
|
||||||
|
selectedSystemId: number | null;
|
||||||
|
onSystemChange: (systemId: number) => void;
|
||||||
|
// 仓库项目
|
||||||
|
repoProjects: any[];
|
||||||
|
loadingRepoProjects: boolean;
|
||||||
|
selectedProjectId: number | null;
|
||||||
|
onProjectChange: (projectId: number) => void;
|
||||||
|
// 分支
|
||||||
|
branches: RepositoryBranchResponse[];
|
||||||
|
loadingBranches: boolean;
|
||||||
|
selectedBranch: string;
|
||||||
|
onBranchChange: (branch: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const GitConfigSelector: React.FC<GitConfigSelectorProps> = ({
|
||||||
|
label,
|
||||||
|
gitSystems,
|
||||||
|
selectedSystemId,
|
||||||
|
onSystemChange,
|
||||||
|
repoProjects,
|
||||||
|
loadingRepoProjects,
|
||||||
|
selectedProjectId,
|
||||||
|
onProjectChange,
|
||||||
|
branches,
|
||||||
|
loadingBranches,
|
||||||
|
selectedBranch,
|
||||||
|
onBranchChange,
|
||||||
|
}) => {
|
||||||
|
const [projectSearchValue, setProjectSearchValue] = useState('');
|
||||||
|
const [projectPopoverOpen, setProjectPopoverOpen] = useState(false);
|
||||||
|
const [branchSearchValue, setBranchSearchValue] = useState('');
|
||||||
|
const [branchPopoverOpen, setBranchPopoverOpen] = useState(false);
|
||||||
|
|
||||||
|
// 过滤分支
|
||||||
|
const filteredBranches = branches.filter(branch =>
|
||||||
|
branch.name.toLowerCase().includes(branchSearchValue.toLowerCase())
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label className="text-sm font-semibold">{label}Git配置</Label>
|
||||||
|
<div className="grid grid-cols-3 gap-4">
|
||||||
|
{/* 代码系统 */}
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label className="text-xs text-muted-foreground">{label}代码系统</Label>
|
||||||
|
<Select
|
||||||
|
value={selectedSystemId?.toString() || ''}
|
||||||
|
onValueChange={(value) => onSystemChange(Number(value))}
|
||||||
|
>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="选择系统" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{gitSystems.length === 0 ? (
|
||||||
|
<div className="p-4 text-center text-sm text-muted-foreground">
|
||||||
|
暂无可用的Git系统
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
gitSystems.map((system) => (
|
||||||
|
<SelectItem key={system.id} value={system.id.toString()}>
|
||||||
|
{system.name}
|
||||||
|
</SelectItem>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 仓库项目 */}
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label className="text-xs text-muted-foreground">{label}仓库项目</Label>
|
||||||
|
{selectedSystemId ? (
|
||||||
|
<Popover open={projectPopoverOpen} onOpenChange={setProjectPopoverOpen}>
|
||||||
|
<PopoverTrigger asChild>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
role="combobox"
|
||||||
|
disabled={loadingRepoProjects || repoProjects.length === 0}
|
||||||
|
className={cn(
|
||||||
|
'w-full justify-between',
|
||||||
|
!selectedProjectId && 'text-muted-foreground'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{selectedProjectId
|
||||||
|
? (() => {
|
||||||
|
const selectedProject = repoProjects.find(
|
||||||
|
(p) => p.repoProjectId === selectedProjectId
|
||||||
|
);
|
||||||
|
return selectedProject
|
||||||
|
? (selectedProject.repoGroupName
|
||||||
|
? `${selectedProject.repoGroupName} / ${selectedProject.name}`
|
||||||
|
: selectedProject.name)
|
||||||
|
: '选择项目';
|
||||||
|
})()
|
||||||
|
: loadingRepoProjects
|
||||||
|
? '加载中...'
|
||||||
|
: repoProjects.length === 0
|
||||||
|
? '暂无项目'
|
||||||
|
: '选择项目'}
|
||||||
|
<ChevronDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||||
|
</Button>
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent className="w-[var(--radix-popover-trigger-width)] p-0">
|
||||||
|
<div className="flex items-center border-b px-3">
|
||||||
|
<Search className="mr-2 h-4 w-4 shrink-0 opacity-50" />
|
||||||
|
<input
|
||||||
|
placeholder="搜索项目..."
|
||||||
|
className="flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground"
|
||||||
|
value={projectSearchValue}
|
||||||
|
onChange={(e) => setProjectSearchValue(e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<ScrollArea className="h-[200px]">
|
||||||
|
<div className="p-1">
|
||||||
|
{repoProjects
|
||||||
|
.filter(
|
||||||
|
(project) =>
|
||||||
|
project.name.toLowerCase().includes(projectSearchValue.toLowerCase()) ||
|
||||||
|
project.repoGroupName?.toLowerCase().includes(projectSearchValue.toLowerCase())
|
||||||
|
)
|
||||||
|
.map((project) => (
|
||||||
|
<div
|
||||||
|
key={project.repoProjectId}
|
||||||
|
className={cn(
|
||||||
|
'relative flex cursor-pointer select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground',
|
||||||
|
project.repoProjectId === selectedProjectId && 'bg-accent text-accent-foreground'
|
||||||
|
)}
|
||||||
|
onClick={() => {
|
||||||
|
onProjectChange(project.repoProjectId);
|
||||||
|
setProjectSearchValue('');
|
||||||
|
setProjectPopoverOpen(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="flex-1 truncate">
|
||||||
|
{project.repoGroupName && (
|
||||||
|
<span className="text-muted-foreground">{project.repoGroupName} / </span>
|
||||||
|
)}
|
||||||
|
{project.name}
|
||||||
|
</div>
|
||||||
|
{project.repoProjectId === selectedProjectId && <Check className="ml-2 h-4 w-4" />}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</ScrollArea>
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
) : (
|
||||||
|
<Input placeholder="请先选择系统" disabled />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 分支 */}
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label className="text-xs text-muted-foreground">{label}分支</Label>
|
||||||
|
{selectedProjectId ? (
|
||||||
|
<Popover open={branchPopoverOpen} onOpenChange={setBranchPopoverOpen}>
|
||||||
|
<PopoverTrigger asChild>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
role="combobox"
|
||||||
|
disabled={loadingBranches || branches.length === 0}
|
||||||
|
className={cn('w-full justify-between', !selectedBranch && 'text-muted-foreground')}
|
||||||
|
>
|
||||||
|
{selectedBranch
|
||||||
|
? (() => {
|
||||||
|
const selectedBranchObj = branches.find((b) => b.name === selectedBranch);
|
||||||
|
return (
|
||||||
|
<span className="flex items-center gap-2 truncate">
|
||||||
|
{selectedBranchObj?.name}
|
||||||
|
{selectedBranchObj?.isDefaultBranch && (
|
||||||
|
<span className="text-xs text-muted-foreground">(默认)</span>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
})()
|
||||||
|
: loadingBranches
|
||||||
|
? '加载中...'
|
||||||
|
: branches.length === 0
|
||||||
|
? '无分支'
|
||||||
|
: '选择分支'}
|
||||||
|
<ChevronDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||||
|
</Button>
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent className="w-full p-0">
|
||||||
|
<div className="flex items-center border-b px-3">
|
||||||
|
<Search className="mr-2 h-4 w-4 shrink-0 opacity-50" />
|
||||||
|
<input
|
||||||
|
placeholder="搜索分支..."
|
||||||
|
className="flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground"
|
||||||
|
value={branchSearchValue}
|
||||||
|
onChange={(e) => setBranchSearchValue(e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<ScrollArea className="h-[200px]">
|
||||||
|
<div className="p-1">
|
||||||
|
{filteredBranches.length === 0 ? (
|
||||||
|
<div className="p-4 text-center text-sm text-muted-foreground">未找到分支</div>
|
||||||
|
) : (
|
||||||
|
filteredBranches.map((branch) => (
|
||||||
|
<div
|
||||||
|
key={branch.id}
|
||||||
|
className={cn(
|
||||||
|
'relative flex cursor-pointer select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent',
|
||||||
|
branch.name === selectedBranch && 'bg-accent'
|
||||||
|
)}
|
||||||
|
onClick={() => {
|
||||||
|
onBranchChange(branch.name);
|
||||||
|
setBranchSearchValue('');
|
||||||
|
setBranchPopoverOpen(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span className="flex-1 truncate">
|
||||||
|
{branch.name}
|
||||||
|
{branch.isDefaultBranch && (
|
||||||
|
<span className="ml-2 text-xs text-muted-foreground">(默认)</span>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
{branch.name === selectedBranch && <Check className="ml-2 h-4 w-4" />}
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</ScrollArea>
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
) : (
|
||||||
|
<Input placeholder="请先选择项目" disabled />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -32,6 +32,7 @@ import type { RepositoryBranchResponse } from '@/pages/Resource/Git/List/types';
|
|||||||
import type { WorkflowDefinition } from '@/pages/Workflow/Definition/List/types';
|
import type { WorkflowDefinition } from '@/pages/Workflow/Definition/List/types';
|
||||||
import { getExternalSystemList } from '@/pages/Resource/External/List/service';
|
import { getExternalSystemList } from '@/pages/Resource/External/List/service';
|
||||||
import { getRepositoryProjectsList, getRepositoryBranchesList } from '@/pages/Resource/Git/List/service';
|
import { getRepositoryProjectsList, getRepositoryBranchesList } from '@/pages/Resource/Git/List/service';
|
||||||
|
import { GitConfigSelector } from './GitConfigSelector';
|
||||||
|
|
||||||
interface TeamApplicationDialogProps {
|
interface TeamApplicationDialogProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
@ -39,6 +40,7 @@ interface TeamApplicationDialogProps {
|
|||||||
teamId: number;
|
teamId: number;
|
||||||
environmentId: number;
|
environmentId: number;
|
||||||
environmentName: string;
|
environmentName: string;
|
||||||
|
enableGitSyncCheck: boolean; // 🆕 团队是否启用Git同步检测
|
||||||
application?: TeamApplication; // 编辑时传入
|
application?: TeamApplication; // 编辑时传入
|
||||||
applications: Application[]; // 可选择的应用列表
|
applications: Application[]; // 可选择的应用列表
|
||||||
jenkinsSystems: any[];
|
jenkinsSystems: any[];
|
||||||
@ -55,6 +57,9 @@ interface TeamApplicationDialogProps {
|
|||||||
workflowDefinitionId: number | null;
|
workflowDefinitionId: number | null;
|
||||||
codeSourceSystemId: number | null;
|
codeSourceSystemId: number | null;
|
||||||
codeSourceProjectId: number | null;
|
codeSourceProjectId: number | null;
|
||||||
|
targetGitSystemId: number | null; // 🆕 目标Git系统ID
|
||||||
|
targetGitProjectId: number | null; // 🆕 目标Git项目ID
|
||||||
|
targetBranch: string; // 🆕 目标分支
|
||||||
}) => Promise<void>;
|
}) => Promise<void>;
|
||||||
onLoadBranches: (appId: number, app: Application) => Promise<RepositoryBranchResponse[]>;
|
onLoadBranches: (appId: number, app: Application) => Promise<RepositoryBranchResponse[]>;
|
||||||
onLoadJenkinsJobs: (systemId: number) => Promise<any[]>;
|
onLoadJenkinsJobs: (systemId: number) => Promise<any[]>;
|
||||||
@ -66,6 +71,7 @@ const TeamApplicationDialog: React.FC<TeamApplicationDialogProps> = ({
|
|||||||
teamId,
|
teamId,
|
||||||
environmentId,
|
environmentId,
|
||||||
environmentName,
|
environmentName,
|
||||||
|
enableGitSyncCheck,
|
||||||
application,
|
application,
|
||||||
applications,
|
applications,
|
||||||
jenkinsSystems,
|
jenkinsSystems,
|
||||||
@ -86,8 +92,11 @@ const TeamApplicationDialog: React.FC<TeamApplicationDialogProps> = ({
|
|||||||
deploySystemId: null as number | null,
|
deploySystemId: null as number | null,
|
||||||
deployJob: '',
|
deployJob: '',
|
||||||
workflowDefinitionId: null as number | null,
|
workflowDefinitionId: null as number | null,
|
||||||
codeSourceSystemId: null as number | null,
|
codeSourceSystemId: null as number | null, // 源代码系统ID
|
||||||
codeSourceProjectId: null as number | null,
|
codeSourceProjectId: null as number | null, // 源仓库项目ID
|
||||||
|
targetGitSystemId: null as number | null, // 🆕 目标Git系统ID
|
||||||
|
targetGitProjectId: null as number | null, // 🆕 目标Git项目ID
|
||||||
|
targetBranch: '', // 🆕 目标分支
|
||||||
});
|
});
|
||||||
|
|
||||||
// 加载状态
|
// 加载状态
|
||||||
@ -99,14 +108,15 @@ const TeamApplicationDialog: React.FC<TeamApplicationDialogProps> = ({
|
|||||||
const [gitSystems, setGitSystems] = useState<any[]>([]);
|
const [gitSystems, setGitSystems] = useState<any[]>([]);
|
||||||
const [repoProjects, setRepoProjects] = useState<any[]>([]);
|
const [repoProjects, setRepoProjects] = useState<any[]>([]);
|
||||||
const [loadingRepoProjects, setLoadingRepoProjects] = useState(false);
|
const [loadingRepoProjects, setLoadingRepoProjects] = useState(false);
|
||||||
|
// 🆕 目标Git相关状态
|
||||||
|
const [targetRepoProjects, setTargetRepoProjects] = useState<any[]>([]);
|
||||||
|
const [loadingTargetRepoProjects, setLoadingTargetRepoProjects] = useState(false);
|
||||||
|
const [targetBranches, setTargetBranches] = useState<RepositoryBranchResponse[]>([]);
|
||||||
|
const [loadingTargetBranches, setLoadingTargetBranches] = useState(false);
|
||||||
|
|
||||||
// 搜索和弹窗状态
|
// 搜索和弹窗状态
|
||||||
const [appSearchValue, setAppSearchValue] = useState('');
|
const [appSearchValue, setAppSearchValue] = useState('');
|
||||||
const [appPopoverOpen, setAppPopoverOpen] = useState(false);
|
const [appPopoverOpen, setAppPopoverOpen] = useState(false);
|
||||||
const [branchSearchValue, setBranchSearchValue] = useState('');
|
|
||||||
const [branchPopoverOpen, setBranchPopoverOpen] = useState(false);
|
|
||||||
const [projectSearchValue, setProjectSearchValue] = useState('');
|
|
||||||
const [projectPopoverOpen, setProjectPopoverOpen] = useState(false);
|
|
||||||
const [jobSearchValue, setJobSearchValue] = useState('');
|
const [jobSearchValue, setJobSearchValue] = useState('');
|
||||||
const [jobPopoverOpen, setJobPopoverOpen] = useState(false);
|
const [jobPopoverOpen, setJobPopoverOpen] = useState(false);
|
||||||
|
|
||||||
@ -124,14 +134,17 @@ const TeamApplicationDialog: React.FC<TeamApplicationDialogProps> = ({
|
|||||||
workflowDefinitionId: application.workflowDefinitionId || null,
|
workflowDefinitionId: application.workflowDefinitionId || null,
|
||||||
codeSourceSystemId: application.codeSourceSystemId || null,
|
codeSourceSystemId: application.codeSourceSystemId || null,
|
||||||
codeSourceProjectId: application.codeSourceProjectId || null,
|
codeSourceProjectId: application.codeSourceProjectId || null,
|
||||||
|
targetGitSystemId: application.targetGitSystemId || null,
|
||||||
|
targetGitProjectId: application.targetGitProjectId || null,
|
||||||
|
targetBranch: application.targetBranch || '',
|
||||||
});
|
});
|
||||||
|
|
||||||
// 加载仓库项目
|
// 加载源仓库项目
|
||||||
if (application.codeSourceSystemId) {
|
if (application.codeSourceSystemId) {
|
||||||
loadRepoProjects(application.codeSourceSystemId);
|
loadRepoProjects(application.codeSourceSystemId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载分支(优先使用代码源信息,向后兼容旧数据)
|
// 加载源分支(优先使用代码源信息,向后兼容旧数据)
|
||||||
if (application.codeSourceSystemId && application.codeSourceProjectId) {
|
if (application.codeSourceSystemId && application.codeSourceProjectId) {
|
||||||
// 使用代码源信息加载分支
|
// 使用代码源信息加载分支
|
||||||
loadBranchesFromCodeSource(application.codeSourceSystemId, application.codeSourceProjectId);
|
loadBranchesFromCodeSource(application.codeSourceSystemId, application.codeSourceProjectId);
|
||||||
@ -143,6 +156,16 @@ const TeamApplicationDialog: React.FC<TeamApplicationDialogProps> = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 🆕 加载目标仓库项目(如果有)
|
||||||
|
if (application.targetGitSystemId) {
|
||||||
|
loadTargetRepoProjects(application.targetGitSystemId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 🆕 加载目标分支(如果有)
|
||||||
|
if (application.targetGitSystemId && application.targetGitProjectId) {
|
||||||
|
loadTargetBranches(application.targetGitSystemId, application.targetGitProjectId);
|
||||||
|
}
|
||||||
|
|
||||||
// 加载Jenkins Jobs
|
// 加载Jenkins Jobs
|
||||||
if (application.deploySystemId) {
|
if (application.deploySystemId) {
|
||||||
loadJenkinsJobs(application.deploySystemId);
|
loadJenkinsJobs(application.deploySystemId);
|
||||||
@ -158,6 +181,9 @@ const TeamApplicationDialog: React.FC<TeamApplicationDialogProps> = ({
|
|||||||
workflowDefinitionId: null,
|
workflowDefinitionId: null,
|
||||||
codeSourceSystemId: null,
|
codeSourceSystemId: null,
|
||||||
codeSourceProjectId: null,
|
codeSourceProjectId: null,
|
||||||
|
targetGitSystemId: null,
|
||||||
|
targetGitProjectId: null,
|
||||||
|
targetBranch: '',
|
||||||
});
|
});
|
||||||
setBranches([]);
|
setBranches([]);
|
||||||
setJenkinsJobs([]);
|
setJenkinsJobs([]);
|
||||||
@ -204,20 +230,34 @@ const TeamApplicationDialog: React.FC<TeamApplicationDialogProps> = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 加载仓库项目列表
|
// 加载源仓库项目列表
|
||||||
const loadRepoProjects = async (externalSystemId: number) => {
|
const loadRepoProjects = async (externalSystemId: number) => {
|
||||||
setLoadingRepoProjects(true);
|
setLoadingRepoProjects(true);
|
||||||
try {
|
try {
|
||||||
const projects = await getRepositoryProjectsList({ externalSystemId });
|
const projects = await getRepositoryProjectsList({ externalSystemId });
|
||||||
setRepoProjects(projects || []);
|
setRepoProjects(projects || []);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('加载仓库项目失败:', error);
|
console.error('加载源仓库项目失败:', error);
|
||||||
setRepoProjects([]);
|
setRepoProjects([]);
|
||||||
} finally {
|
} finally {
|
||||||
setLoadingRepoProjects(false);
|
setLoadingRepoProjects(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 🆕 加载目标仓库项目列表
|
||||||
|
const loadTargetRepoProjects = async (externalSystemId: number) => {
|
||||||
|
setLoadingTargetRepoProjects(true);
|
||||||
|
try {
|
||||||
|
const projects = await getRepositoryProjectsList({ externalSystemId });
|
||||||
|
setTargetRepoProjects(projects || []);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载目标仓库项目失败:', error);
|
||||||
|
setTargetRepoProjects([]);
|
||||||
|
} finally {
|
||||||
|
setLoadingTargetRepoProjects(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 初始化加载Git系统列表
|
// 初始化加载Git系统列表
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (open) {
|
if (open) {
|
||||||
@ -236,6 +276,9 @@ const TeamApplicationDialog: React.FC<TeamApplicationDialogProps> = ({
|
|||||||
workflowDefinitionId: null,
|
workflowDefinitionId: null,
|
||||||
codeSourceSystemId: null,
|
codeSourceSystemId: null,
|
||||||
codeSourceProjectId: null,
|
codeSourceProjectId: null,
|
||||||
|
targetGitSystemId: null,
|
||||||
|
targetGitProjectId: null,
|
||||||
|
targetBranch: '',
|
||||||
});
|
});
|
||||||
// 清空分支列表(分支现在基于代码源,不基于应用)
|
// 清空分支列表(分支现在基于代码源,不基于应用)
|
||||||
setBranches([]);
|
setBranches([]);
|
||||||
@ -263,21 +306,35 @@ const TeamApplicationDialog: React.FC<TeamApplicationDialogProps> = ({
|
|||||||
loadJenkinsJobs(systemId);
|
loadJenkinsJobs(systemId);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 加载基于代码源的分支列表
|
// 加载基于源代码的分支列表
|
||||||
const loadBranchesFromCodeSource = async (externalSystemId: number, repoProjectId: number) => {
|
const loadBranchesFromCodeSource = async (externalSystemId: number, repoProjectId: number) => {
|
||||||
setLoadingBranches(true);
|
setLoadingBranches(true);
|
||||||
try {
|
try {
|
||||||
const branchList = await getRepositoryBranchesList({ externalSystemId, repoProjectId });
|
const branchList = await getRepositoryBranchesList({ externalSystemId, repoProjectId });
|
||||||
setBranches(branchList || []);
|
setBranches(branchList || []);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('加载分支失败:', error);
|
console.error('加载源分支失败:', error);
|
||||||
setBranches([]);
|
setBranches([]);
|
||||||
} finally {
|
} finally {
|
||||||
setLoadingBranches(false);
|
setLoadingBranches(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 处理代码源系统选择
|
// 🆕 加载目标分支列表
|
||||||
|
const loadTargetBranches = async (externalSystemId: number, repoProjectId: number) => {
|
||||||
|
setLoadingTargetBranches(true);
|
||||||
|
try {
|
||||||
|
const branchList = await getRepositoryBranchesList({ externalSystemId, repoProjectId });
|
||||||
|
setTargetBranches(branchList || []);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载目标分支失败:', error);
|
||||||
|
setTargetBranches([]);
|
||||||
|
} finally {
|
||||||
|
setLoadingTargetBranches(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 处理源代码系统选择
|
||||||
const handleCodeSourceSystemChange = (systemId: number) => {
|
const handleCodeSourceSystemChange = (systemId: number) => {
|
||||||
setFormData({
|
setFormData({
|
||||||
...formData,
|
...formData,
|
||||||
@ -289,7 +346,7 @@ const TeamApplicationDialog: React.FC<TeamApplicationDialogProps> = ({
|
|||||||
loadRepoProjects(systemId);
|
loadRepoProjects(systemId);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 处理仓库项目选择
|
// 处理源仓库项目选择
|
||||||
const handleCodeSourceProjectChange = (projectId: number) => {
|
const handleCodeSourceProjectChange = (projectId: number) => {
|
||||||
setFormData({
|
setFormData({
|
||||||
...formData,
|
...formData,
|
||||||
@ -302,6 +359,31 @@ const TeamApplicationDialog: React.FC<TeamApplicationDialogProps> = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 🆕 处理目标Git系统选择
|
||||||
|
const handleTargetGitSystemChange = (systemId: number) => {
|
||||||
|
setFormData({
|
||||||
|
...formData,
|
||||||
|
targetGitSystemId: systemId,
|
||||||
|
targetGitProjectId: null,
|
||||||
|
targetBranch: '', // 清空分支
|
||||||
|
});
|
||||||
|
setTargetBranches([]); // 清空分支列表
|
||||||
|
loadTargetRepoProjects(systemId);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 🆕 处理目标仓库项目选择
|
||||||
|
const handleTargetGitProjectChange = (projectId: number) => {
|
||||||
|
setFormData({
|
||||||
|
...formData,
|
||||||
|
targetGitProjectId: projectId,
|
||||||
|
targetBranch: '', // 清空分支
|
||||||
|
});
|
||||||
|
// 加载该项目的分支
|
||||||
|
if (formData.targetGitSystemId) {
|
||||||
|
loadTargetBranches(formData.targetGitSystemId, projectId);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 保存
|
// 保存
|
||||||
const handleSave = async () => {
|
const handleSave = async () => {
|
||||||
// 表单验证
|
// 表单验证
|
||||||
@ -325,6 +407,9 @@ const TeamApplicationDialog: React.FC<TeamApplicationDialogProps> = ({
|
|||||||
workflowDefinitionId: formData.workflowDefinitionId,
|
workflowDefinitionId: formData.workflowDefinitionId,
|
||||||
codeSourceSystemId: formData.codeSourceSystemId,
|
codeSourceSystemId: formData.codeSourceSystemId,
|
||||||
codeSourceProjectId: formData.codeSourceProjectId,
|
codeSourceProjectId: formData.codeSourceProjectId,
|
||||||
|
targetGitSystemId: formData.targetGitSystemId,
|
||||||
|
targetGitProjectId: formData.targetGitProjectId,
|
||||||
|
targetBranch: formData.targetBranch,
|
||||||
});
|
});
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
@ -338,11 +423,6 @@ const TeamApplicationDialog: React.FC<TeamApplicationDialogProps> = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 分支过滤
|
|
||||||
const filteredBranches = branches.filter(branch =>
|
|
||||||
branch.name.toLowerCase().includes(branchSearchValue.toLowerCase())
|
|
||||||
);
|
|
||||||
|
|
||||||
// Job 过滤
|
// Job 过滤
|
||||||
const filteredJobs = jenkinsJobs.filter(job =>
|
const filteredJobs = jenkinsJobs.filter(job =>
|
||||||
job.jobName.toLowerCase().includes(jobSearchValue.toLowerCase())
|
job.jobName.toLowerCase().includes(jobSearchValue.toLowerCase())
|
||||||
@ -599,215 +679,39 @@ const TeamApplicationDialog: React.FC<TeamApplicationDialogProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* 代码源选择 */}
|
{/* 源Git配置 */}
|
||||||
<div className="space-y-2">
|
<GitConfigSelector
|
||||||
<Label>代码源</Label>
|
label="源"
|
||||||
<Select
|
gitSystems={gitSystems}
|
||||||
value={formData.codeSourceSystemId?.toString() || ''}
|
selectedSystemId={formData.codeSourceSystemId}
|
||||||
onValueChange={(value) => handleCodeSourceSystemChange(Number(value))}
|
onSystemChange={handleCodeSourceSystemChange}
|
||||||
>
|
repoProjects={repoProjects}
|
||||||
<SelectTrigger>
|
loadingRepoProjects={loadingRepoProjects}
|
||||||
<SelectValue placeholder="选择代码源" />
|
selectedProjectId={formData.codeSourceProjectId}
|
||||||
</SelectTrigger>
|
onProjectChange={handleCodeSourceProjectChange}
|
||||||
<SelectContent>
|
branches={branches}
|
||||||
{gitSystems.length === 0 ? (
|
loadingBranches={loadingBranches}
|
||||||
<div className="p-4 text-center text-sm text-muted-foreground">
|
selectedBranch={formData.branch}
|
||||||
暂无可用的Git系统
|
onBranchChange={(branch) => setFormData({ ...formData, branch })}
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
gitSystems.map((system) => (
|
|
||||||
<SelectItem key={system.id} value={system.id.toString()}>
|
|
||||||
{system.name}
|
|
||||||
</SelectItem>
|
|
||||||
))
|
|
||||||
)}
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 仓库项目选择 */}
|
|
||||||
<div className="space-y-2">
|
|
||||||
<Label>仓库项目</Label>
|
|
||||||
{formData.codeSourceSystemId ? (
|
|
||||||
<Popover
|
|
||||||
open={projectPopoverOpen}
|
|
||||||
onOpenChange={setProjectPopoverOpen}
|
|
||||||
>
|
|
||||||
<PopoverTrigger asChild>
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
role="combobox"
|
|
||||||
disabled={loadingRepoProjects || repoProjects.length === 0}
|
|
||||||
className={cn(
|
|
||||||
'w-full justify-between',
|
|
||||||
!formData.codeSourceProjectId && 'text-muted-foreground'
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{formData.codeSourceProjectId
|
|
||||||
? (() => {
|
|
||||||
const selectedProject = repoProjects.find(
|
|
||||||
(p) => p.repoProjectId === formData.codeSourceProjectId
|
|
||||||
);
|
|
||||||
return selectedProject
|
|
||||||
? (selectedProject.repoGroupName
|
|
||||||
? `${selectedProject.repoGroupName} / ${selectedProject.name}`
|
|
||||||
: selectedProject.name)
|
|
||||||
: '选择仓库项目';
|
|
||||||
})()
|
|
||||||
: loadingRepoProjects
|
|
||||||
? '加载中...'
|
|
||||||
: repoProjects.length === 0
|
|
||||||
? '暂无项目'
|
|
||||||
: '选择仓库项目'}
|
|
||||||
<ChevronDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
|
||||||
</Button>
|
|
||||||
</PopoverTrigger>
|
|
||||||
<PopoverContent className="w-[var(--radix-popover-trigger-width)] p-0">
|
|
||||||
<div className="flex items-center border-b px-3">
|
|
||||||
<Search className="mr-2 h-4 w-4 shrink-0 opacity-50" />
|
|
||||||
<input
|
|
||||||
placeholder="搜索项目..."
|
|
||||||
className="flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground"
|
|
||||||
value={projectSearchValue}
|
|
||||||
onChange={(e) => setProjectSearchValue(e.target.value)}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
<ScrollArea className="h-[200px]">
|
|
||||||
<div className="p-1">
|
|
||||||
{repoProjects
|
|
||||||
.filter((project) =>
|
|
||||||
project.name.toLowerCase().includes(projectSearchValue.toLowerCase()) ||
|
|
||||||
(project.repoGroupName?.toLowerCase().includes(projectSearchValue.toLowerCase()))
|
|
||||||
)
|
|
||||||
.map((project) => (
|
|
||||||
<div
|
|
||||||
key={project.repoProjectId}
|
|
||||||
className={cn(
|
|
||||||
'relative flex cursor-pointer select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground',
|
|
||||||
project.repoProjectId === formData.codeSourceProjectId &&
|
|
||||||
'bg-accent text-accent-foreground'
|
|
||||||
)}
|
|
||||||
onClick={() => {
|
|
||||||
handleCodeSourceProjectChange(project.repoProjectId);
|
|
||||||
setProjectSearchValue('');
|
|
||||||
setProjectPopoverOpen(false);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className="flex-1 truncate">
|
|
||||||
{project.repoGroupName && (
|
|
||||||
<span className="text-muted-foreground">{project.repoGroupName} / </span>
|
|
||||||
)}
|
|
||||||
{project.name}
|
|
||||||
</div>
|
|
||||||
{project.repoProjectId === formData.codeSourceProjectId && (
|
|
||||||
<Check className="ml-2 h-4 w-4" />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</ScrollArea>
|
|
||||||
</PopoverContent>
|
|
||||||
</Popover>
|
|
||||||
) : (
|
|
||||||
<Input placeholder="请先选择代码源" disabled />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 分支选择 */}
|
{/* 🆕 目标Git配置(仅当启用Git同步检测时显示) */}
|
||||||
<div className="space-y-2">
|
{enableGitSyncCheck && (
|
||||||
<Label>分支</Label>
|
<GitConfigSelector
|
||||||
{formData.codeSourceProjectId ? (
|
label="目标"
|
||||||
<Popover
|
gitSystems={gitSystems}
|
||||||
open={branchPopoverOpen}
|
selectedSystemId={formData.targetGitSystemId}
|
||||||
onOpenChange={setBranchPopoverOpen}
|
onSystemChange={handleTargetGitSystemChange}
|
||||||
>
|
repoProjects={targetRepoProjects}
|
||||||
<PopoverTrigger asChild>
|
loadingRepoProjects={loadingTargetRepoProjects}
|
||||||
<Button
|
selectedProjectId={formData.targetGitProjectId}
|
||||||
variant="outline"
|
onProjectChange={handleTargetGitProjectChange}
|
||||||
role="combobox"
|
branches={targetBranches}
|
||||||
disabled={loadingBranches || branches.length === 0}
|
loadingBranches={loadingTargetBranches}
|
||||||
className={cn(
|
selectedBranch={formData.targetBranch}
|
||||||
'w-full justify-between',
|
onBranchChange={(branch) => setFormData({ ...formData, targetBranch: branch })}
|
||||||
!formData.branch && 'text-muted-foreground'
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{formData.branch
|
|
||||||
? (() => {
|
|
||||||
const selectedBranch = branches.find(
|
|
||||||
(b) => b.name === formData.branch
|
|
||||||
);
|
|
||||||
return (
|
|
||||||
<span className="flex items-center gap-2 truncate">
|
|
||||||
{selectedBranch?.name}
|
|
||||||
{selectedBranch?.isDefaultBranch && (
|
|
||||||
<span className="text-xs text-muted-foreground">
|
|
||||||
(默认)
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
})()
|
|
||||||
: loadingBranches
|
|
||||||
? '加载中...'
|
|
||||||
: branches.length === 0
|
|
||||||
? '无分支'
|
|
||||||
: '选择分支'}
|
|
||||||
<ChevronDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
|
||||||
</Button>
|
|
||||||
</PopoverTrigger>
|
|
||||||
<PopoverContent className="w-full p-0">
|
|
||||||
<div className="flex items-center border-b px-3">
|
|
||||||
<Search className="mr-2 h-4 w-4 shrink-0 opacity-50" />
|
|
||||||
<input
|
|
||||||
placeholder="搜索分支..."
|
|
||||||
className="flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground"
|
|
||||||
value={branchSearchValue}
|
|
||||||
onChange={(e) => setBranchSearchValue(e.target.value)}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
<ScrollArea className="h-[200px]">
|
|
||||||
<div className="p-1">
|
|
||||||
{filteredBranches.length === 0 ? (
|
|
||||||
<div className="p-4 text-center text-sm text-muted-foreground">
|
|
||||||
未找到分支
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
filteredBranches.map((branch) => (
|
|
||||||
<div
|
|
||||||
key={branch.id}
|
|
||||||
className={cn(
|
|
||||||
'relative flex cursor-pointer select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent',
|
|
||||||
branch.name === formData.branch &&
|
|
||||||
'bg-accent'
|
|
||||||
)}
|
)}
|
||||||
onClick={() => {
|
|
||||||
setFormData({ ...formData, branch: branch.name });
|
|
||||||
setBranchSearchValue('');
|
|
||||||
setBranchPopoverOpen(false);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<span className="flex-1 truncate">
|
|
||||||
{branch.name}
|
|
||||||
{branch.isDefaultBranch && (
|
|
||||||
<span className="ml-2 text-xs text-muted-foreground">
|
|
||||||
(默认)
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
{branch.name === formData.branch && (
|
|
||||||
<Check className="ml-2 h-4 w-4" />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
))
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</ScrollArea>
|
|
||||||
</PopoverContent>
|
|
||||||
</Popover>
|
|
||||||
) : (
|
|
||||||
<Input placeholder="请先选择仓库项目" disabled />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 工作流定义 */}
|
{/* 工作流定义 */}
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
|
|||||||
@ -10,8 +10,9 @@ import {
|
|||||||
import { ConfirmDialog } from '@/components/ui/confirm-dialog';
|
import { ConfirmDialog } from '@/components/ui/confirm-dialog';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { useToast } from '@/components/ui/use-toast';
|
import { useToast } from '@/components/ui/use-toast';
|
||||||
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
|
||||||
import { PaginatedTable, type ColumnDef, type PaginatedTableRef } from '@/components/ui/paginated-table';
|
import { PaginatedTable, type ColumnDef, type PaginatedTableRef } from '@/components/ui/paginated-table';
|
||||||
import { Plus, Edit, Trash2 } from 'lucide-react';
|
import { Plus, Edit, Trash2, GitBranch } from 'lucide-react';
|
||||||
import type { Environment } from '@/pages/Deploy/Environment/List/types';
|
import type { Environment } from '@/pages/Deploy/Environment/List/types';
|
||||||
import type { TeamApplication, Application } from '../types';
|
import type { TeamApplication, Application } from '../types';
|
||||||
import type { WorkflowDefinition } from '@/pages/Workflow/Definition/List/types';
|
import type { WorkflowDefinition } from '@/pages/Workflow/Definition/List/types';
|
||||||
@ -32,6 +33,7 @@ interface TeamApplicationManageDialogProps {
|
|||||||
open: boolean;
|
open: boolean;
|
||||||
onOpenChange: (open: boolean) => void;
|
onOpenChange: (open: boolean) => void;
|
||||||
teamId: number;
|
teamId: number;
|
||||||
|
enableGitSyncCheck: boolean; // 🆕 团队是否启用Git同步检测
|
||||||
environmentId?: number; // 可选:如果指定,则只管理该环境的应用
|
environmentId?: number; // 可选:如果指定,则只管理该环境的应用
|
||||||
environments: Environment[];
|
environments: Environment[];
|
||||||
onSuccess?: () => void;
|
onSuccess?: () => void;
|
||||||
@ -39,7 +41,7 @@ interface TeamApplicationManageDialogProps {
|
|||||||
|
|
||||||
export const TeamApplicationManageDialog: React.FC<
|
export const TeamApplicationManageDialog: React.FC<
|
||||||
TeamApplicationManageDialogProps
|
TeamApplicationManageDialogProps
|
||||||
> = ({ open, onOpenChange, teamId, environmentId, environments, onSuccess }) => {
|
> = ({ open, onOpenChange, teamId, enableGitSyncCheck, environmentId, environments, onSuccess }) => {
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const tableRef = useRef<PaginatedTableRef<TeamApplication>>(null);
|
const tableRef = useRef<PaginatedTableRef<TeamApplication>>(null);
|
||||||
const [teamApplications, setTeamApplications] = useState<TeamApplication[]>([]);
|
const [teamApplications, setTeamApplications] = useState<TeamApplication[]>([]);
|
||||||
@ -127,6 +129,9 @@ export const TeamApplicationManageDialog: React.FC<
|
|||||||
workflowDefinitionId: number | null;
|
workflowDefinitionId: number | null;
|
||||||
codeSourceSystemId: number | null;
|
codeSourceSystemId: number | null;
|
||||||
codeSourceProjectId: number | null;
|
codeSourceProjectId: number | null;
|
||||||
|
targetGitSystemId: number | null; // 🆕 目标Git系统ID
|
||||||
|
targetGitProjectId: number | null; // 🆕 目标Git项目ID
|
||||||
|
targetBranch: string; // 🆕 目标分支
|
||||||
}) => {
|
}) => {
|
||||||
if (!editingEnvironment) return;
|
if (!editingEnvironment) return;
|
||||||
|
|
||||||
@ -142,6 +147,10 @@ export const TeamApplicationManageDialog: React.FC<
|
|||||||
workflowDefinitionId: data.workflowDefinitionId || undefined,
|
workflowDefinitionId: data.workflowDefinitionId || undefined,
|
||||||
codeSourceSystemId: data.codeSourceSystemId || undefined,
|
codeSourceSystemId: data.codeSourceSystemId || undefined,
|
||||||
codeSourceProjectId: data.codeSourceProjectId || undefined,
|
codeSourceProjectId: data.codeSourceProjectId || undefined,
|
||||||
|
// 🆕 目标Git相关字段
|
||||||
|
targetGitSystemId: data.targetGitSystemId || undefined,
|
||||||
|
targetGitProjectId: data.targetGitProjectId || undefined,
|
||||||
|
targetBranch: data.targetBranch || undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (appDialogMode === 'edit' && data.id) {
|
if (appDialogMode === 'edit' && data.id) {
|
||||||
@ -207,6 +216,84 @@ export const TeamApplicationManageDialog: React.FC<
|
|||||||
width: '100px',
|
width: '100px',
|
||||||
render: (_, app) => getEnvironmentName(app.environmentId),
|
render: (_, app) => getEnvironmentName(app.environmentId),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'gitConfig',
|
||||||
|
title: 'Git配置',
|
||||||
|
width: '350px',
|
||||||
|
render: (_, app) => {
|
||||||
|
const hasTargetGit = app.targetGitSystemId && app.targetGitProjectId;
|
||||||
|
|
||||||
|
if (!hasTargetGit) {
|
||||||
|
// 未配置目标:单行显示
|
||||||
|
return (
|
||||||
|
<div className="flex items-center gap-2 text-sm">
|
||||||
|
<span className="font-medium truncate">
|
||||||
|
{app.codeSourceSystemName || '-'} / {app.codeSourceProjectName || '-'}
|
||||||
|
</span>
|
||||||
|
{app.branch && (
|
||||||
|
<span className="text-xs text-muted-foreground">({app.branch})</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 配置了目标:对称双行显示
|
||||||
|
return (
|
||||||
|
<TooltipProvider>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<div className="space-y-0.5 cursor-help">
|
||||||
|
{/* 源Git */}
|
||||||
|
<div className="text-sm">
|
||||||
|
<span className="text-muted-foreground">源:</span>
|
||||||
|
<span className="font-medium">
|
||||||
|
{app.codeSourceSystemName || '-'} / {app.codeSourceProjectName || '-'}
|
||||||
|
</span>
|
||||||
|
{app.branch && (
|
||||||
|
<span className="text-muted-foreground">({app.branch})</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{/* 同步标识 - 居中 */}
|
||||||
|
<div className="flex justify-center text-xs text-blue-500">
|
||||||
|
<span>⇅ 同步</span>
|
||||||
|
</div>
|
||||||
|
{/* 目标Git */}
|
||||||
|
<div className="text-sm">
|
||||||
|
<span className="text-muted-foreground">目:</span>
|
||||||
|
<span className="font-medium text-blue-600">
|
||||||
|
{app.targetGitSystemName || '-'} / {app.targetGitProjectName || '-'}
|
||||||
|
</span>
|
||||||
|
{app.targetBranch && (
|
||||||
|
<span className="text-blue-500">({app.targetBranch})</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent side="top" className="max-w-xs">
|
||||||
|
<div className="space-y-2 text-xs">
|
||||||
|
<div>
|
||||||
|
<div className="font-semibold mb-1">源Git</div>
|
||||||
|
<div className="text-muted-foreground">
|
||||||
|
<div>系统: {app.codeSourceSystemName}</div>
|
||||||
|
<div>项目: {app.codeSourceProjectName}</div>
|
||||||
|
<div>分支: {app.branch || '-'}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="border-t pt-2">
|
||||||
|
<div className="font-semibold mb-1">目标Git</div>
|
||||||
|
<div className="text-muted-foreground">
|
||||||
|
<div>系统: {app.targetGitSystemName}</div>
|
||||||
|
<div>项目: {app.targetGitProjectName}</div>
|
||||||
|
<div>分支: {app.targetBranch || '-'}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'buildType',
|
key: 'buildType',
|
||||||
title: '构建类型',
|
title: '构建类型',
|
||||||
@ -214,13 +301,6 @@ export const TeamApplicationManageDialog: React.FC<
|
|||||||
render: (_, app) =>
|
render: (_, app) =>
|
||||||
app.buildType === 'JENKINS' ? 'Jenkins构建' : app.buildType === 'NATIVE' ? '脚本部署' : '-',
|
app.buildType === 'JENKINS' ? 'Jenkins构建' : app.buildType === 'NATIVE' ? '脚本部署' : '-',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
key: 'branch',
|
|
||||||
title: '分支',
|
|
||||||
dataIndex: 'branch',
|
|
||||||
width: '100px',
|
|
||||||
render: (value) => value || '-',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
key: 'deploySystemName',
|
key: 'deploySystemName',
|
||||||
title: 'Jenkins系统',
|
title: 'Jenkins系统',
|
||||||
@ -315,6 +395,7 @@ export const TeamApplicationManageDialog: React.FC<
|
|||||||
open={appDialogOpen}
|
open={appDialogOpen}
|
||||||
onOpenChange={setAppDialogOpen}
|
onOpenChange={setAppDialogOpen}
|
||||||
mode={appDialogMode}
|
mode={appDialogMode}
|
||||||
|
enableGitSyncCheck={enableGitSyncCheck}
|
||||||
teamId={teamId}
|
teamId={teamId}
|
||||||
environmentId={editingEnvironment.id}
|
environmentId={editingEnvironment.id}
|
||||||
environmentName={editingEnvironment.envName}
|
environmentName={editingEnvironment.envName}
|
||||||
|
|||||||
@ -44,6 +44,7 @@ interface TeamEnvironmentManageDialogProps {
|
|||||||
onOpenChange: (open: boolean) => void;
|
onOpenChange: (open: boolean) => void;
|
||||||
teamId: number;
|
teamId: number;
|
||||||
teamName: string;
|
teamName: string;
|
||||||
|
enableGitSyncCheck: boolean; // 🆕 团队是否启用Git同步检测
|
||||||
environments: Environment[];
|
environments: Environment[];
|
||||||
users: User[];
|
users: User[];
|
||||||
onSuccess?: () => void;
|
onSuccess?: () => void;
|
||||||
@ -56,6 +57,7 @@ export const TeamEnvironmentManageDialog: React.FC<
|
|||||||
onOpenChange,
|
onOpenChange,
|
||||||
teamId,
|
teamId,
|
||||||
teamName,
|
teamName,
|
||||||
|
enableGitSyncCheck,
|
||||||
environments,
|
environments,
|
||||||
users,
|
users,
|
||||||
onSuccess,
|
onSuccess,
|
||||||
@ -301,6 +303,7 @@ export const TeamEnvironmentManageDialog: React.FC<
|
|||||||
open={appManageDialogOpen}
|
open={appManageDialogOpen}
|
||||||
onOpenChange={setAppManageDialogOpen}
|
onOpenChange={setAppManageDialogOpen}
|
||||||
teamId={teamId}
|
teamId={teamId}
|
||||||
|
enableGitSyncCheck={enableGitSyncCheck}
|
||||||
environmentId={selectedEnvironmentId}
|
environmentId={selectedEnvironmentId}
|
||||||
environments={environments}
|
environments={environments}
|
||||||
onSuccess={handleConfigSuccess}
|
onSuccess={handleConfigSuccess}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import type { TeamResponse } from '../types';
|
import type { TeamResponse } from '../types';
|
||||||
|
import { DevelopmentModeEnum, DEVELOPMENT_MODE_OPTIONS } from '../types';
|
||||||
import { createTeam, updateTeam } from '../service';
|
import { createTeam, updateTeam } from '../service';
|
||||||
import { getUserList } from '@/pages/System/User/List/service';
|
import { getUserList } from '@/pages/System/User/List/service';
|
||||||
import type { UserResponse } from '@/pages/System/User/List/types';
|
import type { UserResponse } from '@/pages/System/User/List/types';
|
||||||
@ -25,6 +26,7 @@ import {
|
|||||||
Select,
|
Select,
|
||||||
SelectContent,
|
SelectContent,
|
||||||
SelectItem,
|
SelectItem,
|
||||||
|
SelectItemWithDescription,
|
||||||
SelectTrigger,
|
SelectTrigger,
|
||||||
SelectValue,
|
SelectValue,
|
||||||
} from "@/components/ui/select";
|
} from "@/components/ui/select";
|
||||||
@ -62,9 +64,21 @@ const TeamModal: React.FC<TeamModalProps> = ({
|
|||||||
ownerName: "",
|
ownerName: "",
|
||||||
enabled: true,
|
enabled: true,
|
||||||
sort: 0,
|
sort: 0,
|
||||||
|
developmentMode: DevelopmentModeEnum.STANDARD,
|
||||||
|
enableGitSyncCheck: false,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 监听开发模式变化,自动调整Git同步检测选项
|
||||||
|
const developmentMode = form.watch('developmentMode');
|
||||||
|
useEffect(() => {
|
||||||
|
const modeOption = DEVELOPMENT_MODE_OPTIONS.find(opt => opt.value === developmentMode);
|
||||||
|
if (modeOption && !modeOption.enablesGitSyncCheck) {
|
||||||
|
// 如果当前模式不支持Git同步检测,自动禁用
|
||||||
|
form.setValue('enableGitSyncCheck', false);
|
||||||
|
}
|
||||||
|
}, [developmentMode, form]);
|
||||||
|
|
||||||
// 加载用户列表
|
// 加载用户列表
|
||||||
const loadUsers = async () => {
|
const loadUsers = async () => {
|
||||||
try {
|
try {
|
||||||
@ -89,6 +103,8 @@ const TeamModal: React.FC<TeamModalProps> = ({
|
|||||||
ownerName: initialValues.ownerName || "",
|
ownerName: initialValues.ownerName || "",
|
||||||
enabled: initialValues.enabled,
|
enabled: initialValues.enabled,
|
||||||
sort: initialValues.sort,
|
sort: initialValues.sort,
|
||||||
|
developmentMode: initialValues.developmentMode || DevelopmentModeEnum.STANDARD,
|
||||||
|
enableGitSyncCheck: initialValues.enableGitSyncCheck || false,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
form.reset({
|
form.reset({
|
||||||
@ -99,6 +115,8 @@ const TeamModal: React.FC<TeamModalProps> = ({
|
|||||||
ownerName: "",
|
ownerName: "",
|
||||||
enabled: true,
|
enabled: true,
|
||||||
sort: 0,
|
sort: 0,
|
||||||
|
developmentMode: DevelopmentModeEnum.STANDARD,
|
||||||
|
enableGitSyncCheck: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -236,6 +254,61 @@ const TeamModal: React.FC<TeamModalProps> = ({
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="developmentMode"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>开发模式</FormLabel>
|
||||||
|
<Select
|
||||||
|
onValueChange={field.onChange}
|
||||||
|
value={field.value}
|
||||||
|
>
|
||||||
|
<FormControl>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="请选择开发模式" />
|
||||||
|
</SelectTrigger>
|
||||||
|
</FormControl>
|
||||||
|
<SelectContent>
|
||||||
|
{DEVELOPMENT_MODE_OPTIONS.map((option) => (
|
||||||
|
<SelectItemWithDescription
|
||||||
|
key={option.value}
|
||||||
|
value={option.value}
|
||||||
|
label={option.label}
|
||||||
|
description={option.description}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{developmentMode === 'SYNC_MODE' && (
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="enableGitSyncCheck"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Git同步检测</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<div className="flex items-center gap-2 h-10">
|
||||||
|
<Switch
|
||||||
|
checked={field.value}
|
||||||
|
onCheckedChange={field.onChange}
|
||||||
|
/>
|
||||||
|
<span className="text-sm text-muted-foreground">
|
||||||
|
{field.value ? '启用' : '禁用'}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-2 gap-4">
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import React, { useState, useEffect, useMemo, useRef } from 'react';
|
|||||||
import { PageContainer } from '@/components/ui/page-container';
|
import { PageContainer } from '@/components/ui/page-container';
|
||||||
import { getTeams } from './service';
|
import { getTeams } from './service';
|
||||||
import type { TeamResponse, TeamQuery } from './types';
|
import type { TeamResponse, TeamQuery } from './types';
|
||||||
|
import { DEVELOPMENT_MODE_OPTIONS } from './types';
|
||||||
import TeamModal from './components/TeamModal';
|
import TeamModal from './components/TeamModal';
|
||||||
import DeleteDialog from './components/DeleteDialog';
|
import DeleteDialog from './components/DeleteDialog';
|
||||||
import MemberManageDialog from './components/MemberManageDialog';
|
import MemberManageDialog from './components/MemberManageDialog';
|
||||||
@ -149,6 +150,28 @@ const TeamList: React.FC = () => {
|
|||||||
width: '140px',
|
width: '140px',
|
||||||
render: (_, record) => record.ownerName || '-',
|
render: (_, record) => record.ownerName || '-',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'developmentMode',
|
||||||
|
title: '开发模式',
|
||||||
|
width: '160px',
|
||||||
|
render: (_, record) => {
|
||||||
|
const modeOption = DEVELOPMENT_MODE_OPTIONS.find(opt => opt.value === record.developmentMode);
|
||||||
|
return (
|
||||||
|
<div className="space-y-1">
|
||||||
|
<Badge variant="outline" className="inline-flex">
|
||||||
|
{modeOption?.label || record.developmentMode}
|
||||||
|
</Badge>
|
||||||
|
{record.enableGitSyncCheck && (
|
||||||
|
<div className="text-xs text-muted-foreground">
|
||||||
|
<Badge variant="secondary" className="text-xs">
|
||||||
|
Git同步检测
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'memberCount',
|
key: 'memberCount',
|
||||||
title: '成员数量',
|
title: '成员数量',
|
||||||
@ -332,6 +355,7 @@ const TeamList: React.FC = () => {
|
|||||||
onOpenChange={setEnvManageDialogOpen}
|
onOpenChange={setEnvManageDialogOpen}
|
||||||
teamId={currentTeam.id}
|
teamId={currentTeam.id}
|
||||||
teamName={currentTeam.teamName}
|
teamName={currentTeam.teamName}
|
||||||
|
enableGitSyncCheck={currentTeam.enableGitSyncCheck}
|
||||||
environments={environments}
|
environments={environments}
|
||||||
users={users}
|
users={users}
|
||||||
onSuccess={handleSuccess}
|
onSuccess={handleSuccess}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
import { DevelopmentModeEnum } from './types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 搜索表单校验
|
* 搜索表单校验
|
||||||
@ -20,6 +21,8 @@ export const teamFormSchema = z.object({
|
|||||||
ownerName: z.string().optional(),
|
ownerName: z.string().optional(),
|
||||||
enabled: z.boolean().default(true),
|
enabled: z.boolean().default(true),
|
||||||
sort: z.number().min(0).default(0),
|
sort: z.number().min(0).default(0),
|
||||||
|
developmentMode: z.nativeEnum(DevelopmentModeEnum).default(DevelopmentModeEnum.STANDARD),
|
||||||
|
enableGitSyncCheck: z.boolean().default(false),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type SearchFormValues = z.infer<typeof searchFormSchema>;
|
export type SearchFormValues = z.infer<typeof searchFormSchema>;
|
||||||
|
|||||||
@ -5,6 +5,56 @@ import type { Application } from '@/pages/Deploy/Application/List/types';
|
|||||||
// 导出环境和应用类型供使用
|
// 导出环境和应用类型供使用
|
||||||
export type { Environment, Application };
|
export type { Environment, Application };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开发模式枚举
|
||||||
|
*/
|
||||||
|
export enum DevelopmentModeEnum {
|
||||||
|
/** 标准模式 - 单仓库直接开发部署 */
|
||||||
|
STANDARD = 'STANDARD',
|
||||||
|
/** 同步模式 - 源码内外网同步 */
|
||||||
|
SYNC_MODE = 'SYNC_MODE',
|
||||||
|
/** 制品交付模式 - 仅交付编译制品,无源码 */
|
||||||
|
ARTIFACT_DELIVERY = 'ARTIFACT_DELIVERY'
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开发模式选项配置
|
||||||
|
*/
|
||||||
|
export interface DevelopmentModeOption {
|
||||||
|
value: DevelopmentModeEnum;
|
||||||
|
label: string;
|
||||||
|
description: string;
|
||||||
|
requiresExternalRepo: boolean;
|
||||||
|
enablesGitSyncCheck: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开发模式选项列表
|
||||||
|
*/
|
||||||
|
export const DEVELOPMENT_MODE_OPTIONS: DevelopmentModeOption[] = [
|
||||||
|
{
|
||||||
|
value: DevelopmentModeEnum.STANDARD,
|
||||||
|
label: '标准模式',
|
||||||
|
description: '单仓库直接开发部署',
|
||||||
|
requiresExternalRepo: false,
|
||||||
|
enablesGitSyncCheck: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: DevelopmentModeEnum.SYNC_MODE,
|
||||||
|
label: '同步模式',
|
||||||
|
description: '源码内外网同步',
|
||||||
|
requiresExternalRepo: true,
|
||||||
|
enablesGitSyncCheck: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: DevelopmentModeEnum.ARTIFACT_DELIVERY,
|
||||||
|
label: '制品交付模式',
|
||||||
|
description: '仅交付编译制品,无源码',
|
||||||
|
requiresExternalRepo: true,
|
||||||
|
enablesGitSyncCheck: false
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 团队查询参数
|
* 团队查询参数
|
||||||
*/
|
*/
|
||||||
@ -25,6 +75,8 @@ export interface TeamResponse extends BaseResponse {
|
|||||||
ownerName?: string;
|
ownerName?: string;
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
sort: number;
|
sort: number;
|
||||||
|
developmentMode: DevelopmentModeEnum; // 开发模式
|
||||||
|
enableGitSyncCheck: boolean; // 是否启用Git同步检测
|
||||||
memberCount?: number;
|
memberCount?: number;
|
||||||
environmentCount?: number;
|
environmentCount?: number;
|
||||||
applicationCount?: number;
|
applicationCount?: number;
|
||||||
@ -41,6 +93,8 @@ export interface TeamRequest {
|
|||||||
ownerName?: string;
|
ownerName?: string;
|
||||||
enabled?: boolean;
|
enabled?: boolean;
|
||||||
sort?: number;
|
sort?: number;
|
||||||
|
developmentMode?: DevelopmentModeEnum; // 开发模式
|
||||||
|
enableGitSyncCheck?: boolean; // 是否启用Git同步检测
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== 团队环境配置相关 ====================
|
// ==================== 团队环境配置相关 ====================
|
||||||
@ -130,16 +184,21 @@ export interface TeamApplication extends BaseResponse {
|
|||||||
deploySystemId?: number;
|
deploySystemId?: number;
|
||||||
deployJob?: string;
|
deployJob?: string;
|
||||||
workflowDefinitionId?: number;
|
workflowDefinitionId?: number;
|
||||||
codeSourceSystemId?: number; // 代码源系统ID
|
codeSourceSystemId?: number; // 源代码系统ID
|
||||||
codeSourceProjectId?: number; // 代码源项目ID
|
codeSourceProjectId?: number; // 源仓库项目ID
|
||||||
|
targetGitSystemId?: number; // 目标Git系统ID(仅SYNC_MODE)
|
||||||
|
targetGitProjectId?: number; // 目标Git项目ID
|
||||||
|
targetBranch?: string; // 目标分支名称
|
||||||
teamName?: string;
|
teamName?: string;
|
||||||
applicationName?: string;
|
applicationName?: string;
|
||||||
applicationCode?: string;
|
applicationCode?: string;
|
||||||
environmentName?: string;
|
environmentName?: string;
|
||||||
deploySystemName?: string;
|
deploySystemName?: string;
|
||||||
workflowDefinitionName?: string;
|
workflowDefinitionName?: string;
|
||||||
codeSourceSystemName?: string; // 代码源系统名称
|
codeSourceSystemName?: string; // 源代码系统名称
|
||||||
codeSourceProjectName?: string; // 代码源项目名称
|
codeSourceProjectName?: string; // 源仓库项目名称
|
||||||
|
targetGitSystemName?: string; // 目标Git系统名称
|
||||||
|
targetGitProjectName?: string; // 目标Git项目名称
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -154,7 +213,10 @@ export interface TeamApplicationRequest {
|
|||||||
deploySystemId?: number;
|
deploySystemId?: number;
|
||||||
deployJob?: string;
|
deployJob?: string;
|
||||||
workflowDefinitionId?: number;
|
workflowDefinitionId?: number;
|
||||||
codeSourceSystemId?: number; // 代码源系统ID
|
codeSourceSystemId?: number; // 源代码系统ID
|
||||||
codeSourceProjectId?: number; // 代码源项目ID
|
codeSourceProjectId?: number; // 源仓库项目ID
|
||||||
|
targetGitSystemId?: number; // 目标Git系统ID(仅SYNC_MODE)
|
||||||
|
targetGitProjectId?: number; // 目标Git项目ID
|
||||||
|
targetBranch?: string; // 目标分支名称
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user