重构消息通知弹窗

This commit is contained in:
dengqichen 2025-11-28 17:37:42 +08:00
parent 763d14f3d3
commit f66524bac6
2 changed files with 111 additions and 112 deletions

View File

@ -174,6 +174,7 @@ export function ConfirmDialog<T = any>({
const handleCancel = () => {
onCancel?.();
onOpenChange(false);
};
// 按钮样式映射

View File

@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react';
import React, { useEffect, useState, useMemo, useRef } from 'react';
import {
Dialog,
DialogContent,
@ -7,23 +7,16 @@ import {
DialogFooter,
DialogBody,
} from '@/components/ui/dialog';
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from '@/components/ui/table';
import { ConfirmDialog } from '@/components/ui/confirm-dialog';
import { Button } from '@/components/ui/button';
import { useToast } from '@/components/ui/use-toast';
import { Plus, Edit, Trash2, Loader2 } from 'lucide-react';
import { PaginatedTable, type ColumnDef, type PaginatedTableRef } from '@/components/ui/paginated-table';
import { Plus, Edit, Trash2 } from 'lucide-react';
import type { Environment } from '@/pages/Deploy/Environment/List/types';
import type { TeamApplication, Application } from '../types';
import type { WorkflowDefinition } from '@/pages/Workflow/Definition/List/types';
import {
getTeamApplications,
getTeamApplicationsPage,
deleteTeamApplication,
getApplicationList,
getJenkinsSystems,
@ -48,7 +41,7 @@ export const TeamApplicationManageDialog: React.FC<
TeamApplicationManageDialogProps
> = ({ open, onOpenChange, teamId, environmentId, environments, onSuccess }) => {
const { toast } = useToast();
const [loading, setLoading] = useState(false);
const tableRef = useRef<PaginatedTableRef<TeamApplication>>(null);
const [teamApplications, setTeamApplications] = useState<TeamApplication[]>([]);
// 如果从环境管理进入,只显示该环境的应用;否则显示所有应用
const selectedEnvironmentId = environmentId || null;
@ -68,13 +61,12 @@ export const TeamApplicationManageDialog: React.FC<
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
const [deletingApp, setDeletingApp] = useState<TeamApplication | null>(null);
// 加载基础数据和应用列表
// 加载基础数据
useEffect(() => {
if (open) {
loadTeamApplications();
loadBaseData();
}
}, [open, teamId, selectedEnvironmentId]);
}, [open]);
const loadBaseData = async () => {
try {
@ -95,23 +87,15 @@ export const TeamApplicationManageDialog: React.FC<
}
};
// 后端已经根据 selectedEnvironmentId 筛选了数据,前端不需要再次筛选
const loadTeamApplications = async () => {
setLoading(true);
try {
// 如果指定了环境ID只加载该环境的应用否则加载所有
const data = await getTeamApplications(teamId, selectedEnvironmentId || undefined);
setTeamApplications(data);
} catch (error: any) {
toast({
title: '加载失败',
description: error.message || '无法加载应用列表',
variant: 'destructive',
});
} finally {
setLoading(false);
}
// 包装 fetchFn
const fetchData = async (query: any) => {
const result = await getTeamApplicationsPage({
...query,
teamId,
environmentId: selectedEnvironmentId || undefined,
});
setTeamApplications(result.content || []);
return result;
};
const handleOpenAddAppDialog = () => {
@ -166,7 +150,7 @@ export const TeamApplicationManageDialog: React.FC<
}
// 刷新应用列表
await loadTeamApplications();
tableRef.current?.refresh();
};
const handleLoadBranches = async (_appId: number, app: Application) => {
@ -202,6 +186,90 @@ export const TeamApplicationManageDialog: React.FC<
);
};
// 列定义
const columns: ColumnDef<TeamApplication>[] = useMemo(() => [
{
key: 'applicationName',
title: '应用名称',
width: '200px',
render: (_, app) => (
<span className="font-medium">
{app.applicationName && app.applicationCode
? `${app.applicationName}${app.applicationCode}`
: app.applicationName || app.applicationCode || `应用 ${app.applicationId}`}
</span>
),
},
{
key: 'environmentId',
title: '环境',
width: '100px',
render: (_, app) => getEnvironmentName(app.environmentId),
},
{
key: 'buildType',
title: '构建类型',
width: '120px',
render: (_, app) =>
app.buildType === 'JENKINS' ? 'Jenkins构建' : app.buildType === 'NATIVE' ? '脚本部署' : '-',
},
{
key: 'branch',
title: '分支',
dataIndex: 'branch',
width: '100px',
render: (value) => value || '-',
},
{
key: 'deploySystemName',
title: 'Jenkins系统',
width: '150px',
render: (_, app) =>
app.buildType === 'JENKINS'
? (app.deploySystemName || (app.deploySystemId ? `系统 ${app.deploySystemId}` : '-'))
: '-',
},
{
key: 'deployJob',
title: 'Jenkins Job',
width: '150px',
render: (_, app) => (app.buildType === 'JENKINS' ? (app.deployJob || '-') : '-'),
},
{
key: 'workflowDefinitionName',
title: '工作流',
dataIndex: 'workflowDefinitionName',
width: '180px',
render: (value) => value || '-',
},
{
key: 'actions',
title: '操作',
width: '100px',
sticky: true,
render: (_, app) => (
<div className="flex items-center justify-end gap-1">
<Button
variant="ghost"
size="sm"
className="h-8 w-8 p-0"
onClick={() => handleOpenEditAppDialog(app)}
>
<Edit className="h-3.5 w-3.5" />
</Button>
<Button
variant="ghost"
size="sm"
className="h-8 w-8 p-0"
onClick={() => handleOpenDeleteDialog(app)}
>
<Trash2 className="h-3.5 w-3.5 text-destructive" />
</Button>
</div>
),
},
], [environments]);
return (
<>
<Dialog open={open} onOpenChange={onOpenChange}>
@ -221,84 +289,14 @@ export const TeamApplicationManageDialog: React.FC<
{/* 应用列表表格 */}
<div className="border rounded-lg">
{loading ? (
<div className="flex items-center justify-center h-64">
<Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
</div>
) : teamApplications.length === 0 ? (
<div className="flex flex-col items-center justify-center h-64 text-muted-foreground">
<p></p>
<Button
variant="link"
onClick={handleOpenAddAppDialog}
className="mt-2"
>
</Button>
</div>
) : (
<Table>
<TableHeader>
<TableRow>
<TableHead className="whitespace-nowrap" style={{ minWidth: '150px' }}></TableHead>
<TableHead className="whitespace-nowrap" style={{ minWidth: '80px' }}></TableHead>
<TableHead className="whitespace-nowrap" style={{ minWidth: '100px' }}></TableHead>
<TableHead className="whitespace-nowrap" style={{ minWidth: '80px' }}></TableHead>
<TableHead className="whitespace-nowrap" style={{ minWidth: '120px' }}>Jenkins系统</TableHead>
<TableHead className="whitespace-nowrap" style={{ minWidth: '120px' }}>Jenkins Job</TableHead>
<TableHead className="whitespace-nowrap" style={{ minWidth: '150px' }}></TableHead>
<TableHead className="text-right sticky right-0 bg-background" style={{ width: '80px' }}></TableHead>
</TableRow>
</TableHeader>
<TableBody>
{teamApplications.map((app) => (
<TableRow key={app.id}>
<TableCell className="font-medium whitespace-nowrap">
{app.applicationName && app.applicationCode
? `${app.applicationName}${app.applicationCode}`
: app.applicationName || app.applicationCode || `应用 ${app.applicationId}`}
</TableCell>
<TableCell className="whitespace-nowrap">
{getEnvironmentName(app.environmentId)}
</TableCell>
<TableCell className="whitespace-nowrap">
{app.buildType === 'JENKINS' ? 'Jenkins构建' : app.buildType === 'NATIVE' ? '脚本部署' : '-'}
</TableCell>
<TableCell className="whitespace-nowrap">{app.branch || '-'}</TableCell>
<TableCell className="whitespace-nowrap">
{app.buildType === 'JENKINS'
? (app.deploySystemName || (app.deploySystemId ? `系统 ${app.deploySystemId}` : '-'))
: '-'}
</TableCell>
<TableCell className="whitespace-nowrap">
{app.buildType === 'JENKINS' ? (app.deployJob || '-') : '-'}
</TableCell>
<TableCell className="whitespace-nowrap">
{app.workflowDefinitionName || '-'}
</TableCell>
<TableCell className="text-right sticky right-0 bg-background">
<div className="flex items-center justify-end gap-2">
<Button
variant="ghost"
size="sm"
onClick={() => handleOpenEditAppDialog(app)}
>
<Edit className="h-4 w-4" />
</Button>
<Button
variant="ghost"
size="sm"
onClick={() => handleOpenDeleteDialog(app)}
>
<Trash2 className="h-4 w-4 text-destructive" />
</Button>
</div>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
)}
<PaginatedTable<TeamApplication, any>
ref={tableRef}
fetchFn={fetchData}
columns={columns}
rowKey="id"
minWidth="1000px"
pageSize={10}
/>
</div>
</DialogBody>
@ -353,7 +351,7 @@ export const TeamApplicationManageDialog: React.FC<
description: '应用配置已删除',
});
setDeletingApp(null);
loadTeamApplications();
tableRef.current?.refresh();
onSuccess?.();
}}
variant="destructive"