重构消息通知弹窗

This commit is contained in:
dengqichen 2025-11-27 18:14:52 +08:00
parent 6f218dca6a
commit b9d5fbe360
3 changed files with 185 additions and 111 deletions

View File

@ -25,7 +25,9 @@ import { useToast } from '@/components/ui/use-toast';
import type { import type {
TeamApplication, TeamApplication,
Application, Application,
BuildType,
} from '../types'; } from '../types';
import { BUILD_TYPE_OPTIONS } from '../types';
import type { RepositoryBranchResponse } from '@/pages/Resource/Git/List/types'; 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';
@ -46,6 +48,7 @@ interface TeamApplicationDialogProps {
onSave: (data: { onSave: (data: {
id?: number; id?: number;
appId: number; appId: number;
buildType: BuildType | null;
branch: string; branch: string;
deploySystemId: number | null; deploySystemId: number | null;
deployJob: string; deployJob: string;
@ -78,6 +81,7 @@ const TeamApplicationDialog: React.FC<TeamApplicationDialogProps> = ({
// 表单状态 // 表单状态
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
appId: null as number | null, appId: null as number | null,
buildType: 'JENKINS' as BuildType | null,
branch: '', branch: '',
deploySystemId: null as number | null, deploySystemId: null as number | null,
deployJob: '', deployJob: '',
@ -111,6 +115,7 @@ const TeamApplicationDialog: React.FC<TeamApplicationDialogProps> = ({
// 编辑模式:填充现有数据 // 编辑模式:填充现有数据
setFormData({ setFormData({
appId: application.applicationId, appId: application.applicationId,
buildType: application.buildType || 'JENKINS',
branch: application.branch || '', branch: application.branch || '',
deploySystemId: application.deploySystemId || null, deploySystemId: application.deploySystemId || null,
deployJob: application.deployJob || '', deployJob: application.deployJob || '',
@ -144,6 +149,7 @@ const TeamApplicationDialog: React.FC<TeamApplicationDialogProps> = ({
// 新建模式:重置表单 // 新建模式:重置表单
setFormData({ setFormData({
appId: null, appId: null,
buildType: 'JENKINS',
branch: '', branch: '',
deploySystemId: null, deploySystemId: null,
deployJob: '', deployJob: '',
@ -221,6 +227,7 @@ const TeamApplicationDialog: React.FC<TeamApplicationDialogProps> = ({
const handleAppChange = (appId: number) => { const handleAppChange = (appId: number) => {
setFormData({ setFormData({
appId: appId, appId: appId,
buildType: formData.buildType,
branch: '', branch: '',
deploySystemId: null, deploySystemId: null,
deployJob: '', deployJob: '',
@ -232,6 +239,18 @@ const TeamApplicationDialog: React.FC<TeamApplicationDialogProps> = ({
setBranches([]); setBranches([]);
}; };
// 处理构建类型选择
const handleBuildTypeChange = (buildType: BuildType) => {
setFormData({
...formData,
buildType,
// 切换构建类型时清空 Jenkins 相关配置
deploySystemId: null,
deployJob: '',
});
setJenkinsJobs([]);
};
// 处理 Jenkins 系统选择 // 处理 Jenkins 系统选择
const handleJenkinsSystemChange = (systemId: number) => { const handleJenkinsSystemChange = (systemId: number) => {
setFormData({ setFormData({
@ -297,9 +316,10 @@ const TeamApplicationDialog: React.FC<TeamApplicationDialogProps> = ({
await onSave({ await onSave({
id: mode === 'edit' && application ? application.id : undefined, id: mode === 'edit' && application ? application.id : undefined,
appId: formData.appId, appId: formData.appId,
buildType: formData.buildType,
branch: formData.branch, branch: formData.branch,
deploySystemId: formData.deploySystemId, deploySystemId: formData.buildType === 'JENKINS' ? formData.deploySystemId : null,
deployJob: formData.deployJob, deployJob: formData.buildType === 'JENKINS' ? formData.deployJob : '',
workflowDefinitionId: formData.workflowDefinitionId, workflowDefinitionId: formData.workflowDefinitionId,
codeSourceSystemId: formData.codeSourceSystemId, codeSourceSystemId: formData.codeSourceSystemId,
codeSourceProjectId: formData.codeSourceProjectId, codeSourceProjectId: formData.codeSourceProjectId,
@ -328,14 +348,14 @@ const TeamApplicationDialog: React.FC<TeamApplicationDialogProps> = ({
return ( return (
<Dialog open={open} onOpenChange={onOpenChange}> <Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="max-w-2xl"> <DialogContent className="max-w-2xl h-[680px] flex flex-col">
<DialogHeader> <DialogHeader>
<DialogTitle> <DialogTitle>
{mode === 'edit' ? '编辑' : '添加'} - {environmentName} {mode === 'edit' ? '编辑' : '添加'} - {environmentName}
</DialogTitle> </DialogTitle>
</DialogHeader> </DialogHeader>
<DialogBody> <DialogBody className="flex-1 overflow-y-auto">
<div className="space-y-4"> <div className="space-y-4">
{/* 应用选择 */} {/* 应用选择 */}
<div className="space-y-2"> <div className="space-y-2">
@ -378,6 +398,140 @@ const TeamApplicationDialog: React.FC<TeamApplicationDialogProps> = ({
)} )}
</div> </div>
{/* 构建类型选择 */}
<div className="space-y-2">
<Label>
<span className="text-destructive">*</span>
</Label>
<Select
value={formData.buildType || ''}
onValueChange={(value) => handleBuildTypeChange(value as BuildType)}
>
<SelectTrigger>
<SelectValue placeholder="选择构建类型" />
</SelectTrigger>
<SelectContent>
{BUILD_TYPE_OPTIONS.map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
</SelectContent>
</Select>
<p className="text-xs text-muted-foreground">
Jenkins构建Jenkins执行构建任务
</p>
</div>
{/* Jenkins 系统 - 仅在构建类型为 JENKINS 时显示 */}
{formData.buildType === 'JENKINS' && (
<div className="space-y-2">
<Label>Jenkins系统</Label>
<Select
value={formData.deploySystemId?.toString() || ''}
onValueChange={(value) =>
handleJenkinsSystemChange(Number(value))
}
>
<SelectTrigger>
<SelectValue placeholder="选择Jenkins系统" />
</SelectTrigger>
<SelectContent>
{jenkinsSystems.length === 0 ? (
<div className="p-4 text-center text-sm text-muted-foreground">
Jenkins系统
</div>
) : (
jenkinsSystems.map((system) => (
<SelectItem key={system.id} value={system.id.toString()}>
{system.name}
</SelectItem>
))
)}
</SelectContent>
</Select>
</div>
)}
{/* Jenkins Job - 仅在构建类型为 JENKINS 时显示 */}
{formData.buildType === 'JENKINS' && (
<div className="space-y-2">
<Label>Jenkins Job</Label>
{formData.deploySystemId ? (
<Popover open={jobPopoverOpen} onOpenChange={setJobPopoverOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
role="combobox"
disabled={loadingJobs || jenkinsJobs.length === 0}
className={cn(
'w-full justify-between',
!formData.deployJob && 'text-muted-foreground'
)}
>
<span className="truncate">
{formData.deployJob ||
(loadingJobs
? '加载中...'
: jenkinsJobs.length === 0
? '无Job'
: '选择Job')}
</span>
<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="搜索Job..."
className="flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground"
value={jobSearchValue}
onChange={(e) => setJobSearchValue(e.target.value)}
/>
</div>
<ScrollArea className="h-[200px]">
<div className="p-1">
{filteredJobs.length === 0 ? (
<div className="p-4 text-center text-sm text-muted-foreground">
Job
</div>
) : (
filteredJobs.map((job) => (
<div
key={job.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',
job.jobName === formData.deployJob && 'bg-accent'
)}
onClick={() => {
setFormData({
...formData,
deployJob: job.jobName,
});
setJobSearchValue('');
setJobPopoverOpen(false);
}}
>
<span className="flex-1 truncate">
{job.jobName}
</span>
{job.jobName === formData.deployJob && (
<Check className="ml-2 h-4 w-4" />
)}
</div>
))
)}
</div>
</ScrollArea>
</PopoverContent>
</Popover>
) : (
<Input placeholder="请先选择Jenkins系统" disabled />
)}
</div>
)}
{/* 代码源选择 */} {/* 代码源选择 */}
<div className="space-y-2"> <div className="space-y-2">
<Label></Label> <Label></Label>
@ -588,111 +742,6 @@ const TeamApplicationDialog: React.FC<TeamApplicationDialogProps> = ({
)} )}
</div> </div>
{/* Jenkins 系统 */}
<div className="space-y-2">
<Label>Jenkins系统</Label>
<Select
value={formData.deploySystemId?.toString() || ''}
onValueChange={(value) =>
handleJenkinsSystemChange(Number(value))
}
>
<SelectTrigger>
<SelectValue placeholder="选择Jenkins系统" />
</SelectTrigger>
<SelectContent>
{jenkinsSystems.length === 0 ? (
<div className="p-4 text-center text-sm text-muted-foreground">
Jenkins系统
</div>
) : (
jenkinsSystems.map((system) => (
<SelectItem key={system.id} value={system.id.toString()}>
{system.name}
</SelectItem>
))
)}
</SelectContent>
</Select>
</div>
{/* Jenkins Job */}
<div className="space-y-2">
<Label>Jenkins Job</Label>
{formData.deploySystemId ? (
<Popover open={jobPopoverOpen} onOpenChange={setJobPopoverOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
role="combobox"
disabled={loadingJobs || jenkinsJobs.length === 0}
className={cn(
'w-full justify-between',
!formData.deployJob && 'text-muted-foreground'
)}
>
<span className="truncate">
{formData.deployJob ||
(loadingJobs
? '加载中...'
: jenkinsJobs.length === 0
? '无Job'
: '选择Job')}
</span>
<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="搜索Job..."
className="flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground"
value={jobSearchValue}
onChange={(e) => setJobSearchValue(e.target.value)}
/>
</div>
<ScrollArea className="h-[200px]">
<div className="p-1">
{filteredJobs.length === 0 ? (
<div className="p-4 text-center text-sm text-muted-foreground">
Job
</div>
) : (
filteredJobs.map((job) => (
<div
key={job.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',
job.jobName === formData.deployJob && 'bg-accent'
)}
onClick={() => {
setFormData({
...formData,
deployJob: job.jobName,
});
setJobSearchValue('');
setJobPopoverOpen(false);
}}
>
<span className="flex-1 truncate">
{job.jobName}
</span>
{job.jobName === formData.deployJob && (
<Check className="ml-2 h-4 w-4" />
)}
</div>
))
)}
</div>
</ScrollArea>
</PopoverContent>
</Popover>
) : (
<Input placeholder="请先选择Jenkins系统" disabled />
)}
</div>
{/* 工作流定义 */} {/* 工作流定义 */}
<div className="space-y-2"> <div className="space-y-2">
<Label></Label> <Label></Label>

View File

@ -136,6 +136,7 @@ export const TeamApplicationManageDialog: React.FC<
const handleSaveApplication = async (data: { const handleSaveApplication = async (data: {
id?: number; id?: number;
appId: number; appId: number;
buildType: 'JENKINS' | 'NATIVE' | null;
branch: string; branch: string;
deploySystemId: number | null; deploySystemId: number | null;
deployJob: string; deployJob: string;
@ -149,6 +150,7 @@ export const TeamApplicationManageDialog: React.FC<
teamId, teamId,
applicationId: data.appId, applicationId: data.appId,
environmentId: editingEnvironment.id, environmentId: editingEnvironment.id,
buildType: data.buildType || undefined,
branch: data.branch, branch: data.branch,
deploySystemId: data.deploySystemId || undefined, deploySystemId: data.deploySystemId || undefined,
deployJob: data.deployJob, deployJob: data.deployJob,
@ -240,6 +242,7 @@ export const TeamApplicationManageDialog: React.FC<
<TableRow> <TableRow>
<TableHead></TableHead> <TableHead></TableHead>
<TableHead></TableHead> <TableHead></TableHead>
<TableHead></TableHead>
<TableHead></TableHead> <TableHead></TableHead>
<TableHead>Jenkins系统</TableHead> <TableHead>Jenkins系统</TableHead>
<TableHead>Jenkins Job</TableHead> <TableHead>Jenkins Job</TableHead>
@ -258,11 +261,18 @@ export const TeamApplicationManageDialog: React.FC<
<TableCell> <TableCell>
{getEnvironmentName(app.environmentId)} {getEnvironmentName(app.environmentId)}
</TableCell> </TableCell>
<TableCell>
{app.buildType === 'JENKINS' ? 'Jenkins构建' : app.buildType === 'NATIVE' ? '脚本部署' : '-'}
</TableCell>
<TableCell>{app.branch || '-'}</TableCell> <TableCell>{app.branch || '-'}</TableCell>
<TableCell> <TableCell>
{app.deploySystemName || `系统 ${app.deploySystemId}`} {app.buildType === 'JENKINS'
? (app.deploySystemName || (app.deploySystemId ? `系统 ${app.deploySystemId}` : '-'))
: '-'}
</TableCell>
<TableCell>
{app.buildType === 'JENKINS' ? (app.deployJob || '-') : '-'}
</TableCell> </TableCell>
<TableCell>{app.deployJob || '-'}</TableCell>
<TableCell> <TableCell>
{app.workflowDefinitionName || '-'} {app.workflowDefinitionName || '-'}
</TableCell> </TableCell>

View File

@ -105,6 +105,19 @@ export interface TeamEnvironmentConfigRequest {
// ==================== 团队应用关联相关 ==================== // ==================== 团队应用关联相关 ====================
/**
*
*/
export type BuildType = 'JENKINS' | 'NATIVE';
/**
*
*/
export const BUILD_TYPE_OPTIONS = [
{ value: 'JENKINS', label: 'Jenkins构建' },
{ value: 'NATIVE', label: '脚本部署' },
] as const;
/** /**
* *
*/ */
@ -112,6 +125,7 @@ export interface TeamApplication extends BaseResponse {
teamId: number; teamId: number;
applicationId: number; applicationId: number;
environmentId: number; environmentId: number;
buildType?: BuildType; // 构建类型
branch?: string; branch?: string;
deploySystemId?: number; deploySystemId?: number;
deployJob?: string; deployJob?: string;
@ -135,6 +149,7 @@ export interface TeamApplicationRequest {
teamId: number; teamId: number;
applicationId: number; applicationId: number;
environmentId: number; environmentId: number;
buildType?: BuildType; // 构建类型
branch?: string; branch?: string;
deploySystemId?: number; deploySystemId?: number;
deployJob?: string; deployJob?: string;